Wed Jan 8 2020 09:49:54

Asterisk developer's documentation


app_queue.c File Reference

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

#include "asterisk.h"
#include <sys/time.h>
#include <sys/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/event.h"
#include "asterisk/astobj2.h"
#include "asterisk/strings.h"
#include "asterisk/global_datastores.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/aoc.h"
#include "asterisk/callerid.h"
#include "asterisk/cel.h"
#include "asterisk/data.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  member
 
struct  penalty_rule
 
struct  queue_end_bridge
 
struct  queue_ent
 
struct  queue_transfer_ds
 
struct  rule_list
 
struct  rule_lists
 
struct  statechange
 
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 DATA_EXPORT_CALL_QUEUE(MEMBER)
 
#define DATA_EXPORT_MEMBER(MEMBER)
 
#define DATA_EXPORT_QUEUE_ENT(MEMBER)
 
#define DEFAULT_MIN_ANNOUNCE_FREQUENCY   15
 
#define DEFAULT_RETRY   5
 
#define DEFAULT_TIMEOUT   15
 
#define MAX_PERIODIC_ANNOUNCEMENTS   10
 
#define MAX_QUEUE_BUCKETS   53
 
#define QUEUE_EVENT_VARIABLES   3
 
#define queue_t_ref(a, b)   queue_ref(a)
 
#define queue_t_unref(a, b)   queue_unref(a)
 
#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_DYNAMIC   (-4)
 
#define RES_OKAY   0
 
#define RES_OUTOFMEMORY   (-2)
 

Enumerations

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  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)
 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...
 
 AST_DATA_STRUCTURE (call_queue, DATA_EXPORT_CALL_QUEUE)
 
 AST_DATA_STRUCTURE (member, DATA_EXPORT_MEMBER)
 
 AST_DATA_STRUCTURE (queue_ent, DATA_EXPORT_QUEUE_ENT)
 
static int attended_transfer_occurred (struct ast_channel *chan)
 mechanism to tell if a queue caller was atxferred by a queue member. More...
 
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 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_penalty (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)
 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 device_state_cb (const struct ast_event *event, void *unused)
 
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 int extension_state_cb (char *context, char *exten, enum ast_extension_states state, 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_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 int get_member_penalty (char *queuename, char *interface)
 
static int get_member_status (struct call_queue *q, int max_penalty, int min_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 char * handle_queue_add_member (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 int handle_statechange (void *datap)
 set a member's status based on device state of that member's interface More...
 
static void hangupcalls (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_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_dead_queues (void *obj, void *arg, int flags)
 
static void leave_queue (struct queue_ent *qe)
 Caller leaving queue. More...
 
static int load_module (void)
 
static struct call_queueload_realtime_queue (const char *queuename)
 
static int manager_add_queue_member (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_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_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_dead_and_unfound (void *obj, void *arg, int flags)
 
static int mark_member_dead (void *obj, void *arg, int flags)
 
static void member_add_to_queue (struct call_queue *queue, struct member *mem)
 
static void member_call_pending_clear (struct member *mem)
 
static int member_call_pending_set (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 play_file (struct ast_channel *chan, const char *filename)
 
static int pqm_exec (struct ast_channel *chan, const char *data)
 PauseQueueMember application. More...
 
static int ql_exec (struct ast_channel *chan, const char *data)
 QueueLog application. More...
 
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_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 (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_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_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_queuememberpaused (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
static int queue_function_queuememberstatus (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
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 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 call_queuequeue_ref (struct call_queue *q)
 
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 void queue_transfer_destroy (void *data)
 
static void queue_transfer_fixup (void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
 Log an attended transfer when a queue caller channel is masqueraded. More...
 
static struct call_queuequeue_unref (struct call_queue *q)
 
static int queues_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
 
static void queues_data_provider_get_helper (const struct ast_data_search *search, struct ast_data *data_root, struct call_queue *queue)
 
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 int remove_members_and_mark_unfound (void *obj, void *arg, int flags)
 
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, char *interface, char *membername, int pause)
 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 *interface, const char *rt_uniqueid, const char *membername, const char *penalty_str, const char *paused_str, const char *state_interface)
 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 struct queue_ent *qe, const char *queuename, const struct ast_channel *peer, const struct member *member, time_t callstart, char *vars, size_t vars_len, 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 (const char *queuename, const char *interface, int penalty)
 
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 struct ast_datastoresetup_transfer_datastore (struct queue_ent *qe, struct member *member, time_t starttime, int callcompletedinsl)
 create a datastore for storing relevant info to log attended transfers in the queue_log More...
 
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, const char *options, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing)
 A large function which calls members, updates statistics, and bridges the caller and a member. More...
 
static int unload_module (void)
 
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, int newtalktime)
 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 int 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 char * vars2manager (struct ast_channel *chan, char *vars, size_t len)
 convert "\n" to "\nVariable: " ready for manager to use 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, int ringing)
 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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_CONSUMER, .nonoptreq = "res_monitor", }
 
static char * app = "Queue"
 
static char * app_aqm = "AddQueueMember"
 
static char * app_pqm = "PauseQueueMember"
 
static char * app_ql = "QueueLog"
 
static char * app_rqm = "RemoveQueueMember"
 
static char * app_upqm = "UnpauseQueueMember"
 
static struct ast_module_infoast_module_info = &__mod_info
 
static int autofill_default = 1
 queues.conf [general] option More...
 
static struct autopause autopausesmodes []
 
static struct ast_cli_entry cli_queue []
 
static struct ast_event_subdevice_state_sub
 Subscription to device state change events. More...
 
static struct ast_taskprocessordevicestate_tps
 
static int montype_default = 0
 queues.conf [general] option More...
 
static const char *const pm_family = "Queue/PersistentMembers"
 Persistent Members astdb family. More...
 
static const char qpm_cmd_usage []
 
static const char qsmp_cmd_usage []
 
static struct ast_data_entry queue_data_providers []
 
static int queue_debug = 0
 queues.conf [general] extra debug option More...
 
static int queue_persistent_members = 0
 queues.conf [general] option More...
 
struct {
   enum queue_result   id
 
   char *   text
 
queue_results []
 
static struct ast_datastore_info queue_transfer_info
 a datastore used to help correctly log attended transfers of queue callers More...
 
static struct ast_custom_function queueexists_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 queuememberpaused_function
 
static struct ast_custom_function queuememberpenalty_function
 
static struct ast_custom_function queuememberstatus_function
 
static struct ao2_containerqueues
 
static struct ast_data_handler queues_data_provider
 
static struct ast_custom_function queuevar_function
 
static struct ast_custom_function queuewaitingcount_function
 
static const char qum_cmd_usage []
 
static struct rule_lists rule_lists = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } , }
 
static int shared_lastcall = 1
 queues.conf [general] option More...
 
static struct strategy strategies []
 
static int update_cdr = 0
 queues.conf [general] option More...
 
static int use_weight = 0
 queues.conf per-queue weight option 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

#define ANNOUNCEHOLDTIME_ALWAYS   1

Definition at line 1208 of file app_queue.c.

Referenced by queue_set_param().

#define ANNOUNCEHOLDTIME_ONCE   2

Definition at line 1209 of file app_queue.c.

Referenced by queue_set_param(), and say_position().

#define ANNOUNCEPOSITION_LIMIT   4

We not announce position more than <limit>

Definition at line 1224 of file app_queue.c.

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

#define ANNOUNCEPOSITION_MORE_THAN   3

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

Definition at line 1223 of file app_queue.c.

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

#define ANNOUNCEPOSITION_NO   2

We don't announce position

Definition at line 1222 of file app_queue.c.

Referenced by queue_set_param(), and queues_data_provider_get_helper().

#define ANNOUNCEPOSITION_YES   1

We announce position

Definition at line 1221 of file app_queue.c.

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

#define AST_MAX_WATCHERS   256

Definition at line 3775 of file app_queue.c.

Referenced by wait_for_answer().

#define DATA_EXPORT_CALL_QUEUE (   MEMBER)

Definition at line 8805 of file app_queue.c.

#define DATA_EXPORT_MEMBER (   MEMBER)

Definition at line 8870 of file app_queue.c.

#define DATA_EXPORT_QUEUE_ENT (   MEMBER)

Definition at line 8884 of file app_queue.c.

#define DEFAULT_MIN_ANNOUNCE_FREQUENCY   15

The minimum number of seconds between position announcements \ The default value of 15 provides backwards compatibility

Definition at line 1028 of file app_queue.c.

Referenced by init_queue().

#define DEFAULT_RETRY   5

Definition at line 1024 of file app_queue.c.

Referenced by init_queue(), and queue_set_param().

#define DEFAULT_TIMEOUT   15

Definition at line 1025 of file app_queue.c.

Referenced by init_queue(), and queue_set_param().

#define MAX_PERIODIC_ANNOUNCEMENTS   10

The maximum periodic announcements we can have

Definition at line 1027 of file app_queue.c.

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

#define MAX_QUEUE_BUCKETS   53

Definition at line 1031 of file app_queue.c.

Referenced by load_module().

#define QUEUE_EVENT_VARIABLES   3

Definition at line 1210 of file app_queue.c.

Referenced by queue_set_param(), ring_entry(), rna(), send_agent_complete(), and try_calling().

#define queue_t_ref (   a,
 
)    queue_ref(a)

Definition at line 1472 of file app_queue.c.

Referenced by leave_queue(), and try_calling().

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

Definition at line 1474 of file app_queue.c.

Referenced by find_queue_by_name_rt(), and reload_single_queue().

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

Definition at line 1475 of file app_queue.c.

Referenced by find_queue_by_name_rt(), leave_queue(), and unload_module().

#define RECHECK   1

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

Definition at line 1026 of file app_queue.c.

Referenced by wait_our_turn().

#define RES_NOT_DYNAMIC   (-4)

Enumeration Type Documentation

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

anonymous enum
Enumerator
QUEUE_AUTOPAUSE_OFF 
QUEUE_AUTOPAUSE_ON 
QUEUE_AUTOPAUSE_ALL 

Definition at line 984 of file app_queue.c.

Enumerator
CALLER 
AGENT 
TRANSFER 

Definition at line 4630 of file app_queue.c.

4639 {
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 1196 of file app_queue.c.

1211  {
Enumerator
QUEUE_RELOAD_PARAMETERS 
QUEUE_RELOAD_MEMBER 
QUEUE_RELOAD_RULES 
QUEUE_RESET_STATS 

Definition at line 990 of file app_queue.c.

990  {
991  QUEUE_RELOAD_PARAMETERS = (1 << 0),
992  QUEUE_RELOAD_MEMBER = (1 << 1),
993  QUEUE_RELOAD_RULES = (1 << 2),
994  QUEUE_RESET_STATS = (1 << 3),
995 };
Enumerator
QUEUE_UNKNOWN 
QUEUE_TIMEOUT 
QUEUE_JOINEMPTY 
QUEUE_LEAVEEMPTY 
QUEUE_JOINUNAVAIL 
QUEUE_LEAVEUNAVAIL 
QUEUE_FULL 
QUEUE_CONTINUE 

Definition at line 1078 of file app_queue.c.

1088  {
Enumerator
TIMEOUT_PRIORITY_APP 
TIMEOUT_PRIORITY_CONF 

Definition at line 1103 of file app_queue.c.

1119  {

Function Documentation

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 7603 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_check_realtime(), ast_config_destroy(), ast_devstate2str(), ast_load_realtime_multientry(), ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_strlen_zero(), member::calls, call_queue::callsabandoned, call_queue::callscompleted, call_queue::callscompletedinsl, queue_ent::chan, CLI_SHOWUSAGE, CLI_SUCCESS, call_queue::count, do_print(), member::dynamic, call_queue::head, call_queue::holdtime, int2strat(), member::interface, member::lastcall, load_realtime_queue(), call_queue::maxlen, member::membername, call_queue::members, ast_channel::name, call_queue::name, queue_ent::next, member::paused, member::penalty, queue_ent::pos, queue_ent::prio, queue_t_unref, queues, member::realtime, call_queue::realtime, call_queue::ringlimit, SENTINEL, call_queue::servicelevel, queue_ent::start, member::status, call_queue::strategy, call_queue::talktime, and call_queue::weight.

Referenced by manager_queues_show(), and queue_show().

7603 {
7604  struct call_queue *q;
7605  struct ast_str *out = ast_str_alloca(240);
7606  int found = 0;
7607  time_t now = time(NULL);
7608  struct ao2_iterator queue_iter;
7609  struct ao2_iterator mem_iter;
7610 
7611  if (argc != 2 && argc != 3)
7612  return CLI_SHOWUSAGE;
7613 
7614  if (argc == 3) { /* specific queue */
7615  if ((q = load_realtime_queue(argv[2]))) {
7616  queue_t_unref(q, "Done with temporary pointer");
7617  }
7618  } else if (ast_check_realtime("queues")) {
7619  /* This block is to find any queues which are defined in realtime but
7620  * which have not yet been added to the in-core container
7621  */
7622  struct ast_config *cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
7623  char *queuename;
7624  if (cfg) {
7625  for (queuename = ast_category_browse(cfg, NULL); !ast_strlen_zero(queuename); queuename = ast_category_browse(cfg, queuename)) {
7626  if ((q = load_realtime_queue(queuename))) {
7627  queue_t_unref(q, "Done with temporary pointer");
7628  }
7629  }
7630  ast_config_destroy(cfg);
7631  }
7632  }
7633 
7634  ao2_lock(queues);
7636  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
7637  float sl;
7638  struct call_queue *realtime_queue = NULL;
7639 
7640  ao2_lock(q);
7641  /* This check is to make sure we don't print information for realtime
7642  * queues which have been deleted from realtime but which have not yet
7643  * been deleted from the in-core container. Only do this if we're not
7644  * looking for a specific queue.
7645  */
7646  if (argc < 3 && q->realtime) {
7647  realtime_queue = load_realtime_queue(q->name);
7648  if (!realtime_queue) {
7649  ao2_unlock(q);
7650  queue_t_unref(q, "Done with iterator");
7651  continue;
7652  }
7653  queue_t_unref(realtime_queue, "Queue is already in memory");
7654  }
7655 
7656  if (argc == 3 && strcasecmp(q->name, argv[2])) {
7657  ao2_unlock(q);
7658  queue_t_unref(q, "Done with iterator");
7659  continue;
7660  }
7661  found = 1;
7662 
7663  ast_str_set(&out, 0, "%s has %d calls (max ", q->name, q->count);
7664  if (q->maxlen)
7665  ast_str_append(&out, 0, "%d", q->maxlen);
7666  else
7667  ast_str_append(&out, 0, "unlimited");
7668  sl = 0;
7669  if (q->callscompleted > 0)
7670  sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
7671  ast_str_append(&out, 0, ") in '%s' strategy (%ds holdtime, %ds talktime), R:%d, W:%d, C:%d, A:%d, SL:%2.1f%% within %ds",
7672  int2strat(q->strategy), q->holdtime, q->talktime, q->ringlimit, q->weight,
7674  do_print(s, fd, ast_str_buffer(out));
7675  if (!ao2_container_count(q->members))
7676  do_print(s, fd, " No Members");
7677  else {
7678  struct member *mem;
7679 
7680  do_print(s, fd, " Members: ");
7681  mem_iter = ao2_iterator_init(q->members, 0);
7682  while ((mem = ao2_iterator_next(&mem_iter))) {
7683  ast_str_set(&out, 0, " %s", mem->membername);
7684  if (strcasecmp(mem->membername, mem->interface)) {
7685  ast_str_append(&out, 0, " (%s)", mem->interface);
7686  }
7687  if (mem->penalty)
7688  ast_str_append(&out, 0, " with penalty %d", mem->penalty);
7689  ast_str_append(&out, 0, "%s%s%s (%s)",
7690  mem->dynamic ? " (dynamic)" : "",
7691  mem->realtime ? " (realtime)" : "",
7692  mem->paused ? " (paused)" : "",
7693  ast_devstate2str(mem->status));
7694  if (mem->calls)
7695  ast_str_append(&out, 0, " has taken %d calls (last was %ld secs ago)",
7696  mem->calls, (long) (time(NULL) - mem->lastcall));
7697  else
7698  ast_str_append(&out, 0, " has taken no calls yet");
7699  do_print(s, fd, ast_str_buffer(out));
7700  ao2_ref(mem, -1);
7701  }
7702  ao2_iterator_destroy(&mem_iter);
7703  }
7704  if (!q->head)
7705  do_print(s, fd, " No Callers");
7706  else {
7707  struct queue_ent *qe;
7708  int pos = 1;
7709 
7710  do_print(s, fd, " Callers: ");
7711  for (qe = q->head; qe; qe = qe->next) {
7712  ast_str_set(&out, 0, " %d. %s (wait: %ld:%2.2ld, prio: %d)",
7713  pos++, qe->chan->name, (long) (now - qe->start) / 60,
7714  (long) (now - qe->start) % 60, qe->prio);
7715  do_print(s, fd, ast_str_buffer(out));
7716  }
7717  }
7718  do_print(s, fd, ""); /* blank line between entries */
7719  ao2_unlock(q);
7720  queue_t_unref(q, "Done with iterator"); /* Unref the iterator's reference */
7721  }
7722  ao2_iterator_destroy(&queue_iter);
7723  ao2_unlock(queues);
7724  if (!found) {
7725  if (argc == 3)
7726  ast_str_set(&out, 0, "No such queue: %s.", argv[2]);
7727  else
7728  ast_str_set(&out, 0, "No queues.");
7729  do_print(s, fd, ast_str_buffer(out));
7730  }
7731  return CLI_SUCCESS;
7732 }
7733 
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:7589
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Find devicestate as text message for output.
Definition: devicestate.c:215
int servicelevel
Definition: app_queue.c:1299
int dynamic
Definition: app_queue.c:1182
int paused
Definition: app_queue.c:1185
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
Definition: astobj2.c:470
struct ast_channel * chan
Definition: app_queue.c:1168
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
time_t start
Definition: app_queue.c:1165
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
#define ao2_t_iterator_next(arg1, arg2)
Definition: astobj2.h:1125
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:900
int realtime
Definition: app_queue.c:1183
char interface[80]
Definition: app_queue.c:1175
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
#define ast_str_alloca(init_len)
Definition: strings.h:608
int ringlimit
Definition: app_queue.c:1307
struct ao2_container * members
Definition: app_queue.c:1320
struct queue_ent * head
Definition: app_queue.c:1321
int callscompletedinsl
Definition: app_queue.c:1300
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
char membername[80]
Definition: app_queue.c:1179
int holdtime
Definition: app_queue.c:1295
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:874
#define SENTINEL
Definition: compiler.h:75
static struct ao2_container * queues
Definition: app_queue.c:1334
int penalty
Definition: app_queue.c:1180
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ao2_ref(o, delta)
Definition: astobj2.h:472
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
#define ao2_lock(a)
Definition: astobj2.h:488
int strategy
Definition: app_queue.c:1281
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
#define CLI_SHOWUSAGE
Definition: cli.h:44
static struct call_queue * load_realtime_queue(const char *queuename)
Definition: app_queue.c:2573
const ast_string_field name
Definition: app_queue.c:1266
const ast_string_field name
Definition: channel.h:787
int talktime
Definition: app_queue.c:1296
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
int calls
Definition: app_queue.c:1181
int status
Definition: app_queue.c:1184
#define CLI_SUCCESS
Definition: cli.h:43
int callsabandoned
Definition: app_queue.c:1298
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
unsigned int realtime
Definition: app_queue.c:1283
struct queue_ent * next
Definition: app_queue.c:1171
int callscompleted
Definition: app_queue.c:1297
time_t lastcall
Definition: app_queue.c:1187
static const char * int2strat(int strategy)
Definition: app_queue.c:1353
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: config.c:2650
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: config.c:2587
static void __reg_module ( void  )
static

Definition at line 9216 of file app_queue.c.

static void __unreg_module ( void  )
static

Definition at line 9216 of file app_queue.c.

static int add_to_queue ( const char *  queuename,
const char *  interface,
const char *  membername,
int  penalty,
int  paused,
int  dump,
const char *  state_interface 
)
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 5763 of file app_queue.c.

References ao2_lock, ao2_ref, ao2_unlock, member::calls, create_queue_member(), dump_queue_members(), member::dynamic, EVENT_FLAG_AGENT, member::interface, interface_exists(), member::lastcall, load_realtime_queue(), manager_event, member_add_to_queue(), member::membername, call_queue::name, member::paused, member::penalty, queue_t_unref, RES_EXISTS, RES_NOSUCHQUEUE, RES_OKAY, RES_OUTOFMEMORY, and member::status.

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

5763 {
5764  struct call_queue *q;
5765  struct member *new_member, *old_member;
5766  int res = RES_NOSUCHQUEUE;
5767 
5768  /*! \note Ensure the appropriate realtime queue is loaded. Note that this
5769  * short-circuits if the queue is already in memory. */
5770  if (!(q = load_realtime_queue(queuename)))
5771  return res;
5772 
5773  ao2_lock(q);
5774  if ((old_member = interface_exists(q, interface)) == NULL) {
5776  new_member->dynamic = 1;
5777  member_add_to_queue(q, new_member);
5778  manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
5779  "Queue: %s\r\n"
5780  "Location: %s\r\n"
5781  "MemberName: %s\r\n"
5782  "Membership: %s\r\n"
5783  "Penalty: %d\r\n"
5784  "CallsTaken: %d\r\n"
5785  "LastCall: %d\r\n"
5786  "Status: %d\r\n"
5787  "Paused: %d\r\n",
5788  q->name, new_member->interface, new_member->membername,
5789  "dynamic",
5790  new_member->penalty, new_member->calls, (int) new_member->lastcall,
5791  new_member->status, new_member->paused);
5792 
5793  ao2_ref(new_member, -1);
5794  new_member = NULL;
5795 
5796  if (dump)
5797  dump_queue_members(q);
5798 
5799  res = RES_OKAY;
5800  } else {
5801  res = RES_OUTOFMEMORY;
5802  }
5803  } else {
5804  ao2_ref(old_member, -1);
5805  res = RES_EXISTS;
5806  }
5807  ao2_unlock(q);
5808  queue_t_unref(q, "Expiring temporary reference");
5809 
5810  return res;
5811 }
5812 
int dynamic
Definition: app_queue.c:1182
int paused
Definition: app_queue.c:1185
#define RES_OKAY
Definition: app_queue.c:1033
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
char interface[80]
Definition: app_queue.c:1175
char state_interface[80]
Definition: app_queue.c:1178
#define ao2_unlock(a)
Definition: astobj2.h:497
char membername[80]
Definition: app_queue.c:1179
#define RES_OUTOFMEMORY
Definition: app_queue.c:1035
static struct member * interface_exists(struct call_queue *q, const char *interface)
Definition: app_queue.c:5637
static void member_add_to_queue(struct call_queue *queue, struct member *mem)
Definition: app_queue.c:2300
int penalty
Definition: app_queue.c:1180
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
static struct call_queue * load_realtime_queue(const char *queuename)
Definition: app_queue.c:2573
const ast_string_field name
Definition: app_queue.c:1266
#define EVENT_FLAG_AGENT
Definition: manager.h:76
static void dump_queue_members(struct call_queue *pm_queue)
Dump all members in a specific queue to the database.
Definition: app_queue.c:5663
int calls
Definition: app_queue.c:1181
#define RES_NOSUCHQUEUE
Definition: app_queue.c:1036
int status
Definition: app_queue.c:1184
static struct member * create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface)
allocate space for new queue member and set fields based on parameters passed
Definition: app_queue.c:1801
#define RES_EXISTS
Definition: app_queue.c:1034
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
time_t lastcall
Definition: app_queue.c:1187
static struct call_queue* alloc_queue ( const char *  queuename)
static

Definition at line 2418 of file app_queue.c.

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

Referenced by find_queue_by_name_rt(), and reload_single_queue().

2418 {
2419  struct call_queue *q;
2420 
2421  if ((q = ao2_t_alloc(sizeof(*q), destroy_queue, "Allocate queue"))) {
2422  if (ast_string_field_init(q, 64)) {
2423  queue_t_unref(q, "String field allocation failed");
2424  return NULL;
2425  }
2426  ast_string_field_set(q, name, queuename);
2427  }
2428  return q;
2429 }
2430 
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Allocate and initialize an object.
Definition: astobj2.h:429
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:249
static void destroy_queue(void *obj)
Free queue&#39;s member list then its string fields.
Definition: app_queue.c:2404
static const char name[]
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
static int aqm_exec ( struct ast_channel chan,
const char *  data 
)
static

AddQueueMember application.

Definition at line 6195 of file app_queue.c.

References add_to_queue(), args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_queue_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_channel::name, parse(), pbx_builtin_setvar_helper(), RES_EXISTS, RES_NOSUCHQUEUE, RES_OKAY, RES_OUTOFMEMORY, and ast_channel::uniqueid.

Referenced by load_module().

6195 {
6196  int res=-1;
6197  char *parse, *temppos = NULL;
6199  AST_APP_ARG(queuename);
6200  AST_APP_ARG(interface);
6201  AST_APP_ARG(penalty);
6202  AST_APP_ARG(options);
6203  AST_APP_ARG(membername);
6204  AST_APP_ARG(state_interface);
6205  );
6206  int penalty = 0;
6207 
6208  if (ast_strlen_zero(data)) {
6209  ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename[,interface[,penalty[,options[,membername[,stateinterface]]]]])\n");
6210  return -1;
6211  }
6212 
6213  parse = ast_strdupa(data);
6214 
6215  AST_STANDARD_APP_ARGS(args, parse);
6216 
6217  if (ast_strlen_zero(args.interface)) {
6218  args.interface = ast_strdupa(chan->name);
6219  temppos = strrchr(args.interface, '-');
6220  if (temppos)
6221  *temppos = '\0';
6222  }
6223 
6224  if (!ast_strlen_zero(args.penalty)) {
6225  if ((sscanf(args.penalty, "%30d", &penalty) != 1) || penalty < 0) {
6226  ast_log(LOG_WARNING, "Penalty '%s' is invalid, must be an integer >= 0\n", args.penalty);
6227  penalty = 0;
6228  }
6229  }
6230 
6231  switch (add_to_queue(args.queuename, args.interface, args.membername, penalty, 0, queue_persistent_members, args.state_interface)) {
6232  case RES_OKAY:
6233  ast_queue_log(args.queuename, chan->uniqueid, args.interface, "ADDMEMBER", "%s", "");
6234  ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", args.interface, args.queuename);
6235  pbx_builtin_setvar_helper(chan, "AQMSTATUS", "ADDED");
6236  res = 0;
6237  break;
6238  case RES_EXISTS:
6239  ast_log(LOG_WARNING, "Unable to add interface '%s' to queue '%s': Already there\n", args.interface, args.queuename);
6240  pbx_builtin_setvar_helper(chan, "AQMSTATUS", "MEMBERALREADY");
6241  res = 0;
6242  break;
6243  case RES_NOSUCHQUEUE:
6244  ast_log(LOG_WARNING, "Unable to add interface to queue '%s': No such queue\n", args.queuename);
6245  pbx_builtin_setvar_helper(chan, "AQMSTATUS", "NOSUCHQUEUE");
6246  res = 0;
6247  break;
6248  case RES_OUTOFMEMORY:
6249  ast_log(LOG_ERROR, "Out of memory adding member %s to queue %s\n", args.interface, args.queuename);
6250  break;
6251  }
6252 
6253  return res;
6254 }
6255 
#define RES_OKAY
Definition: app_queue.c:1033
const ast_string_field uniqueid
Definition: channel.h:787
#define LOG_WARNING
Definition: logger.h:144
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
#define RES_OUTOFMEMORY
Definition: app_queue.c:1035
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define LOG_ERROR
Definition: logger.h:155
static struct @350 args
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
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...
Definition: pbx.c:10546
#define RES_NOSUCHQUEUE
Definition: app_queue.c:1036
#define RES_EXISTS
Definition: app_queue.c:1034
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump, const char *state_interface)
Add member to queue.
Definition: app_queue.c:5763
static int queue_persistent_members
queues.conf [general] option
Definition: app_queue.c:1058
AST_DATA_STRUCTURE ( call_queue  ,
DATA_EXPORT_CALL_QUEUE   
)
AST_DATA_STRUCTURE ( member  ,
DATA_EXPORT_MEMBER   
)
AST_DATA_STRUCTURE ( queue_ent  ,
DATA_EXPORT_QUEUE_ENT   
)
static int attended_transfer_occurred ( struct ast_channel chan)
static

mechanism to tell if a queue caller was atxferred by a queue member.

When a caller is atxferred, then the queue_transfer_info datastore is removed from the channel. If it's still there after the bridge is broken, then the caller was not atxferred.

Note
Only call this with chan locked

Definition at line 4735 of file app_queue.c.

References ast_channel_datastore_find(), and queue_transfer_info.

Referenced by try_calling().

4735 {
4736  return ast_channel_datastore_find(chan, &queue_transfer_info, NULL) ? 0 : 1;
4737 }
4738 
static struct ast_datastore_info queue_transfer_info
a datastore used to help correctly log attended transfers of queue callers
Definition: app_queue.c:4688
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2604
static int autopause2int ( const char *  autopause)
static

Definition at line 1377 of file app_queue.c.

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

Referenced by queue_set_param().

1377 {
1378  int x;
1379  /*This 'double check' that default value is OFF */
1381  return QUEUE_AUTOPAUSE_OFF;
1382 
1383  /*This 'double check' is to ensure old values works */
1384  if(ast_true(autopause))
1385  return QUEUE_AUTOPAUSE_ON;
1386 
1387  for (x = 0; x < ARRAY_LEN(autopausesmodes); x++) {
1388  if (!strcasecmp(autopause, autopausesmodes[x].name))
1389  return autopausesmodes[x].autopause;
1390  }
1391 
1392  /*This 'double check' that default value is OFF */
1393  return QUEUE_AUTOPAUSE_OFF;
1394 }
1395 
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static struct autopause autopausesmodes[]
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
static const char name[]
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 4554 of file app_queue.c.

References ao2_container_count(), ast_debug, ast_log(), ast_random(), member::calls, member::interface, member::lastcall, queue_ent::linpos, queue_ent::linwrapped, LOG_DEBUG, LOG_WARNING, queue_ent::max_penalty, call_queue::members, callattempt::metric, queue_ent::min_penalty, option_debug, member::penalty, call_queue::penaltymemberslimit, queue_ent::pos, 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, member::ringcount, call_queue::ringlimit, call_queue::rrpos, call_queue::strategy, and call_queue::wrapped.

Referenced by try_calling().

4554 {
4555  /* disregarding penalty on too few members? */
4556  int membercount = ao2_container_count(q->members);
4557  unsigned char usepenalty = (membercount <= q->penaltymemberslimit) ? 0 : 1;
4558 
4559  if (usepenalty) {
4560  if ((qe->max_penalty != INT_MAX && mem->penalty > qe->max_penalty) ||
4561  (qe->min_penalty != INT_MAX && mem->penalty < qe->min_penalty)) {
4562  return -1;
4563  }
4564  } else {
4565  ast_debug(1, "Disregarding penalty, %d members and %d in penaltymemberslimit.\n",
4566  membercount, q->penaltymemberslimit);
4567  }
4568 
4569  switch (q->strategy) {
4571  /* Everyone equal, except for penalty */
4572  tmp->metric = mem->penalty * 1000000 * usepenalty;
4573  break;
4574  case QUEUE_STRATEGY_LINEAR:
4575  if (pos < qe->linpos) {
4576  tmp->metric = 1000 + pos;
4577  } else {
4578  if (pos > qe->linpos)
4579  /* Indicate there is another priority */
4580  qe->linwrapped = 1;
4581  tmp->metric = pos;
4582  }
4583  tmp->metric += mem->penalty * 1000000 * usepenalty;
4584  break;
4587  pos = mem->queuepos;
4588  if (pos < q->rrpos) {
4589  tmp->metric = 1000 + pos;
4590  } else {
4591  if (pos > q->rrpos)
4592  /* Indicate there is another priority */
4593  q->wrapped = 1;
4594  tmp->metric = pos;
4595  }
4596  tmp->metric += mem->penalty * 1000000 * usepenalty;
4597  break;
4598  case QUEUE_STRATEGY_RANDOM:
4599  tmp->metric = ast_random() % 1000;
4600  tmp->metric += mem->penalty * 1000000 * usepenalty;
4601  break;
4603  tmp->metric = ast_random() % ((1 + mem->penalty) * 1000);
4604  break;
4606  tmp->metric = mem->calls;
4607  tmp->metric += mem->penalty * 1000000 * usepenalty;
4608  break;
4610  if (!mem->lastcall)
4611  tmp->metric = 0;
4612  else
4613  tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
4614  tmp->metric += mem->penalty * 1000000 * usepenalty;
4615  break;
4616  default:
4617  ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
4618  break;
4619  }
4620  if (q->ringlimit && (mem->ringcount >= q->ringlimit)) {
4621  tmp->metric += (mem->ringcount / q->ringlimit) * 10000000;
4622  }
4623  if (option_debug)
4624  ast_log(LOG_DEBUG, "New metric %d for member %s with %d rings (limit %d)\n",
4625  tmp->metric, mem->interface, mem->ringcount, q->ringlimit);
4626  return 0;
4627 }
4628 
int queuepos
Definition: app_queue.c:1186
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
Definition: astobj2.c:470
int min_penalty
Definition: app_queue.c:1162
int max_penalty
Definition: app_queue.c:1161
int option_debug
Definition: asterisk.c:182
int penaltymemberslimit
Definition: app_queue.c:1306
#define LOG_WARNING
Definition: logger.h:144
int linwrapped
Definition: app_queue.c:1164
char interface[80]
Definition: app_queue.c:1175
int ringlimit
Definition: app_queue.c:1307
#define LOG_DEBUG
Definition: logger.h:122
struct ao2_container * members
Definition: app_queue.c:1320
unsigned int wrapped
Definition: app_queue.c:1277
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int penalty
Definition: app_queue.c:1180
long int ast_random(void)
Definition: utils.c:1640
int strategy
Definition: app_queue.c:1281
int linpos
Definition: app_queue.c:1163
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int calls
Definition: app_queue.c:1181
time_t lastcall
Definition: app_queue.c:1187
int ringcount
Definition: app_queue.c:1190
static void callattempt_free ( struct callattempt doomed)
static

Definition at line 3080 of file app_queue.c.

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

Referenced by hangupcalls(), and try_calling().

3080 {
3081  if (doomed->member) {
3082  ao2_ref(doomed->member, -1);
3083  }
3085  ast_free(doomed);
3086 }
3087 
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2353
struct ast_party_connected_line connected
Definition: app_queue.c:1130
#define ao2_ref(o, delta)
Definition: astobj2.h:472
struct member * member
Definition: app_queue.c:1128
#define ast_free(a)
Definition: astmm.h:97
static int can_ring_entry ( struct queue_ent qe,
struct callattempt call 
)
static

Definition at line 3300 of file app_queue.c.

References ast_debug, ast_log(), compare_weight(), get_queue_member_status(), callattempt::interface, callattempt::lastcall, callattempt::lastqueue, LOG_NOTICE, callattempt::member, member_call_pending_clear(), member_call_pending_set(), member_status_available(), call_queue::name, queue_ent::parent, member::paused, call_queue::ringinuse, member::status, and call_queue::wrapuptime.

Referenced by ring_entry().

3300 {
3301  if (call->member->paused) {
3302  if (queue_debug)
3303  ast_log(LOG_NOTICE, "%s paused, can't receive call\n", call->interface);
3304  return 0;
3305  }
3306 
3307  if (!qe->parent->ringinuse && !member_status_available(call->member->status)) {
3308  if (queue_debug)
3309  ast_log(LOG_NOTICE, "%s not available, can't receive call\n", call->interface);
3310  return 0;
3311  }
3312 
3313  if ((call->lastqueue && call->lastqueue->wrapuptime && (time(NULL) - call->lastcall < call->lastqueue->wrapuptime))
3314  || (!call->lastqueue && qe->parent->wrapuptime && (time(NULL) - call->lastcall < qe->parent->wrapuptime))) {
3315  if (queue_debug)
3316  ast_log(LOG_NOTICE, "Wrapuptime not yet expired on queue %s for %s\n",
3317  (call->lastqueue ? call->lastqueue->name : qe->parent->name),
3318  call->interface);
3319  return 0;
3320  }
3321 
3322  if (use_weight && compare_weight(qe->parent, call->member)) {
3323  if (queue_debug)
3324  ast_log(LOG_NOTICE, "Priority queue delaying call to %s:%s\n",
3325  qe->parent->name, call->interface);
3326  return 0;
3327  }
3328 
3329  if (!qe->parent->ringinuse) {
3330  if (member_call_pending_set(call->member)) {
3331  if (queue_debug)
3332  ast_log(LOG_NOTICE, "%s has another call pending, can't receive call\n",
3333  call->interface);
3334  return 0;
3335  }
3336 
3337  /*
3338  * The queue member is available. Get current status to be sure
3339  * because the device state and extension state callbacks may
3340  * not have updated the status yet.
3341  */
3343  ast_debug(1, "%s actually not available, can't receive call\n",
3344  call->interface);
3346  return 0;
3347  }
3348  }
3349 
3350  return 1;
3351 }
3352 
struct call_queue * parent
Definition: app_queue.c:1144
int paused
Definition: app_queue.c:1185
time_t lastcall
Definition: app_queue.c:1126
int wrapuptime
Definition: app_queue.c:1305
struct call_queue * lastqueue
Definition: app_queue.c:1127
unsigned int ringinuse
Definition: app_queue.c:1271
static void member_call_pending_clear(struct member *mem)
Definition: app_queue.c:3264
char interface[256]
Definition: app_queue.c:1124
static int member_status_available(int status)
Definition: app_queue.c:3251
static int compare_weight(struct call_queue *rq, struct member *member)
Definition: app_queue.c:3163
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
struct member * member
Definition: app_queue.c:1128
const ast_string_field name
Definition: app_queue.c:1266
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
static int member_call_pending_set(struct member *mem)
Definition: app_queue.c:3279
int status
Definition: app_queue.c:1184
static int queue_debug
queues.conf [general] extra debug option
Definition: app_queue.c:1055
static int use_weight
queues.conf per-queue weight option
Definition: app_queue.c:1061
static int get_queue_member_status(struct member *cur)
Return the current state of a member.
Definition: app_queue.c:1795
static void clear_queue ( struct call_queue q)
static

Definition at line 1943 of file app_queue.c.

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

Referenced by clear_stats(), and find_queue_by_name_rt().

1943 {
1944  q->holdtime = 0;
1945  q->callscompleted = 0;
1946  q->callsabandoned = 0;
1947  q->callscompletedinsl = 0;
1948  q->talktime = 0;
1949 
1950  if (q->members) {
1951  struct member *mem;
1952  struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
1953  while ((mem = ao2_iterator_next(&mem_iter))) {
1954  mem->calls = 0;
1955  mem->lastcall = 0;
1956  ao2_ref(mem, -1);
1957  }
1958  ao2_iterator_destroy(&mem_iter);
1959  }
1960 }
1961 
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
struct ao2_container * members
Definition: app_queue.c:1320
int callscompletedinsl
Definition: app_queue.c:1300
int holdtime
Definition: app_queue.c:1295
#define ao2_ref(o, delta)
Definition: astobj2.h:472
int talktime
Definition: app_queue.c:1296
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
int calls
Definition: app_queue.c:1181
int callsabandoned
Definition: app_queue.c:1298
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
int callscompleted
Definition: app_queue.c:1297
time_t lastcall
Definition: app_queue.c:1187
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 7542 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, queue_t_unref, and queues.

Referenced by reload_handler().

7542 {
7543  struct call_queue *q;
7544  struct ao2_iterator queue_iter;
7545 
7546  queue_iter = ao2_iterator_init(queues, 0);
7547  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
7548  ao2_lock(q);
7549  if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename))
7550  clear_queue(q);
7551  ao2_unlock(q);
7552  queue_t_unref(q, "Done with iterator");
7553  }
7554  ao2_iterator_destroy(&queue_iter);
7555  return 0;
7556 }
7557 
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
#define ao2_t_iterator_next(arg1, arg2)
Definition: astobj2.h:1125
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
static void clear_queue(struct call_queue *q)
Definition: app_queue.c:1943
static struct ao2_container * queues
Definition: app_queue.c:1334
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ao2_lock(a)
Definition: astobj2.h:488
const ast_string_field name
Definition: app_queue.c:1266
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
static int compare_weight ( struct call_queue rq,
struct member member 
)
static

Definition at line 3163 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, queues, and call_queue::weight.

Referenced by can_ring_entry().

3163 {
3164  struct call_queue *q;
3165  struct member *mem;
3166  int found = 0;
3167  struct ao2_iterator queue_iter;
3168 
3169  queue_iter = ao2_iterator_init(queues, 0);
3170  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
3171  if (q == rq) { /* don't check myself, could deadlock */
3172  queue_t_unref(q, "Done with iterator");
3173  continue;
3174  }
3175  ao2_lock(q);
3176  if (q->count && q->members) {
3177  if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
3178  ast_debug(1, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
3179  if (q->weight > rq->weight && q->count >= num_available_members(q)) {
3180  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);
3181  found = 1;
3182  }
3183  ao2_ref(mem, -1);
3184  }
3185  }
3186  ao2_unlock(q);
3187  queue_t_unref(q, "Done with iterator");
3188  if (found) {
3189  break;
3190  }
3191  }
3192  ao2_iterator_destroy(&queue_iter);
3193  return found;
3194 }
3195 
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
#define ao2_t_iterator_next(arg1, arg2)
Definition: astobj2.h:1125
char interface[80]
Definition: app_queue.c:1175
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
struct ao2_container * members
Definition: app_queue.c:1320
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static struct ao2_container * queues
Definition: app_queue.c:1334
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
static int num_available_members(struct call_queue *q)
Get the number of members available to accept a call.
Definition: app_queue.c:3117
const ast_string_field name
Definition: app_queue.c:1266
#define ao2_find(arg1, arg2, arg3)
Definition: astobj2.h:964
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
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 7807 of file app_queue.c.

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

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

7807 {
7808  struct call_queue *q;
7809  char *ret = NULL;
7810  int which = 0;
7811  int wordlen = strlen(word);
7812  struct ao2_iterator queue_iter;
7813  const char *word_list = NULL;
7814 
7815  /* for certain commands, already completed items should be left out of
7816  * the list */
7817  if (word_list_offset && strlen(line) >= word_list_offset) {
7818  word_list = line + word_list_offset;
7819  }
7820 
7821  queue_iter = ao2_iterator_init(queues, 0);
7822  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
7823  if (!strncasecmp(word, q->name, wordlen) && ++which > state
7824  && (!word_list_offset || !word_in_list(word_list, q->name))) {
7825  ret = ast_strdup(q->name);
7826  queue_t_unref(q, "Done with iterator");
7827  break;
7828  }
7829  queue_t_unref(q, "Done with iterator");
7830  }
7831  ao2_iterator_destroy(&queue_iter);
7832 
7833  /* Pretend "rules" is at the end of the queues list in certain
7834  * circumstances since it is an alternate command that should be
7835  * tab-completable for "queue show" */
7836  if (!ret && which == state && !wordlen && !strncmp("queue show", line, 10)) {
7837  ret = ast_strdup("rules");
7838  }
7839 
7840  return ret;
7841 }
7842 
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
#define ast_strdup(a)
Definition: astmm.h:109
#define ao2_t_iterator_next(arg1, arg2)
Definition: astobj2.h:1125
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
Definition: ael.tab.c:203
static struct ao2_container * queues
Definition: app_queue.c:1334
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:7748
const ast_string_field name
Definition: app_queue.c:1266
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
static char* complete_queue_add_member ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 8270 of file app_queue.c.

References ast_malloc, ast_strdup, and complete_queue().

Referenced by handle_queue_add_member().

8270 {
8271  /* 0 - queue; 1 - add; 2 - member; 3 - <interface>; 4 - to; 5 - <queue>; 6 - penalty; 7 - <penalty>; 8 - as; 9 - <membername> */
8272  switch (pos) {
8273  case 3: /* Don't attempt to complete name of interface (infinite possibilities) */
8274  return NULL;
8275  case 4: /* only one possible match, "to" */
8276  return state == 0 ? ast_strdup("to") : NULL;
8277  case 5: /* <queue> */
8278  return complete_queue(line, word, pos, state, 0);
8279  case 6: /* only one possible match, "penalty" */
8280  return state == 0 ? ast_strdup("penalty") : NULL;
8281  case 7:
8282  if (state < 100) { /* 0-99 */
8283  char *num;
8284  if ((num = ast_malloc(3))) {
8285  sprintf(num, "%d", state);
8286  }
8287  return num;
8288  } else {
8289  return NULL;
8290  }
8291  case 8: /* only one possible match, "as" */
8292  return state == 0 ? ast_strdup("as") : NULL;
8293  case 9: /* Don't attempt to complete name of member (infinite possibilities) */
8294  return NULL;
8295  default:
8296  return NULL;
8297  }
8298 }
8299 
#define ast_strdup(a)
Definition: astmm.h:109
Definition: ael.tab.c:203
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:7807
#define ast_malloc(a)
Definition: astmm.h:91
static char* complete_queue_pause_member ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 8492 of file app_queue.c.

References ast_strdup, and complete_queue().

Referenced by handle_queue_pause_member().

8492 {
8493  /* 0 - queue; 1 - pause; 2 - member; 3 - <interface>; 4 - queue; 5 - <queue>; 6 - reason; 7 - <reason> */
8494  switch (pos) {
8495  case 3: /* Don't attempt to complete name of interface (infinite possibilities) */
8496  return NULL;
8497  case 4: /* only one possible match, "queue" */
8498  return state == 0 ? ast_strdup("queue") : NULL;
8499  case 5: /* <queue> */
8500  return complete_queue(line, word, pos, state, 0);
8501  case 6: /* "reason" */
8502  return state == 0 ? ast_strdup("reason") : NULL;
8503  case 7: /* Can't autocomplete a reason, since it's 100% customizeable */
8504  return NULL;
8505  default:
8506  return NULL;
8507  }
8508 }
8509 
#define ast_strdup(a)
Definition: astmm.h:109
Definition: ael.tab.c:203
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:7807
static char* complete_queue_remove_member ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 8400 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, queue_t_unref, and queues.

Referenced by handle_queue_remove_member().

8400 {
8401  int which = 0;
8402  struct call_queue *q;
8403  struct member *m;
8404  struct ao2_iterator queue_iter;
8405  struct ao2_iterator mem_iter;
8406  int wordlen = strlen(word);
8407 
8408  /* 0 - queue; 1 - remove; 2 - member; 3 - <member>; 4 - from; 5 - <queue> */
8409  if (pos > 5 || pos < 3)
8410  return NULL;
8411  if (pos == 4) /* only one possible match, 'from' */
8412  return (state == 0 ? ast_strdup("from") : NULL);
8413 
8414  if (pos == 5) { /* No need to duplicate code */
8415  return complete_queue(line, word, pos, state, 0);
8416  }
8417 
8418  /* here is the case for 3, <member> */
8419  queue_iter = ao2_iterator_init(queues, 0);
8420  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
8421  ao2_lock(q);
8422  mem_iter = ao2_iterator_init(q->members, 0);
8423  while ((m = ao2_iterator_next(&mem_iter))) {
8424  if (!strncasecmp(word, m->membername, wordlen) && ++which > state) {
8425  char *tmp;
8426  tmp = ast_strdup(m->interface);
8427  ao2_ref(m, -1);
8428  ao2_iterator_destroy(&mem_iter);
8429  ao2_unlock(q);
8430  queue_t_unref(q, "Done with iterator, returning interface name");
8431  ao2_iterator_destroy(&queue_iter);
8432  return tmp;
8433  }
8434  ao2_ref(m, -1);
8435  }
8436  ao2_iterator_destroy(&mem_iter);
8437  ao2_unlock(q);
8438  queue_t_unref(q, "Done with iterator");
8439  }
8440  ao2_iterator_destroy(&queue_iter);
8441 
8442  return NULL;
8443 }
8444 
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
#define ast_strdup(a)
Definition: astmm.h:109
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
#define ao2_t_iterator_next(arg1, arg2)
Definition: astobj2.h:1125
char interface[80]
Definition: app_queue.c:1175
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
struct ao2_container * members
Definition: app_queue.c:1320
Definition: ael.tab.c:203
char membername[80]
Definition: app_queue.c:1179
static struct ao2_container * queues
Definition: app_queue.c:1334
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:7807
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
static char* complete_queue_rule_show ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 8625 of file app_queue.c.

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

Referenced by handle_queue_rule_show().

8625 {
8626  int which = 0;
8627  struct rule_list *rl_iter;
8628  int wordlen = strlen(word);
8629  char *ret = NULL;
8630  if (pos != 3) /* Wha? */ {
8631  return NULL;
8632  }
8633 
8635  AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
8636  if (!strncasecmp(word, rl_iter->name, wordlen) && ++which > state) {
8637  ret = ast_strdup(rl_iter->name);
8638  break;
8639  }
8640  }
8642 
8643  return ret;
8644 }
8645 
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define ast_strdup(a)
Definition: astmm.h:109
char name[80]
Definition: app_queue.c:1327
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Definition: ael.tab.c:203
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct rule_list::@59 list
static char* complete_queue_set_member_penalty ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 8562 of file app_queue.c.

References ast_strdup, and complete_queue().

Referenced by handle_queue_set_member_penalty().

8562 {
8563  /* 0 - queue; 1 - set; 2 - penalty; 3 - <penalty>; 4 - on; 5 - <member>; 6 - in; 7 - <queue>;*/
8564  switch (pos) {
8565  case 4:
8566  if (state == 0) {
8567  return ast_strdup("on");
8568  } else {
8569  return NULL;
8570  }
8571  case 6:
8572  if (state == 0) {
8573  return ast_strdup("in");
8574  } else {
8575  return NULL;
8576  }
8577  case 7:
8578  return complete_queue(line, word, pos, state, 0);
8579  default:
8580  return NULL;
8581  }
8582 }
8583 
#define ast_strdup(a)
Definition: astmm.h:109
Definition: ael.tab.c:203
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:7807
static char* complete_queue_show ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 7844 of file app_queue.c.

References complete_queue().

Referenced by queue_show().

7844 {
7845  if (pos == 2) {
7846  return complete_queue(line, word, pos, state, 0);
7847  }
7848  return NULL;
7849 }
7850 
Definition: ael.tab.c:203
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:7807
static int compress_char ( const char  c)
static

Definition at line 1833 of file app_queue.c.

Referenced by member_hash_fn().

1833 {
1834  if (c < 32)
1835  return 0;
1836  else if (c > 96)
1837  return c - 64;
1838  else
1839  return c - 32;
1840 }
1841 
static void copy_rules ( struct queue_ent qe,
const char *  rulename 
)
static

Copy rule from global list into specified queue.

Definition at line 6292 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, 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, rule_list::rules, and penalty_rule::time.

Referenced by queue_exec().

6292 {
6293  struct penalty_rule *pr_iter;
6294  struct rule_list *rl_iter;
6295  const char *tmp = ast_strlen_zero(rulename) ? qe->parent->defaultrule : rulename;
6297  AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
6298  if (!strcasecmp(rl_iter->name, tmp))
6299  break;
6300  }
6301  if (rl_iter) {
6302  AST_LIST_TRAVERSE(&rl_iter->rules, pr_iter, list) {
6303  struct penalty_rule *new_pr = ast_calloc(1, sizeof(*new_pr));
6304  if (!new_pr) {
6305  ast_log(LOG_ERROR, "Memory allocation error when copying penalty rules! Aborting!\n");
6306  break;
6307  }
6308  new_pr->time = pr_iter->time;
6309  new_pr->max_value = pr_iter->max_value;
6310  new_pr->min_value = pr_iter->min_value;
6311  new_pr->max_relative = pr_iter->max_relative;
6312  new_pr->min_relative = pr_iter->min_relative;
6313  AST_LIST_INSERT_TAIL(&qe->qe_rules, new_pr, list);
6314  }
6315  }
6317 }
6318 
struct call_queue * parent
Definition: app_queue.c:1144
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
int max_relative
Definition: app_queue.c:1216
struct rule_list::@58 rules
char name[80]
Definition: app_queue.c:1327
int min_relative
Definition: app_queue.c:1217
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define LOG_ERROR
Definition: logger.h:155
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct rule_list::@59 list
const ast_string_field defaultrule
Definition: app_queue.c:1266
#define ast_calloc(a, b)
Definition: astmm.h:82
struct queue_ent::@54 qe_rules
struct penalty_rule::@55 list
static struct member* create_queue_member ( const char *  interface,
const char *  membername,
int  penalty,
int  paused,
const char *  state_interface 
)
static

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

Definition at line 1801 of file app_queue.c.

References ao2_alloc, ast_copy_string(), ast_log(), ast_strdupa, ast_strlen_zero(), queue_ent::context, exten, get_queue_member_status(), member::interface, LOG_WARNING, member::membername, member::paused, member::penalty, S_OR, member::state_context, member::state_exten, member::state_interface, member::status, and strsep().

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

1801 {
1802  struct member *cur;
1803 
1804  if ((cur = ao2_alloc(sizeof(*cur), NULL))) {
1805  cur->penalty = penalty;
1806  cur->paused = paused;
1807  ast_copy_string(cur->interface, interface, sizeof(cur->interface));
1810  else
1813  ast_copy_string(cur->membername, membername, sizeof(cur->membername));
1814  else
1815  ast_copy_string(cur->membername, interface, sizeof(cur->membername));
1816  if (!strchr(cur->interface, '/'))
1817  ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
1818  if (!strncmp(cur->state_interface, "hint:", 5)) {
1819  char *tmp = ast_strdupa(cur->state_interface), *context = tmp;
1820  char *exten = strsep(&context, "@") + 5;
1821 
1822  ast_copy_string(cur->state_exten, exten, sizeof(cur->state_exten));
1823  ast_copy_string(cur->state_context, S_OR(context, "default"), sizeof(cur->state_context));
1824  }
1825  cur->status = get_queue_member_status(cur);
1826  }
1827 
1828  return cur;
1829 }
1830 
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
int paused
Definition: app_queue.c:1185
char * strsep(char **str, const char *delims)
#define LOG_WARNING
Definition: logger.h:144
char interface[80]
Definition: app_queue.c:1175
char state_interface[80]
Definition: app_queue.c:1178
char membername[80]
Definition: app_queue.c:1179
int penalty
Definition: app_queue.c:1180
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:430
int status
Definition: app_queue.c:1184
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
char state_context[AST_MAX_CONTEXT]
Definition: app_queue.c:1177
static int get_queue_member_status(struct member *cur)
Return the current state of a member.
Definition: app_queue.c:1795
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
char state_exten[AST_MAX_EXTENSION]
Definition: app_queue.c:1176
static void destroy_queue ( void *  obj)
static

Free queue's member list then its string fields.

Definition at line 2404 of file app_queue.c.

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

Referenced by alloc_queue().

2404 {
2405  struct call_queue *q = obj;
2406  int i;
2407 
2408  free_members(q, 1);
2410  for (i = 0; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
2411  if (q->sound_periodicannounce[i])
2413  }
2414  ao2_ref(q->members, -1);
2415 }
2416 
struct ast_str * sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS]
Definition: app_queue.c:1268
#define MAX_PERIODIC_ANNOUNCEMENTS
Definition: app_queue.c:1027
struct ao2_container * members
Definition: app_queue.c:1320
static void free_members(struct call_queue *q, int all)
Iterate through queue&#39;s member list and delete them.
Definition: app_queue.c:2388
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define free(a)
Definition: astmm.h:94
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:253
static void device_state_cb ( const struct ast_event event,
void *  unused 
)
static

Definition at line 1699 of file app_queue.c.

References ast_calloc, ast_event_get_ie_str(), ast_event_get_ie_uint(), AST_EVENT_IE_DEVICE, AST_EVENT_IE_STATE, ast_free, ast_log(), ast_strlen_zero(), ast_taskprocessor_push(), statechange::dev, handle_statechange(), LOG_ERROR, state, and statechange::state.

Referenced by load_module().

1699 {
1700  enum ast_device_state state;
1701  const char *device;
1702  struct statechange *sc;
1703  size_t datapsize;
1704 
1705  state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
1706  device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
1707 
1708  if (ast_strlen_zero(device)) {
1709  ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
1710  return;
1711  }
1712  datapsize = sizeof(*sc) + strlen(device) + 1;
1713  if (!(sc = ast_calloc(1, datapsize))) {
1714  ast_log(LOG_ERROR, "failed to calloc a state change struct\n");
1715  return;
1716  }
1717  sc->state = state;
1718  strcpy(sc->dev, device);
1720  ast_free(sc);
1721  }
1722 }
1723 
enum sip_cc_notify_state state
Definition: chan_sip.c:842
ast_device_state
Device States.
Definition: devicestate.h:51
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap)
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static struct ast_taskprocessor * devicestate_tps
Definition: app_queue.c:1022
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static int handle_statechange(void *datap)
set a member&#39;s status based on device state of that member&#39;s interface
Definition: app_queue.c:1655
char dev[0]
Definition: app_queue.c:1622
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_free(a)
Definition: astmm.h:97
uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has an integer payload.
Definition: event.c:1075
#define ast_calloc(a, b)
Definition: astmm.h:82
Generic State IE Used by AST_EVENT_DEVICE_STATE_CHANGE Payload type: UINT The actual state values dep...
Definition: event_defs.h:115
const char * ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has a string payload.
Definition: event.c:1102
Device Name Used by AST_EVENT_DEVICE_STATE_CHANGE Payload type: STR.
Definition: event_defs.h:107
static void do_hang ( struct callattempt o)
static

common hangup actions

Definition at line 3198 of file app_queue.c.

References ast_hangup(), callattempt::chan, and callattempt::stillgoing.

Referenced by ring_entry(), and wait_for_answer().

3198 {
3199  o->stillgoing = 0;
3200  ast_hangup(o->chan);
3201  o->chan = NULL;
3202 }
3203 
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
struct ast_channel * chan
Definition: app_queue.c:1123
unsigned int stillgoing
Definition: app_queue.c:1138
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 7589 of file app_queue.c.

References ast_cli(), and astman_append().

Referenced by __queues_show().

7589 {
7590  if (s)
7591  astman_append(s, "%s\r\n", str);
7592  else
7593  ast_cli(fd, "%s\n", str);
7594 }
7595 
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:2068
const char * str
Definition: app_jack.c:144
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
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 5663 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::state_interface, and value.

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

5663 {
5664  struct member *cur_member;
5665  struct ast_str *value;
5666  struct ao2_iterator mem_iter;
5667 
5668  if (!pm_queue) {
5669  return;
5670  }
5671 
5672  /* 4K is a reasonable default for most applications, but we grow to
5673  * accommodate more if necessary. */
5674  if (!(value = ast_str_create(4096))) {
5675  return;
5676  }
5677 
5678  mem_iter = ao2_iterator_init(pm_queue->members, 0);
5679  while ((cur_member = ao2_iterator_next(&mem_iter))) {
5680  if (!cur_member->dynamic) {
5681  ao2_ref(cur_member, -1);
5682  continue;
5683  }
5684 
5685  ast_str_append(&value, 0, "%s%s;%d;%d;%s;%s",
5686  ast_str_strlen(value) ? "|" : "",
5687  cur_member->interface,
5688  cur_member->penalty,
5689  cur_member->paused,
5690  cur_member->membername,
5691  cur_member->state_interface);
5692 
5693  ao2_ref(cur_member, -1);
5694  }
5695  ao2_iterator_destroy(&mem_iter);
5696 
5697  if (ast_str_strlen(value) && !cur_member) {
5698  if (ast_db_put(pm_family, pm_queue->name, ast_str_buffer(value)))
5699  ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n");
5700  } else {
5701  /* Delete the entry if the queue is empty or there is an error */
5702  ast_db_del(pm_family, pm_queue->name);
5703  }
5704 
5705  ast_free(value);
5706 }
5707 
int dynamic
Definition: app_queue.c:1182
int paused
Definition: app_queue.c:1185
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
#define LOG_WARNING
Definition: logger.h:144
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
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:900
struct ast_str * ast_str_create(size_t init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:420
char interface[80]
Definition: app_queue.c:1175
char state_interface[80]
Definition: app_queue.c:1178
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
int value
Definition: syslog.c:39
struct ao2_container * members
Definition: app_queue.c:1320
char membername[80]
Definition: app_queue.c:1179
int penalty
Definition: app_queue.c:1180
#define ao2_ref(o, delta)
Definition: astobj2.h:472
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
const ast_string_field name
Definition: app_queue.c:1266
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_free(a)
Definition: astmm.h:97
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:471
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: db.c:365
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: db.c:260
static const char *const pm_family
Persistent Members astdb family.
Definition: app_queue.c:1052
static void end_bridge_callback ( void *  data)
static

Definition at line 4783 of file app_queue.c.

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

Referenced by try_calling().

4783 {
4784  struct queue_end_bridge *qeb = data;
4785  struct call_queue *q = qeb->q;
4786  struct ast_channel *chan = qeb->chan;
4787 
4788  if (ao2_ref(qeb, -1) == 1) {
4789  set_queue_variables(q, chan);
4790  /* This unrefs the reference we made in try_calling when we allocated qeb */
4791  queue_t_unref(q, "Expire bridge_config reference");
4792  }
4793 }
4794 
Main Channel structure associated with a channel.
Definition: channel.h:742
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
struct call_queue * q
Definition: app_queue.c:4772
#define ao2_ref(o, delta)
Definition: astobj2.h:472
struct ast_channel * chan
Definition: app_queue.c:4773
static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
Set variables of queue.
Definition: app_queue.c:1490
static void end_bridge_callback_data_fixup ( struct ast_bridge_config bconfig,
struct ast_channel originator,
struct ast_channel terminator 
)
static

Definition at line 4776 of file app_queue.c.

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

Referenced by try_calling().

4776 {
4777  struct queue_end_bridge *qeb = bconfig->end_bridge_callback_data;
4778  ao2_ref(qeb, +1);
4779  qeb->chan = originator;
4780 }
4781 
void * end_bridge_callback_data
Definition: channel.h:989
#define ao2_ref(o, delta)
Definition: astobj2.h:472
struct ast_channel * chan
Definition: app_queue.c:4773
static int extension_state_cb ( char *  context,
char *  exten,
enum ast_extension_states  state,
void *  data 
)
static

Definition at line 1757 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(), extensionstate2devicestate(), call_queue::found, call_queue::members, queue_t_unref, queues, member::state_context, member::state_exten, and update_status().

Referenced by load_module(), and unload_module().

1757 {
1758  struct ao2_iterator miter, qiter;
1759  struct member *m;
1760  struct call_queue *q;
1761  int found = 0, device_state = extensionstate2devicestate(state);
1762 
1763  qiter = ao2_iterator_init(queues, 0);
1764  while ((q = ao2_t_iterator_next(&qiter, "Iterate through queues"))) {
1765  ao2_lock(q);
1766 
1767  miter = ao2_iterator_init(q->members, 0);
1768  for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
1769  if (!strcmp(m->state_context, context) && !strcmp(m->state_exten, exten)) {
1770  update_status(q, m, device_state);
1771  ao2_ref(m, -1);
1772  found = 1;
1773  break;
1774  }
1775  }
1776  ao2_iterator_destroy(&miter);
1777 
1778  ao2_unlock(q);
1779  queue_t_unref(q, "Done with iterator");
1780  }
1781  ao2_iterator_destroy(&qiter);
1782 
1783  if (found) {
1784  ast_debug(1, "Extension '%s@%s' changed to state '%d' (%s)\n", exten, context, device_state, ast_devstate2str(device_state));
1785  } else {
1786  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",
1787  exten, context, device_state, ast_devstate2str(device_state));
1788  }
1789 
1790  return 0;
1791 }
1792 
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Find devicestate as text message for output.
Definition: devicestate.c:215
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
#define ao2_t_iterator_next(arg1, arg2)
Definition: astobj2.h:1125
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
struct ao2_container * members
Definition: app_queue.c:1320
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static struct ao2_container * queues
Definition: app_queue.c:1334
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
static int extensionstate2devicestate(int state)
Helper function which converts from extension state to device state values.
Definition: app_queue.c:1726
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
unsigned int found
Definition: app_queue.c:1284
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
char state_context[AST_MAX_CONTEXT]
Definition: app_queue.c:1177
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static int 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:1630
char state_exten[AST_MAX_EXTENSION]
Definition: app_queue.c:1176
static int extensionstate2devicestate ( int  state)
static

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

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

1726 {
1727  switch (state) {
1730  break;
1731  case AST_EXTENSION_INUSE:
1733  break;
1734  case AST_EXTENSION_BUSY:
1736  break;
1737  case AST_EXTENSION_RINGING:
1739  break;
1740  case AST_EXTENSION_ONHOLD:
1742  break;
1745  break;
1746  case AST_EXTENSION_REMOVED:
1748  default:
1750  break;
1751  }
1752 
1753  return state;
1754 }
1755 
enum sip_cc_notify_state state
Definition: chan_sip.c:842
static struct callattempt* find_best ( struct callattempt outgoing)
static

find the entry with the best metric, or NULL

Definition at line 3540 of file app_queue.c.

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

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

3540 {
3541  struct callattempt *best = NULL, *cur;
3542 
3543  for (cur = outgoing; cur; cur = cur->q_next) {
3544  if (cur->stillgoing && /* Not already done */
3545  !cur->chan && /* Isn't already going */
3546  (!best || cur->metric < best->metric)) { /* We haven't found one yet, or it's better */
3547  best = cur;
3548  }
3549  }
3550 
3551  return best;
3552 }
3553 
struct callattempt * q_next
Definition: app_queue.c:1121
We define a custom &quot;local user&quot; structure because we use it not only for keeping track of what is i...
Definition: app_queue.c:1120
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 2442 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_variable_retrieve(), clear_queue(), member::dead, call_queue::dead, init_queue(), member::interface, LOG_WARNING, member_remove_from_queue(), call_queue::members, ast_variable::name, call_queue::name, ast_variable::next, OBJ_POINTER, queue_set_param(), QUEUE_STRATEGY_RINGALL, queue_t_unref, queues, queues_t_link, queues_t_unlink, member::realtime, call_queue::realtime, rt_handle_member_record(), S_OR, strat2int(), call_queue::strategy, and ast_variable::value.

Referenced by load_realtime_queue().

2442 {
2443  struct ast_variable *v;
2444  struct call_queue *q, tmpq = {
2445  .name = queuename,
2446  };
2447  struct member *m;
2448  struct ao2_iterator mem_iter;
2449  char *interface = NULL;
2450  const char *tmp_name;
2451  char *tmp;
2452  char tmpbuf[64]; /* Must be longer than the longest queue param name. */
2453 
2454  /* Static queues override realtime. */
2455  if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Check if static queue exists"))) {
2456  ao2_lock(q);
2457  if (!q->realtime) {
2458  if (q->dead) {
2459  ao2_unlock(q);
2460  queue_t_unref(q, "Queue is dead; can't return it");
2461  return NULL;
2462  } else {
2463  ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
2464  ao2_unlock(q);
2465  return q;
2466  }
2467  }
2468  } else if (!member_config)
2469  /* Not found in the list, and it's not realtime ... */
2470  return NULL;
2471 
2472  /* Check if queue is defined in realtime. */
2473  if (!queue_vars) {
2474  /* Delete queue from in-core list if it has been deleted in realtime. */
2475  if (q) {
2476  /*! \note Hmm, can't seem to distinguish a DB failure from a not
2477  found condition... So we might delete an in-core queue
2478  in case of DB failure. */
2479  ast_debug(1, "Queue %s not found in realtime.\n", queuename);
2480 
2481  q->dead = 1;
2482  /* Delete if unused (else will be deleted when last caller leaves). */
2483  queues_t_unlink(queues, q, "Unused; removing from container");
2484  ao2_unlock(q);
2485  queue_t_unref(q, "Queue is dead; can't return it");
2486  }
2487  return NULL;
2488  }
2489 
2490  /* Create a new queue if an in-core entry does not exist yet. */
2491  if (!q) {
2492  struct ast_variable *tmpvar = NULL;
2493  if (!(q = alloc_queue(queuename)))
2494  return NULL;
2495  ao2_lock(q);
2496  clear_queue(q);
2497  q->realtime = 1;
2498  /*Before we initialize the queue, we need to set the strategy, so that linear strategy
2499  * will allocate the members properly
2500  */
2501  for (tmpvar = queue_vars; tmpvar; tmpvar = tmpvar->next) {
2502  if (!strcasecmp(tmpvar->name, "strategy")) {
2503  q->strategy = strat2int(tmpvar->value);
2504  if (q->strategy < 0) {
2505  ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
2506  tmpvar->value, q->name);
2508  }
2509  break;
2510  }
2511  }
2512  /* We traversed all variables and didn't find a strategy */
2513  if (!tmpvar)
2515  queues_t_link(queues, q, "Add queue to container");
2516  }
2517  init_queue(q); /* Ensure defaults for all parameters not set explicitly. */
2518 
2519  memset(tmpbuf, 0, sizeof(tmpbuf));
2520  for (v = queue_vars; v; v = v->next) {
2521  /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
2522  if (strchr(v->name, '_')) {
2523  ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
2524  tmp_name = tmpbuf;
2525  tmp = tmpbuf;
2526  while ((tmp = strchr(tmp, '_')))
2527  *tmp++ = '-';
2528  } else
2529  tmp_name = v->name;
2530 
2531  /* NULL values don't get returned from realtime; blank values should
2532  * still get set. If someone doesn't want a value to be set, they
2533  * should set the realtime column to NULL, not blank. */
2534  queue_set_param(q, tmp_name, v->value, -1, 0);
2535  }
2536 
2537  /* Temporarily set realtime members dead so we can detect deleted ones. */
2538  mem_iter = ao2_iterator_init(q->members, 0);
2539  while ((m = ao2_iterator_next(&mem_iter))) {
2540  if (m->realtime)
2541  m->dead = 1;
2542  ao2_ref(m, -1);
2543  }
2544  ao2_iterator_destroy(&mem_iter);
2545 
2546  while ((interface = ast_category_browse(member_config, interface))) {
2547  rt_handle_member_record(q, interface,
2548  ast_variable_retrieve(member_config, interface, "uniqueid"),
2549  S_OR(ast_variable_retrieve(member_config, interface, "membername"),interface),
2550  ast_variable_retrieve(member_config, interface, "penalty"),
2551  ast_variable_retrieve(member_config, interface, "paused"),
2552  S_OR(ast_variable_retrieve(member_config, interface, "state_interface"),interface));
2553  }
2554 
2555  /* Delete all realtime members that have been deleted in DB. */
2556  mem_iter = ao2_iterator_init(q->members, 0);
2557  while ((m = ao2_iterator_next(&mem_iter))) {
2558  if (m->dead) {
2559  ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
2561  }
2562  ao2_ref(m, -1);
2563  }
2564  ao2_iterator_destroy(&mem_iter);
2565 
2566  ao2_unlock(q);
2567 
2568  return q;
2569 }
2570 
#define ao2_t_find(arg1, arg2, arg3, arg4)
Definition: astobj2.h:963
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
#define LOG_WARNING
Definition: logger.h:144
static void member_remove_from_queue(struct call_queue *queue, struct member *mem)
Definition: app_queue.c:2314
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
int realtime
Definition: app_queue.c:1183
char interface[80]
Definition: app_queue.c:1175
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
unsigned int dead
Definition: app_queue.c:1189
static void clear_queue(struct call_queue *q)
Definition: app_queue.c:1943
struct ao2_container * members
Definition: app_queue.c:1320
static int strat2int(const char *strategy)
Definition: app_queue.c:1365
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
const char * value
Definition: config.h:79
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:2093
static struct ao2_container * queues
Definition: app_queue.c:1334
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
const char * name
Definition: config.h:77
int strategy
Definition: app_queue.c:1281
unsigned int dead
Definition: app_queue.c:1269
const ast_string_field name
Definition: app_queue.c:1266
static void rt_handle_member_record(struct call_queue *q, char *interface, const char *rt_uniqueid, const char *membername, const char *penalty_str, const char *paused_str, const char *state_interface)
Find rt member record to update otherwise create one.
Definition: app_queue.c:2328
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct call_queue * alloc_queue(const char *queuename)
Definition: app_queue.c:2418
#define queues_t_link(c, q, tag)
Definition: app_queue.c:1474
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
unsigned int realtime
Definition: app_queue.c:1283
struct ast_variable * next
Definition: config.h:82
static void init_queue(struct call_queue *q)
Initialize Queue default values.
Definition: app_queue.c:1865
#define queues_t_unlink(c, q, tag)
Definition: app_queue.c:1475
static void free_members ( struct call_queue q,
int  all 
)
static

Iterate through queue's member list and delete them.

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

2388 {
2389  /* Free non-dynamic members */
2390  struct member *cur;
2391  struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
2392 
2393  while ((cur = ao2_iterator_next(&mem_iter))) {
2394  if (all || !cur->dynamic) {
2395  member_remove_from_queue(q, cur);
2396  }
2397  ao2_ref(cur, -1);
2398  }
2399  ao2_iterator_destroy(&mem_iter);
2400 }
2401 
int dynamic
Definition: app_queue.c:1182
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
static void member_remove_from_queue(struct call_queue *queue, struct member *mem)
Definition: app_queue.c:2314
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
struct ao2_container * members
Definition: app_queue.c:1320
#define ao2_ref(o, delta)
Definition: astobj2.h:472
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
static int get_member_penalty ( char *  queuename,
char *  interface 
)
static

Definition at line 5940 of file app_queue.c.

References ao2_lock, ao2_ref, ao2_t_find, ao2_unlock, ast_log(), interface_exists(), LOG_ERROR, call_queue::name, OBJ_POINTER, member::penalty, queue_t_unref, queues, and RESULT_FAILURE.

Referenced by queue_function_memberpenalty_read().

5940 {
5941  int foundqueue = 0, penalty;
5942  struct call_queue *q, tmpq = {
5943  .name = queuename,
5944  };
5945  struct member *mem;
5946 
5947  if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Search for queue"))) {
5948  foundqueue = 1;
5949  ao2_lock(q);
5950  if ((mem = interface_exists(q, interface))) {
5951  penalty = mem->penalty;
5952  ao2_ref(mem, -1);
5953  ao2_unlock(q);
5954  queue_t_unref(q, "Search complete");
5955  return penalty;
5956  }
5957  ao2_unlock(q);
5958  queue_t_unref(q, "Search complete");
5959  }
5960 
5961  /* some useful debuging */
5962  if (foundqueue)
5963  ast_log (LOG_ERROR, "Invalid queuename\n");
5964  else
5965  ast_log (LOG_ERROR, "Invalid interface\n");
5966 
5967  return RESULT_FAILURE;
5968 }
5969 
#define ao2_t_find(arg1, arg2, arg3, arg4)
Definition: astobj2.h:963
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
char interface[80]
Definition: app_queue.c:1175
#define ao2_unlock(a)
Definition: astobj2.h:497
static struct member * interface_exists(struct call_queue *q, const char *interface)
Definition: app_queue.c:5637
static struct ao2_container * queues
Definition: app_queue.c:1334
int penalty
Definition: app_queue.c:1180
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
#define LOG_ERROR
Definition: logger.h:155
const ast_string_field name
Definition: app_queue.c:1266
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define RESULT_FAILURE
Definition: cli.h:41
static int get_member_status ( struct call_queue q,
int  max_penalty,
int  min_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 1545 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, member::lastcall, member::membername, call_queue::members, queue_ent::min_penalty, 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, member::status, and call_queue::wrapuptime.

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

1545 {
1546  struct member *member;
1547  struct ao2_iterator mem_iter;
1548 
1549  ao2_lock(q);
1550  mem_iter = ao2_iterator_init(q->members, 0);
1551  for (; (member = ao2_iterator_next(&mem_iter)); ao2_ref(member, -1)) {
1552  if ((max_penalty != INT_MAX && member->penalty > max_penalty) || (min_penalty != INT_MAX && member->penalty < min_penalty)) {
1553  if (conditions & QUEUE_EMPTY_PENALTY) {
1554  ast_debug(4, "%s is unavailable because his penalty is not between %d and %d\n", member->membername, min_penalty, max_penalty);
1555  continue;
1556  }
1557  }
1558 
1559  switch (devstate ? ast_device_state(member->state_interface) : member->status) {
1560  case AST_DEVICE_INVALID:
1561  if (conditions & QUEUE_EMPTY_INVALID) {
1562  ast_debug(4, "%s is unavailable because his device state is 'invalid'\n", member->membername);
1563  break;
1564  }
1565  goto default_case;
1567  if (conditions & QUEUE_EMPTY_UNAVAILABLE) {
1568  ast_debug(4, "%s is unavailable because his device state is 'unavailable'\n", member->membername);
1569  break;
1570  }
1571  goto default_case;
1572  case AST_DEVICE_INUSE:
1573  if (conditions & QUEUE_EMPTY_INUSE) {
1574  ast_debug(4, "%s is unavailable because his device state is 'inuse'\n", member->membername);
1575  break;
1576  }
1577  goto default_case;
1578  case AST_DEVICE_RINGING:
1579  if (conditions & QUEUE_EMPTY_RINGING) {
1580  ast_debug(4, "%s is unavailable because his device state is 'ringing'\n", member->membername);
1581  break;
1582  }
1583  goto default_case;
1584  case AST_DEVICE_UNKNOWN:
1585  if (conditions & QUEUE_EMPTY_UNKNOWN) {
1586  ast_debug(4, "%s is unavailable because his device state is 'unknown'\n", member->membername);
1587  break;
1588  }
1589  /* Fall-through */
1590  default:
1591  default_case:
1592  if (member->paused && (conditions & QUEUE_EMPTY_PAUSED)) {
1593  ast_debug(4, "%s is unavailable because he is paused'\n", member->membername);
1594  break;
1595  } else if ((conditions & QUEUE_EMPTY_WRAPUP) && member->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < member->lastcall)) {
1596  ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n", member->membername, (int) (time(NULL) - member->lastcall), q->wrapuptime);
1597  break;
1598  } else {
1599  ao2_ref(member, -1);
1600  ao2_iterator_destroy(&mem_iter);
1601  ao2_unlock(q);
1602  ast_debug(4, "%s is available.\n", member->membername);
1603  return 0;
1604  }
1605  break;
1606  }
1607  }
1608  ao2_iterator_destroy(&mem_iter);
1609  ao2_unlock(q);
1610 
1611  if (!devstate && (conditions & QUEUE_EMPTY_RINGING)) {
1612  /* member state still may be RINGING due to lag in event message - check again with device state */
1613  return get_member_status(q, max_penalty, min_penalty, conditions, 1);
1614  }
1615  return -1;
1616 }
1617 
ast_device_state
Device States.
Definition: devicestate.h:51
int paused
Definition: app_queue.c:1185
static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, enum empty_conditions conditions, int devstate)
Check if members are available.
Definition: app_queue.c:1545
int wrapuptime
Definition: app_queue.c:1305
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
char state_interface[80]
Definition: app_queue.c:1178
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
struct ao2_container * members
Definition: app_queue.c:1320
char membername[80]
Definition: app_queue.c:1179
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int penalty
Definition: app_queue.c:1180
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
int status
Definition: app_queue.c:1184
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
time_t lastcall
Definition: app_queue.c:1187
static int get_queue_member_status ( struct member cur)
static

Return the current state of a member.

Definition at line 1795 of file app_queue.c.

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

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

1795 {
1796  return ast_strlen_zero(cur->state_exten) ? ast_device_state(cur->state_interface) : extensionstate2devicestate(ast_extension_state(NULL, cur->state_context, cur->state_exten));
1797 }
1798 
ast_device_state
Device States.
Definition: devicestate.h:51
char state_interface[80]
Definition: app_queue.c:1178
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static int extensionstate2devicestate(int state)
Helper function which converts from extension state to device state values.
Definition: app_queue.c:1726
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:4914
char state_exten[AST_MAX_EXTENSION]
Definition: app_queue.c:1176
static char* handle_queue_add_member ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 8326 of file app_queue.c.

References add_to_queue(), ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_queue_log(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_queue_add_member(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, RES_EXISTS, RES_NOSUCHQUEUE, RES_NOT_DYNAMIC, RES_OKAY, RES_OUTOFMEMORY, ast_cli_entry::usage, and ast_cli_args::word.

8326 {
8327  const char *queuename, *interface, *membername = NULL, *state_interface = NULL;
8328  int penalty;
8329 
8330  switch ( cmd ) {
8331  case CLI_INIT:
8332  e->command = "queue add member";
8333  e->usage =
8334  "Usage: queue add member <dial string> to <queue> [[[penalty <penalty>] as <membername>] state_interface <interface>]\n"
8335  " Add a dial string (Such as a channel,e.g. SIP/6001) to a queue with optionally: a penalty, membername and a state_interface\n";
8336  return NULL;
8337  case CLI_GENERATE:
8338  return complete_queue_add_member(a->line, a->word, a->pos, a->n);
8339  }
8340 
8341  if ((a->argc != 6) && (a->argc != 8) && (a->argc != 10) && (a->argc != 12)) {
8342  return CLI_SHOWUSAGE;
8343  } else if (strcmp(a->argv[4], "to")) {
8344  return CLI_SHOWUSAGE;
8345  } else if ((a->argc >= 8) && strcmp(a->argv[6], "penalty")) {
8346  return CLI_SHOWUSAGE;
8347  } else if ((a->argc >= 10) && strcmp(a->argv[8], "as")) {
8348  return CLI_SHOWUSAGE;
8349  } else if ((a->argc == 12) && strcmp(a->argv[10], "state_interface")) {
8350  return CLI_SHOWUSAGE;
8351  }
8352 
8353  queuename = a->argv[5];
8354  interface = a->argv[3];
8355  if (a->argc >= 8) {
8356  if (sscanf(a->argv[7], "%30d", &penalty) == 1) {
8357  if (penalty < 0) {
8358  ast_cli(a->fd, "Penalty must be >= 0\n");
8359  penalty = 0;
8360  }
8361  } else {
8362  ast_cli(a->fd, "Penalty must be an integer >= 0\n");
8363  penalty = 0;
8364  }
8365  } else {
8366  penalty = 0;
8367  }
8368 
8369  if (a->argc >= 10) {
8370  membername = a->argv[9];
8371  }
8372 
8373  if (a->argc >= 12) {
8374  state_interface = a->argv[11];
8375  }
8376 
8377  switch (add_to_queue(queuename, interface, membername, penalty, 0, queue_persistent_members, state_interface)) {
8378  case RES_OKAY:
8379  ast_queue_log(queuename, "CLI", interface, "ADDMEMBER", "%s", "");
8380  ast_cli(a->fd, "Added interface '%s' to queue '%s'\n", interface, queuename);
8381  return CLI_SUCCESS;
8382  case RES_EXISTS:
8383  ast_cli(a->fd, "Unable to add interface '%s' to queue '%s': Already there\n", interface, queuename);
8384  return CLI_FAILURE;
8385  case RES_NOSUCHQUEUE:
8386  ast_cli(a->fd, "Unable to add interface to queue '%s': No such queue\n", queuename);
8387  return CLI_FAILURE;
8388  case RES_OUTOFMEMORY:
8389  ast_cli(a->fd, "Out of memory\n");
8390  return CLI_FAILURE;
8391  case RES_NOT_DYNAMIC:
8392  ast_cli(a->fd, "Member not dynamic\n");
8393  return CLI_FAILURE;
8394  default:
8395  return CLI_FAILURE;
8396  }
8397 }
8398 
#define RES_OKAY
Definition: app_queue.c:1033
const int argc
Definition: cli.h:154
#define RES_NOT_DYNAMIC
Definition: app_queue.c:1037
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
Definition: cli.h:146
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const char * line
Definition: cli.h:156
#define RES_OUTOFMEMORY
Definition: app_queue.c:1035
const int fd
Definition: cli.h:153
const int n
Definition: cli.h:159
const char *const * argv
Definition: cli.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
#define CLI_FAILURE
Definition: cli.h:45
char * command
Definition: cli.h:180
const char * word
Definition: cli.h:157
static char * complete_queue_add_member(const char *line, const char *word, int pos, int state)
Definition: app_queue.c:8270
const char * usage
Definition: cli.h:171
#define RES_NOSUCHQUEUE
Definition: app_queue.c:1036
#define CLI_SUCCESS
Definition: cli.h:43
const int pos
Definition: cli.h:158
#define RES_EXISTS
Definition: app_queue.c:1034
static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump, const char *state_interface)
Add member to queue.
Definition: app_queue.c:5763
static int queue_persistent_members
queues.conf [general] option
Definition: app_queue.c:1058
static char* handle_queue_pause_member ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 8511 of file app_queue.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_queue_pause_member(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, RESULT_SUCCESS, set_member_paused(), and ast_cli_entry::usage.

8511 {
8512  const char *queuename, *interface, *reason;
8513  int paused;
8514 
8515  switch (cmd) {
8516  case CLI_INIT:
8517  e->command = "queue {pause|unpause} member";
8518  e->usage =
8519  "Usage: queue {pause|unpause} member <member> [queue <queue> [reason <reason>]]\n"
8520  " Pause or unpause a queue member. Not specifying a particular queue\n"
8521  " will pause or unpause a member across all queues to which the member\n"
8522  " belongs.\n";
8523  return NULL;
8524  case CLI_GENERATE:
8525  return complete_queue_pause_member(a->line, a-> word, a->pos, a->n);
8526  }
8527 
8528  if (a->argc < 4 || a->argc == 5 || a->argc == 7 || a->argc > 8) {
8529  return CLI_SHOWUSAGE;
8530  } else if (a->argc >= 5 && strcmp(a->argv[4], "queue")) {
8531  return CLI_SHOWUSAGE;
8532  } else if (a->argc == 8 && strcmp(a->argv[6], "reason")) {
8533  return CLI_SHOWUSAGE;
8534  }
8535 
8536 
8537  interface = a->argv[3];
8538  queuename = a->argc >= 6 ? a->argv[5] : NULL;
8539  reason = a->argc == 8 ? a->argv[7] : NULL;
8540  paused = !strcasecmp(a->argv[1], "pause");
8541 
8542  if (set_member_paused(queuename, interface, reason, paused) == RESULT_SUCCESS) {
8543  ast_cli(a->fd, "%spaused interface '%s'", paused ? "" : "un", interface);
8544  if (!ast_strlen_zero(queuename))
8545  ast_cli(a->fd, " in queue '%s'", queuename);
8546  if (!ast_strlen_zero(reason))
8547  ast_cli(a->fd, " for reason '%s'", reason);
8548  ast_cli(a->fd, "\n");
8549  return CLI_SUCCESS;
8550  } else {
8551  ast_cli(a->fd, "Unable to %spause interface '%s'", paused ? "" : "un", interface);
8552  if (!ast_strlen_zero(queuename))
8553  ast_cli(a->fd, " in queue '%s'", queuename);
8554  if (!ast_strlen_zero(reason))
8555  ast_cli(a->fd, " for reason '%s'", reason);
8556  ast_cli(a->fd, "\n");
8557  return CLI_FAILURE;
8558  }
8559 }
8560 
static char * complete_queue_pause_member(const char *line, const char *word, int pos, int state)
Definition: app_queue.c:8492
const int argc
Definition: cli.h:154
Definition: cli.h:146
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
Definition: ael.tab.c:203
const char * line
Definition: cli.h:156
const int fd
Definition: cli.h:153
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
const int n
Definition: cli.h:159
const char *const * argv
Definition: cli.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused)
Definition: app_queue.c:5814
#define CLI_FAILURE
Definition: cli.h:45
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
const int pos
Definition: cli.h:158
#define RESULT_SUCCESS
Definition: cli.h:39
static char* handle_queue_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 8720 of file app_queue.c.

References ast_cli_args::argc, ast_cli_args::argv, AST_FLAGS_ALL, ast_set_flag, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_queue(), ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, QUEUE_RELOAD_MEMBER, QUEUE_RELOAD_PARAMETERS, QUEUE_RELOAD_RULES, reload_handler(), ast_cli_entry::usage, and ast_cli_args::word.

8720 {
8721  struct ast_flags mask = {0,};
8722  int i;
8723 
8724  switch (cmd) {
8725  case CLI_INIT:
8726  e->command = "queue reload {parameters|members|rules|all}";
8727  e->usage =
8728  "Usage: queue reload {parameters|members|rules|all} [<queuenames>]\n"
8729  "Reload queues. If <queuenames> are specified, only reload information pertaining\n"
8730  "to <queuenames>. One of 'parameters,' 'members,' 'rules,' or 'all' must be\n"
8731  "specified in order to know what information to reload. Below is an explanation\n"
8732  "of each of these qualifiers.\n"
8733  "\n"
8734  "\t'members' - reload queue members from queues.conf\n"
8735  "\t'parameters' - reload all queue options except for queue members\n"
8736  "\t'rules' - reload the queuerules.conf file\n"
8737  "\t'all' - reload queue rules, parameters, and members\n"
8738  "\n"
8739  "Note: the 'rules' qualifier here cannot actually be applied to a specific queue.\n"
8740  "Use of the 'rules' qualifier causes queuerules.conf to be reloaded. Even if only\n"
8741  "one queue is specified when using this command, reloading queue rules may cause\n"
8742  "other queues to be affected\n";
8743  return NULL;
8744  case CLI_GENERATE:
8745  if (a->pos >= 3) {
8746  /* find the point at which the list of queue names starts */
8747  const char *command_end = a->line + strlen("queue reload ");
8748  command_end = strchr(command_end, ' ');
8749  if (!command_end) {
8750  command_end = a->line + strlen(a->line);
8751  }
8752  return complete_queue(a->line, a->word, a->pos, a->n, command_end - a->line);
8753  } else {
8754  return NULL;
8755  }
8756  }
8757 
8758  if (a->argc < 3)
8759  return CLI_SHOWUSAGE;
8760 
8761  if (!strcasecmp(a->argv[2], "rules")) {
8763  } else if (!strcasecmp(a->argv[2], "members")) {
8765  } else if (!strcasecmp(a->argv[2], "parameters")) {
8767  } else if (!strcasecmp(a->argv[2], "all")) {
8768  ast_set_flag(&mask, AST_FLAGS_ALL);
8769  }
8770 
8771  if (a->argc == 3) {
8772  reload_handler(1, &mask, NULL);
8773  return CLI_SUCCESS;
8774  }
8775 
8776  for (i = 3; i < a->argc; ++i) {
8777  reload_handler(1, &mask, a->argv[i]);
8778  }
8779 
8780  return CLI_SUCCESS;
8781 }
8782 
#define ast_set_flag(p, flag)
Definition: utils.h:70
const int argc
Definition: cli.h:154
Definition: cli.h:146
const char * line
Definition: cli.h:156
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:7807
const int n
Definition: cli.h:159
static int reload_handler(int reload, struct ast_flags *mask, const char *queuename)
The command center for all reload operations.
Definition: app_queue.c:7572
const char *const * argv
Definition: cli.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
char * command
Definition: cli.h:180
#define AST_FLAGS_ALL
Definition: utils.h:196
const char * word
Definition: cli.h:157
Structure used to handle boolean flags.
Definition: utils.h:200
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
const int pos
Definition: cli.h:158
static char* handle_queue_remove_member ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 8446 of file app_queue.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_queue_log(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_queue_remove_member(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, remove_from_queue(), RES_EXISTS, RES_NOSUCHQUEUE, RES_NOT_DYNAMIC, RES_OKAY, RES_OUTOFMEMORY, ast_cli_entry::usage, and ast_cli_args::word.

8446 {
8447  const char *queuename, *interface;
8448 
8449  switch (cmd) {
8450  case CLI_INIT:
8451  e->command = "queue remove member";
8452  e->usage =
8453  "Usage: queue remove member <channel> from <queue>\n"
8454  " Remove a specific channel from a queue.\n";
8455  return NULL;
8456  case CLI_GENERATE:
8457  return complete_queue_remove_member(a->line, a->word, a->pos, a->n);
8458  }
8459 
8460  if (a->argc != 6) {
8461  return CLI_SHOWUSAGE;
8462  } else if (strcmp(a->argv[4], "from")) {
8463  return CLI_SHOWUSAGE;
8464  }
8465 
8466  queuename = a->argv[5];
8467  interface = a->argv[3];
8468 
8469  switch (remove_from_queue(queuename, interface)) {
8470  case RES_OKAY:
8471  ast_queue_log(queuename, "CLI", interface, "REMOVEMEMBER", "%s", "");
8472  ast_cli(a->fd, "Removed interface '%s' from queue '%s'\n", interface, queuename);
8473  return CLI_SUCCESS;
8474  case RES_EXISTS:
8475  ast_cli(a->fd, "Unable to remove interface '%s' from queue '%s': Not there\n", interface, queuename);
8476  return CLI_FAILURE;
8477  case RES_NOSUCHQUEUE:
8478  ast_cli(a->fd, "Unable to remove interface from queue '%s': No such queue\n", queuename);
8479  return CLI_FAILURE;
8480  case RES_OUTOFMEMORY:
8481  ast_cli(a->fd, "Out of memory\n");
8482  return CLI_FAILURE;
8483  case RES_NOT_DYNAMIC:
8484  ast_cli(a->fd, "Unable to remove interface '%s' from queue '%s': Member is not dynamic\n", interface, queuename);
8485  return CLI_FAILURE;
8486  default:
8487  return CLI_FAILURE;
8488  }
8489 }
8490 
#define RES_OKAY
Definition: app_queue.c:1033
const int argc
Definition: cli.h:154
#define RES_NOT_DYNAMIC
Definition: app_queue.c:1037
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
Definition: cli.h:146
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const char * line
Definition: cli.h:156
#define RES_OUTOFMEMORY
Definition: app_queue.c:1035
const int fd
Definition: cli.h:153
const int n
Definition: cli.h:159
const char *const * argv
Definition: cli.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
#define CLI_FAILURE
Definition: cli.h:45
char * command
Definition: cli.h:180
static char * complete_queue_remove_member(const char *line, const char *word, int pos, int state)
Definition: app_queue.c:8400
const char * word
Definition: cli.h:157
const char * usage
Definition: cli.h:171
#define RES_NOSUCHQUEUE
Definition: app_queue.c:1036
#define CLI_SUCCESS
Definition: cli.h:43
const int pos
Definition: cli.h:158
#define RES_EXISTS
Definition: app_queue.c:1034
static int remove_from_queue(const char *queuename, const char *interface)
Remove member from queue.
Definition: app_queue.c:5715
static char* handle_queue_reset ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 8681 of file app_queue.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_queue(), ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, QUEUE_RESET_STATS, reload_handler(), ast_cli_entry::usage, and ast_cli_args::word.

8681 {
8682  struct ast_flags mask = {QUEUE_RESET_STATS,};
8683  int i;
8684 
8685  switch (cmd) {
8686  case CLI_INIT:
8687  e->command = "queue reset stats";
8688  e->usage =
8689  "Usage: queue reset stats [<queuenames>]\n"
8690  "\n"
8691  "Issuing this command will reset statistics for\n"
8692  "<queuenames>, or for all queues if no queue is\n"
8693  "specified.\n";
8694  return NULL;
8695  case CLI_GENERATE:
8696  if (a->pos >= 3) {
8697  return complete_queue(a->line, a->word, a->pos, a->n, 17);
8698  } else {
8699  return NULL;
8700  }
8701  }
8702 
8703  if (a->argc < 3) {
8704  return CLI_SHOWUSAGE;
8705  }
8706 
8707  if (a->argc == 3) {
8708  reload_handler(1, &mask, NULL);
8709  return CLI_SUCCESS;
8710  }
8711 
8712  for (i = 3; i < a->argc; ++i) {
8713  reload_handler(1, &mask, a->argv[i]);
8714  }
8715 
8716  return CLI_SUCCESS;
8717 }
8718 
const int argc
Definition: cli.h:154
Definition: cli.h:146
const char * line
Definition: cli.h:156
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:7807
const int n
Definition: cli.h:159
static int reload_handler(int reload, struct ast_flags *mask, const char *queuename)
The command center for all reload operations.
Definition: app_queue.c:7572
const char *const * argv
Definition: cli.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
char * command
Definition: cli.h:180
const char * word
Definition: cli.h:157
Structure used to handle boolean flags.
Definition: utils.h:200
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
const int pos
Definition: cli.h:158
static char* handle_queue_rule_show ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 8647 of file app_queue.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_queue_rule_show(), ast_cli_args::fd, ast_cli_args::line, penalty_rule::max_relative, penalty_rule::max_value, penalty_rule::min_relative, penalty_rule::min_value, ast_cli_args::n, rule_list::name, ast_cli_args::pos, rule_list::rules, penalty_rule::time, ast_cli_entry::usage, and ast_cli_args::word.

8647 {
8648  const char *rule;
8649  struct rule_list *rl_iter;
8650  struct penalty_rule *pr_iter;
8651  switch (cmd) {
8652  case CLI_INIT:
8653  e->command = "queue show rules";
8654  e->usage =
8655  "Usage: queue show rules [rulename]\n"
8656  " Show the list of rules associated with rulename. If no\n"
8657  " rulename is specified, list all rules defined in queuerules.conf\n";
8658  return NULL;
8659  case CLI_GENERATE:
8660  return complete_queue_rule_show(a->line, a->word, a->pos, a->n);
8661  }
8662 
8663  if (a->argc != 3 && a->argc != 4)
8664  return CLI_SHOWUSAGE;
8665 
8666  rule = a->argc == 4 ? a->argv[3] : "";
8668  AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
8669  if (ast_strlen_zero(rule) || !strcasecmp(rl_iter->name, rule)) {
8670  ast_cli(a->fd, "Rule: %s\n", rl_iter->name);
8671  AST_LIST_TRAVERSE(&rl_iter->rules, pr_iter, list) {
8672  ast_cli(a->fd, "\tAfter %d seconds, adjust QUEUE_MAX_PENALTY %s %d and adjust QUEUE_MIN_PENALTY %s %d\n", pr_iter->time, pr_iter->max_relative ? "by" : "to", pr_iter->max_value, pr_iter->min_relative ? "by" : "to", pr_iter->min_value);
8673  }
8674  }
8675  }
8677  return CLI_SUCCESS;
8678 }
8679 
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
int max_relative
Definition: app_queue.c:1216
struct rule_list::@58 rules
char name[80]
Definition: app_queue.c:1327
int min_relative
Definition: app_queue.c:1217
const int argc
Definition: cli.h:154
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Definition: cli.h:146
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const char * line
Definition: cli.h:156
const int fd
Definition: cli.h:153
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
const int n
Definition: cli.h:159
const char *const * argv
Definition: cli.h:155
static char * complete_queue_rule_show(const char *line, const char *word, int pos, int state)
Definition: app_queue.c:8625
#define CLI_SHOWUSAGE
Definition: cli.h:44
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
char * command
Definition: cli.h:180
const char * word
Definition: cli.h:157
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
const int pos
Definition: cli.h:158
struct penalty_rule::@55 list
static char* handle_queue_set_member_penalty ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 8585 of file app_queue.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_queue_set_member_penalty(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, RESULT_FAILURE, RESULT_SUCCESS, set_member_penalty(), ast_cli_entry::usage, and ast_cli_args::word.

8585 {
8586  const char *queuename = NULL, *interface;
8587  int penalty = 0;
8588 
8589  switch (cmd) {
8590  case CLI_INIT:
8591  e->command = "queue set penalty";
8592  e->usage =
8593  "Usage: queue set penalty <penalty> on <interface> [in <queue>]\n"
8594  " Set a member's penalty in the queue specified. If no queue is specified\n"
8595  " then that interface's penalty is set in all queues to which that interface is a member\n";
8596  return NULL;
8597  case CLI_GENERATE:
8598  return complete_queue_set_member_penalty(a->line, a->word, a->pos, a->n);
8599  }
8600 
8601  if (a->argc != 6 && a->argc != 8) {
8602  return CLI_SHOWUSAGE;
8603  } else if (strcmp(a->argv[4], "on") || (a->argc > 6 && strcmp(a->argv[6], "in"))) {
8604  return CLI_SHOWUSAGE;
8605  }
8606 
8607  if (a->argc == 8)
8608  queuename = a->argv[7];
8609  interface = a->argv[5];
8610  penalty = atoi(a->argv[3]);
8611 
8612  switch (set_member_penalty(queuename, interface, penalty)) {
8613  case RESULT_SUCCESS:
8614  ast_cli(a->fd, "Set penalty on interface '%s' from queue '%s'\n", interface, queuename);
8615  return CLI_SUCCESS;
8616  case RESULT_FAILURE:
8617  ast_cli(a->fd, "Failed to set penalty on interface '%s' from queue '%s'\n", interface, queuename);
8618  return CLI_FAILURE;
8619  default:
8620  return CLI_FAILURE;
8621  }
8622 }
8623 
const int argc
Definition: cli.h:154
Definition: cli.h:146
static int set_member_penalty(const char *queuename, const char *interface, int penalty)
Definition: app_queue.c:5891
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const char * line
Definition: cli.h:156
static char * complete_queue_set_member_penalty(const char *line, const char *word, int pos, int state)
Definition: app_queue.c:8562
const int fd
Definition: cli.h:153
const int n
Definition: cli.h:159
const char *const * argv
Definition: cli.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
#define CLI_FAILURE
Definition: cli.h:45
char * command
Definition: cli.h:180
const char * word
Definition: cli.h:157
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
const int pos
Definition: cli.h:158
#define RESULT_SUCCESS
Definition: cli.h:39
#define RESULT_FAILURE
Definition: cli.h:41
static int handle_statechange ( void *  datap)
static

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

Definition at line 1655 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_devstate2str(), ast_free, statechange::dev, call_queue::found, call_queue::members, queue_t_unref, queues, statechange::state, member::state_interface, and update_status().

Referenced by device_state_cb().

1655 {
1656  struct statechange *sc = datap;
1657  struct ao2_iterator miter, qiter;
1658  struct member *m;
1659  struct call_queue *q;
1660  char interface[80], *slash_pos;
1661  int found = 0;
1662 
1663  qiter = ao2_iterator_init(queues, 0);
1664  while ((q = ao2_t_iterator_next(&qiter, "Iterate over queues"))) {
1665  ao2_lock(q);
1666 
1667  miter = ao2_iterator_init(q->members, 0);
1668  for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
1669  ast_copy_string(interface, m->state_interface, sizeof(interface));
1670 
1671  if ((slash_pos = strchr(interface, '/')))
1672  if (!strncasecmp(interface, "Local/", 6) && (slash_pos = strchr(slash_pos + 1, '/')))
1673  *slash_pos = '\0';
1674 
1675  if (!strcasecmp(interface, sc->dev)) {
1676  found = 1;
1677  update_status(q, m, sc->state);
1678  ao2_ref(m, -1);
1679  break;
1680  }
1681  }
1682  ao2_iterator_destroy(&miter);
1683 
1684  ao2_unlock(q);
1685  queue_t_unref(q, "Done with iterator");
1686  }
1687  ao2_iterator_destroy(&qiter);
1688 
1689  if (found)
1690  ast_debug(1, "Device '%s' changed to state '%d' (%s)\n", sc->dev, sc->state, ast_devstate2str(sc->state));
1691  else
1692  ast_debug(3, "Device '%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n", sc->dev, sc->state, ast_devstate2str(sc->state));
1693 
1694  ast_free(sc);
1695  return 0;
1696 }
1697 
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Find devicestate as text message for output.
Definition: devicestate.c:215
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
#define ao2_t_iterator_next(arg1, arg2)
Definition: astobj2.h:1125
char state_interface[80]
Definition: app_queue.c:1178
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
struct ao2_container * members
Definition: app_queue.c:1320
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static struct ao2_container * queues
Definition: app_queue.c:1334
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
char dev[0]
Definition: app_queue.c:1622
#define ast_free(a)
Definition: astmm.h:97
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
unsigned int found
Definition: app_queue.c:1284
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static int 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:1630
static void hangupcalls ( struct callattempt outgoing,
struct ast_channel exception,
int  cancel_answered_elsewhere 
)
static

Hang up a list of outgoing calls.

Definition at line 3090 of file app_queue.c.

References callattempt::aoc_s_rate_list, ast_aoc_destroy_decoded(), AST_FLAG_ANSWERED_ELSEWHERE, ast_hangup(), ast_set_flag, callattempt_free(), callattempt::chan, and callattempt::q_next.

Referenced by try_calling().

3090 {
3091  struct callattempt *oo;
3092 
3093  while (outgoing) {
3094  /* If someone else answered the call we should indicate this in the CANCEL */
3095  /* Hangup any existing lines we have open */
3096  if (outgoing->chan && (outgoing->chan != exception)) {
3097  if (exception || cancel_answered_elsewhere)
3099  ast_hangup(outgoing->chan);
3100  }
3101  oo = outgoing;
3102  outgoing = outgoing->q_next;
3104  callattempt_free(oo);
3105  }
3106 }
3107 
struct callattempt * q_next
Definition: app_queue.c:1121
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
#define ast_set_flag(p, flag)
Definition: utils.h:70
void * ast_aoc_destroy_decoded(struct ast_aoc_decoded *decoded)
free an ast_aoc_decoded object
Definition: aoc.c:176
struct ast_aoc_decoded * aoc_s_rate_list
Definition: app_queue.c:1139
We define a custom &quot;local user&quot; structure because we use it not only for keeping track of what is i...
Definition: app_queue.c:1120
static void callattempt_free(struct callattempt *doomed)
Definition: app_queue.c:3080
struct ast_channel * chan
Definition: app_queue.c:1123
static void init_queue ( struct call_queue q)
static

Initialize Queue default values.

Note
the queue's lock must be held before executing this function

Definition at line 1865 of file app_queue.c.

References call_queue::announce_to_first_user, call_queue::announcefrequency, call_queue::announceholdtime, call_queue::announceposition, ANNOUNCEPOSITION_YES, call_queue::announcepositionlimit, ao2_container_alloc, ast_free, AST_LIST_REMOVE_HEAD, ast_str_create(), ast_str_set(), ast_string_field_set, call_queue::autofill, autofill_default, call_queue::autopause, call_queue::dead, DEFAULT_MIN_ANNOUNCE_FREQUENCY, DEFAULT_RETRY, DEFAULT_TIMEOUT, call_queue::eventwhencalled, call_queue::found, call_queue::joinempty, call_queue::leavewhenempty, call_queue::maskmemberstatus, MAX_PERIODIC_ANNOUNCEMENTS, call_queue::maxlen, member_cmp_fn(), member_hash_fn(), call_queue::memberdelay, call_queue::members, call_queue::minannouncefrequency, call_queue::monfmt, call_queue::montype, montype_default, call_queue::numperiodicannounce, call_queue::penaltymemberslimit, call_queue::periodicannouncefrequency, QUEUE_AUTOPAUSE_OFF, QUEUE_STRATEGY_LINEAR, QUEUE_STRATEGY_RRORDERED, call_queue::randomperiodicannounce, call_queue::reportholdtime, call_queue::retry, call_queue::ringinuse, call_queue::ringlimit, call_queue::roundingseconds, call_queue::rules, call_queue::servicelevel, call_queue::setinterfacevar, call_queue::setqueueentryvar, call_queue::setqueuevar, call_queue::sound_periodicannounce, call_queue::strategy, call_queue::timeout, TIMEOUT_PRIORITY_APP, call_queue::timeoutpriority, call_queue::timeoutrestart, call_queue::weight, and call_queue::wrapuptime.

Referenced by find_queue_by_name_rt(), and reload_single_queue().

1865 {
1866  int i;
1867  struct penalty_rule *pr_iter;
1868 
1869  q->dead = 0;
1870  q->retry = DEFAULT_RETRY;
1871  q->timeout = DEFAULT_TIMEOUT;
1872  q->maxlen = 0;
1873  q->ringlimit = 0;
1874  q->announcefrequency = 0;
1876  q->announceholdtime = 1;
1877  q->announcepositionlimit = 10; /* Default 10 positions */
1878  q->announceposition = ANNOUNCEPOSITION_YES; /* Default yes */
1879  q->roundingseconds = 0; /* Default - don't announce seconds */
1880  q->servicelevel = 0;
1881  q->ringinuse = 1;
1882  q->announce_to_first_user = 0;
1883  q->setinterfacevar = 0;
1884  q->setqueuevar = 0;
1885  q->setqueueentryvar = 0;
1887  q->montype = montype_default;
1888  q->monfmt[0] = '\0';
1889  q->reportholdtime = 0;
1890  q->wrapuptime = 0;
1891  q->penaltymemberslimit = 0;
1892  q->joinempty = 0;
1893  q->leavewhenempty = 0;
1894  q->memberdelay = 0;
1895  q->maskmemberstatus = 0;
1896  q->eventwhencalled = 0;
1897  q->weight = 0;
1898  q->timeoutrestart = 0;
1900  q->randomperiodicannounce = 0;
1901  q->numperiodicannounce = 0;
1904  if (!q->members) {
1906  /* linear strategy depends on order, so we have to place all members in a single bucket */
1908  else
1910  }
1911  q->found = 1;
1912 
1913  ast_string_field_set(q, sound_next, "queue-youarenext");
1914  ast_string_field_set(q, sound_thereare, "queue-thereare");
1915  ast_string_field_set(q, sound_calls, "queue-callswaiting");
1916  ast_string_field_set(q, queue_quantity1, "queue-quantity1");
1917  ast_string_field_set(q, queue_quantity2, "queue-quantity2");
1918  ast_string_field_set(q, sound_holdtime, "queue-holdtime");
1919  ast_string_field_set(q, sound_minutes, "queue-minutes");
1920  ast_string_field_set(q, sound_minute, "queue-minute");
1921  ast_string_field_set(q, sound_seconds, "queue-seconds");
1922  ast_string_field_set(q, sound_thanks, "queue-thankyou");
1923  ast_string_field_set(q, sound_reporthold, "queue-reporthold");
1924 
1925  if (!q->sound_periodicannounce[0]) {
1927  }
1928 
1929  if (q->sound_periodicannounce[0]) {
1930  ast_str_set(&q->sound_periodicannounce[0], 0, "queue-periodic-announce");
1931  }
1932 
1933  for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
1934  if (q->sound_periodicannounce[i])
1935  ast_str_set(&q->sound_periodicannounce[i], 0, "%s", "");
1936  }
1937 
1938  while ((pr_iter = AST_LIST_REMOVE_HEAD(&q->rules,list)))
1939  ast_free(pr_iter);
1940 }
1941 
struct ast_str * sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS]
Definition: app_queue.c:1268
int servicelevel
Definition: app_queue.c:1299
static int member_hash_fn(const void *obj, const int flags)
Definition: app_queue.c:1843
#define MAX_PERIODIC_ANNOUNCEMENTS
Definition: app_queue.c:1027
unsigned int eventwhencalled
Definition: app_queue.c:1270
int wrapuptime
Definition: app_queue.c:1305
int penaltymemberslimit
Definition: app_queue.c:1306
unsigned int setqueuevar
Definition: app_queue.c:1274
#define DEFAULT_RETRY
Definition: app_queue.c:1024
#define DEFAULT_MIN_ANNOUNCE_FREQUENCY
Definition: app_queue.c:1028
struct call_queue::@57 rules
unsigned int maskmemberstatus
Definition: app_queue.c:1282
int minannouncefrequency
Definition: app_queue.c:1290
int autopause
Definition: app_queue.c:1312
unsigned int ringinuse
Definition: app_queue.c:1271
unsigned int timeoutrestart
Definition: app_queue.c:1278
unsigned int announceholdtime
Definition: app_queue.c:1279
struct ast_str * ast_str_create(size_t init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:420
unsigned int setinterfacevar
Definition: app_queue.c:1273
int ringlimit
Definition: app_queue.c:1307
unsigned int announce_to_first_user
Definition: app_queue.c:1272
struct ao2_container * members
Definition: app_queue.c:1320
char monfmt[8]
Definition: app_queue.c:1301
int announcepositionlimit
Definition: app_queue.c:1288
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:874
int periodicannouncefrequency
Definition: app_queue.c:1291
int memberdelay
Definition: app_queue.c:1317
int strategy
Definition: app_queue.c:1281
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
static int montype_default
queues.conf [general] option
Definition: app_queue.c:1067
static int member_cmp_fn(void *obj1, void *obj2, int flags)
Definition: app_queue.c:1855
static int autofill_default
queues.conf [general] option
Definition: app_queue.c:1064
#define ANNOUNCEPOSITION_YES
Definition: app_queue.c:1221
unsigned int dead
Definition: app_queue.c:1269
unsigned int reportholdtime
Definition: app_queue.c:1276
int autofill
Definition: app_queue.c:1318
int roundingseconds
Definition: app_queue.c:1294
#define ast_free(a)
Definition: astmm.h:97
#define DEFAULT_TIMEOUT
Definition: app_queue.c:1025
int timeoutpriority
Definition: app_queue.c:1313
unsigned int announceposition
Definition: app_queue.c:1280
unsigned int found
Definition: app_queue.c:1284
int randomperiodicannounce
Definition: app_queue.c:1293
unsigned int setqueueentryvar
Definition: app_queue.c:1275
int numperiodicannounce
Definition: app_queue.c:1292
#define ao2_container_alloc(arg1, arg2, arg3)
Definition: astobj2.h:734
enum empty_conditions leavewhenempty
Definition: app_queue.c:1287
struct penalty_rule::@55 list
enum empty_conditions joinempty
Definition: app_queue.c:1286
int announcefrequency
Definition: app_queue.c:1289
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
static void insert_entry ( struct call_queue q,
struct queue_ent prev,
struct queue_ent new,
int *  pos 
)
inlinestatic

Insert the 'new' entry after the 'prev' entry of queue 'q'.

Definition at line 1515 of file app_queue.c.

References call_queue::head, queue_ent::next, queue_ent::pos, and queue_ref().

Referenced by join_queue().

1515 {
1516  struct queue_ent *cur;
1517 
1518  if (!q || !new)
1519  return;
1520  if (prev) {
1521  cur = prev->next;
1522  prev->next = new;
1523  } else {
1524  cur = q->head;
1525  q->head = new;
1526  }
1527  new->next = cur;
1528 
1529  /* every queue_ent must have a reference to it's parent call_queue, this
1530  * reference does not go away until the end of the queue_ent's life, meaning
1531  * that even when the queue_ent leaves the call_queue this ref must remain. */
1532  queue_ref(q);
1533  new->parent = q;
1534  new->pos = ++(*pos);
1535  new->opos = *pos;
1536 }
1537 
struct queue_ent * head
Definition: app_queue.c:1321
static struct call_queue * queue_ref(struct call_queue *q)
Definition: app_queue.c:1476
struct queue_ent * next
Definition: app_queue.c:1171
static int insert_penaltychange ( const char *  list_name,
const char *  content,
const int  linenum 
)
static

Change queue penalty by adding rule.

Check rule for errors with time or fomatting, see if rule is relative to rest of queue, iterate list of rules to find correct insertion point, insert and return.

Return values
-1on failure
0on success
Note
Call this with the rule_lists locked

Definition at line 1972 of file app_queue.c.

References ast_calloc, ast_free, AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, penalty_rule::max_relative, penalty_rule::max_value, penalty_rule::min_relative, penalty_rule::min_value, rule_list::name, rule_list::rules, and penalty_rule::time.

Referenced by reload_queue_rules().

1972 {
1973  char *timestr, *maxstr, *minstr, *contentdup;
1974  struct penalty_rule *rule = NULL, *rule_iter;
1975  struct rule_list *rl_iter;
1976  int penaltychangetime, inserted = 0;
1977 
1978  if (!(rule = ast_calloc(1, sizeof(*rule)))) {
1979  return -1;
1980  }
1981 
1982  contentdup = ast_strdupa(content);
1983 
1984  if (!(maxstr = strchr(contentdup, ','))) {
1985  ast_log(LOG_WARNING, "Improperly formatted penaltychange rule at line %d. Ignoring.\n", linenum);
1986  ast_free(rule);
1987  return -1;
1988  }
1989 
1990  *maxstr++ = '\0';
1991  timestr = contentdup;
1992 
1993  if ((penaltychangetime = atoi(timestr)) < 0) {
1994  ast_log(LOG_WARNING, "Improper time parameter specified for penaltychange rule at line %d. Ignoring.\n", linenum);
1995  ast_free(rule);
1996  return -1;
1997  }
1998 
1999  rule->time = penaltychangetime;
2000 
2001  if ((minstr = strchr(maxstr,',')))
2002  *minstr++ = '\0';
2003 
2004  /* The last check will evaluate true if either no penalty change is indicated for a given rule
2005  * OR if a min penalty change is indicated but no max penalty change is */
2006  if (*maxstr == '+' || *maxstr == '-' || *maxstr == '\0') {
2007  rule->max_relative = 1;
2008  }
2009 
2010  rule->max_value = atoi(maxstr);
2011 
2012  if (!ast_strlen_zero(minstr)) {
2013  if (*minstr == '+' || *minstr == '-')
2014  rule->min_relative = 1;
2015  rule->min_value = atoi(minstr);
2016  } else /*there was no minimum specified, so assume this means no change*/
2017  rule->min_relative = 1;
2018 
2019  /*We have the rule made, now we need to insert it where it belongs*/
2020  AST_LIST_TRAVERSE(&rule_lists, rl_iter, list){
2021  if (strcasecmp(rl_iter->name, list_name))
2022  continue;
2023 
2024  AST_LIST_TRAVERSE_SAFE_BEGIN(&rl_iter->rules, rule_iter, list) {
2025  if (rule->time < rule_iter->time) {
2027  inserted = 1;
2028  break;
2029  }
2030  }
2032 
2033  if (!inserted) {
2034  AST_LIST_INSERT_TAIL(&rl_iter->rules, rule, list);
2035  inserted = 1;
2036  }
2037 
2038  break;
2039  }
2040 
2041  if (!inserted) {
2042  ast_log(LOG_WARNING, "Unknown rule list name %s; ignoring.\n", list_name);
2043  ast_free(rule);
2044  return -1;
2045  }
2046  return 0;
2047 }
2048 
int max_relative
Definition: app_queue.c:1216
struct rule_list::@58 rules
char name[80]
Definition: app_queue.c:1327
int min_relative
Definition: app_queue.c:1217
#define LOG_WARNING
Definition: logger.h:144
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_free(a)
Definition: astmm.h:97
struct rule_list::@59 list
#define ast_calloc(a, b)
Definition: astmm.h:82
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
Definition: linkedlists.h:584
static const char* int2strat ( int  strategy)
static

Definition at line 1353 of file app_queue.c.

References ARRAY_LEN, strategy::name, and strategies.

Referenced by __queues_show(), manager_queues_status(), queue_function_var(), queues_data_provider_get_helper(), and set_queue_variables().

1353 {
1354  int x;
1355 
1356  for (x = 0; x < ARRAY_LEN(strategies); x++) {
1357  if (strategy == strategies[x].strategy)
1358  return strategies[x].name;
1359  }
1360 
1361  return "<unknown>";
1362 }
1363 
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static struct strategy strategies[]
const char * name
Definition: app_queue.c:999
static struct member* interface_exists ( struct call_queue q,
const char *  interface 
)
static

Definition at line 5637 of file app_queue.c.

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

Referenced by add_to_queue(), get_member_penalty(), set_member_paused(), and set_member_penalty().

5637 {
5638  struct member *mem;
5639  struct ao2_iterator mem_iter;
5640 
5641  if (!q)
5642  return NULL;
5643 
5644  mem_iter = ao2_iterator_init(q->members, 0);
5645  while ((mem = ao2_iterator_next(&mem_iter))) {
5646  if (!strcasecmp(interface, mem->interface)) {
5647  ao2_iterator_destroy(&mem_iter);
5648  return mem;
5649  }
5650  ao2_ref(mem, -1);
5651  }
5652  ao2_iterator_destroy(&mem_iter);
5653 
5654  return NULL;
5655 }
5656 
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
char interface[80]
Definition: app_queue.c:1175
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
struct ao2_container * members
Definition: app_queue.c:1320
#define ao2_ref(o, delta)
Definition: astobj2.h:472
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
static int is_our_turn ( struct queue_ent qe)
static

Check if we should start attempting to call queue members.

A simple process, really. Count the number of members who are available to take our call and then see if we are in a position in the queue at which a member could accept our call.

Parameters
[in]qeThe caller who wants to know if it is his turn
Return values
0It is not our turn
1It is our turn

Definition at line 4324 of file app_queue.c.

References ao2_lock, ao2_unlock, ast_debug, call_queue::autofill, queue_ent::chan, call_queue::head, ast_channel::name, queue_ent::next, num_available_members(), queue_ent::parent, queue_ent::pending, and queue_ent::pos.

Referenced by queue_exec(), and wait_our_turn().

4324 {
4325  struct queue_ent *ch;
4326  int res;
4327  int avl;
4328  int idx = 0;
4329  /* This needs a lock. How many members are available to be served? */
4330  ao2_lock(qe->parent);
4331 
4332  avl = num_available_members(qe->parent);
4333 
4334  ch = qe->parent->head;
4335 
4336  ast_debug(1, "There %s %d available %s.\n", avl != 1 ? "are" : "is", avl, avl != 1 ? "members" : "member");
4337 
4338  while ((idx < avl) && (ch) && (ch != qe)) {
4339  if (!ch->pending)
4340  idx++;
4341  ch = ch->next;
4342  }
4343 
4344  ao2_unlock(qe->parent);
4345  /* If the queue entry is within avl [the number of available members] calls from the top ...
4346  * Autofill and position check added to support autofill=no (as only calls
4347  * from the front of the queue are valid when autofill is disabled)
4348  */
4349  if (ch && idx < avl && (qe->parent->autofill || qe->pos == 1)) {
4350  ast_debug(1, "It's our turn (%s).\n", qe->chan->name);
4351  res = 1;
4352  } else {
4353  ast_debug(1, "It's not our turn (%s).\n", qe->chan->name);
4354  res = 0;
4355  }
4356 
4357  return res;
4358 }
4359 
struct call_queue * parent
Definition: app_queue.c:1144
struct ast_channel * chan
Definition: app_queue.c:1168
#define ao2_unlock(a)
Definition: astobj2.h:497
struct queue_ent * head
Definition: app_queue.c:1321
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define ao2_lock(a)
Definition: astobj2.h:488
static int num_available_members(struct call_queue *q)
Get the number of members available to accept a call.
Definition: app_queue.c:3117
int autofill
Definition: app_queue.c:1318
const ast_string_field name
Definition: channel.h:787
int pending
Definition: app_queue.c:1160
struct queue_ent * next
Definition: app_queue.c:1171
static int join_queue ( char *  queuename,
struct queue_ent qe,
enum queue_result reason,
int  position 
)
static

Definition at line 2700 of file app_queue.c.

References queue_ent::announce, call_queue::announce, ao2_lock, ao2_unlock, ast_copy_string(), ast_debug, ast_log(), ast_manager_event, ast_channel::caller, queue_ent::chan, ast_channel::connected, queue_ent::context, call_queue::context, call_queue::count, EVENT_FLAG_CALL, get_member_status(), call_queue::head, ast_party_caller::id, ast_party_connected_line::id, insert_entry(), call_queue::joinempty, load_realtime_queue(), LOG_NOTICE, queue_ent::max_penalty, call_queue::maxlen, queue_ent::min_penalty, queue_ent::moh, call_queue::moh, ast_party_id::name, ast_channel::name, call_queue::name, queue_ent::next, ast_party_id::number, queue_ent::pos, queue_ent::prio, QUEUE_FULL, QUEUE_JOINEMPTY, queue_t_unref, QUEUE_UNKNOWN, S_COR, status, ast_party_name::str, ast_party_number::str, ast_channel::uniqueid, ast_party_name::valid, and ast_party_number::valid.

Referenced by queue_exec().

2700 {
2701  struct call_queue *q;
2702  struct queue_ent *cur, *prev = NULL;
2703  int res = -1;
2704  int pos = 0;
2705  int inserted = 0;
2706 
2707  if (!(q = load_realtime_queue(queuename)))
2708  return res;
2709 
2710  ao2_lock(q);
2711 
2712  /* This is our one */
2713  if (q->joinempty) {
2714  int status = 0;
2715  if ((status = get_member_status(q, qe->max_penalty, qe->min_penalty, q->joinempty, 0))) {
2716  *reason = QUEUE_JOINEMPTY;
2717  ao2_unlock(q);
2718  queue_t_unref(q, "Done with realtime queue");
2719  return res;
2720  }
2721  }
2722  if (*reason == QUEUE_UNKNOWN && q->maxlen && (q->count >= q->maxlen))
2723  *reason = QUEUE_FULL;
2724  else if (*reason == QUEUE_UNKNOWN) {
2725  /* There's space for us, put us at the right position inside
2726  * the queue.
2727  * Take into account the priority of the calling user */
2728  inserted = 0;
2729  prev = NULL;
2730  cur = q->head;
2731  while (cur) {
2732  /* We have higher priority than the current user, enter
2733  * before him, after all the other users with priority
2734  * higher or equal to our priority. */
2735  if ((!inserted) && (qe->prio > cur->prio)) {
2736  insert_entry(q, prev, qe, &pos);
2737  inserted = 1;
2738  }
2739  /* <= is necessary for the position comparison because it may not be possible to enter
2740  * at our desired position since higher-priority callers may have taken the position we want
2741  */
2742  if (!inserted && (qe->prio >= cur->prio) && position && (position <= pos + 1)) {
2743  insert_entry(q, prev, qe, &pos);
2744  inserted = 1;
2745  /*pos is incremented inside insert_entry, so don't need to add 1 here*/
2746  if (position < pos) {
2747  ast_log(LOG_NOTICE, "Asked to be inserted at position %d but forced into position %d due to higher priority callers\n", position, pos);
2748  }
2749  }
2750  cur->pos = ++pos;
2751  prev = cur;
2752  cur = cur->next;
2753  }
2754  /* No luck, join at the end of the queue */
2755  if (!inserted)
2756  insert_entry(q, prev, qe, &pos);
2757  ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
2758  ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
2759  ast_copy_string(qe->context, q->context, sizeof(qe->context));
2760  q->count++;
2761  res = 0;
2762  ast_manager_event(qe->chan, EVENT_FLAG_CALL, "Join",
2763  "Channel: %s\r\n"
2764  "CallerIDNum: %s\r\n"
2765  "CallerIDName: %s\r\n"
2766  "ConnectedLineNum: %s\r\n"
2767  "ConnectedLineName: %s\r\n"
2768  "Queue: %s\r\n"
2769  "Position: %d\r\n"
2770  "Count: %d\r\n"
2771  "Uniqueid: %s\r\n",
2772  qe->chan->name,
2773  S_COR(qe->chan->caller.id.number.valid, qe->chan->caller.id.number.str, "unknown"),/* XXX somewhere else it is <unknown> */
2774  S_COR(qe->chan->caller.id.name.valid, qe->chan->caller.id.name.str, "unknown"),
2775  S_COR(qe->chan->connected.id.number.valid, qe->chan->connected.id.number.str, "unknown"),/* XXX somewhere else it is <unknown> */
2776  S_COR(qe->chan->connected.id.name.valid, qe->chan->connected.id.name.str, "unknown"),
2777  q->name, qe->pos, q->count, qe->chan->uniqueid );
2778  ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos );
2779  }
2780  ao2_unlock(q);
2781  queue_t_unref(q, "Done with realtime queue");
2782 
2783  return res;
2784 }
2785 
char moh[80]
Definition: app_queue.c:1145
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
struct ast_party_connected_line connected
Channel Connected Line ID information.
Definition: channel.h:811
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
struct ast_channel * chan
Definition: app_queue.c:1168
static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, enum empty_conditions conditions, int devstate)
Check if members are available.
Definition: app_queue.c:1545
int min_penalty
Definition: app_queue.c:1162
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
const ast_string_field uniqueid
Definition: channel.h:787
int max_penalty
Definition: app_queue.c:1161
struct ast_party_id id
Connected party ID.
Definition: channel.h:403
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
#define EVENT_FLAG_CALL
Definition: manager.h:72
char * str
Subscriber name (Malloced)
Definition: channel.h:214
#define ao2_unlock(a)
Definition: astobj2.h:497
struct queue_ent * head
Definition: app_queue.c:1321
#define ast_manager_event(chan, category, event, contents,...)
Definition: manager.h:221
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
const ast_string_field context
Definition: app_queue.c:1266
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
#define ao2_lock(a)
Definition: astobj2.h:488
static struct call_queue * load_realtime_queue(const char *queuename)
Definition: app_queue.c:2573
const ast_string_field name
Definition: app_queue.c:1266
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
const ast_string_field moh
Definition: app_queue.c:1266
const ast_string_field announce
Definition: app_queue.c:1266
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
Insert the &#39;new&#39; entry after the &#39;prev&#39; entry of queue &#39;q&#39;.
Definition: app_queue.c:1515
struct queue_ent * next
Definition: app_queue.c:1171
char context[AST_MAX_CONTEXT]
Definition: app_queue.c:1147
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
enum empty_conditions joinempty
Definition: app_queue.c:1286
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
char announce[PATH_MAX]
Definition: app_queue.c:1146
jack_status_t status
Definition: app_jack.c:143
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int kill_dead_members ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 7310 of file app_queue.c.

References CMP_MATCH, member::delme, get_queue_member_status(), and member::status.

Referenced by reload_single_queue().

7310 {
7311  struct member *member = obj;
7312 
7313  if (!member->delme) {
7314  member->status = get_queue_member_status(member);
7315  return 0;
7316  } else {
7317  return CMP_MATCH;
7318  }
7319 }
7320 
unsigned int delme
Definition: app_queue.c:1191
int status
Definition: app_queue.c:1184
static int get_queue_member_status(struct member *cur)
Return the current state of a member.
Definition: app_queue.c:1795
static int kill_dead_queues ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 7454 of file app_queue.c.

References ast_strlen_zero(), CMP_MATCH, call_queue::dead, and call_queue::name.

Referenced by reload_queues().

7454 {
7455  struct call_queue *q = obj;
7456  char *queuename = arg;
7457  if ((ast_strlen_zero(queuename) || !strcasecmp(queuename, q->name)) && q->dead) {
7458  return CMP_MATCH;
7459  } else {
7460  return 0;
7461  }
7462 }
7463 
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
unsigned int dead
Definition: app_queue.c:1269
const ast_string_field name
Definition: app_queue.c:1266
static void leave_queue ( struct queue_ent qe)
static

Caller leaving queue.

Search the queue to find the leaving client, if found remove from queue create manager event, move others up the queue.

Definition at line 3012 of file app_queue.c.

References ao2_lock, ao2_unlock, ast_debug, ast_free, AST_LIST_REMOVE_HEAD, ast_load_realtime(), ast_manager_event, ast_variables_destroy(), queue_ent::chan, call_queue::count, call_queue::dead, EVENT_FLAG_CALL, call_queue::head, ast_channel::name, call_queue::name, queue_ent::next, queue_ent::parent, pbx_builtin_setvar_helper(), queue_ent::pos, queue_ent::qe_rules, queue_t_ref, queue_t_unref, queues, queues_t_unlink, call_queue::realtime, SENTINEL, ast_channel::uniqueid, and var.

Referenced by queue_exec(), try_calling(), and wait_our_turn().

3012 {
3013  struct call_queue *q;
3014  struct queue_ent *current, *prev = NULL;
3015  struct penalty_rule *pr_iter;
3016  int pos = 0;
3017 
3018  if (!(q = qe->parent))
3019  return;
3020  queue_t_ref(q, "Copy queue pointer from queue entry");
3021  ao2_lock(q);
3022 
3023  prev = NULL;
3024  for (current = q->head; current; current = current->next) {
3025  if (current == qe) {
3026  char posstr[20];
3027  q->count--;
3028 
3029  /* Take us out of the queue */
3030  ast_manager_event(qe->chan, EVENT_FLAG_CALL, "Leave",
3031  "Channel: %s\r\nQueue: %s\r\nCount: %d\r\nPosition: %d\r\nUniqueid: %s\r\n",
3032  qe->chan->name, q->name, q->count, qe->pos, qe->chan->uniqueid);
3033  ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name );
3034  /* Take us out of the queue */
3035  if (prev)
3036  prev->next = current->next;
3037  else
3038  q->head = current->next;
3039  /* Free penalty rules */
3040  while ((pr_iter = AST_LIST_REMOVE_HEAD(&qe->qe_rules, list)))
3041  ast_free(pr_iter);
3042  snprintf(posstr, sizeof(posstr), "%d", qe->pos);
3043  pbx_builtin_setvar_helper(qe->chan, "QUEUEPOSITION", posstr);
3044  } else {
3045  /* Renumber the people after us in the queue based on a new count */
3046  current->pos = ++pos;
3047  prev = current;
3048  }
3049  }
3050  ao2_unlock(q);
3051 
3052  /*If the queue is a realtime queue, check to see if it's still defined in real time*/
3053  if (q->realtime) {
3054  struct ast_variable *var;
3055  if (!(var = ast_load_realtime("queues", "name", q->name, SENTINEL))) {
3056  q->dead = 1;
3057  } else {
3058  ast_variables_destroy(var);
3059  }
3060  }
3061 
3062  if (q->dead) {
3063  /* It's dead and nobody is in it, so kill it */
3064  queues_t_unlink(queues, q, "Queue is now dead; remove it from the container");
3065  }
3066  /* unref the explicit ref earlier in the function */
3067  queue_t_unref(q, "Expire copied reference");
3068 }
3069 
struct call_queue * parent
Definition: app_queue.c:1144
struct ast_channel * chan
Definition: app_queue.c:1168
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
const ast_string_field uniqueid
Definition: channel.h:787
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define var
Definition: ast_expr2f.c:606
#define EVENT_FLAG_CALL
Definition: manager.h:72
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: config.c:2548
#define ao2_unlock(a)
Definition: astobj2.h:497
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: config.c:586
struct queue_ent * head
Definition: app_queue.c:1321
#define ast_manager_event(chan, category, event, contents,...)
Definition: manager.h:221
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define SENTINEL
Definition: compiler.h:75
static struct ao2_container * queues
Definition: app_queue.c:1334
#define ao2_lock(a)
Definition: astobj2.h:488
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
unsigned int dead
Definition: app_queue.c:1269
const ast_string_field name
Definition: app_queue.c:1266
const ast_string_field name
Definition: channel.h:787
#define ast_free(a)
Definition: astmm.h:97
#define queue_t_ref(a, b)
Definition: app_queue.c:1472
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...
Definition: pbx.c:10546
unsigned int realtime
Definition: app_queue.c:1283
struct queue_ent::@54 qe_rules
struct queue_ent * next
Definition: app_queue.c:1171
struct penalty_rule::@55 list
#define queues_t_unlink(c, q, tag)
Definition: app_queue.c:1475
static int load_module ( void  )
static

Definition at line 9134 of file app_queue.c.

References ao2_container_alloc, aqm_exec(), ARRAY_LEN, ast_add_extension2(), ast_cli_register_multiple(), ast_context_find_or_create(), ast_custom_function_register, ast_data_register_multiple, AST_EVENT_DEVICE_STATE, AST_EVENT_IE_END, ast_event_subscribe(), ast_extension_state_add(), AST_FLAGS_ALL, ast_free_ptr(), ast_log(), ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, ast_realtime_require_field(), ast_register_application_xml, ast_strdup, ast_taskprocessor_get(), cli_queue, device_state_cb(), EVENT_FLAG_AGENT, extension_state_cb(), LOG_ERROR, LOG_WARNING, manager_add_queue_member(), manager_pause_queue_member(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_queue_rule_show(), manager_queues_show(), manager_queues_status(), manager_queues_summary(), manager_remove_queue_member(), MAX_QUEUE_BUCKETS, pqm_exec(), ql_exec(), queue_cmp_cb(), queue_data_providers, queue_exec(), queue_hash_cb(), queueexists_function, queuemembercount_dep, queuemembercount_function, queuememberlist_function, queuememberpaused_function, queuememberpenalty_function, queuememberstatus_function, queues, queuevar_function, queuewaitingcount_function, reload_handler(), reload_queue_members(), RQ_INTEGER1, RQ_UINTEGER2, rqm_exec(), SENTINEL, and upqm_exec().

9134 {
9135  int res;
9136  struct ast_context *con;
9137  struct ast_flags mask = {AST_FLAGS_ALL, };
9138 
9140 
9141  use_weight = 0;
9142 
9143  if (reload_handler(0, &mask, NULL))
9144  return AST_MODULE_LOAD_DECLINE;
9145 
9146  con = ast_context_find_or_create(NULL, NULL, "app_queue_gosub_virtual_context", "app_queue");
9147  if (!con)
9148  ast_log(LOG_ERROR, "Queue virtual context 'app_queue_gosub_virtual_context' does not exist and unable to create\n");
9149  else
9150  ast_add_extension2(con, 1, "s", 1, NULL, NULL, "NoOp", ast_strdup(""), ast_free_ptr, "app_queue");
9151 
9154 
9156 
9164  res |= ast_manager_register_xml("Queues", 0, manager_queues_show);
9165  res |= ast_manager_register_xml("QueueStatus", 0, manager_queues_status);
9166  res |= ast_manager_register_xml("QueueSummary", 0, manager_queues_summary);
9172  res |= ast_manager_register_xml("QueueRule", 0, manager_queue_rule_show);
9173  res |= ast_manager_register_xml("QueueReload", 0, manager_queue_reload);
9174  res |= ast_manager_register_xml("QueueReset", 0, manager_queue_reset);
9184 
9185  if (!(devicestate_tps = ast_taskprocessor_get("app_queue", 0))) {
9186  ast_log(LOG_WARNING, "devicestate taskprocessor reference failed - devicestate notifications will not occur\n");
9187  }
9188 
9189  /* in the following subscribe call, do I use DEVICE_STATE, or DEVICE_STATE_CHANGE? */
9191  res = -1;
9192  }
9193 
9194  ast_extension_state_add(NULL, NULL, extension_state_cb, NULL);
9195 
9196  ast_realtime_require_field("queue_members", "paused", RQ_INTEGER1, 1, "uniqueid", RQ_UINTEGER2, 5, SENTINEL);
9197 
9198  return res ? AST_MODULE_LOAD_DECLINE : 0;
9199 }
9200 
static struct ast_custom_function queuewaitingcount_function
Definition: app_queue.c:7112
static char * app_ql
Definition: app_queue.c:1049
static int rqm_exec(struct ast_channel *chan, const char *data)
RemoveQueueMember application.
Definition: app_queue.c:6139
static struct ast_custom_function queuememberstatus_function
Definition: app_queue.c:7128
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static struct ast_data_entry queue_data_providers[]
Definition: app_queue.c:9071
#define ast_strdup(a)
Definition: astmm.h:109
static char * app_aqm
Definition: app_queue.c:1041
static int upqm_exec(struct ast_channel *chan, const char *data)
UnPauseQueueMember application.
Definition: app_queue.c:6103
static int manager_queue_reset(struct mansession *s, const struct message *m)
Definition: app_queue.c:8255
#define LOG_WARNING
Definition: logger.h:144
static int manager_queue_member_penalty(struct mansession *s, const struct message *m)
Definition: app_queue.c:8301
int ast_add_extension2(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add an extension to an extension context, this time with an ast_context *.
Definition: pbx.c:9052
struct ast_taskprocessor * ast_taskprocessor_get(const char *name, enum ast_tps_options create)
Get a reference to a taskprocessor with the specified name and create the taskprocessor if necessary...
#define MAX_QUEUE_BUCKETS
Definition: app_queue.c:1031
static struct ast_custom_function queuemembercount_dep
Definition: app_queue.c:7107
static char * app_rqm
Definition: app_queue.c:1043
void ast_free_ptr(void *ptr)
static struct ast_custom_function queueexists_function
Definition: app_queue.c:7092
static char * app
Definition: app_queue.c:1039
static int manager_queue_rule_show(struct mansession *s, const struct message *m)
Definition: app_queue.c:7881
static void device_state_cb(const struct ast_event *event, void *unused)
Definition: app_queue.c:1699
static struct ast_taskprocessor * devicestate_tps
Definition: app_queue.c:1022
#define SENTINEL
Definition: compiler.h:75
static struct ast_custom_function queuemembercount_function
Definition: app_queue.c:7102
static struct ao2_container * queues
Definition: app_queue.c:1334
static struct ast_custom_function queuememberpenalty_function
Definition: app_queue.c:7122
static int pqm_exec(struct ast_channel *chan, const char *data)
PauseQueueMember application.
Definition: app_queue.c:6067
#define ast_manager_register_xml(a, b, c)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:172
static int reload_handler(int reload, struct ast_flags *mask, const char *queuename)
The command center for all reload operations.
Definition: app_queue.c:7572
#define ast_data_register_multiple(data_entries, entries)
Definition: data.h:377
static int queue_cmp_cb(void *obj, void *arg, int flags)
Definition: app_queue.c:1404
#define LOG_ERROR
Definition: logger.h:155
static int manager_queue_log_custom(struct mansession *s, const struct message *m)
Definition: app_queue.c:8202
static int manager_queue_reload(struct mansession *s, const struct message *m)
Definition: app_queue.c:8223
static struct ast_custom_function queuememberlist_function
Definition: app_queue.c:7117
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define EVENT_FLAG_AGENT
Definition: manager.h:76
static int ql_exec(struct ast_channel *chan, const char *data)
QueueLog application.
Definition: app_queue.c:6258
static char * app_pqm
Definition: app_queue.c:1045
#define AST_FLAGS_ALL
Definition: utils.h:196
static int manager_queues_status(struct mansession *s, const struct message *m)
Queue status info via AMI.
Definition: app_queue.c:7991
Structure used to handle boolean flags.
Definition: utils.h:200
int ast_realtime_require_field(const char *family,...) attribute_sentinel
Inform realtime what fields that may be stored.
Definition: config.c:2606
static int manager_queues_show(struct mansession *s, const struct message *m)
Definition: app_queue.c:7871
static int manager_queues_summary(struct mansession *s, const struct message *m)
Summary of queue info via the AMI.
Definition: app_queue.c:7916
static struct ast_custom_function queuememberpaused_function
Definition: app_queue.c:7133
static struct ast_cli_entry cli_queue[]
Definition: app_queue.c:8793
static struct ast_custom_function queuevar_function
Definition: app_queue.c:7097
struct ast_event_sub * ast_event_subscribe(enum ast_event_type event_type, ast_event_cb_t cb, const char *description, void *userdata,...)
Subscribe to events.
Definition: event.c:909
#define ao2_container_alloc(arg1, arg2, arg3)
Definition: astobj2.h:734
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
static int aqm_exec(struct ast_channel *chan, const char *data)
AddQueueMember application.
Definition: app_queue.c:6195
static struct ast_event_sub * device_state_sub
Subscription to device state change events.
Definition: app_queue.c:1073
static int use_weight
queues.conf per-queue weight option
Definition: app_queue.c:1061
static int queue_exec(struct ast_channel *chan, const char *data)
The starting point for all queue calls.
Definition: app_queue.c:6332
static void reload_queue_members(void)
Reload dynamic queue members persisted into the astdb.
Definition: app_queue.c:5972
static int queue_hash_cb(const void *obj, const int flags)
Definition: app_queue.c:1397
static int manager_add_queue_member(struct mansession *s, const struct message *m)
Definition: app_queue.c:8093
static int extension_state_cb(char *context, char *exten, enum ast_extension_states state, void *data)
Definition: app_queue.c:1757
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:7726
int ast_extension_state_add(const char *context, const char *exten, ast_state_cb_type change_cb, void *data)
Registers a state change callback.
Definition: pbx.c:5135
static int manager_pause_queue_member(struct mansession *s, const struct message *m)
Definition: app_queue.c:8178
ast_context: An extension context
Definition: pbx.c:955
static char * app_upqm
Definition: app_queue.c:1047
static int manager_remove_queue_member(struct mansession *s, const struct message *m)
Definition: app_queue.c:8144
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1164
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
static int queue_persistent_members
queues.conf [general] option
Definition: app_queue.c:1058
static struct call_queue* load_realtime_queue ( const char *  queuename)
static
Note
Returns a reference to the loaded realtime queue.
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 2573 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(), call_queue::name, OBJ_POINTER, queue_t_unref, queues, call_queue::realtime, SENTINEL, update_realtime_members(), and call_queue::weight.

Referenced by __queues_show(), add_to_queue(), join_queue(), queue_function_exists(), queue_function_qac(), queue_function_qac_dep(), queues_data_provider_get(), and reload_queue_members().

2573 {
2574  struct ast_variable *queue_vars;
2575  struct ast_config *member_config = NULL;
2576  struct call_queue *q = NULL, tmpq = {
2577  .name = queuename,
2578  };
2579  int prev_weight = 0;
2580 
2581  /* Find the queue in the in-core list first. */
2582  q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Look for queue in memory first");
2583 
2584  if (!q || q->realtime) {
2585  /*! \note Load from realtime before taking the "queues" container lock, to avoid blocking all
2586  queue operations while waiting for the DB.
2587 
2588  This will be two separate database transactions, so we might
2589  see queue parameters as they were before another process
2590  changed the queue and member list as it was after the change.
2591  Thus we might see an empty member list when a queue is
2592  deleted. In practise, this is unlikely to cause a problem. */
2593 
2594  queue_vars = ast_load_realtime("queues", "name", queuename, SENTINEL);
2595  if (queue_vars) {
2596  member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, SENTINEL);
2597  if (!member_config) {
2598  ast_debug(1, "No queue_members defined in config extconfig.conf\n");
2599  member_config = ast_config_new();
2600  }
2601  }
2602  if (q) {
2603  prev_weight = q->weight ? 1 : 0;
2604  queue_t_unref(q, "Need to find realtime queue");
2605  }
2606 
2607  q = find_queue_by_name_rt(queuename, queue_vars, member_config);
2608  ast_config_destroy(member_config);
2609  ast_variables_destroy(queue_vars);
2610 
2611  /* update the use_weight value if the queue's has gained or lost a weight */
2612  if (q) {
2613  if (!q->weight && prev_weight) {
2615  }
2616  if (q->weight && !prev_weight) {
2618  }
2619  }
2620  /* Other cases will end up with the proper value for use_weight */
2621  } else {
2623  }
2624  return q;
2625 }
2626 
#define ao2_t_find(arg1, arg2, arg3, arg4)
Definition: astobj2.h:963
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
static void update_realtime_members(struct call_queue *q)
Definition: app_queue.c:2642
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: config.c:2548
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: config.c:586
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define SENTINEL
Definition: compiler.h:75
static struct ao2_container * queues
Definition: app_queue.c:1334
const ast_string_field name
Definition: app_queue.c:1266
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: config.c:888
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:2442
unsigned int realtime
Definition: app_queue.c:1283
static int use_weight
queues.conf per-queue weight option
Definition: app_queue.c:1061
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: config.c:2650
static int manager_add_queue_member ( struct mansession s,
const struct message m 
)
static

Definition at line 8093 of file app_queue.c.

References add_to_queue(), ast_queue_log(), ast_strlen_zero(), ast_true(), astman_get_header(), astman_send_ack(), astman_send_error(), RES_EXISTS, RES_NOSUCHQUEUE, RES_OKAY, and RES_OUTOFMEMORY.

Referenced by load_module().

8093 {
8094  const char *queuename, *interface, *penalty_s, *paused_s, *membername, *state_interface;
8095  int paused, penalty = 0;
8096 
8097  queuename = astman_get_header(m, "Queue");
8098  interface = astman_get_header(m, "Interface");
8099  penalty_s = astman_get_header(m, "Penalty");
8100  paused_s = astman_get_header(m, "Paused");
8101  membername = astman_get_header(m, "MemberName");
8102  state_interface = astman_get_header(m, "StateInterface");
8103 
8104  if (ast_strlen_zero(queuename)) {
8105  astman_send_error(s, m, "'Queue' not specified.");
8106  return 0;
8107  }
8108 
8109  if (ast_strlen_zero(interface)) {
8110  astman_send_error(s, m, "'Interface' not specified.");
8111  return 0;
8112  }
8113 
8114  if (ast_strlen_zero(penalty_s))
8115  penalty = 0;
8116  else if (sscanf(penalty_s, "%30d", &penalty) != 1 || penalty < 0)
8117  penalty = 0;
8118 
8119  if (ast_strlen_zero(paused_s))
8120  paused = 0;
8121  else
8122  paused = abs(ast_true(paused_s));
8123 
8124  switch (add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members, state_interface)) {
8125  case RES_OKAY:
8126  ast_queue_log(queuename, "MANAGER", interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
8127  astman_send_ack(s, m, "Added interface to queue");
8128  break;
8129  case RES_EXISTS:
8130  astman_send_error(s, m, "Unable to add interface: Already there");
8131  break;
8132  case RES_NOSUCHQUEUE:
8133  astman_send_error(s, m, "Unable to add interface to queue: No such queue");
8134  break;
8135  case RES_OUTOFMEMORY:
8136  astman_send_error(s, m, "Out of memory");
8137  break;
8138  }
8139 
8140  return 0;
8141 }
8142 
#define RES_OKAY
Definition: app_queue.c:1033
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2135
#define RES_OUTOFMEMORY
Definition: app_queue.c:1035
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
#define RES_NOSUCHQUEUE
Definition: app_queue.c:1036
#define RES_EXISTS
Definition: app_queue.c:1034
static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump, const char *state_interface)
Add member to queue.
Definition: app_queue.c:5763
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:2130
static int queue_persistent_members
queues.conf [general] option
Definition: app_queue.c:1058
static int manager_pause_queue_member ( struct mansession s,
const struct message m 
)
static

Definition at line 8178 of file app_queue.c.

References ast_strlen_zero(), ast_true(), astman_get_header(), astman_send_ack(), astman_send_error(), and set_member_paused().

Referenced by load_module().

8178 {
8179  const char *queuename, *interface, *paused_s, *reason;
8180  int paused;
8181 
8182  interface = astman_get_header(m, "Interface");
8183  paused_s = astman_get_header(m, "Paused");
8184  queuename = astman_get_header(m, "Queue"); /* Optional - if not supplied, pause the given Interface in all queues */
8185  reason = astman_get_header(m, "Reason"); /* Optional - Only used for logging purposes */
8186 
8187  if (ast_strlen_zero(interface) || ast_strlen_zero(paused_s)) {
8188  astman_send_error(s, m, "Need 'Interface' and 'Paused' parameters.");
8189  return 0;
8190  }
8191 
8192  paused = abs(ast_true(paused_s));
8193 
8194  if (set_member_paused(queuename, interface, reason, paused))
8195  astman_send_error(s, m, "Interface not found");
8196  else
8197  astman_send_ack(s, m, paused ? "Interface paused successfully" : "Interface unpaused successfully");
8198  return 0;
8199 }
8200 
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2135
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused)
Definition: app_queue.c:5814
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:2130
static int manager_queue_log_custom ( struct mansession s,
const struct message m 
)
static

Definition at line 8202 of file app_queue.c.

References ast_queue_log(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), and S_OR.

Referenced by load_module().

8202 {
8203  const char *queuename, *event, *message, *interface, *uniqueid;
8204 
8205  queuename = astman_get_header(m, "Queue");
8206  uniqueid = astman_get_header(m, "UniqueId");
8207  interface = astman_get_header(m, "Interface");
8208  event = astman_get_header(m, "Event");
8209  message = astman_get_header(m, "Message");
8210 
8211  if (ast_strlen_zero(queuename) || ast_strlen_zero(event)) {
8212  astman_send_error(s, m, "Need 'Queue' and 'Event' parameters.");
8213  return 0;
8214  }
8215 
8216  ast_queue_log(queuename, S_OR(uniqueid, "NONE"), interface, event, "%s", message);
8217  astman_send_ack(s, m, "Event added successfully");
8218 
8219  return 0;
8220 }
8221 
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2135
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:2130
static int manager_queue_member_penalty ( struct mansession s,
const struct message m 
)
static

Definition at line 8301 of file app_queue.c.

References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), and set_member_penalty().

Referenced by load_module().

8301 {
8302  const char *queuename, *interface, *penalty_s;
8303  int penalty;
8304 
8305  interface = astman_get_header(m, "Interface");
8306  penalty_s = astman_get_header(m, "Penalty");
8307  /* Optional - if not supplied, set the penalty value for the given Interface in all queues */
8308  queuename = astman_get_header(m, "Queue");
8309 
8310  if (ast_strlen_zero(interface) || ast_strlen_zero(penalty_s)) {
8311  astman_send_error(s, m, "Need 'Interface' and 'Penalty' parameters.");
8312  return 0;
8313  }
8314 
8315  penalty = atoi(penalty_s);
8316 
8317  if (set_member_penalty((char *)queuename, (char *)interface, penalty))
8318  astman_send_error(s, m, "Invalid interface, queuename or penalty");
8319  else
8320  astman_send_ack(s, m, "Interface penalty set successfully");
8321 
8322  return 0;
8323 }
8324 
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2135
static int set_member_penalty(const char *queuename, const char *interface, int penalty)
Definition: app_queue.c:5891
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:2130
static int manager_queue_reload ( struct mansession s,
const struct message m 
)
static

Definition at line 8223 of file app_queue.c.

References AST_FLAGS_ALL, ast_set_flag, astman_get_header(), astman_send_ack(), astman_send_error(), QUEUE_RELOAD_MEMBER, QUEUE_RELOAD_PARAMETERS, QUEUE_RELOAD_RULES, reload_handler(), and S_OR.

Referenced by load_module().

8223 {
8224  struct ast_flags mask = {0,};
8225  const char *queuename = NULL;
8226  int header_found = 0;
8227 
8228  queuename = astman_get_header(m, "Queue");
8229  if (!strcasecmp(S_OR(astman_get_header(m, "Members"), ""), "yes")) {
8231  header_found = 1;
8232  }
8233  if (!strcasecmp(S_OR(astman_get_header(m, "Rules"), ""), "yes")) {
8235  header_found = 1;
8236  }
8237  if (!strcasecmp(S_OR(astman_get_header(m, "Parameters"), ""), "yes")) {
8239  header_found = 1;
8240  }
8241 
8242  if (!header_found) {
8243  ast_set_flag(&mask, AST_FLAGS_ALL);
8244  }
8245 
8246  if (!reload_handler(1, &mask, queuename)) {
8247  astman_send_ack(s, m, "Queue reloaded successfully");
8248  } else {
8249  astman_send_error(s, m, "Error encountered while reloading queue");
8250  }
8251  return 0;
8252 }
8253 
#define ast_set_flag(p, flag)
Definition: utils.h:70
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2135
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
static int reload_handler(int reload, struct ast_flags *mask, const char *queuename)
The command center for all reload operations.
Definition: app_queue.c:7572
#define AST_FLAGS_ALL
Definition: utils.h:196
Structure used to handle boolean flags.
Definition: utils.h:200
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:2130
static int manager_queue_reset ( struct mansession s,
const struct message m 
)
static

Definition at line 8255 of file app_queue.c.

References astman_get_header(), astman_send_ack(), astman_send_error(), QUEUE_RESET_STATS, and reload_handler().

Referenced by load_module().

8255 {
8256  const char *queuename = NULL;
8257  struct ast_flags mask = {QUEUE_RESET_STATS,};
8258 
8259  queuename = astman_get_header(m, "Queue");
8260 
8261  if (!reload_handler(1, &mask, queuename)) {
8262  astman_send_ack(s, m, "Queue stats reset successfully");
8263  } else {
8264  astman_send_error(s, m, "Error encountered while resetting queue stats");
8265  }
8266  return 0;
8267 }
8268 
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2135
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
static int reload_handler(int reload, struct ast_flags *mask, const char *queuename)
The command center for all reload operations.
Definition: app_queue.c:7572
Structure used to handle boolean flags.
Definition: utils.h:200
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:2130
static int manager_queue_rule_show ( struct mansession s,
const struct message m 
)
static

Definition at line 7881 of file app_queue.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), astman_append(), astman_get_header(), penalty_rule::max_relative, penalty_rule::max_value, penalty_rule::min_relative, penalty_rule::min_value, rule_list::name, RESULT_SUCCESS, rule_list::rules, and penalty_rule::time.

Referenced by load_module().

7881 {
7882  const char *rule = astman_get_header(m, "Rule");
7883  const char *id = astman_get_header(m, "ActionID");
7884  struct rule_list *rl_iter;
7885  struct penalty_rule *pr_iter;
7886 
7887  astman_append(s, "Response: Success\r\n");
7888  if (!ast_strlen_zero(id)) {
7889  astman_append(s, "ActionID: %s\r\n", id);
7890  }
7891 
7893  AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
7894  if (ast_strlen_zero(rule) || !strcasecmp(rule, rl_iter->name)) {
7895  astman_append(s, "RuleList: %s\r\n", rl_iter->name);
7896  AST_LIST_TRAVERSE(&rl_iter->rules, pr_iter, list) {
7897  astman_append(s, "Rule: %d,%s%d,%s%d\r\n", pr_iter->time, pr_iter->max_relative && pr_iter->max_value >= 0 ? "+" : "", pr_iter->max_value, pr_iter->min_relative && pr_iter->min_value >= 0 ? "+" : "", pr_iter->min_value );
7898  }
7899  if (!ast_strlen_zero(rule))
7900  break;
7901  }
7902  }
7904 
7905  /*
7906  * Two blank lines instead of one because the Response and
7907  * ActionID headers used to not be present.
7908  */
7909  astman_append(s, "\r\n\r\n");
7910 
7911  return RESULT_SUCCESS;
7912 }
7913 
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:2068
int max_relative
Definition: app_queue.c:1216
struct rule_list::@58 rules
char name[80]
Definition: app_queue.c:1327
int min_relative
Definition: app_queue.c:1217
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct penalty_rule::@55 list
#define RESULT_SUCCESS
Definition: cli.h:39
static int manager_queues_show ( struct mansession s,
const struct message m 
)
static

Definition at line 7871 of file app_queue.c.

References __queues_show(), astman_append(), and RESULT_SUCCESS.

Referenced by load_module().

7871 {
7872  static const char * const a[] = { "queue", "show" };
7873 
7874  __queues_show(s, -1, 2, a);
7875  astman_append(s, "\r\n\r\n"); /* Properly terminate Manager output */
7876 
7877  return RESULT_SUCCESS;
7878 }
7879 
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:2068
static char * __queues_show(struct mansession *s, int fd, int argc, const char *const *argv)
Show queue(s) status and statistics.
Definition: app_queue.c:7603
#define RESULT_SUCCESS
Definition: cli.h:39
static int manager_queues_status ( struct mansession s,
const struct message m 
)
static

Queue status info via AMI.

Definition at line 7991 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_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), ast_channel::caller, member::calls, call_queue::callsabandoned, call_queue::callscompleted, call_queue::callscompletedinsl, queue_ent::chan, ast_channel::connected, call_queue::count, member::dynamic, call_queue::head, call_queue::holdtime, ast_party_caller::id, ast_party_connected_line::id, int2strat(), member::interface, member::lastcall, call_queue::maxlen, member::membername, call_queue::members, ast_party_id::name, ast_channel::name, call_queue::name, queue_ent::next, ast_party_id::number, member::paused, member::penalty, queue_ent::pos, queue_t_unref, queues, RESULT_SUCCESS, call_queue::ringlimit, S_COR, call_queue::servicelevel, queue_ent::start, member::status, ast_party_name::str, ast_party_number::str, call_queue::strategy, call_queue::talktime, ast_channel::uniqueid, ast_party_name::valid, ast_party_number::valid, and call_queue::weight.

Referenced by load_module().

7991 {
7992  time_t now;
7993  int pos;
7994  const char *id = astman_get_header(m,"ActionID");
7995  const char *queuefilter = astman_get_header(m,"Queue");
7996  const char *memberfilter = astman_get_header(m,"Member");
7997  char idText[256] = "";
7998  struct call_queue *q;
7999  struct queue_ent *qe;
8000  float sl = 0;
8001  struct member *mem;
8002  struct ao2_iterator queue_iter;
8003  struct ao2_iterator mem_iter;
8004 
8005  astman_send_ack(s, m, "Queue status will follow");
8006  time(&now);
8007  if (!ast_strlen_zero(id))
8008  snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
8009 
8010  queue_iter = ao2_iterator_init(queues, 0);
8011  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
8012  ao2_lock(q);
8013 
8014  /* List queue properties */
8015  if (ast_strlen_zero(queuefilter) || !strcmp(q->name, queuefilter)) {
8016  sl = ((q->callscompleted > 0) ? 100 * ((float)q->callscompletedinsl / (float)q->callscompleted) : 0);
8017  astman_append(s, "Event: QueueParams\r\n"
8018  "Queue: %s\r\n"
8019  "Max: %d\r\n"
8020  "Strategy: %s\r\n"
8021  "Calls: %d\r\n"
8022  "Holdtime: %d\r\n"
8023  "TalkTime: %d\r\n"
8024  "Completed: %d\r\n"
8025  "Abandoned: %d\r\n"
8026  "ServiceLevel: %d\r\n"
8027  "ServicelevelPerf: %2.1f\r\n"
8028  "RingLimit: %d\r\n"
8029  "Weight: %d\r\n"
8030  "%s"
8031  "\r\n",
8032  q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted,
8033  q->callsabandoned, q->servicelevel, sl, q->ringlimit, q->weight, idText);
8034  /* List Queue Members */
8035  mem_iter = ao2_iterator_init(q->members, 0);
8036  while ((mem = ao2_iterator_next(&mem_iter))) {
8037  if (ast_strlen_zero(memberfilter) || !strcmp(mem->interface, memberfilter) || !strcmp(mem->membername, memberfilter)) {
8038  astman_append(s, "Event: QueueMember\r\n"
8039  "Queue: %s\r\n"
8040  "Name: %s\r\n"
8041  "Location: %s\r\n"
8042  "Membership: %s\r\n"
8043  "Penalty: %d\r\n"
8044  "CallsTaken: %d\r\n"
8045  "LastCall: %d\r\n"
8046  "Status: %d\r\n"
8047  "Paused: %d\r\n"
8048  "%s"
8049  "\r\n",
8050  q->name, mem->membername, mem->interface, mem->dynamic ? "dynamic" : "static",
8051  mem->penalty, mem->calls, (int)mem->lastcall, mem->status, mem->paused, idText);
8052  }
8053  ao2_ref(mem, -1);
8054  }
8055  ao2_iterator_destroy(&mem_iter);
8056  /* List Queue Entries */
8057  pos = 1;
8058  for (qe = q->head; qe; qe = qe->next) {
8059  astman_append(s, "Event: QueueEntry\r\n"
8060  "Queue: %s\r\n"
8061  "Position: %d\r\n"
8062  "Channel: %s\r\n"
8063  "Uniqueid: %s\r\n"
8064  "CallerIDNum: %s\r\n"
8065  "CallerIDName: %s\r\n"
8066  "ConnectedLineNum: %s\r\n"
8067  "ConnectedLineName: %s\r\n"
8068  "Wait: %ld\r\n"
8069  "%s"
8070  "\r\n",
8071  q->name, pos++, qe->chan->name, qe->chan->uniqueid,
8072  S_COR(qe->chan->caller.id.number.valid, qe->chan->caller.id.number.str, "unknown"),
8073  S_COR(qe->chan->caller.id.name.valid, qe->chan->caller.id.name.str, "unknown"),
8074  S_COR(qe->chan->connected.id.number.valid, qe->chan->connected.id.number.str, "unknown"),
8075  S_COR(qe->chan->connected.id.name.valid, qe->chan->connected.id.name.str, "unknown"),
8076  (long) (now - qe->start), idText);
8077  }
8078  }
8079  ao2_unlock(q);
8080  queue_t_unref(q, "Done with iterator");
8081  }
8082  ao2_iterator_destroy(&queue_iter);
8083 
8084  astman_append(s,
8085  "Event: QueueStatusComplete\r\n"
8086  "%s"
8087  "\r\n",idText);
8088 
8089  return RESULT_SUCCESS;
8090 }
8091 
int servicelevel
Definition: app_queue.c:1299
int dynamic
Definition: app_queue.c:1182
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
struct ast_party_connected_line connected
Channel Connected Line ID information.
Definition: channel.h:811
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:2068
int paused
Definition: app_queue.c:1185
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
struct ast_channel * chan
Definition: app_queue.c:1168
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
const ast_string_field uniqueid
Definition: channel.h:787
struct ast_party_id id
Connected party ID.
Definition: channel.h:403
time_t start
Definition: app_queue.c:1165
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
#define ao2_t_iterator_next(arg1, arg2)
Definition: astobj2.h:1125
char * str
Subscriber name (Malloced)
Definition: channel.h:214
char interface[80]
Definition: app_queue.c:1175
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2135
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
int ringlimit
Definition: app_queue.c:1307
struct ao2_container * members
Definition: app_queue.c:1320
struct queue_ent * head
Definition: app_queue.c:1321
int callscompletedinsl
Definition: app_queue.c:1300
char membername[80]
Definition: app_queue.c:1179
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
int holdtime
Definition: app_queue.c:1295
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
static struct ao2_container * queues
Definition: app_queue.c:1334
int penalty
Definition: app_queue.c:1180
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
#define ao2_lock(a)
Definition: astobj2.h:488
int strategy
Definition: app_queue.c:1281
const ast_string_field name
Definition: app_queue.c:1266
const ast_string_field name
Definition: channel.h:787
int talktime
Definition: app_queue.c:1296
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
int calls
Definition: app_queue.c:1181
int status
Definition: app_queue.c:1184
int callsabandoned
Definition: app_queue.c:1298
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
struct queue_ent * next
Definition: app_queue.c:1171
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
#define RESULT_SUCCESS
Definition: cli.h:39
int callscompleted
Definition: app_queue.c:1297
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
time_t lastcall
Definition: app_queue.c:1187
static const char * int2strat(int strategy)
Definition: app_queue.c:1353
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int manager_queues_summary ( struct mansession s,
const struct message m 
)
static

Summary of queue info via the AMI.

Definition at line 7916 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_DEVICE_INVALID, AST_DEVICE_UNAVAILABLE, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), call_queue::head, call_queue::holdtime, member_status_available(), call_queue::members, call_queue::name, queue_ent::next, member::paused, queue_t_unref, queues, RESULT_SUCCESS, queue_ent::start, member::status, and call_queue::talktime.

Referenced by load_module().

7916 {
7917  time_t now;
7918  int qmemcount = 0;
7919  int qmemavail = 0;
7920  int qchancount = 0;
7921  int qlongestholdtime = 0;
7922  const char *id = astman_get_header(m, "ActionID");
7923  const char *queuefilter = astman_get_header(m, "Queue");
7924  char idText[256] = "";
7925  struct call_queue *q;
7926  struct queue_ent *qe;
7927  struct member *mem;
7928  struct ao2_iterator queue_iter;
7929  struct ao2_iterator mem_iter;
7930 
7931  astman_send_ack(s, m, "Queue summary will follow");
7932  time(&now);
7933  if (!ast_strlen_zero(id))
7934  snprintf(idText, 256, "ActionID: %s\r\n", id);
7935  queue_iter = ao2_iterator_init(queues, 0);
7936  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
7937  ao2_lock(q);
7938 
7939  /* List queue properties */
7940  if (ast_strlen_zero(queuefilter) || !strcmp(q->name, queuefilter)) {
7941  /* Reset the necessary local variables if no queuefilter is set*/
7942  qmemcount = 0;
7943  qmemavail = 0;
7944  qchancount = 0;
7945  qlongestholdtime = 0;
7946 
7947  /* List Queue Members */
7948  mem_iter = ao2_iterator_init(q->members, 0);
7949  while ((mem = ao2_iterator_next(&mem_iter))) {
7950  if ((mem->status != AST_DEVICE_UNAVAILABLE) && (mem->status != AST_DEVICE_INVALID)) {
7951  ++qmemcount;
7952  if (member_status_available(mem->status) && !mem->paused) {
7953  ++qmemavail;
7954  }
7955  }
7956  ao2_ref(mem, -1);
7957  }
7958  ao2_iterator_destroy(&mem_iter);
7959  for (qe = q->head; qe; qe = qe->next) {
7960  if ((now - qe->start) > qlongestholdtime) {
7961  qlongestholdtime = now - qe->start;
7962  }
7963  ++qchancount;
7964  }
7965  astman_append(s, "Event: QueueSummary\r\n"
7966  "Queue: %s\r\n"
7967  "LoggedIn: %d\r\n"
7968  "Available: %d\r\n"
7969  "Callers: %d\r\n"
7970  "HoldTime: %d\r\n"
7971  "TalkTime: %d\r\n"
7972  "LongestHoldTime: %d\r\n"
7973  "%s"
7974  "\r\n",
7975  q->name, qmemcount, qmemavail, qchancount, q->holdtime, q->talktime, qlongestholdtime, idText);
7976  }
7977  ao2_unlock(q);
7978  queue_t_unref(q, "Done with iterator");
7979  }
7980  ao2_iterator_destroy(&queue_iter);
7981  astman_append(s,
7982  "Event: QueueSummaryComplete\r\n"
7983  "%s"
7984  "\r\n", idText);
7985 
7986  return RESULT_SUCCESS;
7987 }
7988 
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:2068
int paused
Definition: app_queue.c:1185
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
time_t start
Definition: app_queue.c:1165
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
#define ao2_t_iterator_next(arg1, arg2)
Definition: astobj2.h:1125
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2135
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
struct ao2_container * members
Definition: app_queue.c:1320
struct queue_ent * head
Definition: app_queue.c:1321
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
static int member_status_available(int status)
Definition: app_queue.c:3251
int holdtime
Definition: app_queue.c:1295
static struct ao2_container * queues
Definition: app_queue.c:1334
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
const ast_string_field name
Definition: app_queue.c:1266
int talktime
Definition: app_queue.c:1296
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
int status
Definition: app_queue.c:1184
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
struct queue_ent * next
Definition: app_queue.c:1171
#define RESULT_SUCCESS
Definition: cli.h:39
static int manager_remove_queue_member ( struct mansession s,
const struct message m 
)
static

Definition at line 8144 of file app_queue.c.

References ast_queue_log(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), remove_from_queue(), RES_EXISTS, RES_NOSUCHQUEUE, RES_NOT_DYNAMIC, RES_OKAY, and RES_OUTOFMEMORY.

Referenced by load_module().

8144 {
8145  const char *queuename, *interface;
8146 
8147  queuename = astman_get_header(m, "Queue");
8148  interface = astman_get_header(m, "Interface");
8149 
8150  if (ast_strlen_zero(queuename) || ast_strlen_zero(interface)) {
8151  astman_send_error(s, m, "Need 'Queue' and 'Interface' parameters.");
8152  return 0;
8153  }
8154 
8155  switch (remove_from_queue(queuename, interface)) {
8156  case RES_OKAY:
8157  ast_queue_log(queuename, "MANAGER", interface, "REMOVEMEMBER", "%s", "");
8158  astman_send_ack(s, m, "Removed interface from queue");
8159  break;
8160  case RES_EXISTS:
8161  astman_send_error(s, m, "Unable to remove interface: Not there");
8162  break;
8163  case RES_NOSUCHQUEUE:
8164  astman_send_error(s, m, "Unable to remove interface from queue: No such queue");
8165  break;
8166  case RES_OUTOFMEMORY:
8167  astman_send_error(s, m, "Out of memory");
8168  break;
8169  case RES_NOT_DYNAMIC:
8170  astman_send_error(s, m, "Member not dynamic");
8171  break;
8172  }
8173 
8174  return 0;
8175 }
8176 
#define RES_OKAY
Definition: app_queue.c:1033
#define RES_NOT_DYNAMIC
Definition: app_queue.c:1037
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2135
#define RES_OUTOFMEMORY
Definition: app_queue.c:1035
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define RES_NOSUCHQUEUE
Definition: app_queue.c:1036
#define RES_EXISTS
Definition: app_queue.c:1034
static int remove_from_queue(const char *queuename, const char *interface)
Remove member from queue.
Definition: app_queue.c:5715
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:2130
static int mark_dead_and_unfound ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 7443 of file app_queue.c.

References ast_strlen_zero(), call_queue::dead, call_queue::found, call_queue::name, and call_queue::realtime.

Referenced by reload_queues().

7443 {
7444  struct call_queue *q = obj;
7445  char *queuename = arg;
7446  if (!q->realtime && (ast_strlen_zero(queuename) || !strcasecmp(queuename, q->name))) {
7447  q->dead = 1;
7448  q->found = 0;
7449  }
7450  return 0;
7451 }
7452 
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
unsigned int dead
Definition: app_queue.c:1269
const ast_string_field name
Definition: app_queue.c:1266
unsigned int found
Definition: app_queue.c:1284
unsigned int realtime
Definition: app_queue.c:1283
static int mark_member_dead ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 7301 of file app_queue.c.

References member::delme, member::dynamic, and member::realtime.

Referenced by reload_single_queue().

7301 {
7302  struct member *member = obj;
7303  if (!member->dynamic && !member->realtime) {
7304  member->delme = 1;
7305  }
7306  return 0;
7307 }
7308 
int dynamic
Definition: app_queue.c:1182
int realtime
Definition: app_queue.c:1183
unsigned int delme
Definition: app_queue.c:1191
static void member_add_to_queue ( struct call_queue queue,
struct member mem 
)
static

Definition at line 2300 of file app_queue.c.

References ao2_container_count(), ao2_link, ao2_lock, ao2_unlock, call_queue::members, and member::queuepos.

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

2300 {
2301  ao2_lock(queue->members);
2302  mem->queuepos = ao2_container_count(queue->members);
2303  ao2_link(queue->members, mem);
2304  ao2_unlock(queue->members);
2305 }
2306 
int queuepos
Definition: app_queue.c:1186
#define ao2_link(arg1, arg2)
Definition: astobj2.h:785
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
Definition: astobj2.c:470
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_container * members
Definition: app_queue.c:1320
#define ao2_lock(a)
Definition: astobj2.h:488
static void member_call_pending_clear ( struct member mem)
static

Definition at line 3264 of file app_queue.c.

References ao2_lock, ao2_unlock, and member::call_pending.

Referenced by can_ring_entry(), and ring_entry().

3264 {
3265  ao2_lock(mem);
3266  mem->call_pending = 0;
3267  ao2_unlock(mem);
3268 }
3269 
#define ao2_unlock(a)
Definition: astobj2.h:497
#define ao2_lock(a)
Definition: astobj2.h:488
unsigned int call_pending
Definition: app_queue.c:1192
static int member_call_pending_set ( struct member mem)
static

Definition at line 3279 of file app_queue.c.

References ao2_lock, ao2_unlock, and member::call_pending.

Referenced by can_ring_entry().

3279 {
3280  int old_pending;
3281 
3282  ao2_lock(mem);
3283  old_pending = mem->call_pending;
3284  mem->call_pending = 1;
3285  ao2_unlock(mem);
3286 
3287  return old_pending;
3288 }
3289 
#define ao2_unlock(a)
Definition: astobj2.h:497
#define ao2_lock(a)
Definition: astobj2.h:488
unsigned int call_pending
Definition: app_queue.c:1192
static int member_cmp_fn ( void *  obj1,
void *  obj2,
int  flags 
)
static

Definition at line 1855 of file app_queue.c.

References CMP_MATCH, CMP_STOP, and member::interface.

Referenced by init_queue().

1855 {
1856  struct member *mem1 = obj1, *mem2 = obj2;
1857  return strcasecmp(mem1->interface, mem2->interface) ? 0 : CMP_MATCH | CMP_STOP;
1858 }
1859 
char interface[80]
Definition: app_queue.c:1175
static int member_hash_fn ( const void *  obj,
const int  flags 
)
static

Definition at line 1843 of file app_queue.c.

References compress_char(), and member::interface.

Referenced by init_queue().

1843 {
1844  const struct member *mem = obj;
1845  const char *chname = strchr(mem->interface, '/');
1846  int ret = 0, i;
1847  if (!chname)
1848  chname = mem->interface;
1849  for (i = 0; i < 5 && chname[i]; i++)
1850  ret += compress_char(chname[i]) << (i * 6);
1851  return ret;
1852 }
1853 
char interface[80]
Definition: app_queue.c:1175
static int compress_char(const char c)
Definition: app_queue.c:1833
static void member_remove_from_queue ( struct call_queue queue,
struct member mem 
)
static

Definition at line 2314 of file app_queue.c.

References ao2_lock, ao2_unlink, ao2_unlock, call_queue::members, and queue_member_follower_removal().

Referenced by find_queue_by_name_rt(), free_members(), remove_from_queue(), and update_realtime_members().

2314 {
2315  ao2_lock(queue->members);
2316  queue_member_follower_removal(queue, mem);
2317  ao2_unlink(queue->members, mem);
2318  ao2_unlock(queue->members);
2319 }
2320 
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_container * members
Definition: app_queue.c:1320
#define ao2_lock(a)
Definition: astobj2.h:488
static void queue_member_follower_removal(struct call_queue *queue, struct member *mem)
Definition: app_queue.c:1451
#define ao2_unlink(arg1, arg2)
Definition: astobj2.h:817
static int member_status_available ( int  status)
static

Definition at line 3251 of file app_queue.c.

References AST_DEVICE_NOT_INUSE, and AST_DEVICE_UNKNOWN.

Referenced by can_ring_entry(), and manager_queues_summary().

3251 {
3253 }
3254 
jack_status_t status
Definition: app_jack.c:143
static int num_available_members ( struct call_queue q)
static

Get the number of members available to accept a call.

Note
The queue passed in should be locked prior to this function call
Parameters
[in]qThe queue for which we are couting the number of available members
Returns
Return the number of available members in queue q

Definition at line 3117 of file app_queue.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_UNKNOWN, call_queue::autofill, call_queue::members, member::paused, QUEUE_STRATEGY_RINGALL, call_queue::ringinuse, member::status, and call_queue::strategy.

Referenced by compare_weight(), and is_our_turn().

3117 {
3118  struct member *mem;
3119  int avl = 0;
3120  struct ao2_iterator mem_iter;
3121 
3122  mem_iter = ao2_iterator_init(q->members, 0);
3123  while ((mem = ao2_iterator_next(&mem_iter))) {
3124  switch (mem->status) {
3125  case AST_DEVICE_INUSE:
3126  if (!q->ringinuse)
3127  break;
3128  /* else fall through */
3129  case AST_DEVICE_NOT_INUSE:
3130  case AST_DEVICE_ONHOLD:
3131  case AST_DEVICE_RINGINUSE:
3132  case AST_DEVICE_RINGING:
3133  case AST_DEVICE_UNKNOWN:
3134  if (!mem->paused) {
3135  avl++;
3136  }
3137  break;
3138  }
3139  ao2_ref(mem, -1);
3140 
3141  /* If autofill is not enabled or if the queue's strategy is ringall, then
3142  * we really don't care about the number of available members so much as we
3143  * do that there is at least one available.
3144  *
3145  * In fact, we purposely will return from this function stating that only
3146  * one member is available if either of those conditions hold. That way,
3147  * functions which determine what action to take based on the number of available
3148  * members will operate properly. The reasoning is that even if multiple
3149  * members are available, only the head caller can actually be serviced.
3150  */
3151  if ((!q->autofill || q->strategy == QUEUE_STRATEGY_RINGALL) && avl) {
3152  break;
3153  }
3154  }
3155  ao2_iterator_destroy(&mem_iter);
3156 
3157  return avl;
3158 }
3159 
int paused
Definition: app_queue.c:1185
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
unsigned int ringinuse
Definition: app_queue.c:1271
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
struct ao2_container * members
Definition: app_queue.c:1320
#define ao2_ref(o, delta)
Definition: astobj2.h:472
int strategy
Definition: app_queue.c:1281
int autofill
Definition: app_queue.c:1318
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
int status
Definition: app_queue.c:1184
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
static void parse_empty_options ( const char *  value,
enum empty_conditions empty,
int  joinempty 
)
static

Definition at line 2050 of file app_queue.c.

References ast_false(), ast_log(), ast_strdupa, ast_true(), LOG_WARNING, QUEUE_EMPTY_INUSE, QUEUE_EMPTY_INVALID, QUEUE_EMPTY_PAUSED, QUEUE_EMPTY_PENALTY, QUEUE_EMPTY_RINGING, QUEUE_EMPTY_UNAVAILABLE, QUEUE_EMPTY_UNKNOWN, QUEUE_EMPTY_WRAPUP, and strsep().

Referenced by queue_set_param().

2050 {
2051  char *value_copy = ast_strdupa(value);
2052  char *option = NULL;
2053  while ((option = strsep(&value_copy, ","))) {
2054  if (!strcasecmp(option, "paused")) {
2055  *empty |= QUEUE_EMPTY_PAUSED;
2056  } else if (!strcasecmp(option, "penalty")) {
2057  *empty |= QUEUE_EMPTY_PENALTY;
2058  } else if (!strcasecmp(option, "inuse")) {
2059  *empty |= QUEUE_EMPTY_INUSE;
2060  } else if (!strcasecmp(option, "ringing")) {
2061  *empty |= QUEUE_EMPTY_RINGING;
2062  } else if (!strcasecmp(option, "invalid")) {
2063  *empty |= QUEUE_EMPTY_INVALID;
2064  } else if (!strcasecmp(option, "wrapup")) {
2065  *empty |= QUEUE_EMPTY_WRAPUP;
2066  } else if (!strcasecmp(option, "unavailable")) {
2067  *empty |= QUEUE_EMPTY_UNAVAILABLE;
2068  } else if (!strcasecmp(option, "unknown")) {
2069  *empty |= QUEUE_EMPTY_UNKNOWN;
2070  } else if (!strcasecmp(option, "loose")) {
2072  } else if (!strcasecmp(option, "strict")) {
2074  } else if ((ast_false(option) && joinempty) || (ast_true(option) && !joinempty)) {
2076  } else if ((ast_false(option) && !joinempty) || (ast_true(option) && joinempty)) {
2077  *empty = 0;
2078  } else {
2079  ast_log(LOG_WARNING, "Unknown option %s for '%s'\n", option, joinempty ? "joinempty" : "leavewhenempty");
2080  }
2081  }
2082 }
2083 
char * strsep(char **str, const char *delims)
#define LOG_WARNING
Definition: logger.h:144
int value
Definition: syslog.c:39
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is &quot;false&quot;...
Definition: utils.c:1550
static int play_file ( struct ast_channel chan,
const char *  filename 
)
static

Definition at line 2787 of file app_queue.c.

References AST_DIGIT_ANY, ast_fileexists(), ast_stopstream(), ast_streamfile(), ast_strlen_zero(), ast_waitstream(), and ast_channel::language.

Referenced by say_periodic_announcement(), say_position(), and try_calling().

2787 {
2788  int res;
2789 
2790  if (ast_strlen_zero(filename)) {
2791  return 0;
2792  }
2793 
2794  if (!ast_fileexists(filename, NULL, chan->language)) {
2795  return 0;
2796  }
2797 
2798  ast_stopstream(chan);
2799 
2800  res = ast_streamfile(chan, filename, chan->language);
2801  if (!res)
2802  res = ast_waitstream(chan, AST_DIGIT_ANY);
2803 
2804  ast_stopstream(chan);
2805 
2806  return res;
2807 }
2808 
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:946
#define AST_DIGIT_ANY
Definition: file.h:47
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1343
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:919
const ast_string_field language
Definition: channel.h:787
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:128
static int pqm_exec ( struct ast_channel chan,
const char *  data 
)
static

PauseQueueMember application.

Definition at line 6067 of file app_queue.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), LOG_WARNING, parse(), pbx_builtin_setvar_helper(), and set_member_paused().

Referenced by load_module().

6067 {
6068  char *parse;
6070  AST_APP_ARG(queuename);
6071  AST_APP_ARG(interface);
6072  AST_APP_ARG(options);
6073  AST_APP_ARG(reason);
6074  );
6075 
6076  if (ast_strlen_zero(data)) {
6077  ast_log(LOG_WARNING, "PauseQueueMember requires an argument ([queuename],interface[,options][,reason])\n");
6078  return -1;
6079  }
6080 
6081  parse = ast_strdupa(data);
6082 
6083  AST_STANDARD_APP_ARGS(args, parse);
6084 
6085  if (ast_strlen_zero(args.interface)) {
6086  ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename],interface[,options[,reason]])\n");
6087  return -1;
6088  }
6089 
6090  if (set_member_paused(args.queuename, args.interface, args.reason, 1)) {
6091  ast_log(LOG_WARNING, "Attempt to pause interface %s, not found\n", args.interface);
6092  pbx_builtin_setvar_helper(chan, "PQMSTATUS", "NOTFOUND");
6093  return 0;
6094  }
6095 
6096  pbx_builtin_setvar_helper(chan, "PQMSTATUS", "PAUSED");
6097 
6098  return 0;
6099 }
6100 
#define LOG_WARNING
Definition: logger.h:144
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static struct @350 args
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused)
Definition: app_queue.c:5814
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
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...
Definition: pbx.c:10546
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static int ql_exec ( struct ast_channel chan,
const char *  data 
)
static

QueueLog application.

Definition at line 6258 of file app_queue.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_queue_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), LOG_WARNING, and parse().

Referenced by load_module().

6258 {
6259  char *parse;
6260 
6262  AST_APP_ARG(queuename);
6263  AST_APP_ARG(uniqueid);
6264  AST_APP_ARG(membername);
6265  AST_APP_ARG(event);
6266  AST_APP_ARG(params);
6267  );
6268 
6269  if (ast_strlen_zero(data)) {
6270  ast_log(LOG_WARNING, "QueueLog requires arguments (queuename,uniqueid,membername,event[,additionalinfo]\n");
6271  return -1;
6272  }
6273 
6274  parse = ast_strdupa(data);
6275 
6276  AST_STANDARD_APP_ARGS(args, parse);
6277 
6278  if (ast_strlen_zero(args.queuename) || ast_strlen_zero(args.uniqueid)
6279  || ast_strlen_zero(args.membername) || ast_strlen_zero(args.event)) {
6280  ast_log(LOG_WARNING, "QueueLog requires arguments (queuename,uniqueid,membername,event[,additionalinfo])\n");
6281  return -1;
6282  }
6283 
6284  ast_queue_log(args.queuename, args.uniqueid, args.membername, args.event,
6285  "%s", args.params ? args.params : "");
6286 
6287  return 0;
6288 }
6289 
#define LOG_WARNING
Definition: logger.h:144
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static struct @350 args
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static int queue_cmp_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 1404 of file app_queue.c.

References CMP_MATCH, CMP_STOP, and call_queue::name.

Referenced by load_module().

1404 {
1405  struct call_queue *q = obj, *q2 = arg;
1406  return !strcasecmp(q->name, q2->name) ? CMP_MATCH | CMP_STOP : 0;
1407 }
1408 
const ast_string_field name
Definition: app_queue.c:1266
static int queue_delme_members_decrement_followers ( void *  obj,
void *  arg,
int  flag 
)
static

Definition at line 1433 of file app_queue.c.

References ao2_callback, member::delme, call_queue::members, OBJ_MULTIPLE, OBJ_NODATA, queue_member_decrement_followers(), member::queuepos, and call_queue::rrpos.

Referenced by reload_single_queue().

1433 {
1434  struct member *mem = obj;
1435  struct call_queue *queue = arg;
1436  int rrpos = mem->queuepos;
1437 
1438  if (mem->delme) {
1440  }
1441 
1442  return 0;
1443 }
1444 
int queuepos
Definition: app_queue.c:1186
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:910
unsigned int delme
Definition: app_queue.c:1191
struct ao2_container * members
Definition: app_queue.c:1320
static int queue_member_decrement_followers(void *obj, void *arg, int flag)
Definition: app_queue.c:1415
static int queue_exec ( struct ast_channel chan,
const char *  data 
)
static

The starting point for all queue calls.

The process involved here is to

  1. Parse the options specified in the call to Queue()
  2. Join the queue
  3. Wait in a loop until it is our turn to try calling a queue member
  4. Attempt to call a queue member
  5. If 4. did not result in a bridged call, then check for between call options such as periodic announcements etc.
  6. Try 4 again unless some condition (such as an expiration time) causes us to exit the queue.

Definition at line 6332 of file app_queue.c.

References call_queue::announcefrequency, ao2_container_count(), args, AST_APP_ARG, ast_assert, ast_channel_lock, ast_channel_unlock, AST_CONTROL_RINGING, ast_debug, AST_DECLARE_APP_ARGS, ast_indicate(), AST_LIST_FIRST, ast_log(), ast_moh_start(), ast_moh_stop(), ast_queue_log(), AST_STANDARD_APP_ARGS, ast_stopstream(), ast_strdupa, ast_strlen_zero(), ast_verb, ast_channel::caller, queue_ent::chan, copy_rules(), queue_ent::digits, queue_ent::expire, get_member_status(), queue_ent::handled, ast_party_caller::id, is_our_turn(), join_queue(), queue_ent::last_periodic_announce_sound, queue_ent::last_periodic_announce_time, queue_ent::last_pos, queue_ent::last_pos_said, leave_queue(), call_queue::leavewhenempty, LOG_WARNING, queue_ent::max_penalty, call_queue::members, queue_ent::min_penalty, queue_ent::moh, ast_channel::name, call_queue::name, ast_party_id::number, queue_ent::opos, queue_ent::parent, parse(), pbx_builtin_getvar_helper(), call_queue::periodicannouncefrequency, queue_ent::pos, queue_ent::pr, queue_ent::prio, queue_ent::qe_rules, QUEUE_CONTINUE, QUEUE_LEAVEEMPTY, QUEUE_TIMEOUT, QUEUE_UNKNOWN, queue_unref(), record_abandoned(), queue_ent::ring_when_ringing, S_COR, S_OR, say_periodic_announcement(), say_position(), set_queue_result(), set_queue_variables(), queue_ent::start, status, stop, ast_party_number::str, penalty_rule::time, queue_ent::tries, try_calling(), ast_channel::uniqueid, update_qe_rule(), update_realtime_members(), url, ast_party_number::valid, queue_ent::valid_digits, wait_a_bit(), and wait_our_turn().

Referenced by load_module().

6332 {
6333  int res=-1;
6334  int ringing=0;
6335  const char *user_priority;
6336  const char *max_penalty_str;
6337  const char *min_penalty_str;
6338  int prio;
6339  int qcontinue = 0;
6340  int max_penalty, min_penalty;
6341  enum queue_result reason = QUEUE_UNKNOWN;
6342  /* whether to exit Queue application after the timeout hits */
6343  int tries = 0;
6344  int noption = 0;
6345  char *parse;
6346  int makeannouncement = 0;
6347  int position = 0;
6349  AST_APP_ARG(queuename);
6350  AST_APP_ARG(options);
6351  AST_APP_ARG(url);
6352  AST_APP_ARG(announceoverride);
6353  AST_APP_ARG(queuetimeoutstr);
6354  AST_APP_ARG(agi);
6355  AST_APP_ARG(macro);
6356  AST_APP_ARG(gosub);
6357  AST_APP_ARG(rule);
6358  AST_APP_ARG(position);
6359  );
6360  /* Our queue entry */
6361  struct queue_ent qe = { 0 };
6362 
6363  if (ast_strlen_zero(data)) {
6364  ast_log(LOG_WARNING, "Queue requires an argument: queuename[,options[,URL[,announceoverride[,timeout[,agi[,macro[,gosub[,rule[,position]]]]]]]]]\n");
6365  return -1;
6366  }
6367 
6368  parse = ast_strdupa(data);
6369  AST_STANDARD_APP_ARGS(args, parse);
6370 
6371  /* Setup our queue entry */
6372  qe.start = time(NULL);
6373 
6374  /* set the expire time based on the supplied timeout; */
6375  if (!ast_strlen_zero(args.queuetimeoutstr))
6376  qe.expire = qe.start + atoi(args.queuetimeoutstr);
6377  else
6378  qe.expire = 0;
6379 
6380  /* Get the priority from the variable ${QUEUE_PRIO} */
6381  ast_channel_lock(chan);
6382  user_priority = pbx_builtin_getvar_helper(chan, "QUEUE_PRIO");
6383  if (user_priority) {
6384  if (sscanf(user_priority, "%30d", &prio) == 1) {
6385  ast_debug(1, "%s: Got priority %d from ${QUEUE_PRIO}.\n", chan->name, prio);
6386  } else {
6387  ast_log(LOG_WARNING, "${QUEUE_PRIO}: Invalid value (%s), channel %s.\n",
6388  user_priority, chan->name);
6389  prio = 0;
6390  }
6391  } else {
6392  ast_debug(3, "NO QUEUE_PRIO variable found. Using default.\n");
6393  prio = 0;
6394  }
6395 
6396  /* Get the maximum penalty from the variable ${QUEUE_MAX_PENALTY} */
6397 
6398  if ((max_penalty_str = pbx_builtin_getvar_helper(chan, "QUEUE_MAX_PENALTY"))) {
6399  if (sscanf(max_penalty_str, "%30d", &max_penalty) == 1) {
6400  ast_debug(1, "%s: Got max penalty %d from ${QUEUE_MAX_PENALTY}.\n", chan->name, max_penalty);
6401  } else {
6402  ast_log(LOG_WARNING, "${QUEUE_MAX_PENALTY}: Invalid value (%s), channel %s.\n",
6403  max_penalty_str, chan->name);
6404  max_penalty = INT_MAX;
6405  }
6406  } else {
6407  max_penalty = INT_MAX;
6408  }
6409 
6410  if ((min_penalty_str = pbx_builtin_getvar_helper(chan, "QUEUE_MIN_PENALTY"))) {
6411  if (sscanf(min_penalty_str, "%30d", &min_penalty) == 1) {
6412  ast_debug(1, "%s: Got min penalty %d from ${QUEUE_MIN_PENALTY}.\n", chan->name, min_penalty);
6413  } else {
6414  ast_log(LOG_WARNING, "${QUEUE_MIN_PENALTY}: Invalid value (%s), channel %s.\n",
6415  min_penalty_str, chan->name);
6416  min_penalty = INT_MAX;
6417  }
6418  } else {
6419  min_penalty = INT_MAX;
6420  }
6421  ast_channel_unlock(chan);
6422 
6423  if (args.options && (strchr(args.options, 'r')))
6424  ringing = 1;
6425 
6426  if (ringing != 1 && args.options && (strchr(args.options, 'R'))) {
6427  qe.ring_when_ringing = 1;
6428  }
6429 
6430  if (args.options && (strchr(args.options, 'c')))
6431  qcontinue = 1;
6432 
6433  if (args.position) {
6434  position = atoi(args.position);
6435  if (position < 0) {
6436  ast_log(LOG_WARNING, "Invalid position '%s' given for call to queue '%s'. Assuming no preference for position\n", args.position, args.queuename);
6437  position = 0;
6438  }
6439  }
6440 
6441  ast_debug(1, "queue: %s, options: %s, url: %s, announce: %s, expires: %ld, priority: %d\n",
6442  args.queuename, args.options, args.url, args.announceoverride, (long)qe.expire, prio);
6443 
6444  qe.chan = chan;
6445  qe.prio = prio;
6446  qe.max_penalty = max_penalty;
6447  qe.min_penalty = min_penalty;
6448  qe.last_pos_said = 0;
6449  qe.last_pos = 0;
6450  qe.last_periodic_announce_time = time(NULL);
6452  qe.valid_digits = 0;
6453  if (join_queue(args.queuename, &qe, &reason, position)) {
6454  ast_log(LOG_WARNING, "Unable to join queue '%s'\n", args.queuename);
6455  set_queue_result(chan, reason);
6456  return 0;
6457  }
6458  ast_assert(qe.parent != NULL);
6459 
6460  ast_queue_log(args.queuename, chan->uniqueid, "NONE", "ENTERQUEUE", "%s|%s|%d",
6461  S_OR(args.url, ""),
6462  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""),
6463  qe.opos);
6464  copy_rules(&qe, args.rule);
6465  qe.pr = AST_LIST_FIRST(&qe.qe_rules);
6466 check_turns:
6467  if (ringing) {
6469  } else {
6470  ast_moh_start(chan, qe.moh, NULL);
6471  }
6472 
6473  /* This is the wait loop for callers 2 through maxlen */
6474  res = wait_our_turn(&qe, ringing, &reason);
6475  if (res) {
6476  goto stop;
6477  }
6478 
6479  makeannouncement = 0;
6480 
6481  for (;;) {
6482  /* This is the wait loop for the head caller*/
6483  /* To exit, they may get their call answered; */
6484  /* they may dial a digit from the queue context; */
6485  /* or, they may timeout. */
6486 
6487  /* Leave if we have exceeded our queuetimeout */
6488  if (qe.expire && (time(NULL) >= qe.expire)) {
6489  record_abandoned(&qe);
6490  reason = QUEUE_TIMEOUT;
6491  res = 0;
6492  ast_queue_log(args.queuename, chan->uniqueid,"NONE", "EXITWITHTIMEOUT", "%d|%d|%ld",
6493  qe.pos, qe.opos, (long) time(NULL) - qe.start);
6494  break;
6495  }
6496 
6497  if (makeannouncement) {
6498  /* Make a position announcement, if enabled */
6499  if (qe.parent->announcefrequency)
6500  if ((res = say_position(&qe,ringing)))
6501  goto stop;
6502  }
6503  makeannouncement = 1;
6504 
6505  /* Make a periodic announcement, if enabled */
6507  if ((res = say_periodic_announcement(&qe,ringing)))
6508  goto stop;
6509 
6510  /* Leave if we have exceeded our queuetimeout */
6511  if (qe.expire && (time(NULL) >= qe.expire)) {
6512  record_abandoned(&qe);
6513  reason = QUEUE_TIMEOUT;
6514  res = 0;
6515  ast_queue_log(args.queuename, chan->uniqueid, "NONE", "EXITWITHTIMEOUT", "%d", qe.pos);
6516  break;
6517  }
6518 
6519  /* see if we need to move to the next penalty level for this queue */
6520  while (qe.pr && ((time(NULL) - qe.start) > qe.pr->time)) {
6521  update_qe_rule(&qe);
6522  }
6523 
6524  /* Try calling all queue members for 'timeout' seconds */
6525  res = try_calling(&qe, args.options, args.announceoverride, args.url, &tries, &noption, args.agi, args.macro, args.gosub, ringing);
6526  if (res) {
6527  goto stop;
6528  }
6529 
6530  if (qe.parent->leavewhenempty) {
6531  int status = 0;
6532  if ((status = get_member_status(qe.parent, qe.max_penalty, qe.min_penalty, qe.parent->leavewhenempty, 0))) {
6533  record_abandoned(&qe);
6534  reason = QUEUE_LEAVEEMPTY;
6535  ast_queue_log(args.queuename, chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe.pos, qe.opos, (long)(time(NULL) - qe.start));
6536  res = 0;
6537  break;
6538  }
6539  }
6540 
6541  /* exit after 'timeout' cycle if 'n' option enabled */
6542  if (noption && tries >= ao2_container_count(qe.parent->members)) {
6543  ast_verb(3, "Exiting on time-out cycle\n");
6544  ast_queue_log(args.queuename, chan->uniqueid, "NONE", "EXITWITHTIMEOUT", "%d", qe.pos);
6545  record_abandoned(&qe);
6546  reason = QUEUE_TIMEOUT;
6547  res = 0;
6548  break;
6549  }
6550 
6551 
6552  /* Leave if we have exceeded our queuetimeout */
6553  if (qe.expire && (time(NULL) >= qe.expire)) {
6554  record_abandoned(&qe);
6555  reason = QUEUE_TIMEOUT;
6556  res = 0;
6557  ast_queue_log(qe.parent->name, qe.chan->uniqueid,"NONE", "EXITWITHTIMEOUT", "%d|%d|%ld", qe.pos, qe.opos, (long) time(NULL) - qe.start);
6558  break;
6559  }
6560 
6561  /* If using dynamic realtime members, we should regenerate the member list for this queue */
6563  /* OK, we didn't get anybody; wait for 'retry' seconds; may get a digit to exit with */
6564  res = wait_a_bit(&qe);
6565  if (res)
6566  goto stop;
6567 
6568  /* Since this is a priority queue and
6569  * it is not sure that we are still at the head
6570  * of the queue, go and check for our turn again.
6571  */
6572  if (!is_our_turn(&qe)) {
6573  ast_debug(1, "Darn priorities, going back in queue (%s)!\n", qe.chan->name);
6574  goto check_turns;
6575  }
6576  }
6577 
6578 stop:
6579  if (res) {
6580  if (res < 0) {
6581  if (!qe.handled) {
6582  record_abandoned(&qe);
6583  ast_queue_log(args.queuename, chan->uniqueid, "NONE", "ABANDON",
6584  "%d|%d|%ld", qe.pos, qe.opos,
6585  (long) time(NULL) - qe.start);
6586  res = -1;
6587  } else if (qcontinue) {
6588  reason = QUEUE_CONTINUE;
6589  res = 0;
6590  }
6591  } else if (qe.valid_digits) {
6592  ast_queue_log(args.queuename, chan->uniqueid, "NONE", "EXITWITHKEY",
6593  "%s|%d|%d|%ld", qe.digits, qe.pos, qe.opos, (long) time(NULL) - qe.start);
6594  }
6595  }
6596 
6597  /* Don't allow return code > 0 */
6598  if (res >= 0) {
6599  res = 0;
6600  if (ringing) {
6601  ast_indicate(chan, -1);
6602  } else {
6603  ast_moh_stop(chan);
6604  }
6605  ast_stopstream(chan);
6606  }
6607 
6609 
6610  leave_queue(&qe);
6611  if (reason != QUEUE_UNKNOWN)
6612  set_queue_result(chan, reason);
6613 
6614  /*
6615  * every queue_ent is given a reference to it's parent
6616  * call_queue when it joins the queue. This ref must be taken
6617  * away right before the queue_ent is destroyed. In this case
6618  * the queue_ent is about to be returned on the stack
6619  */
6620  qe.parent = queue_unref(qe.parent);
6621 
6622  return res;
6623 }
6624 
static int say_position(struct queue_ent *qe, int ringing)
Definition: app_queue.c:2849
struct call_queue * parent
Definition: app_queue.c:1144
char moh[80]
Definition: app_queue.c:1145
#define ast_channel_lock(chan)
Definition: channel.h:2466
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
Definition: astobj2.c:470
char digits[AST_MAX_EXTENSION]
Definition: app_queue.c:1148
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
struct ast_channel * chan
Definition: app_queue.c:1168
static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, enum empty_conditions conditions, int devstate)
Check if members are available.
Definition: app_queue.c:1545
int min_penalty
Definition: app_queue.c:1162
const ast_string_field uniqueid
Definition: channel.h:787
int max_penalty
Definition: app_queue.c:1161
int last_periodic_announce_sound
Definition: app_queue.c:1155
time_t start
Definition: app_queue.c:1165
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
static void update_realtime_members(struct call_queue *q)
Definition: app_queue.c:2642
int last_pos_said
Definition: app_queue.c:1152
#define LOG_WARNING
Definition: logger.h:144
time_t expire
Definition: app_queue.c:1166
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
unsigned int stop
Definition: app_meetme.c:969
queue_result
Definition: app_queue.c:1078
#define ast_assert(a)
Definition: utils.h:738
static void set_queue_result(struct ast_channel *chan, enum queue_result res)
sets the QUEUESTATUS channel variable
Definition: app_queue.c:1341
static int say_periodic_announcement(struct queue_ent *qe, int ringing)
Playback announcement to queued members if period has elapsed.
Definition: app_queue.c:3650
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:8051
struct ao2_container * members
Definition: app_queue.c:1320
#define ast_verb(level,...)
Definition: logger.h:243
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
static int wait_a_bit(struct queue_ent *qe)
Definition: app_queue.c:5625
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int periodicannouncefrequency
Definition: app_queue.c:1291
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int ring_when_ringing
Definition: app_queue.c:1153
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
int valid_digits
Definition: app_queue.c:1149
static void leave_queue(struct queue_ent *qe)
Caller leaving queue.
Definition: app_queue.c:3012
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason, int position)
Definition: app_queue.c:2700
static struct @350 args
const ast_string_field name
Definition: app_queue.c:1266
const ast_string_field name
Definition: channel.h:787
static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing)
A large function which calls members, updates statistics, and bridges the caller and a member...
Definition: app_queue.c:4823
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:8040
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
time_t last_pos
Definition: app_queue.c:1156
static struct call_queue * queue_unref(struct call_queue *q)
Definition: app_queue.c:1482
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
struct penalty_rule * pr
Definition: app_queue.c:1170
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.
Definition: app_queue.c:4430
static void record_abandoned(struct queue_ent *qe)
Record that a caller gave up on waiting in queue.
Definition: app_queue.c:3706
time_t last_periodic_announce_time
Definition: app_queue.c:1154
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
Set variables of queue.
Definition: app_queue.c:1490
enum empty_conditions leavewhenempty
Definition: app_queue.c:1287
struct queue_ent::@54 qe_rules
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
int handled
Definition: app_queue.c:1158
static void copy_rules(struct queue_ent *qe, const char *rulename)
Copy rule from global list into specified queue.
Definition: app_queue.c:6292
static char url[512]
static void update_qe_rule(struct queue_ent *qe)
update rules for queues
Definition: app_queue.c:4367
static int is_our_turn(struct queue_ent *qe)
Check if we should start attempting to call queue members.
Definition: app_queue.c:4324
int announcefrequency
Definition: app_queue.c:1289
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:128
jack_status_t status
Definition: app_jack.c:143
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int queue_function_exists ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Check if a given queue exists.

Definition at line 6678 of file app_queue.c.

References ast_log(), ast_strlen_zero(), load_realtime_queue(), LOG_ERROR, and queue_t_unref.

6678 {
6679  struct call_queue *q;
6680 
6681  buf[0] = '\0';
6682 
6683  if (ast_strlen_zero(data)) {
6684  ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
6685  return -1;
6686  }
6687  q = load_realtime_queue(data);
6688  snprintf(buf, len, "%d", q != NULL? 1 : 0);
6689  if (q) {
6690  queue_t_unref(q, "Done with temporary reference in QUEUE_EXISTS()");
6691  }
6692 
6693  return 0;
6694 }
6695 
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define LOG_ERROR
Definition: logger.h:155
static struct call_queue * load_realtime_queue(const char *queuename)
Definition: app_queue.c:2573
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int queue_function_memberpenalty_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Dialplan function QUEUE_MEMBER_PENALTY() Gets the members penalty.

Definition at line 6907 of file app_queue.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), get_member_penalty(), and LOG_ERROR.

6907 {
6908  int penalty;
6910  AST_APP_ARG(queuename);
6911  AST_APP_ARG(interface);
6912  );
6913  /* Make sure the returned value on error is NULL. */
6914  buf[0] = '\0';
6915 
6916  if (ast_strlen_zero(data)) {
6917  ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
6918  return -1;
6919  }
6920 
6921  AST_STANDARD_APP_ARGS(args, data);
6922 
6923  if (args.argc < 2) {
6924  ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
6925  return -1;
6926  }
6927 
6928  penalty = get_member_penalty (args.queuename, args.interface);
6929 
6930  if (penalty >= 0) /* remember that buf is already '\0' */
6931  snprintf (buf, len, "%d", penalty);
6932 
6933  return 0;
6934 }
6935 
static int get_member_penalty(char *queuename, char *interface)
Definition: app_queue.c:5940
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define LOG_ERROR
Definition: logger.h:155
static struct @350 args
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static int queue_function_memberpenalty_write ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  value 
)
static

Dialplan function QUEUE_MEMBER_PENALTY() Sets the members penalty.

Definition at line 6938 of file app_queue.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), LOG_ERROR, and set_member_penalty().

6938 {
6939  int penalty;
6941  AST_APP_ARG(queuename);
6942  AST_APP_ARG(interface);
6943  );
6944 
6945  if (ast_strlen_zero(data)) {
6946  ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
6947  return -1;
6948  }
6949 
6950  AST_STANDARD_APP_ARGS(args, data);
6951 
6952  if (args.argc < 2) {
6953  ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
6954  return -1;
6955  }
6956 
6957  penalty = atoi(value);
6958 
6959  if (ast_strlen_zero(args.interface)) {
6960  ast_log (LOG_ERROR, "<interface> parameter can't be null\n");
6961  return -1;
6962  }
6963 
6964  /* if queuename = NULL then penalty will be set for interface in all the queues. */
6965  if (set_member_penalty(args.queuename, args.interface, penalty)) {
6966  ast_log(LOG_ERROR, "Invalid interface, queue or penalty\n");
6967  return -1;
6968  }
6969 
6970  return 0;
6971 }
6972 
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
static int set_member_penalty(const char *queuename, const char *interface, int penalty)
Definition: app_queue.c:5891
int value
Definition: syslog.c:39
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define LOG_ERROR
Definition: logger.h:155
static struct @350 args
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static int queue_function_qac ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Get number either busy / free / ready or total members of a specific queue.

Return values
numberof members (busy / free / ready / total)
-1on error

Definition at line 6702 of file app_queue.c.

References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_log(), ast_strlen_zero(), call_queue::count, member::lastcall, load_realtime_queue(), LOG_ERROR, LOG_WARNING, call_queue::members, member::paused, queue_t_unref, member::status, and call_queue::wrapuptime.

6702 {
6703  int count = 0;
6704  struct member *m;
6705  struct ao2_iterator mem_iter;
6706  struct call_queue *q;
6707  char *option;
6708 
6709  if (ast_strlen_zero(data)) {
6710  ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
6711  return -1;
6712  }
6713 
6714  if ((option = strchr(data, ',')))
6715  *option++ = '\0';
6716  else
6717  option = "logged";
6718  if ((q = load_realtime_queue(data))) {
6719  ao2_lock(q);
6720  if (!strcasecmp(option, "logged")) {
6721  mem_iter = ao2_iterator_init(q->members, 0);
6722  while ((m = ao2_iterator_next(&mem_iter))) {
6723  /* Count the agents who are logged in and presently answering calls */
6724  if ((m->status != AST_DEVICE_UNAVAILABLE) && (m->status != AST_DEVICE_INVALID)) {
6725  count++;
6726  }
6727  ao2_ref(m, -1);
6728  }
6729  ao2_iterator_destroy(&mem_iter);
6730  } else if (!strcasecmp(option, "free")) {
6731  mem_iter = ao2_iterator_init(q->members, 0);
6732  while ((m = ao2_iterator_next(&mem_iter))) {
6733  /* Count the agents who are logged in and presently answering calls */
6734  if (((m->status == AST_DEVICE_NOT_INUSE) || (m->status == AST_DEVICE_UNKNOWN)) && (!m->paused)) {
6735  count++;
6736  }
6737  ao2_ref(m, -1);
6738  }
6739  ao2_iterator_destroy(&mem_iter);
6740  } else if (!strcasecmp(option, "ready")) {
6741  time_t now;
6742  time(&now);
6743  mem_iter = ao2_iterator_init(q->members, 0);
6744  while ((m = ao2_iterator_next(&mem_iter))) {
6745  /* Count the agents who are logged in, not paused and not wrapping up */
6746  if (((m->status == AST_DEVICE_NOT_INUSE) || (m->status == AST_DEVICE_UNKNOWN)) && (!m->paused) &&
6747  !(m->lastcall && q->wrapuptime && ((now - q->wrapuptime) < m->lastcall))) {
6748  count++;
6749  }
6750  ao2_ref(m, -1);
6751  }
6752  ao2_iterator_destroy(&mem_iter);
6753  } else if (!strcasecmp(option, "paused")) {
6754  mem_iter = ao2_iterator_init(q->members, 0);
6755  while ((m = ao2_iterator_next(&mem_iter))) {
6756  /* Count paused members */
6757  if (m->paused) {
6758  count++;
6759  }
6760  ao2_ref(m, -1);
6761  }
6762  ao2_iterator_destroy(&mem_iter);
6763  } else /* must be "count" */
6764  count = ao2_container_count(q->members);
6765  ao2_unlock(q);
6766  queue_t_unref(q, "Done with temporary reference in QUEUE_MEMBER()");
6767  } else
6768  ast_log(LOG_WARNING, "queue %s was not found\n", data);
6769 
6770  snprintf(buf, len, "%d", count);
6771 
6772  return 0;
6773 }
6774 
int paused
Definition: app_queue.c:1185
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
Definition: astobj2.c:470
int wrapuptime
Definition: app_queue.c:1305
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
#define LOG_WARNING
Definition: logger.h:144
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
struct ao2_container * members
Definition: app_queue.c:1320
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
#define LOG_ERROR
Definition: logger.h:155
static struct call_queue * load_realtime_queue(const char *queuename)
Definition: app_queue.c:2573
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
int status
Definition: app_queue.c:1184
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
time_t lastcall
Definition: app_queue.c:1187
static int queue_function_qac_dep ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Get the total number of members in a specific queue (Deprecated)

Return values
numberof members
-1on error

Definition at line 6781 of file app_queue.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, AST_DEVICE_INVALID, AST_DEVICE_UNAVAILABLE, ast_log(), ast_strlen_zero(), call_queue::count, load_realtime_queue(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, call_queue::members, queue_t_unref, and member::status.

6781 {
6782  int count = 0;
6783  struct member *m;
6784  struct call_queue *q;
6785  struct ao2_iterator mem_iter;
6786  static int depflag = 1;
6787 
6788  if (depflag) {
6789  depflag = 0;
6790  ast_log(LOG_NOTICE, "The function QUEUE_MEMBER_COUNT has been deprecated in favor of the QUEUE_MEMBER function and will not be in further releases.\n");
6791  }
6792 
6793  if (ast_strlen_zero(data)) {
6794  ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
6795  return -1;
6796  }
6797 
6798  if ((q = load_realtime_queue(data))) {
6799  ao2_lock(q);
6800  mem_iter = ao2_iterator_init(q->members, 0);
6801  while ((m = ao2_iterator_next(&mem_iter))) {
6802  /* Count the agents who are logged in and presently answering calls */
6803  if ((m->status != AST_DEVICE_UNAVAILABLE) && (m->status != AST_DEVICE_INVALID)) {
6804  count++;
6805  }
6806  ao2_ref(m, -1);
6807  }
6808  ao2_iterator_destroy(&mem_iter);
6809  ao2_unlock(q);
6810  queue_t_unref(q, "Done with temporary reference in QUEUE_MEMBER_COUNT");
6811  } else
6812  ast_log(LOG_WARNING, "queue %s was not found\n", data);
6813 
6814  snprintf(buf, len, "%d", count);
6815 
6816  return 0;
6817 }
6818 
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
#define LOG_WARNING
Definition: logger.h:144
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
struct ao2_container * members
Definition: app_queue.c:1320
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
#define LOG_ERROR
Definition: logger.h:155
static struct call_queue * load_realtime_queue(const char *queuename)
Definition: app_queue.c:2573
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
int status
Definition: app_queue.c:1184
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
static int queue_function_queuememberlist ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Dialplan function QUEUE_MEMBER_LIST() Get list of members in a specific queue.

Definition at line 6857 of file app_queue.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_t_find, ao2_unlock, ast_log(), ast_strlen_zero(), member::interface, LOG_ERROR, LOG_WARNING, call_queue::members, call_queue::name, OBJ_POINTER, queue_t_unref, and queues.

6857 {
6858  struct call_queue *q, tmpq = {
6859  .name = data,
6860  };
6861  struct member *m;
6862 
6863  /* Ensure an otherwise empty list doesn't return garbage */
6864  buf[0] = '\0';
6865 
6866  if (ast_strlen_zero(data)) {
6867  ast_log(LOG_ERROR, "QUEUE_MEMBER_LIST requires an argument: queuename\n");
6868  return -1;
6869  }
6870 
6871  if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find for QUEUE_MEMBER_LIST()"))) {
6872  int buflen = 0, count = 0;
6873  struct ao2_iterator mem_iter;
6874 
6875  ao2_lock(q);
6876  mem_iter = ao2_iterator_init(q->members, 0);
6877  while ((m = ao2_iterator_next(&mem_iter))) {
6878  /* strcat() is always faster than printf() */
6879  if (count++) {
6880  strncat(buf + buflen, ",", len - buflen - 1);
6881  buflen++;
6882  }
6883  strncat(buf + buflen, m->interface, len - buflen - 1);
6884  buflen += strlen(m->interface);
6885  /* Safeguard against overflow (negative length) */
6886  if (buflen >= len - 2) {
6887  ao2_ref(m, -1);
6888  ast_log(LOG_WARNING, "Truncating list\n");
6889  break;
6890  }
6891  ao2_ref(m, -1);
6892  }
6893  ao2_iterator_destroy(&mem_iter);
6894  ao2_unlock(q);
6895  queue_t_unref(q, "Done with QUEUE_MEMBER_LIST()");
6896  } else
6897  ast_log(LOG_WARNING, "queue %s was not found\n", data);
6898 
6899  /* We should already be terminated, but let's make sure. */
6900  buf[len - 1] = '\0';
6901 
6902  return 0;
6903 }
6904 
#define ao2_t_find(arg1, arg2, arg3, arg4)
Definition: astobj2.h:963
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
#define LOG_WARNING
Definition: logger.h:144
char interface[80]
Definition: app_queue.c:1175
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
struct ao2_container * members
Definition: app_queue.c:1320
static struct ao2_container * queues
Definition: app_queue.c:1334
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
#define LOG_ERROR
Definition: logger.h:155
const ast_string_field name
Definition: app_queue.c:1266
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
static int queue_function_queuememberpaused ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 7033 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, args, AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_free, ast_log(), ast_malloc, ast_module_user_add, ast_module_user_remove, AST_STANDARD_APP_ARGS, ast_strlen_zero(), LOG_WARNING, member::membername, call_queue::members, call_queue::name, member::paused, queue_t_unref, and queues.

7033 {
7034  struct ast_module_user *lu;
7035  struct call_queue *q;
7036  struct member *cur;
7037  struct ao2_iterator queue_iter;
7038  struct ao2_iterator mem_iter;
7039  char tmp[128] = "";
7040  char *buffer;
7041 
7043  AST_APP_ARG(queue);
7044  AST_APP_ARG(interface);
7045  );
7046 
7047  AST_STANDARD_APP_ARGS(args, data);
7048  if (ast_strlen_zero(args.interface)) {
7049  ast_log(LOG_WARNING, "This function requires an interface name.\n");
7050  return -1;
7051  }
7052  lu = ast_module_user_add(chan);
7053 
7054  buffer = ast_malloc(len);
7055  buffer[0]='\0';
7056 
7057  queue_iter = ao2_iterator_init(queues,0);
7058  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
7059  ao2_lock(q);
7060  if (ast_strlen_zero(args.queue) ||
7061  (!ast_strlen_zero(args.queue) && !strncmp(args.queue, q->name, strlen(args.queue)))
7062  ) {
7063  /* Iterate over queue members */
7064  mem_iter = ao2_iterator_init(q->members, 0);
7065  while ((cur = ao2_iterator_next(&mem_iter))) {
7066  if (!strncasecmp(args.interface, cur->membername, strlen(args.interface))) {
7067  if (!ast_strlen_zero(args.queue)) {
7068  ast_copy_string(buffer, cur->paused?"1":"0", len);
7069  } else {
7070  snprintf(tmp, sizeof(tmp), "%s%s:%s", ast_strlen_zero(tmp)?"":",", q->name, cur->paused?"1":"0");
7071  strncat(buffer, tmp, sizeof(tmp));
7072  }
7073  ao2_ref(cur, -1);
7074  break;
7075  }
7076  ao2_ref(cur, -1);
7077  }
7078  ao2_iterator_destroy(&mem_iter);
7079  }
7080  ao2_unlock(q);
7081  queue_t_unref(q, "Done with iterator");
7082  }
7083  ao2_iterator_destroy(&queue_iter);
7084  ast_copy_string(buf, buffer, len);
7085  ast_free(buffer);
7086 
7088  return 0;
7089 }
7090 
int paused
Definition: app_queue.c:1185
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
#define LOG_WARNING
Definition: logger.h:144
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
#define ao2_t_iterator_next(arg1, arg2)
Definition: astobj2.h:1125
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
#define ast_module_user_remove(user)
Definition: module.h:269
struct ao2_container * members
Definition: app_queue.c:1320
char membername[80]
Definition: app_queue.c:1179
static struct ao2_container * queues
Definition: app_queue.c:1334
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
#define ast_module_user_add(chan)
Definition: module.h:268
static struct @350 args
const ast_string_field name
Definition: app_queue.c:1266
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_free(a)
Definition: astmm.h:97
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
#define ast_malloc(a)
Definition: astmm.h:91
static int queue_function_queuememberstatus ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 6974 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, args, AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_devstate2str(), ast_free, ast_log(), ast_malloc, ast_module_user_add, ast_module_user_remove, AST_STANDARD_APP_ARGS, ast_strlen_zero(), LOG_WARNING, member::membername, call_queue::members, call_queue::name, queue_t_unref, queues, and member::status.

6974 {
6975  struct ast_module_user *lu;
6976  struct call_queue *q;
6977  struct member *cur;
6978  struct ao2_iterator queue_iter;
6979  struct ao2_iterator mem_iter;
6980  char tmp[128] = "";
6981  char *buffer;
6982 
6984  AST_APP_ARG(queue);
6985  AST_APP_ARG(interface);
6986  );
6987 
6988  AST_STANDARD_APP_ARGS(args, data);
6989  if (ast_strlen_zero(args.interface)) {
6990  ast_log(LOG_WARNING, "This function requires an interface name.\n");
6991  return -1;
6992  }
6993  lu = ast_module_user_add(chan);
6994 
6995  buffer = ast_malloc(len);
6996  buffer[0]='\0';
6997 
6998  queue_iter = ao2_iterator_init(queues,0);
6999  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
7000  ao2_lock(q);
7001  if (ast_strlen_zero(args.queue) ||
7002  (!ast_strlen_zero(args.queue) && !strncmp(args.queue, q->name, strlen(args.queue)))
7003  ) {
7004  /* Iterate over queue members */
7005  mem_iter = ao2_iterator_init(q->members, 0);
7006  while ((cur = ao2_iterator_next(&mem_iter))) {
7007  if (!strncasecmp(args.interface, cur->membername, strlen(args.interface))) {
7008  if (!ast_strlen_zero(args.queue)) {
7009  ast_copy_string(buffer, ast_devstate2str(cur->status), len);
7010  } else {
7011  snprintf(tmp, sizeof(tmp), "%s%s:%s", ast_strlen_zero(tmp)?"":",", q->name, ast_devstate2str(cur->status));
7012  strncat(buffer, tmp, sizeof(tmp));
7013  }
7014  ao2_ref(cur, -1);
7015  continue;
7016  }
7017  ao2_ref(cur, -1);
7018  }
7019  ao2_iterator_destroy(&mem_iter);
7020  }
7021  ao2_unlock(q);
7022  queue_t_unref(q, "Done with iterator");
7023  }
7024  ao2_iterator_destroy(&queue_iter);
7025  ast_copy_string(buf, buffer, len);
7026  ast_free(buffer);
7027 
7029  return 0;
7030 }
7031 
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Find devicestate as text message for output.
Definition: devicestate.c:215
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
#define LOG_WARNING
Definition: logger.h:144
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
#define ao2_t_iterator_next(arg1, arg2)
Definition: astobj2.h:1125
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
#define ast_module_user_remove(user)
Definition: module.h:269
struct ao2_container * members
Definition: app_queue.c:1320
char membername[80]
Definition: app_queue.c:1179
static struct ao2_container * queues
Definition: app_queue.c:1334
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
#define ast_module_user_add(chan)
Definition: module.h:268
static struct @350 args
const ast_string_field name
Definition: app_queue.c:1266
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_free(a)
Definition: astmm.h:97
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
int status
Definition: app_queue.c:1184
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
#define ast_malloc(a)
Definition: astmm.h:91
static int queue_function_queuewaitingcount ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Dialplan function QUEUE_WAITING_COUNT() Get number callers waiting in a specific queue.

Definition at line 6821 of file app_queue.c.

References ao2_lock, ao2_t_find, ao2_unlock, ast_load_realtime(), ast_log(), ast_strlen_zero(), ast_variables_destroy(), call_queue::count, LOG_ERROR, LOG_WARNING, call_queue::name, OBJ_POINTER, queue_t_unref, queues, SENTINEL, and var.

6821 {
6822  int count = 0;
6823  struct call_queue *q, tmpq = {
6824  .name = data,
6825  };
6826  struct ast_variable *var = NULL;
6827 
6828  buf[0] = '\0';
6829 
6830  if (ast_strlen_zero(data)) {
6831  ast_log(LOG_ERROR, "QUEUE_WAITING_COUNT requires an argument: queuename\n");
6832  return -1;
6833  }
6834 
6835  if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find for QUEUE_WAITING_COUNT()"))) {
6836  ao2_lock(q);
6837  count = q->count;
6838  ao2_unlock(q);
6839  queue_t_unref(q, "Done with reference in QUEUE_WAITING_COUNT()");
6840  } else if ((var = ast_load_realtime("queues", "name", data, SENTINEL))) {
6841  /* if the queue is realtime but was not found in memory, this
6842  * means that the queue had been deleted from memory since it was
6843  * "dead." This means it has a 0 waiting count
6844  */
6845  count = 0;
6846  ast_variables_destroy(var);
6847  } else
6848  ast_log(LOG_WARNING, "queue %s was not found\n", data);
6849 
6850  snprintf(buf, len, "%d", count);
6851 
6852  return 0;
6853 }
6854 
#define ao2_t_find(arg1, arg2, arg3, arg4)
Definition: astobj2.h:963
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
#define LOG_WARNING
Definition: logger.h:144
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define var
Definition: ast_expr2f.c:606
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: config.c:2548
#define ao2_unlock(a)
Definition: astobj2.h:497
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: config.c:586
#define SENTINEL
Definition: compiler.h:75
static struct ao2_container * queues
Definition: app_queue.c:1334
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ao2_lock(a)
Definition: astobj2.h:488
#define LOG_ERROR
Definition: logger.h:155
const ast_string_field name
Definition: app_queue.c:1266
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int queue_function_var ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

create interface var with all queue details.

Return values
0on success
-1on error

Definition at line 6631 of file app_queue.c.

References ao2_lock, ao2_t_find, ao2_unlock, ast_log(), ast_strlen_zero(), call_queue::callsabandoned, call_queue::callscompleted, call_queue::callscompletedinsl, call_queue::count, call_queue::holdtime, int2strat(), LOG_ERROR, LOG_WARNING, call_queue::maxlen, call_queue::name, OBJ_POINTER, pbx_builtin_setvar_multiple(), queue_t_unref, queues, call_queue::servicelevel, call_queue::setqueuevar, call_queue::strategy, and call_queue::talktime.

6631 {
6632  int res = -1;
6633  struct call_queue *q, tmpq = {
6634  .name = data,
6635  };
6636 
6637  char interfacevar[256] = "";
6638  float sl = 0;
6639 
6640  if (ast_strlen_zero(data)) {
6641  ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
6642  return -1;
6643  }
6644 
6645  if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find for QUEUE() function"))) {
6646  ao2_lock(q);
6647  if (q->setqueuevar) {
6648  sl = 0;
6649  res = 0;
6650 
6651  if (q->callscompleted > 0) {
6652  sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
6653  }
6654 
6655  snprintf(interfacevar, sizeof(interfacevar),
6656  "QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUETALKTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
6658 
6659  pbx_builtin_setvar_multiple(chan, interfacevar);
6660  }
6661 
6662  ao2_unlock(q);
6663  queue_t_unref(q, "Done with QUEUE() function");
6664  } else {
6665  ast_log(LOG_WARNING, "queue %s was not found\n", data);
6666  }
6667 
6668  snprintf(buf, len, "%d", res);
6669 
6670  return 0;
6671 }
6672 
#define ao2_t_find(arg1, arg2, arg3, arg4)
Definition: astobj2.h:963
int servicelevel
Definition: app_queue.c:1299
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
unsigned int setqueuevar
Definition: app_queue.c:1274
#define LOG_WARNING
Definition: logger.h:144
#define ao2_unlock(a)
Definition: astobj2.h:497
int callscompletedinsl
Definition: app_queue.c:1300
int holdtime
Definition: app_queue.c:1295
static struct ao2_container * queues
Definition: app_queue.c:1334
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ao2_lock(a)
Definition: astobj2.h:488
int strategy
Definition: app_queue.c:1281
#define LOG_ERROR
Definition: logger.h:155
const ast_string_field name
Definition: app_queue.c:1266
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int pbx_builtin_setvar_multiple(struct ast_channel *chan, const char *data)
Parse and set multiple channel variables, where the pairs are separated by the &#39;,&#39; character...
Definition: pbx.c:10633
int talktime
Definition: app_queue.c:1296
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int callsabandoned
Definition: app_queue.c:1298
int callscompleted
Definition: app_queue.c:1297
static const char * int2strat(int strategy)
Definition: app_queue.c:1353
static int queue_hash_cb ( const void *  obj,
const int  flags 
)
static

Definition at line 1397 of file app_queue.c.

References ast_str_case_hash(), and call_queue::name.

Referenced by load_module().

1397 {
1398  const struct call_queue *q = obj;
1399 
1400  return ast_str_case_hash(q->name);
1401 }
1402 
const ast_string_field name
Definition: app_queue.c:1266
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:989
static int queue_member_decrement_followers ( void *  obj,
void *  arg,
int  flag 
)
static

Definition at line 1415 of file app_queue.c.

References member::queuepos.

Referenced by queue_delme_members_decrement_followers(), and queue_member_follower_removal().

1415 {
1416  struct member *mem = obj;
1417  int *decrement_followers_after = arg;
1418 
1419  if (mem->queuepos > *decrement_followers_after) {
1420  mem->queuepos--;
1421  }
1422 
1423  return 0;
1424 }
1425 
int queuepos
Definition: app_queue.c:1186
static void queue_member_follower_removal ( struct call_queue queue,
struct member mem 
)
static

Definition at line 1451 of file app_queue.c.

References ao2_callback, call_queue::members, OBJ_MULTIPLE, OBJ_NODATA, queue_ent::pos, queue_member_decrement_followers(), member::queuepos, and call_queue::rrpos.

Referenced by member_remove_from_queue().

1451 {
1452  int pos = mem->queuepos;
1453 
1454  /* If the position being removed is less than the current place in the queue, reduce the queue position by one so that we don't skip the member
1455  * who would have been next otherwise. */
1456  if (pos < queue->rrpos) {
1457  queue->rrpos--;
1458  }
1459 
1461 }
1462 
int queuepos
Definition: app_queue.c:1186
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:910
struct ao2_container * members
Definition: app_queue.c:1320
static int queue_member_decrement_followers(void *obj, void *arg, int flag)
Definition: app_queue.c:1415
static struct call_queue* queue_ref ( struct call_queue q)
static

Definition at line 1476 of file app_queue.c.

References ao2_ref.

Referenced by insert_entry().

1476 {
1477  ao2_ref(q, 1);
1478  return q;
1479 }
1480 
#define ao2_ref(o, delta)
Definition: astobj2.h:472
static void queue_set_global_params ( struct ast_config cfg)
static

Set the global queue parameters as defined in the "general" section of queues.conf

Definition at line 7193 of file app_queue.c.

References ast_true(), and ast_variable_retrieve().

Referenced by reload_queues().

7193 {
7194  const char *general_val = NULL;
7195  queue_debug = 0;
7196  if ((general_val = ast_variable_retrieve(cfg, "general", "debug")))
7197  queue_debug = ast_true(general_val);
7199  if ((general_val = ast_variable_retrieve(cfg, "general", "persistentmembers")))
7200  queue_persistent_members = ast_true(general_val);
7201  autofill_default = 0;
7202  if ((general_val = ast_variable_retrieve(cfg, "general", "autofill")))
7203  autofill_default = ast_true(general_val);
7204  montype_default = 0;
7205  if ((general_val = ast_variable_retrieve(cfg, "general", "monitor-type"))) {
7206  if (!strcasecmp(general_val, "mixmonitor"))
7207  montype_default = 1;
7208  }
7209  update_cdr = 0;
7210  if ((general_val = ast_variable_retrieve(cfg, "general", "updatecdr")))
7211  update_cdr = ast_true(general_val);
7212  shared_lastcall = 0;
7213  if ((general_val = ast_variable_retrieve(cfg, "general", "shared_lastcall")))
7214  shared_lastcall = ast_true(general_val);
7215 }
7216 
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
static int montype_default
queues.conf [general] option
Definition: app_queue.c:1067
static int autofill_default
queues.conf [general] option
Definition: app_queue.c:1064
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
static int queue_debug
queues.conf [general] extra debug option
Definition: app_queue.c:1055
static int shared_lastcall
queues.conf [general] option
Definition: app_queue.c:1070
static int queue_persistent_members
queues.conf [general] option
Definition: app_queue.c:1058
static int update_cdr
queues.conf [general] option
Definition: app_queue.c:1076
static void queue_set_param ( struct call_queue q,
const char *  param,
const char *  val,
int  linenum,
int  failunknown 
)
static

Configure a queue parameter.

The failunknown flag is set for config files (and static realtime) to show errors for unknown parameters. It is cleared for dynamic realtime to allow extra fields in the tables.

Note
For error reporting, line number is passed for .conf static configuration, for Realtime queues, linenum is -1.

Definition at line 2093 of file app_queue.c.

References queue_ent::announce, call_queue::announce_to_first_user, call_queue::announcefrequency, call_queue::announceholdtime, ANNOUNCEHOLDTIME_ALWAYS, ANNOUNCEHOLDTIME_ONCE, call_queue::announceposition, ANNOUNCEPOSITION_LIMIT, ANNOUNCEPOSITION_MORE_THAN, ANNOUNCEPOSITION_NO, ANNOUNCEPOSITION_YES, call_queue::announcepositionlimit, ast_copy_string(), ast_debug, ast_log(), ast_str_create(), ast_str_set(), ast_strdupa, ast_string_field_set, ast_true(), call_queue::autofill, call_queue::autopause, autopause2int(), queue_ent::context, DEFAULT_RETRY, DEFAULT_TIMEOUT, call_queue::eventwhencalled, call_queue::joinempty, call_queue::leavewhenempty, LOG_WARNING, call_queue::maskmemberstatus, MAX_PERIODIC_ANNOUNCEMENTS, call_queue::maxlen, call_queue::memberdelay, call_queue::minannouncefrequency, queue_ent::moh, call_queue::monfmt, call_queue::montype, call_queue::name, call_queue::numperiodicannounce, parse_empty_options(), call_queue::penaltymemberslimit, call_queue::periodicannouncefrequency, QUEUE_EVENT_VARIABLES, QUEUE_STRATEGY_LINEAR, QUEUE_STRATEGY_RINGALL, call_queue::randomperiodicannounce, call_queue::relativeperiodicannounce, call_queue::reportholdtime, call_queue::retry, call_queue::ringinuse, call_queue::ringlimit, call_queue::roundingseconds, call_queue::servicelevel, call_queue::setinterfacevar, call_queue::setqueueentryvar, call_queue::setqueuevar, call_queue::sound_periodicannounce, strat2int(), call_queue::strategy, strsep(), call_queue::timeout, TIMEOUT_PRIORITY_APP, TIMEOUT_PRIORITY_CONF, call_queue::timeoutpriority, call_queue::timeoutrestart, call_queue::weight, and call_queue::wrapuptime.

Referenced by find_queue_by_name_rt(), and reload_single_queue().

2093 {
2094  if (!strcasecmp(param, "musicclass") ||
2095  !strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
2097  } else if (!strcasecmp(param, "announce")) {
2098  ast_string_field_set(q, announce, val);
2099  } else if (!strcasecmp(param, "context")) {
2101  } else if (!strcasecmp(param, "timeout")) {
2102  q->timeout = atoi(val);
2103  if (q->timeout < 0)
2104  q->timeout = DEFAULT_TIMEOUT;
2105  } else if (!strcasecmp(param, "ringinuse")) {
2106  q->ringinuse = ast_true(val);
2107  } else if (!strcasecmp(param, "setinterfacevar")) {
2109  } else if (!strcasecmp(param, "setqueuevar")) {
2110  q->setqueuevar = ast_true(val);
2111  } else if (!strcasecmp(param, "setqueueentryvar")) {
2113  } else if (!strcasecmp(param, "monitor-format")) {
2114  ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
2115  } else if (!strcasecmp(param, "membermacro")) {
2116  ast_string_field_set(q, membermacro, val);
2117  } else if (!strcasecmp(param, "membergosub")) {
2118  ast_string_field_set(q, membergosub, val);
2119  } else if (!strcasecmp(param, "queue-youarenext")) {
2120  ast_string_field_set(q, sound_next, val);
2121  } else if (!strcasecmp(param, "queue-thereare")) {
2122  ast_string_field_set(q, sound_thereare, val);
2123  } else if (!strcasecmp(param, "queue-callswaiting")) {
2124  ast_string_field_set(q, sound_calls, val);
2125  } else if (!strcasecmp(param, "queue-quantity1")) {
2126  ast_string_field_set(q, queue_quantity1, val);
2127  } else if (!strcasecmp(param, "queue-quantity2")) {
2128  ast_string_field_set(q, queue_quantity2, val);
2129  } else if (!strcasecmp(param, "queue-holdtime")) {
2130  ast_string_field_set(q, sound_holdtime, val);
2131  } else if (!strcasecmp(param, "queue-minutes")) {
2132  ast_string_field_set(q, sound_minutes, val);
2133  } else if (!strcasecmp(param, "queue-minute")) {
2134  ast_string_field_set(q, sound_minute, val);
2135  } else if (!strcasecmp(param, "queue-seconds")) {
2136  ast_string_field_set(q, sound_seconds, val);
2137  } else if (!strcasecmp(param, "queue-thankyou")) {
2138  ast_string_field_set(q, sound_thanks, val);
2139  } else if (!strcasecmp(param, "queue-callerannounce")) {
2140  ast_string_field_set(q, sound_callerannounce, val);
2141  } else if (!strcasecmp(param, "queue-reporthold")) {
2142  ast_string_field_set(q, sound_reporthold, val);
2143  } else if (!strcasecmp(param, "announce-frequency")) {
2144  q->announcefrequency = atoi(val);
2145  } else if (!strcasecmp(param, "announce-to-first-user")) {
2147  } else if (!strcasecmp(param, "min-announce-frequency")) {
2148  q->minannouncefrequency = atoi(val);
2149  ast_debug(1, "%s=%s for queue '%s'\n", param, val, q->name);
2150  } else if (!strcasecmp(param, "announce-round-seconds")) {
2151  q->roundingseconds = atoi(val);
2152  /* Rounding to any other values just doesn't make sense... */
2153  if (!(q->roundingseconds == 0 || q->roundingseconds == 5 || q->roundingseconds == 10
2154  || q->roundingseconds == 15 || q->roundingseconds == 20 || q->roundingseconds == 30)) {
2155  if (linenum >= 0) {
2156  ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
2157  "using 0 instead for queue '%s' at line %d of queues.conf\n",
2158  val, param, q->name, linenum);
2159  } else {
2160  ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
2161  "using 0 instead for queue '%s'\n", val, param, q->name);
2162  }
2163  q->roundingseconds=0;
2164  }
2165  } else if (!strcasecmp(param, "announce-holdtime")) {
2166  if (!strcasecmp(val, "once"))
2168  else if (ast_true(val))
2170  else
2171  q->announceholdtime = 0;
2172  } else if (!strcasecmp(param, "announce-position")) {
2173  if (!strcasecmp(val, "limit"))
2175  else if (!strcasecmp(val, "more"))
2177  else if (ast_true(val))
2179  else
2181  } else if (!strcasecmp(param, "announce-position-limit")) {
2182  q->announcepositionlimit = atoi(val);
2183  } else if (!strcasecmp(param, "periodic-announce")) {
2184  if (strchr(val, ',')) {
2185  char *s, *buf = ast_strdupa(val);
2186  unsigned int i = 0;
2187 
2188  while ((s = strsep(&buf, ",|"))) {
2189  if (!q->sound_periodicannounce[i])
2191  ast_str_set(&q->sound_periodicannounce[i], 0, "%s", s);
2192  i++;
2193  if (i == MAX_PERIODIC_ANNOUNCEMENTS)
2194  break;
2195  }
2196  q->numperiodicannounce = i;
2197  } else {
2198  ast_str_set(&q->sound_periodicannounce[0], 0, "%s", val);
2199  q->numperiodicannounce = 1;
2200  }
2201  } else if (!strcasecmp(param, "periodic-announce-frequency")) {
2202  q->periodicannouncefrequency = atoi(val);
2203  } else if (!strcasecmp(param, "relative-periodic-announce")) {
2205  } else if (!strcasecmp(param, "random-periodic-announce")) {
2207  } else if (!strcasecmp(param, "retry")) {
2208  q->retry = atoi(val);
2209  if (q->retry <= 0)
2210  q->retry = DEFAULT_RETRY;
2211  } else if (!strcasecmp(param, "wrapuptime")) {
2212  q->wrapuptime = atoi(val);
2213  } else if (!strcasecmp(param, "penaltymemberslimit")) {
2214  if ((sscanf(val, "%10d", &q->penaltymemberslimit) != 1)) {
2215  q->penaltymemberslimit = 0;
2216  }
2217  } else if (!strcasecmp(param, "autofill")) {
2218  q->autofill = ast_true(val);
2219  } else if (!strcasecmp(param, "monitor-type")) {
2220  if (!strcasecmp(val, "mixmonitor"))
2221  q->montype = 1;
2222  } else if (!strcasecmp(param, "autopause")) {
2223  q->autopause = autopause2int(val);
2224  } else if (!strcasecmp(param, "maxlen")) {
2225  q->maxlen = atoi(val);
2226  if (q->maxlen < 0)
2227  q->maxlen = 0;
2228  } else if (!strcasecmp(param, "ringlimit")) {
2229  q->ringlimit = atoi(val);
2230  if (q->ringlimit < 0)
2231  q->ringlimit = 0;
2232  } else if (!strcasecmp(param, "servicelevel")) {
2233  q->servicelevel= atoi(val);
2234  } else if (!strcasecmp(param, "strategy")) {
2235  int strategy;
2236 
2237  /* We are a static queue and already have set this, no need to do it again */
2238  if (failunknown) {
2239  return;
2240  }
2241  strategy = strat2int(val);
2242  if (strategy < 0) {
2243  ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
2244  val, q->name);
2246  }
2247  if (strategy == q->strategy) {
2248  return;
2249  }
2250  if (strategy == QUEUE_STRATEGY_LINEAR) {
2251  ast_log(LOG_WARNING, "Changing to the linear strategy currently requires asterisk to be restarted.\n");
2252  return;
2253  }
2254  q->strategy = strategy;
2255  } else if (!strcasecmp(param, "joinempty")) {
2257  } else if (!strcasecmp(param, "leavewhenempty")) {
2259  } else if (!strcasecmp(param, "eventmemberstatus")) {
2260  q->maskmemberstatus = !ast_true(val);
2261  } else if (!strcasecmp(param, "eventwhencalled")) {
2262  if (!strcasecmp(val, "vars")) {
2264  } else {
2265  q->eventwhencalled = ast_true(val) ? 1 : 0;
2266  }
2267  } else if (!strcasecmp(param, "reportholdtime")) {
2268  q->reportholdtime = ast_true(val);
2269  } else if (!strcasecmp(param, "memberdelay")) {
2270  q->memberdelay = atoi(val);
2271  } else if (!strcasecmp(param, "weight")) {
2272  q->weight = atoi(val);
2273  } else if (!strcasecmp(param, "timeoutrestart")) {
2274  q->timeoutrestart = ast_true(val);
2275  } else if (!strcasecmp(param, "defaultrule")) {
2276  ast_string_field_set(q, defaultrule, val);
2277  } else if (!strcasecmp(param, "timeoutpriority")) {
2278  if (!strcasecmp(val, "conf")) {
2280  } else {
2282  }
2283  } else if (failunknown) {
2284  if (linenum >= 0) {
2285  ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
2286  q->name, param, linenum);
2287  } else {
2288  ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s\n", q->name, param);
2289  }
2290  }
2291 }
2292 
struct ast_str * sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS]
Definition: app_queue.c:1268
int servicelevel
Definition: app_queue.c:1299
#define MAX_PERIODIC_ANNOUNCEMENTS
Definition: app_queue.c:1027
unsigned int eventwhencalled
Definition: app_queue.c:1270
char * strsep(char **str, const char *delims)
int wrapuptime
Definition: app_queue.c:1305
Definition: ast_expr2.c:325
int penaltymemberslimit
Definition: app_queue.c:1306
unsigned int setqueuevar
Definition: app_queue.c:1274
#define DEFAULT_RETRY
Definition: app_queue.c:1024
#define ANNOUNCEPOSITION_NO
Definition: app_queue.c:1222
unsigned int maskmemberstatus
Definition: app_queue.c:1282
int minannouncefrequency
Definition: app_queue.c:1290
#define LOG_WARNING
Definition: logger.h:144
int autopause
Definition: app_queue.c:1312
unsigned int ringinuse
Definition: app_queue.c:1271
unsigned int timeoutrestart
Definition: app_queue.c:1278
unsigned int announceholdtime
Definition: app_queue.c:1279
struct ast_str * ast_str_create(size_t init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:420
unsigned int setinterfacevar
Definition: app_queue.c:1273
int ringlimit
Definition: app_queue.c:1307
unsigned int announce_to_first_user
Definition: app_queue.c:1272
char monfmt[8]
Definition: app_queue.c:1301
int announcepositionlimit
Definition: app_queue.c:1288
static int strat2int(const char *strategy)
Definition: app_queue.c:1365
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:874
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int periodicannouncefrequency
Definition: app_queue.c:1291
int memberdelay
Definition: app_queue.c:1317
static void parse_empty_options(const char *value, enum empty_conditions *empty, int joinempty)
Definition: app_queue.c:2050
int strategy
Definition: app_queue.c:1281
#define ANNOUNCEPOSITION_MORE_THAN
Definition: app_queue.c:1223
static char moh[80]
Definition: chan_agent.c:209
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
#define ANNOUNCEPOSITION_YES
Definition: app_queue.c:1221
const ast_string_field name
Definition: app_queue.c:1266
unsigned int reportholdtime
Definition: app_queue.c:1276
int autofill
Definition: app_queue.c:1318
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int roundingseconds
Definition: app_queue.c:1294
#define DEFAULT_TIMEOUT
Definition: app_queue.c:1025
int timeoutpriority
Definition: app_queue.c:1313
unsigned int announceposition
Definition: app_queue.c:1280
int randomperiodicannounce
Definition: app_queue.c:1293
#define ANNOUNCEHOLDTIME_ALWAYS
Definition: app_queue.c:1208
unsigned int setqueueentryvar
Definition: app_queue.c:1275
#define ANNOUNCEPOSITION_LIMIT
Definition: app_queue.c:1224
int numperiodicannounce
Definition: app_queue.c:1292
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static int autopause2int(const char *autopause)
Definition: app_queue.c:1377
enum empty_conditions leavewhenempty
Definition: app_queue.c:1287
unsigned int relativeperiodicannounce
Definition: app_queue.c:1285
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
#define ANNOUNCEHOLDTIME_ONCE
Definition: app_queue.c:1209
enum empty_conditions joinempty
Definition: app_queue.c:1286
int announcefrequency
Definition: app_queue.c:1289
#define QUEUE_EVENT_VARIABLES
Definition: app_queue.c:1210
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
static char* queue_show ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 7852 of file app_queue.c.

References __queues_show(), ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, complete_queue_show(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

7852 {
7853  switch ( cmd ) {
7854  case CLI_INIT:
7855  e->command = "queue show";
7856  e->usage =
7857  "Usage: queue show\n"
7858  " Provides summary information on a specified queue.\n";
7859  return NULL;
7860  case CLI_GENERATE:
7861  return complete_queue_show(a->line, a->word, a->pos, a->n);
7862  }
7863 
7864  return __queues_show(NULL, a->fd, a->argc, a->argv);
7865 }
7866 
const int argc
Definition: cli.h:154
Definition: cli.h:146
static char * __queues_show(struct mansession *s, int fd, int argc, const char *const *argv)
Show queue(s) status and statistics.
Definition: app_queue.c:7603
const char * line
Definition: cli.h:156
const int fd
Definition: cli.h:153
const int n
Definition: cli.h:159
const char *const * argv
Definition: cli.h:155
char * command
Definition: cli.h:180
const char * word
Definition: cli.h:157
const char * usage
Definition: cli.h:171
const int pos
Definition: cli.h:158
static char * complete_queue_show(const char *line, const char *word, int pos, int state)
Definition: app_queue.c:7844
static void queue_transfer_destroy ( void *  data)
static

Definition at line 4680 of file app_queue.c.

References ast_free.

4680 {
4681  struct queue_transfer_ds *qtds = data;
4682  ast_free(qtds);
4683 }
4684 
#define ast_free(a)
Definition: astmm.h:97
static void queue_transfer_fixup ( void *  data,
struct ast_channel old_chan,
struct ast_channel new_chan 
)
static

Log an attended transfer when a queue caller channel is masqueraded.

When a caller is masqueraded, we want to log a transfer. Fixup time is the closest we can come to when the actual transfer occurs. This happens during the masquerade after datastores are moved from old_chan to new_chan. This is why new_chan is referenced for exten, context, and datastore information.

At the end of this, we want to remove the datastore so that this fixup function is not called on any future masquerades of the caller during the current call.

Definition at line 4703 of file app_queue.c.

References ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_log(), ast_queue_log(), queue_transfer_ds::callcompletedinsl, queue_ent::chan, ast_channel::context, ast_channel::exten, LOG_WARNING, queue_transfer_ds::member, member::membername, call_queue::name, queue_ent::opos, queue_ent::parent, queue_transfer_ds::qe, queue_transfer_info, queue_ent::start, queue_transfer_ds::starttime, ast_channel::uniqueid, and update_queue().

4703 {
4704  struct queue_transfer_ds *qtds = data;
4705  struct queue_ent *qe = qtds->qe;
4706  struct member *member = qtds->member;
4707  time_t callstart = qtds->starttime;
4708  int callcompletedinsl = qtds->callcompletedinsl;
4709  struct ast_datastore *datastore;
4710 
4711  ast_queue_log(qe->parent->name, qe->chan->uniqueid, member->membername, "TRANSFER", "%s|%s|%ld|%ld|%d",
4712  new_chan->exten, new_chan->context, (long) (callstart - qe->start),
4713  (long) (time(NULL) - callstart), qe->opos);
4714 
4715  update_queue(qe->parent, member, callcompletedinsl, (time(NULL) - callstart));
4716 
4717  /* No need to lock the channels because they are already locked in ast_do_masquerade */
4718  if ((datastore = ast_channel_datastore_find(old_chan, &queue_transfer_info, NULL))) {
4719  ast_channel_datastore_remove(old_chan, datastore);
4720  /* Datastore is freed in try_calling() */
4721  } else {
4722  ast_log(LOG_WARNING, "Can't find the queue_transfer datastore.\n");
4723  }
4724 }
4725 
struct call_queue * parent
Definition: app_queue.c:1144
struct ast_channel * chan
Definition: app_queue.c:1168
static struct ast_datastore_info queue_transfer_info
a datastore used to help correctly log attended transfers of queue callers
Definition: app_queue.c:4688
const ast_string_field uniqueid
Definition: channel.h:787
time_t start
Definition: app_queue.c:1165
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define LOG_WARNING
Definition: logger.h:144
struct queue_ent * qe
Definition: app_queue.c:4674
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl, int newtalktime)
update the queue status
Definition: app_queue.c:4506
Structure for a data store object.
Definition: datastore.h:54
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2604
char membername[80]
Definition: app_queue.c:1179
const ast_string_field name
Definition: app_queue.c:1266
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
struct member * member
Definition: app_queue.c:4675
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2599
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
static struct call_queue* queue_unref ( struct call_queue q)
static

Definition at line 1482 of file app_queue.c.

References ao2_ref.

Referenced by queue_exec(), and queues_data_provider_get().

1482 {
1483  ao2_ref(q, -1);
1484  return NULL;
1485 }
1486 #endif
#define ao2_ref(o, delta)
Definition: astobj2.h:472
static int queues_data_provider_get ( const struct ast_data_search search,
struct ast_data data_root 
)
static

Definition at line 9022 of file app_queue.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, ast_category_browse(), ast_config_destroy(), ast_load_realtime_multientry(), ast_strlen_zero(), load_realtime_queue(), call_queue::name, queue_unref(), queues, queues_data_provider_get_helper(), call_queue::realtime, and SENTINEL.

9023 {
9024  struct ao2_iterator i;
9025  struct call_queue *queue, *queue_realtime = NULL;
9026  struct ast_config *cfg;
9027  char *queuename;
9028 
9029  /* load realtime queues. */
9030  cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
9031  if (cfg) {
9032  for (queuename = ast_category_browse(cfg, NULL);
9033  !ast_strlen_zero(queuename);
9034  queuename = ast_category_browse(cfg, queuename)) {
9035  if ((queue = load_realtime_queue(queuename))) {
9036  queue_unref(queue);
9037  }
9038  }
9039  ast_config_destroy(cfg);
9040  }
9041 
9042  /* static queues. */
9043  i = ao2_iterator_init(queues, 0);
9044  while ((queue = ao2_iterator_next(&i))) {
9045  ao2_lock(queue);
9046  if (queue->realtime) {
9047  queue_realtime = load_realtime_queue(queue->name);
9048  if (!queue_realtime) {
9049  ao2_unlock(queue);
9050  queue_unref(queue);
9051  continue;
9052  }
9053  queue_unref(queue_realtime);
9054  }
9055 
9056  queues_data_provider_get_helper(search, data_root, queue);
9057  ao2_unlock(queue);
9058  queue_unref(queue);
9059  }
9061 
9062  return 0;
9063 }
9064 
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
#define SENTINEL
Definition: compiler.h:75
static struct ao2_container * queues
Definition: app_queue.c:1334
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
#define ao2_lock(a)
Definition: astobj2.h:488
static struct call_queue * load_realtime_queue(const char *queuename)
Definition: app_queue.c:2573
const ast_string_field name
Definition: app_queue.c:1266
static struct call_queue * queue_unref(struct call_queue *q)
Definition: app_queue.c:1482
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
unsigned int realtime
Definition: app_queue.c:1283
static void queues_data_provider_get_helper(const struct ast_data_search *search, struct ast_data *data_root, struct call_queue *queue)
Definition: app_queue.c:8916
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: config.c:2650
static void queues_data_provider_get_helper ( const struct ast_data_search search,
struct ast_data data_root,
struct call_queue queue 
)
static

Definition at line 8916 of file app_queue.c.

References call_queue::announceposition, ANNOUNCEPOSITION_LIMIT, ANNOUNCEPOSITION_MORE_THAN, ANNOUNCEPOSITION_NO, ANNOUNCEPOSITION_YES, ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_channel_data_add_structure(), ast_data_add_int(), ast_data_add_node(), ast_data_add_str(), ast_data_add_structure, ast_data_remove_node(), ast_data_search_match(), queue_ent::chan, call_queue::head, int2strat(), call_queue::members, queue_ent::next, and call_queue::strategy.

Referenced by queues_data_provider_get().

8917 {
8918  struct ao2_iterator im;
8919  struct member *member;
8920  struct queue_ent *qe;
8921  struct ast_data *data_queue, *data_members = NULL, *enum_node;
8922  struct ast_data *data_member, *data_callers = NULL, *data_caller, *data_caller_channel;
8923 
8924  data_queue = ast_data_add_node(data_root, "queue");
8925  if (!data_queue) {
8926  return;
8927  }
8928 
8929  ast_data_add_structure(call_queue, data_queue, queue);
8930 
8931  ast_data_add_str(data_queue, "strategy", int2strat(queue->strategy));
8932  ast_data_add_int(data_queue, "membercount", ao2_container_count(queue->members));
8933 
8934  /* announce position */
8935  enum_node = ast_data_add_node(data_queue, "announceposition");
8936  if (!enum_node) {
8937  return;
8938  }
8939  switch (queue->announceposition) {
8941  ast_data_add_str(enum_node, "text", "limit");
8942  break;
8944  ast_data_add_str(enum_node, "text", "more");
8945  break;
8946  case ANNOUNCEPOSITION_YES:
8947  ast_data_add_str(enum_node, "text", "yes");
8948  break;
8949  case ANNOUNCEPOSITION_NO:
8950  ast_data_add_str(enum_node, "text", "no");
8951  break;
8952  default:
8953  ast_data_add_str(enum_node, "text", "unknown");
8954  break;
8955  }
8956  ast_data_add_int(enum_node, "value", queue->announceposition);
8957 
8958  /* add queue members */
8959  im = ao2_iterator_init(queue->members, 0);
8960  while ((member = ao2_iterator_next(&im))) {
8961  if (!data_members) {
8962  data_members = ast_data_add_node(data_queue, "members");
8963  if (!data_members) {
8964  ao2_ref(member, -1);
8965  continue;
8966  }
8967  }
8968 
8969  data_member = ast_data_add_node(data_members, "member");
8970  if (!data_member) {
8971  ao2_ref(member, -1);
8972  continue;
8973  }
8974 
8975  ast_data_add_structure(member, data_member, member);
8976 
8977  ao2_ref(member, -1);
8978  }
8979  ao2_iterator_destroy(&im);
8980 
8981  /* include the callers inside the result. */
8982  if (queue->head) {
8983  for (qe = queue->head; qe; qe = qe->next) {
8984  if (!data_callers) {
8985  data_callers = ast_data_add_node(data_queue, "callers");
8986  if (!data_callers) {
8987  continue;
8988  }
8989  }
8990 
8991  data_caller = ast_data_add_node(data_callers, "caller");
8992  if (!data_caller) {
8993  continue;
8994  }
8995 
8996  ast_data_add_structure(queue_ent, data_caller, qe);
8997 
8998  /* add the caller channel. */
8999  data_caller_channel = ast_data_add_node(data_caller, "channel");
9000  if (!data_caller_channel) {
9001  continue;
9002  }
9003 
9004  ast_channel_data_add_structure(data_caller_channel, qe->chan, 1);
9005  }
9006  }
9007 
9008  /* if this queue doesn't match remove the added queue. */
9009  if (!ast_data_search_match(search, data_queue)) {
9010  ast_data_remove_node(data_root, data_queue);
9011  }
9012 }
9013 
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
Definition: astobj2.c:470
The data tree to be returned by the callbacks and managed by functions local to this file...
Definition: data.c:85
struct ast_channel * chan
Definition: app_queue.c:1168
#define ANNOUNCEPOSITION_NO
Definition: app_queue.c:1222
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
struct ao2_container * members
Definition: app_queue.c:1320
struct queue_ent * head
Definition: app_queue.c:1321
int ast_channel_data_add_structure(struct ast_data *tree, struct ast_channel *chan, int add_bridged)
Insert into an astdata tree, the channel structure.
Definition: channel.c:357
struct ast_data * ast_data_add_node(struct ast_data *root, const char *childname)
Add a container child.
Definition: data.c:2317
#define ao2_ref(o, delta)
Definition: astobj2.h:472
int strategy
Definition: app_queue.c:1281
#define ANNOUNCEPOSITION_MORE_THAN
Definition: app_queue.c:1223
#define ast_data_add_structure(structure_name, root, structure)
Definition: data.h:620
#define ANNOUNCEPOSITION_YES
Definition: app_queue.c:1221
void ast_data_remove_node(struct ast_data *root, struct ast_data *child)
Remove a node that was added using ast_data_add_.
Definition: data.c:2486
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
unsigned int announceposition
Definition: app_queue.c:1280
#define ANNOUNCEPOSITION_LIMIT
Definition: app_queue.c:1224
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
struct queue_ent * next
Definition: app_queue.c:1171
struct ast_data * ast_data_add_str(struct ast_data *root, const char *childname, const char *string)
Add a string node type.
Definition: data.c:2401
struct ast_data * ast_data_add_int(struct ast_data *root, const char *childname, int value)
Add an integer node type.
Definition: data.c:2322
int ast_data_search_match(const struct ast_data_search *search, struct ast_data *data)
Check the current generated node to know if it matches the search condition.
Definition: data.c:1458
static const char * int2strat(int strategy)
Definition: app_queue.c:1353
static void recalc_holdtime ( struct queue_ent qe,
int  newholdtime 
)
static

Definition at line 2993 of file app_queue.c.

References ao2_lock, ao2_unlock, call_queue::holdtime, and queue_ent::parent.

Referenced by try_calling().

2993 {
2994  int oldvalue;
2995 
2996  /* Calculate holdtime using an exponential average */
2997  /* Thanks to SRT for this contribution */
2998  /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */
2999 
3000  ao2_lock(qe->parent);
3001  oldvalue = qe->parent->holdtime;
3002  qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newholdtime) >> 2;
3003  ao2_unlock(qe->parent);
3004 }
3005 
struct call_queue * parent
Definition: app_queue.c:1144
#define ao2_unlock(a)
Definition: astobj2.h:497
int holdtime
Definition: app_queue.c:1295
#define ao2_lock(a)
Definition: astobj2.h:488
static void record_abandoned ( struct queue_ent qe)
static

Record that a caller gave up on waiting in queue.

Definition at line 3706 of file app_queue.c.

References ao2_lock, ao2_unlock, call_queue::callsabandoned, queue_ent::chan, EVENT_FLAG_AGENT, manager_event, call_queue::name, queue_ent::opos, queue_ent::parent, queue_ent::pos, set_queue_variables(), queue_ent::start, and ast_channel::uniqueid.

Referenced by queue_exec(), and try_calling().

3706 {
3707  set_queue_variables(qe->parent, qe->chan);
3708  ao2_lock(qe->parent);
3709  manager_event(EVENT_FLAG_AGENT, "QueueCallerAbandon",
3710  "Queue: %s\r\n"
3711  "Uniqueid: %s\r\n"
3712  "Position: %d\r\n"
3713  "OriginalPosition: %d\r\n"
3714  "HoldTime: %d\r\n",
3715  qe->parent->name, qe->chan->uniqueid, qe->pos, qe->opos, (int)(time(NULL) - qe->start));
3716 
3717  qe->parent->callsabandoned++;
3718  ao2_unlock(qe->parent);
3719 }
3720 
struct call_queue * parent
Definition: app_queue.c:1144
struct ast_channel * chan
Definition: app_queue.c:1168
const ast_string_field uniqueid
Definition: channel.h:787
time_t start
Definition: app_queue.c:1165
#define ao2_unlock(a)
Definition: astobj2.h:497
#define ao2_lock(a)
Definition: astobj2.h:488
const ast_string_field name
Definition: app_queue.c:1266
#define EVENT_FLAG_AGENT
Definition: manager.h:76
int callsabandoned
Definition: app_queue.c:1298
static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
Set variables of queue.
Definition: app_queue.c:1490
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
static int reload ( void  )
static

Definition at line 9202 of file app_queue.c.

References AST_FLAGS_ALL, ast_unload_realtime(), QUEUE_RESET_STATS, and reload_handler().

9202 {
9203  struct ast_flags mask = {AST_FLAGS_ALL & ~QUEUE_RESET_STATS,};
9204  ast_unload_realtime("queue_members");
9205  reload_handler(1, &mask, NULL);
9206  return 0;
9207 }
9208 
int ast_unload_realtime(const char *family)
Release any resources cached for a realtime family.
Definition: config.c:2630
static int reload_handler(int reload, struct ast_flags *mask, const char *queuename)
The command center for all reload operations.
Definition: app_queue.c:7572
#define AST_FLAGS_ALL
Definition: utils.h:196
Structure used to handle boolean flags.
Definition: utils.h:200
static int reload_handler ( int  reload,
struct ast_flags mask,
const char *  queuename 
)
static

The command center for all reload operations.

Whenever any piece of queue information is to be reloaded, this function is called. It interprets the flags set in the mask parameter and acts based on how they are set.

Parameters
reloadTrue if we are reloading information, false if we are loading information for the first time.
maskA bitmask which tells the handler what actions to take
queuenameThe name of the queue on which we wish to take action
Return values
0All reloads were successful
non-zeroThere was a failure

Definition at line 7572 of file app_queue.c.

References ast_test_flag, clear_stats(), QUEUE_RELOAD_MEMBER, QUEUE_RELOAD_PARAMETERS, QUEUE_RELOAD_RULES, QUEUE_RESET_STATS, reload_queue_rules(), and reload_queues().

Referenced by handle_queue_reload(), handle_queue_reset(), load_module(), manager_queue_reload(), manager_queue_reset(), and reload().

7572 {
7573  int res = 0;
7574 
7575  if (ast_test_flag(mask, QUEUE_RELOAD_RULES)) {
7576  res |= reload_queue_rules(reload);
7577  }
7578  if (ast_test_flag(mask, QUEUE_RESET_STATS)) {
7579  res |= clear_stats(queuename);
7580  }
7582  res |= reload_queues(reload, mask, queuename);
7583  }
7584  return res;
7585 }
7586 
#define ast_test_flag(p, flag)
Definition: utils.h:63
static int reload(void)
Definition: app_queue.c:9202
static int reload_queue_rules(int reload)
Reload the rules defined in queuerules.conf.
Definition: app_queue.c:7144
static int reload_queues(int reload, struct ast_flags *mask, const char *queuename)
reload the queues.conf file
Definition: app_queue.c:7477
static int clear_stats(const char *queuename)
Facilitates resetting statistics for a queue.
Definition: app_queue.c:7542
static void reload_queue_members ( void  )
static

Reload dynamic queue members persisted into the astdb.

Definition at line 5972 of file app_queue.c.

References add_to_queue(), ao2_t_find, ast_db_del(), ast_db_freetree(), ast_db_get_allocated(), ast_db_gettree(), ast_debug, ast_free, ast_log(), ast_strlen_zero(), errno, member::interface, ast_db_entry::key, load_realtime_queue(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, member::membername, call_queue::name, ast_db_entry::next, OBJ_POINTER, member::paused, member::penalty, queue_t_unref, queues, RES_OUTOFMEMORY, member::state_interface, and strsep().

Referenced by load_module().

5972 {
5973  char *cur_ptr;
5974  const char *queue_name;
5975  char *member;
5976  char *interface;
5977  char *membername = NULL;
5978  char *state_interface;
5979  char *penalty_tok;
5980  int penalty = 0;
5981  char *paused_tok;
5982  int paused = 0;
5983  struct ast_db_entry *db_tree;
5984  struct ast_db_entry *entry;
5985  struct call_queue *cur_queue;
5986  char *queue_data;
5987 
5988  /* Each key in 'pm_family' is the name of a queue */
5989  db_tree = ast_db_gettree(pm_family, NULL);
5990  for (entry = db_tree; entry; entry = entry->next) {
5991 
5992  queue_name = entry->key + strlen(pm_family) + 2;
5993 
5994  {
5995  struct call_queue tmpq = {
5996  .name = queue_name,
5997  };
5998  cur_queue = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Reload queue members");
5999  }
6000 
6001  if (!cur_queue)
6002  cur_queue = load_realtime_queue(queue_name);
6003 
6004  if (!cur_queue) {
6005  /* If the queue no longer exists, remove it from the
6006  * database */
6007  ast_log(LOG_WARNING, "Error loading persistent queue: '%s': it does not exist\n", queue_name);
6008  ast_db_del(pm_family, queue_name);
6009  continue;
6010  }
6011 
6012  if (ast_db_get_allocated(pm_family, queue_name, &queue_data)) {
6013  queue_t_unref(cur_queue, "Expire reload reference");
6014  continue;
6015  }
6016 
6017  cur_ptr = queue_data;
6018  while ((member = strsep(&cur_ptr, ",|"))) {
6019  if (ast_strlen_zero(member))
6020  continue;
6021 
6022  interface = strsep(&member, ";");
6023  penalty_tok = strsep(&member, ";");
6024  paused_tok = strsep(&member, ";");
6025  membername = strsep(&member, ";");
6026  state_interface = strsep(&member, ";");
6027 
6028  if (!penalty_tok) {
6029  ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (penalty)\n", queue_name);
6030  break;
6031  }
6032  penalty = strtol(penalty_tok, NULL, 10);
6033  if (errno == ERANGE) {
6034  ast_log(LOG_WARNING, "Error converting penalty: %s: Out of range.\n", penalty_tok);
6035  break;
6036  }
6037 
6038  if (!paused_tok) {
6039  ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (paused)\n", queue_name);
6040  break;
6041  }
6042  paused = strtol(paused_tok, NULL, 10);
6043  if ((errno == ERANGE) || paused < 0 || paused > 1) {
6044  ast_log(LOG_WARNING, "Error converting paused: %s: Expected 0 or 1.\n", paused_tok);
6045  break;
6046  }
6047 
6048  ast_debug(1, "Reload Members: Queue: %s Member: %s Name: %s Penalty: %d Paused: %d\n", queue_name, interface, membername, penalty, paused);
6049 
6050  if (add_to_queue(queue_name, interface, membername, penalty, paused, 0, state_interface) == RES_OUTOFMEMORY) {
6051  ast_log(LOG_ERROR, "Out of Memory when reloading persistent queue member\n");
6052  break;
6053  }
6054  }
6055  queue_t_unref(cur_queue, "Expire reload reference");
6056  ast_free(queue_data);
6057  }
6058 
6059  if (db_tree) {
6060  ast_log(LOG_NOTICE, "Queue members successfully reloaded from database.\n");
6061  ast_db_freetree(db_tree);
6062  }
6063 }
6064 
#define ao2_t_find(arg1, arg2, arg3, arg4)
Definition: astobj2.h:963
char * strsep(char **str, const char *delims)
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
#define LOG_WARNING
Definition: logger.h:144
void ast_db_freetree(struct ast_db_entry *entry)
Free structure created by ast_db_gettree()
Definition: db.c:656
int ast_db_get_allocated(const char *family, const char *key, char **out)
Get key value specified by family/key as a heap allocated string.
Definition: db.c:358
#define RES_OUTOFMEMORY
Definition: app_queue.c:1035
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
struct ast_db_entry * next
Definition: astdb.h:31
static struct ao2_container * queues
Definition: app_queue.c:1334
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define LOG_ERROR
Definition: logger.h:155
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree If family is specified, only those keys will be returned...
Definition: db.c:631
static struct call_queue * load_realtime_queue(const char *queuename)
Definition: app_queue.c:2573
const ast_string_field name
Definition: app_queue.c:1266
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
Definition: astdb.h:30
int errno
#define ast_free(a)
Definition: astmm.h:97
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: db.c:365
static const char *const pm_family
Persistent Members astdb family.
Definition: app_queue.c:1052
static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump, const char *state_interface)
Add member to queue.
Definition: app_queue.c:5763
char * key
Definition: astdb.h:32
static int reload_queue_rules ( int  reload)
static

Reload the rules defined in queuerules.conf.

Parameters
reloadIf 1, then only process queuerules.conf if the file has changed since the last time we inspected it.
Returns
Always returns AST_MODULE_LOAD_SUCCESS

Definition at line 7144 of file app_queue.c.

References ast_calloc, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_log(), AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_variable_browse(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, insert_penaltychange(), ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_variable::name, rule_list::name, ast_variable::next, rule_list::rules, and ast_variable::value.

Referenced by reload_handler().

7144 {
7145  struct ast_config *cfg;
7146  struct rule_list *rl_iter, *new_rl;
7147  struct penalty_rule *pr_iter;
7148  char *rulecat = NULL;
7149  struct ast_variable *rulevar = NULL;
7150  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
7151 
7152  if (!(cfg = ast_config_load("queuerules.conf", config_flags))) {
7153  ast_log(LOG_NOTICE, "No queuerules.conf file found, queues will not follow penalty rules\n");
7154  return AST_MODULE_LOAD_SUCCESS;
7155  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
7156  ast_log(LOG_NOTICE, "queuerules.conf has not changed since it was last loaded. Not taking any action.\n");
7157  return AST_MODULE_LOAD_SUCCESS;
7158  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
7159  ast_log(LOG_ERROR, "Config file queuerules.conf is in an invalid format. Aborting.\n");
7160  return AST_MODULE_LOAD_SUCCESS;
7161  }
7162 
7164  while ((rl_iter = AST_LIST_REMOVE_HEAD(&rule_lists, list))) {
7165  while ((pr_iter = AST_LIST_REMOVE_HEAD(&rl_iter->rules, list)))
7166  ast_free(pr_iter);
7167  ast_free(rl_iter);
7168  }
7169  while ((rulecat = ast_category_browse(cfg, rulecat))) {
7170  if (!(new_rl = ast_calloc(1, sizeof(*new_rl)))) {
7172  ast_config_destroy(cfg);
7173  return AST_MODULE_LOAD_FAILURE;
7174  } else {
7175  ast_copy_string(new_rl->name, rulecat, sizeof(new_rl->name));
7176  AST_LIST_INSERT_TAIL(&rule_lists, new_rl, list);
7177  for (rulevar = ast_variable_browse(cfg, rulecat); rulevar; rulevar = rulevar->next)
7178  if(!strcasecmp(rulevar->name, "penaltychange"))
7179  insert_penaltychange(new_rl->name, rulevar->value, rulevar->lineno);
7180  else
7181  ast_log(LOG_WARNING, "Don't know how to handle rule type '%s' on line %d\n", rulevar->name, rulevar->lineno);
7182  }
7183  }
7185 
7186  ast_config_destroy(cfg);
7187 
7188  return AST_MODULE_LOAD_SUCCESS;
7189 }
7190 
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
struct rule_list::@58 rules
char name[80]
Definition: app_queue.c:1327
static int reload(void)
Definition: app_queue.c:9202
#define LOG_WARNING
Definition: logger.h:144
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
int lineno
Definition: config.h:87
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
static int insert_penaltychange(const char *list_name, const char *content, const int linenum)
Change queue penalty by adding rule.
Definition: app_queue.c:1972
const char * value
Definition: config.h:79
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
const char * name
Definition: config.h:77
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
#define LOG_ERROR
Definition: logger.h:155
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
#define ast_free(a)
Definition: astmm.h:97
Structure used to handle boolean flags.
Definition: utils.h:200
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
struct ast_variable * next
Definition: config.h:82
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
#define CONFIG_STATUS_FILEUNCHANGED
Definition: config.h:51
static int reload_queues ( int  reload,
struct ast_flags mask,
const char *  queuename 
)
static

reload the queues.conf file

This function reloads the information in the general section of the queues.conf file and potentially more, depending on the value of mask.

Parameters
reload0 if we are calling this the first time, 1 every other time
maskGives flags telling us what information to actually reload
queuenameIf set to a non-zero string, then only reload information from that particular queue. Otherwise inspect all queues
Return values
-1Failure occurred
0All clear!

Definition at line 7477 of file app_queue.c.

References ao2_callback, ao2_lock, ao2_unlock, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_log(), ast_strlen_zero(), ast_test_flag, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, kill_dead_queues(), LOG_ERROR, LOG_NOTICE, mark_dead_and_unfound(), OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, QUEUE_RELOAD_MEMBER, QUEUE_RELOAD_PARAMETERS, queue_set_global_params(), queues, reload_single_queue(), and remove_members_and_mark_unfound().

Referenced by reload_handler().

7477 {
7478  struct ast_config *cfg;
7479  char *cat;
7480  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
7481  const int queue_reload = ast_test_flag(mask, QUEUE_RELOAD_PARAMETERS);
7482  const int member_reload = ast_test_flag(mask, QUEUE_RELOAD_MEMBER);
7483 
7484  if (!(cfg = ast_config_load("queues.conf", config_flags))) {
7485  ast_log(LOG_NOTICE, "No call queueing config file (queues.conf), so no call queues\n");
7486  return -1;
7487  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
7488  return 0;
7489  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
7490  ast_log(LOG_ERROR, "Config file queues.conf is in an invalid format. Aborting.\n");
7491  return -1;
7492  }
7493 
7494  /* We've made it here, so it looks like we're doing operations on all queues. */
7495  ao2_lock(queues);
7496 
7497  /* Mark all queues as dead for the moment if we're reloading queues.
7498  * For clarity, we could just be reloading members, in which case we don't want to mess
7499  * with the other queue parameters at all*/
7500  if (queue_reload) {
7501  ao2_callback(queues, OBJ_NODATA, mark_dead_and_unfound, (char *) queuename);
7502  }
7503 
7504  if (member_reload) {
7506  }
7507 
7508  /* Chug through config file */
7509  cat = NULL;
7510  while ((cat = ast_category_browse(cfg, cat)) ) {
7511  if (!strcasecmp(cat, "general") && queue_reload) {
7513  continue;
7514  }
7515  if (ast_strlen_zero(queuename) || !strcasecmp(cat, queuename))
7516  reload_single_queue(cfg, mask, cat);
7517  }
7518 
7519  ast_config_destroy(cfg);
7520  /* Unref all the dead queues if we were reloading queues */
7521  if (queue_reload) {
7523  }
7524  ao2_unlock(queues);
7525  return 0;
7526 }
7527 
static int remove_members_and_mark_unfound(void *obj, void *arg, int flags)
Definition: app_queue.c:7432
#define ast_test_flag(p, flag)
Definition: utils.h:63
static int reload(void)
Definition: app_queue.c:9202
static int mark_dead_and_unfound(void *obj, void *arg, int flags)
Definition: app_queue.c:7443
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:910
#define ao2_unlock(a)
Definition: astobj2.h:497
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
static struct ao2_container * queues
Definition: app_queue.c:1334
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
#define ao2_lock(a)
Definition: astobj2.h:488
static void queue_set_global_params(struct ast_config *cfg)
Definition: app_queue.c:7193
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
Structure used to handle boolean flags.
Definition: utils.h:200
static void reload_single_queue(struct ast_config *cfg, struct ast_flags *mask, const char *queuename)
Reload information pertaining to a particular queue.
Definition: app_queue.c:7333
static int kill_dead_queues(void *obj, void *arg, int flags)
Definition: app_queue.c:7454
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
#define CONFIG_STATUS_FILEUNCHANGED
Definition: config.h:51
static void reload_single_member ( const char *  memberdata,
struct call_queue q 
)
static

reload information pertaining to a single member

This function is called when a member = line is encountered in queues.conf.

Parameters
memberdataThe part after member = in the config file
qThe queue to which this member belongs

Definition at line 7226 of file app_queue.c.

References ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlink, ao2_unlock, args, AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strip(), ast_strlen_zero(), create_queue_member(), member::interface, LOG_WARNING, member_add_to_queue(), call_queue::members, OBJ_POINTER, parse(), member::paused, member::penalty, and member::queuepos.

Referenced by reload_single_queue().

7226 {
7227  char *membername, *interface, *state_interface, *tmp;
7228  char *parse;
7229  struct member *cur, *newm;
7230  struct member tmpmem;
7231  int penalty;
7233  AST_APP_ARG(interface);
7234  AST_APP_ARG(penalty);
7235  AST_APP_ARG(membername);
7236  AST_APP_ARG(state_interface);
7237  );
7238 
7239  if (ast_strlen_zero(memberdata)) {
7240  ast_log(LOG_WARNING, "Empty queue member definition. Moving on!\n");
7241  return;
7242  }
7243 
7244  /* Add a new member */
7245  parse = ast_strdupa(memberdata);
7246 
7247  AST_STANDARD_APP_ARGS(args, parse);
7248 
7249  interface = args.interface;
7250  if (!ast_strlen_zero(args.penalty)) {
7251  tmp = args.penalty;
7252  ast_strip(tmp);
7253  penalty = atoi(tmp);
7254  if (penalty < 0) {
7255  penalty = 0;
7256  }
7257  } else {
7258  penalty = 0;
7259  }
7260 
7261  if (!ast_strlen_zero(args.membername)) {
7262  membername = args.membername;
7263  ast_strip(membername);
7264  } else {
7265  membername = interface;
7266  }
7267 
7268  if (!ast_strlen_zero(args.state_interface)) {
7269  state_interface = args.state_interface;
7270  ast_strip(state_interface);
7271  } else {
7272  state_interface = interface;
7273  }
7274 
7275  /* Find the old position in the list */
7276  ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
7277  cur = ao2_find(q->members, &tmpmem, OBJ_POINTER);
7278 
7279  if ((newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0, state_interface))) {
7280  if (cur) {
7281  /* Round Robin Queue Position must be copied if this is replacing an existing member */
7282  ao2_lock(q->members);
7283  newm->queuepos = cur->queuepos;
7284  ao2_link(q->members, newm);
7285  ao2_unlink(q->members, cur);
7286  ao2_unlock(q->members);
7287  } else {
7288  /* Otherwise we need to add using the function that will apply a round robin queue position manually. */
7289  member_add_to_queue(q, newm);
7290  }
7291  ao2_ref(newm, -1);
7292  }
7293  newm = NULL;
7294 
7295  if (cur) {
7296  ao2_ref(cur, -1);
7297  }
7298 }
7299 
int queuepos
Definition: app_queue.c:1186
#define ao2_link(arg1, arg2)
Definition: astobj2.h:785
int paused
Definition: app_queue.c:1185
#define LOG_WARNING
Definition: logger.h:144
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_container * members
Definition: app_queue.c:1320
static void member_add_to_queue(struct call_queue *queue, struct member *mem)
Definition: app_queue.c:2300
int penalty
Definition: app_queue.c:1180
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:155
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static struct @350 args
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ao2_find(arg1, arg2, arg3)
Definition: astobj2.h:964
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
static struct member * create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface)
allocate space for new queue member and set fields based on parameters passed
Definition: app_queue.c:1801
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
#define ao2_unlink(arg1, arg2)
Definition: astobj2.h:817
static void reload_single_queue ( struct ast_config cfg,
struct ast_flags mask,
const char *  queuename 
)
static

Reload information pertaining to a particular queue.

Once we have isolated a queue within reload_queues, we call this. This will either reload information for the queue or if we're just reloading member information, we'll just reload that without touching other settings within the queue

Parameters
cfgThe configuration which we are reading
maskTells us what information we need to reload
queuenameThe name of the queue we are reloading information from
Return values
void

Definition at line 7333 of file app_queue.c.

References alloc_queue(), ao2_callback, ao2_lock, ao2_t_find, ao2_unlock, ast_atomic_fetchadd_int(), ast_log(), ast_test_flag, ast_variable_browse(), ast_variable_retrieve(), call_queue::found, init_queue(), kill_dead_members(), ast_variable::lineno, LOG_WARNING, mark_member_dead(), call_queue::members, ast_variable::name, call_queue::name, ast_variable::next, OBJ_MULTIPLE, OBJ_NODATA, OBJ_POINTER, OBJ_UNLINK, queue_delme_members_decrement_followers(), QUEUE_RELOAD_MEMBER, QUEUE_RELOAD_PARAMETERS, queue_set_param(), QUEUE_STRATEGY_RINGALL, queue_t_unref, queues, queues_t_link, reload_single_member(), strat2int(), call_queue::strategy, ast_variable::value, var, and call_queue::weight.

Referenced by reload_queues().

7333 {
7334  int new;
7335  struct call_queue *q = NULL;
7336  /*We're defining a queue*/
7337  struct call_queue tmpq = {
7338  .name = queuename,
7339  };
7340  const char *tmpvar;
7341  const int queue_reload = ast_test_flag(mask, QUEUE_RELOAD_PARAMETERS);
7342  const int member_reload = ast_test_flag(mask, QUEUE_RELOAD_MEMBER);
7343  int prev_weight = 0;
7344  struct ast_variable *var;
7345  if (!(q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find queue for reload"))) {
7346  if (queue_reload) {
7347  /* Make one then */
7348  if (!(q = alloc_queue(queuename))) {
7349  return;
7350  }
7351  } else {
7352  /* Since we're not reloading queues, this means that we found a queue
7353  * in the configuration file which we don't know about yet. Just return.
7354  */
7355  return;
7356  }
7357  new = 1;
7358  } else {
7359  new = 0;
7360  }
7361 
7362  if (!new) {
7363  ao2_lock(q);
7364  prev_weight = q->weight ? 1 : 0;
7365  }
7366  /* Check if we already found a queue with this name in the config file */
7367  if (q->found) {
7368  ast_log(LOG_WARNING, "Queue '%s' already defined! Skipping!\n", queuename);
7369  if (!new) {
7370  /* It should be impossible to *not* hit this case*/
7371  ao2_unlock(q);
7372  }
7373  queue_t_unref(q, "We exist! Expiring temporary pointer");
7374  return;
7375  }
7376  /* Due to the fact that the "linear" strategy will have a different allocation
7377  * scheme for queue members, we must devise the queue's strategy before other initializations.
7378  * To be specific, the linear strategy needs to function like a linked list, meaning the ao2
7379  * container used will have only a single bucket instead of the typical number.
7380  */
7381  if (queue_reload) {
7382  if ((tmpvar = ast_variable_retrieve(cfg, queuename, "strategy"))) {
7383  q->strategy = strat2int(tmpvar);
7384  if (q->strategy < 0) {
7385  ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
7386  tmpvar, q->name);
7388  }
7389  } else {
7391  }
7392  init_queue(q);
7393  }
7394  if (member_reload) {
7396  q->found = 1;
7397  }
7398  for (var = ast_variable_browse(cfg, queuename); var; var = var->next) {
7399  if (member_reload && !strcasecmp(var->name, "member")) {
7400  reload_single_member(var->value, q);
7401  } else if (queue_reload) {
7402  queue_set_param(q, var->name, var->value, var->lineno, 1);
7403  }
7404  }
7405  /* At this point, we've determined if the queue has a weight, so update use_weight
7406  * as appropriate
7407  */
7408  if (!q->weight && prev_weight) {
7410  }
7411  else if (q->weight && !prev_weight) {
7413  }
7414 
7415  /* Free remaining members marked as delme */
7416  if (member_reload) {
7417  ao2_lock(q->members);
7420  ao2_unlock(q->members);
7421  }
7422 
7423  if (new) {
7424  queues_t_link(queues, q, "Add queue to container");
7425  } else {
7426  ao2_unlock(q);
7427  }
7428  queue_t_unref(q, "Expiring creation reference");
7429 }
7430 
#define ao2_t_find(arg1, arg2, arg3, arg4)
Definition: astobj2.h:963
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
static int mark_member_dead(void *obj, void *arg, int flags)
Definition: app_queue.c:7301
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:144
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:910
int lineno
Definition: config.h:87
static int kill_dead_members(void *obj, void *arg, int flags)
Definition: app_queue.c:7310
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define var
Definition: ast_expr2f.c:606
static void reload_single_member(const char *memberdata, struct call_queue *q)
reload information pertaining to a single member
Definition: app_queue.c:7226
#define ao2_unlock(a)
Definition: astobj2.h:497
static int queue_delme_members_decrement_followers(void *obj, void *arg, int flag)
Definition: app_queue.c:1433
struct ao2_container * members
Definition: app_queue.c:1320
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
static int strat2int(const char *strategy)
Definition: app_queue.c:1365
const char * value
Definition: config.h:79
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:2093
static struct ao2_container * queues
Definition: app_queue.c:1334
#define ao2_lock(a)
Definition: astobj2.h:488
const char * name
Definition: config.h:77
int strategy
Definition: app_queue.c:1281
const ast_string_field name
Definition: app_queue.c:1266
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct call_queue * alloc_queue(const char *queuename)
Definition: app_queue.c:2418
#define queues_t_link(c, q, tag)
Definition: app_queue.c:1474
unsigned int found
Definition: app_queue.c:1284
static int use_weight
queues.conf per-queue weight option
Definition: app_queue.c:1061
struct ast_variable * next
Definition: config.h:82
static void init_queue(struct call_queue *q)
Initialize Queue default values.
Definition: app_queue.c:1865
static int remove_from_queue ( const char *  queuename,
const char *  interface 
)
static

Remove member from queue.

Return values
RES_NOT_DYNAMICwhen they aren't a RT member
RES_NOSUCHQUEUEqueue does not exist
RES_OKAYremoved member from queue
RES_EXISTSqueue exists but no members

Definition at line 5715 of file app_queue.c.

References ao2_find, ao2_lock, ao2_ref, ao2_t_find, ao2_unlock, ast_copy_string(), dump_queue_members(), member::dynamic, EVENT_FLAG_AGENT, member::interface, manager_event, member_remove_from_queue(), member::membername, call_queue::members, call_queue::name, OBJ_POINTER, queue_t_unref, queues, RES_EXISTS, RES_NOSUCHQUEUE, RES_NOT_DYNAMIC, and RES_OKAY.

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

5715 {
5716  struct call_queue *q, tmpq = {
5717  .name = queuename,
5718  };
5719  struct member *mem, tmpmem;
5720  int res = RES_NOSUCHQUEUE;
5721 
5722  ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
5723  if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Temporary reference for interface removal"))) {
5724  ao2_lock(q);
5725  if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) {
5726  /* XXX future changes should beware of this assumption!! */
5727  if (!mem->dynamic) {
5728  ao2_ref(mem, -1);
5729  ao2_unlock(q);
5730  queue_t_unref(q, "Interface wasn't dynamic, expiring temporary reference");
5731  return RES_NOT_DYNAMIC;
5732  }
5733  manager_event(EVENT_FLAG_AGENT, "QueueMemberRemoved",
5734  "Queue: %s\r\n"
5735  "Location: %s\r\n"
5736  "MemberName: %s\r\n",
5737  q->name, mem->interface, mem->membername);
5738  member_remove_from_queue(q, mem);
5739  ao2_ref(mem, -1);
5740 
5742  dump_queue_members(q);
5743 
5744  res = RES_OKAY;
5745  } else {
5746  res = RES_EXISTS;
5747  }
5748  ao2_unlock(q);
5749  queue_t_unref(q, "Expiring temporary reference");
5750  }
5751 
5752  return res;
5753 }
5754 
#define ao2_t_find(arg1, arg2, arg3, arg4)
Definition: astobj2.h:963
int dynamic
Definition: app_queue.c:1182
#define RES_OKAY
Definition: app_queue.c:1033
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
static void member_remove_from_queue(struct call_queue *queue, struct member *mem)
Definition: app_queue.c:2314
#define RES_NOT_DYNAMIC
Definition: app_queue.c:1037
char interface[80]
Definition: app_queue.c:1175
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_container * members
Definition: app_queue.c:1320
char membername[80]
Definition: app_queue.c:1179
static struct ao2_container * queues
Definition: app_queue.c:1334
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
const ast_string_field name
Definition: app_queue.c:1266
#define EVENT_FLAG_AGENT
Definition: manager.h:76
static void dump_queue_members(struct call_queue *pm_queue)
Dump all members in a specific queue to the database.
Definition: app_queue.c:5663
#define ao2_find(arg1, arg2, arg3)
Definition: astobj2.h:964
#define RES_NOSUCHQUEUE
Definition: app_queue.c:1036
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define RES_EXISTS
Definition: app_queue.c:1034
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
static int queue_persistent_members
queues.conf [general] option
Definition: app_queue.c:1058
static int remove_members_and_mark_unfound ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 7432 of file app_queue.c.

References ast_strlen_zero(), call_queue::found, call_queue::name, and call_queue::realtime.

Referenced by reload_queues().

7432 {
7433  struct call_queue *q = obj;
7434  char *queuename = arg;
7435  if (!q->realtime && (ast_strlen_zero(queuename) || !strcasecmp(queuename, q->name))) {
7436  q->found = 0;
7437 
7438  }
7439  return 0;
7440 }
7441 
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
const ast_string_field name
Definition: app_queue.c:1266
unsigned int found
Definition: app_queue.c:1284
unsigned int realtime
Definition: app_queue.c:1283
static int ring_entry ( struct queue_ent qe,
struct callattempt tmp,
int *  busies 
)
static

Part 2 of ring_one.

Does error checking before attempting to request a channel and call a member. This function is only called from ring_one(). Failure can occur if:

  • Agent on call
  • Agent is paused
  • Wrapup time not expired
  • Priority by another queue
Return values
1on success to reach a free agent
0on failure to get agent.

Definition at line 3368 of file app_queue.c.

References ast_cdr::accountcode, ast_channel::adsicpe, ast_cdr::amaflags, ast_party_caller::ani, ast_party_connected_line::ani, ao2_lock, ao2_unlock, ast_channel::appl, ast_assert, ast_call(), ast_cdr_busy(), ast_cdr_isset_unanswered(), ast_cdr_setdestchan(), ast_channel_datastore_inherit(), ast_channel_inherit_variables(), ast_channel_lock_both, ast_channel_set_caller_event(), ast_channel_unlock, ast_connected_line_copy_from_caller(), ast_copy_string(), AST_FLAG_ANSWERED_ELSEWHERE, ast_log(), ast_party_caller_set_init(), ast_party_redirecting_copy(), ast_request(), ast_set_callerid(), ast_set_flag, ast_string_field_set, ast_strlen_zero(), ast_verb, member::call_pending, ast_channel::caller, can_ring_entry(), queue_ent::cancel_answered_elsewhere, ast_channel::cdr, callattempt::chan, queue_ent::chan, ast_cdr::channel, ast_cdr::clid, ast_channel::connected, ast_channel::context, ast_channel::data, ast_cdr::dcontext, callattempt::dial_callerid_absent, dialcontext, ast_channel::dialed, do_hang(), ast_cdr::dst, EVENT_FLAG_AGENT, call_queue::eventwhencalled, ast_channel::exten, ast_party_caller::id, ast_party_connected_line::id, callattempt::interface, ast_cdr::lastapp, ast_cdr::lastdata, queue_ent::linpos, LOG_DEBUG, LOG_NOTICE, ast_channel::macroexten, manager_event, callattempt::member, member_call_pending_clear(), member::membername, ast_party_id::name, ast_channel::name, call_queue::name, ast_channel::nativeformats, ast_party_id::number, ast_party_dialed::number, option_debug, queue_ent::parent, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), ast_channel::priority, QUEUE_EVENT_VARIABLES, ast_channel::redirecting, call_queue::ringinuse, call_queue::rrpos, S_COR, S_OR, ast_cdr::src, status, callattempt::stillgoing, ast_party_name::str, ast_party_number::str, ast_party_dialed::str, ast_party_dialed::transit_network_select, ast_channel::uniqueid, ast_cdr::userfield, ast_party_name::valid, ast_party_number::valid, vars2manager(), and ast_channel::whentohangup.

Referenced by ring_one().

3368 {
3369  int res;
3370  int status;
3371  char tech[256];
3372  char *location, *location2;
3373  const char *macrocontext, *macroexten;
3374  char pickupmark[256], chan[128];
3375 
3376  /* on entry here, we know that tmp->chan == NULL */
3377  if (!can_ring_entry(qe, tmp)) {
3378  tmp->stillgoing = 0;
3379  (*busies)++;
3380  return 0;
3381  }
3383 
3384  ast_copy_string(tech, tmp->interface, sizeof(tech));
3385  if ((location = strchr(tech, '/')))
3386  *location++ = '\0';
3387  else
3388  location = "";
3389 
3390  /* Request the peer */
3391  tmp->chan = ast_request(tech, qe->chan->nativeformats, qe->chan, location, &status);
3392  if (!tmp->chan) { /* If we can't, just go on to the next call */
3393  if (queue_debug)
3394  ast_log(LOG_NOTICE, "Unable to create channel of type '%s' for Queue\n", tech);
3395  ao2_lock(qe->parent);
3396  qe->parent->rrpos++;
3397  qe->linpos++;
3398  ao2_unlock(qe->parent);
3399 
3401 
3402  if (qe->chan->cdr) {
3403  ast_cdr_busy(qe->chan->cdr);
3404  }
3405  tmp->stillgoing = 0;
3406  (*busies)++;
3407  return 0;
3408  }
3409 
3410  ast_channel_lock_both(tmp->chan, qe->chan);
3411 
3412  if (qe->cancel_answered_elsewhere) {
3414  }
3415  tmp->chan->appl = "AppQueue";
3416  tmp->chan->data = "(Outgoing Line)";
3417  memset(&tmp->chan->whentohangup, 0, sizeof(tmp->chan->whentohangup));
3418 
3419  /* If the new channel has no callerid, try to guess what it should be */
3420  if (!tmp->chan->caller.id.number.valid) {
3421  if (qe->chan->connected.id.number.valid) {
3422  struct ast_party_caller caller;
3423 
3424  ast_party_caller_set_init(&caller, &tmp->chan->caller);
3425  caller.id = qe->chan->connected.id;
3426  caller.ani = qe->chan->connected.ani;
3427  ast_channel_set_caller_event(tmp->chan, &caller, NULL);
3428  } else if (!ast_strlen_zero(qe->chan->dialed.number.str)) {
3429  ast_set_callerid(tmp->chan, qe->chan->dialed.number.str, NULL, NULL);
3430  } else if (!ast_strlen_zero(S_OR(qe->chan->macroexten, qe->chan->exten))) {
3431  ast_set_callerid(tmp->chan, S_OR(qe->chan->macroexten, qe->chan->exten), NULL, NULL);
3432  }
3433  tmp->dial_callerid_absent = 1;
3434  }
3435 
3437 
3439 
3441 
3442  /* Inherit specially named variables from parent channel */
3445 
3446  /* Presense of ADSI CPE on outgoing channel follows ours */
3447  tmp->chan->adsicpe = qe->chan->adsicpe;
3448 
3449  /* Inherit context and extension */
3450  macrocontext = pbx_builtin_getvar_helper(qe->chan, "MACRO_CONTEXT");
3451  ast_string_field_set(tmp->chan, dialcontext, ast_strlen_zero(macrocontext) ? qe->chan->context : macrocontext);
3452  macroexten = pbx_builtin_getvar_helper(qe->chan, "MACRO_EXTEN");
3453  if (!ast_strlen_zero(macroexten))
3454  ast_copy_string(tmp->chan->exten, macroexten, sizeof(tmp->chan->exten));
3455  else
3456  ast_copy_string(tmp->chan->exten, qe->chan->exten, sizeof(tmp->chan->exten));
3457  if (ast_cdr_isset_unanswered()) {
3458  /* they want to see the unanswered dial attempts! */
3459  /* set up the CDR fields on all the CDRs to give sensical information */
3460  ast_cdr_setdestchan(tmp->chan->cdr, tmp->chan->name);
3461  strcpy(tmp->chan->cdr->clid, qe->chan->cdr->clid);
3462  strcpy(tmp->chan->cdr->channel, qe->chan->cdr->channel);
3463  strcpy(tmp->chan->cdr->src, qe->chan->cdr->src);
3464  strcpy(tmp->chan->cdr->dst, qe->chan->exten);
3465  strcpy(tmp->chan->cdr->dcontext, qe->chan->context);
3466  strcpy(tmp->chan->cdr->lastapp, qe->chan->cdr->lastapp);
3467  strcpy(tmp->chan->cdr->lastdata, qe->chan->cdr->lastdata);
3468  tmp->chan->cdr->amaflags = qe->chan->cdr->amaflags;
3469  strcpy(tmp->chan->cdr->accountcode, qe->chan->cdr->accountcode);
3470  strcpy(tmp->chan->cdr->userfield, qe->chan->cdr->userfield);
3471  }
3472 
3473  ast_channel_unlock(tmp->chan);
3474  ast_channel_unlock(qe->chan);
3475 
3476  /* Add a PICKUPMARK variable to ringing interface */
3477  if (option_debug > 2)
3478  ast_log(LOG_DEBUG, "chan %s, tech: %s, part %s\n", tmp->chan->name, tech, location);
3479  /* Delete DAHDI ring pattern in tech like DAHDI/1r2 */
3480  ast_copy_string(chan, location, sizeof(chan));
3481  if (!strncasecmp(tech, "dahdi", 5)) {
3482  if((chan[0] > '0') && (chan[0] <= '9')) {
3483  if ((location2 = strchr(chan, 'r')))
3484  *location2++ = '\0';
3485  }
3486  }
3487  snprintf(pickupmark, sizeof(pickupmark), "%s/%s", tech, chan);
3488  pbx_builtin_setvar_helper(tmp->chan, "PICKUPMARK", pickupmark);
3489 
3490  /* Place the call, but don't wait on the answer */
3491  if ((res = ast_call(tmp->chan, location, 0))) {
3492  /* Again, keep going even if there's an error */
3493  ast_verb(3, "Couldn't call %s\n", tmp->interface);
3494  do_hang(tmp);
3496  ++*busies;
3497  return 0;
3498  }
3499 
3500  if (qe->parent->eventwhencalled) {
3501  char vars[2048];
3502 
3503  ast_channel_lock_both(tmp->chan, qe->chan);
3504 
3505  manager_event(EVENT_FLAG_AGENT, "AgentCalled",
3506  "Queue: %s\r\n"
3507  "AgentCalled: %s\r\n"
3508  "AgentName: %s\r\n"
3509  "ChannelCalling: %s\r\n"
3510  "DestinationChannel: %s\r\n"
3511  "CallerIDNum: %s\r\n"
3512  "CallerIDName: %s\r\n"
3513  "ConnectedLineNum: %s\r\n"
3514  "ConnectedLineName: %s\r\n"
3515  "Context: %s\r\n"
3516  "Extension: %s\r\n"
3517  "Priority: %d\r\n"
3518  "Uniqueid: %s\r\n"
3519  "%s",
3520  qe->parent->name, tmp->interface, tmp->member->membername, qe->chan->name, tmp->chan->name,
3521  S_COR(qe->chan->caller.id.number.valid, qe->chan->caller.id.number.str, "unknown"),
3522  S_COR(qe->chan->caller.id.name.valid, qe->chan->caller.id.name.str, "unknown"),
3523  S_COR(qe->chan->connected.id.number.valid, qe->chan->connected.id.number.str, "unknown"),
3524  S_COR(qe->chan->connected.id.name.valid, qe->chan->connected.id.name.str, "unknown"),
3525  qe->chan->context, qe->chan->exten, qe->chan->priority, qe->chan->uniqueid,
3526  qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
3527 
3528  ast_channel_unlock(tmp->chan);
3529  ast_channel_unlock(qe->chan);
3530 
3531  ast_verb(3, "Called %s\n", tmp->interface);
3532  }
3533 
3535  return 1;
3536 }
3537 
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
Definition: channel.c:7051
struct call_queue * parent
Definition: app_queue.c:1144
int ast_cdr_isset_unanswered(void)
Definition: cdr.c:185
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:114
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
struct ast_party_connected_line connected
Channel Connected Line ID information.
Definition: channel.h:811
char * str
Subscriber phone number (Malloced)
Definition: channel.h:336
void ast_channel_set_caller_event(struct ast_channel *chan, const struct ast_party_caller *caller, const struct ast_set_party_caller *update)
Set the caller id information in the Asterisk channel and generate an AMI event if the caller id name...
Definition: channel.c:7091
unsigned int eventwhencalled
Definition: app_queue.c:1270
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
struct ast_channel * chan
Definition: app_queue.c:1168
int priority
Definition: channel.h:841
const ast_string_field uniqueid
Definition: channel.h:787
struct ast_party_id id
Connected party ID.
Definition: channel.h:403
int option_debug
Definition: asterisk.c:182
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define ast_set_flag(p, flag)
Definition: utils.h:70
unsigned int ringinuse
Definition: app_queue.c:1271
char dcontext[AST_MAX_EXTENSION]
Definition: cdr.h:90
static void member_call_pending_clear(struct member *mem)
Definition: app_queue.c:3264
struct ast_party_redirecting redirecting
Redirecting/Diversion information.
Definition: channel.h:814
char * str
Subscriber name (Malloced)
Definition: channel.h:214
char interface[256]
Definition: app_queue.c:1124
#define ast_assert(a)
Definition: utils.h:738
struct ast_cdr * cdr
Definition: channel.h:766
#define ao2_unlock(a)
Definition: astobj2.h:497
format_t nativeformats
Definition: channel.h:852
const char * data
Definition: channel.h:755
static int can_ring_entry(struct queue_ent *qe, struct callattempt *call)
Definition: app_queue.c:3300
#define LOG_DEBUG
Definition: logger.h:122
enum ast_channel_adsicpe adsicpe
Definition: channel.h:844
#define ast_verb(level,...)
Definition: logger.h:243
const char * appl
Definition: channel.h:754
char membername[80]
Definition: app_queue.c:1179
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
char lastdata[AST_MAX_EXTENSION]
Definition: cdr.h:98
long int amaflags
Definition: cdr.h:112
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition: channel.c:2573
static char * vars2manager(struct ast_channel *chan, char *vars, size_t len)
convert &quot;\n&quot; to &quot;\nVariable: &quot; ready for manager to use
Definition: app_queue.c:3206
static char dialcontext[AST_MAX_CONTEXT]
struct ast_party_dialed::@155 number
Dialed/Called number.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
Caller Party information.
Definition: channel.h:368
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
#define ao2_lock(a)
Definition: astobj2.h:488
struct member * member
Definition: app_queue.c:1128
char dst[AST_MAX_EXTENSION]
Definition: cdr.h:88
char channel[AST_MAX_EXTENSION]
Definition: cdr.h:92
struct ast_party_id ani
Automatic Number Identification (ANI)
Definition: channel.h:410
int linpos
Definition: app_queue.c:1163
struct ast_party_dialed dialed
Dialed/Called information.
Definition: channel.h:797
char lastapp[AST_MAX_EXTENSION]
Definition: cdr.h:96
void ast_party_caller_set_init(struct ast_party_caller *init, const struct ast_party_caller *guide)
Initialize the given caller structure using the given guide for a set update operation.
Definition: channel.c:2288
const ast_string_field name
Definition: app_queue.c:1266
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define EVENT_FLAG_AGENT
Definition: manager.h:76
#define LOG_NOTICE
Definition: logger.h:133
#define ast_channel_unlock(chan)
Definition: channel.h:2467
void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child)
Inherits channel variable from parent to child channel.
Definition: channel.c:6241
unsigned int call_pending
Definition: app_queue.c:1192
int ast_call(struct ast_channel *chan, char *addr, int timeout)
Make a call.
Definition: channel.c:5761
char src[AST_MAX_EXTENSION]
Definition: cdr.h:86
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...
Definition: pbx.c:10546
char macroexten[AST_MAX_EXTENSION]
Definition: channel.h:871
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2473
int transit_network_select
Transit Network Select.
Definition: channel.h:347
static int queue_debug
queues.conf [general] extra debug option
Definition: app_queue.c:1055
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
Copy the caller information to the connected line information.
Definition: channel.c:8443
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
struct timeval whentohangup
Definition: channel.h:789
static void do_hang(struct callattempt *o)
common hangup actions
Definition: app_queue.c:3198
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
char clid[AST_MAX_EXTENSION]
Definition: cdr.h:84
int cancel_answered_elsewhere
Definition: app_queue.c:1167
unsigned int dial_callerid_absent
Definition: app_queue.c:1136
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
struct ast_channel * chan
Definition: app_queue.c:1123
struct ast_channel * ast_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *status)
Requests a channel.
Definition: channel.c:5695
void ast_cdr_setdestchan(struct ast_cdr *cdr, const char *chan)
Set the destination channel, if there was one.
Definition: cdr.c:812
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
#define QUEUE_EVENT_VARIABLES
Definition: app_queue.c:1210
unsigned int stillgoing
Definition: app_queue.c:1138
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src)
Copy the source redirecting information to the destination redirecting.
Definition: channel.c:2367
jack_status_t status
Definition: app_jack.c:143
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.h:125
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
void ast_cdr_busy(struct ast_cdr *cdr)
Busy a call.
Definition: cdr.c:753
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int ring_one ( struct queue_ent qe,
struct callattempt outgoing,
int *  busies 
)
static

Place a call to a queue member.

Once metrics have been calculated for each member, this function is used to place a call to the appropriate member (or members). The low-level channel-handling and error detection is handled in ring_entry

Return values
1if a member was called successfully
0otherwise

Definition at line 3565 of file app_queue.c.

References ast_debug, callattempt::chan, queue_ent::expire, find_best(), callattempt::interface, callattempt::metric, queue_ent::parent, callattempt::q_next, QUEUE_STRATEGY_RINGALL, ring_entry(), callattempt::stillgoing, and call_queue::strategy.

Referenced by try_calling(), and wait_for_answer().

3565 {
3566  int ret = 0;
3567 
3568  while (ret == 0) {
3569  struct callattempt *best = find_best(outgoing);
3570  if (!best) {
3571  ast_debug(1, "Nobody left to try ringing in queue\n");
3572  break;
3573  }
3574  if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
3575  struct callattempt *cur;
3576  /* Ring everyone who shares this best metric (for ringall) */
3577  for (cur = outgoing; cur; cur = cur->q_next) {
3578  if (cur->stillgoing && !cur->chan && cur->metric <= best->metric) {
3579  ast_debug(1, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
3580  ret |= ring_entry(qe, cur, busies);
3581  }
3582  }
3583  } else {
3584  /* Ring just the best channel */
3585  ast_debug(1, "Trying '%s' with metric %d\n", best->interface, best->metric);
3586  ret = ring_entry(qe, best, busies);
3587  }
3588 
3589  /* If we have timed out, break out */
3590  if (qe->expire && (time(NULL) >= qe->expire)) {
3591  ast_debug(1, "Queue timed out while ringing members.\n");
3592  ret = 0;
3593  break;
3594  }
3595  }
3596 
3597  return ret;
3598 }
3599 
struct callattempt * q_next
Definition: app_queue.c:1121
struct call_queue * parent
Definition: app_queue.c:1144
time_t expire
Definition: app_queue.c:1166
char interface[256]
Definition: app_queue.c:1124
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static struct callattempt * find_best(struct callattempt *outgoing)
find the entry with the best metric, or NULL
Definition: app_queue.c:3540
int strategy
Definition: app_queue.c:1281
static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
Part 2 of ring_one.
Definition: app_queue.c:3368
We define a custom &quot;local user&quot; structure because we use it not only for keeping track of what is i...
Definition: app_queue.c:1120
struct ast_channel * chan
Definition: app_queue.c:1123
unsigned int stillgoing
Definition: app_queue.c:1138
static void rna ( int  rnatime,
struct queue_ent qe,
char *  interface,
char *  membername,
int  pause 
)
static

RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer.

Definition at line 3723 of file app_queue.c.

References ast_indicate(), ast_moh_start(), ast_queue_log(), ast_verb, call_queue::autopause, queue_ent::chan, EVENT_FLAG_AGENT, call_queue::eventwhencalled, manager_event, queue_ent::moh, ast_channel::name, call_queue::name, queue_ent::parent, QUEUE_AUTOPAUSE_OFF, QUEUE_AUTOPAUSE_ON, QUEUE_EVENT_VARIABLES, queue_ent::ring_when_ringing, set_member_paused(), ast_channel::uniqueid, and vars2manager().

Referenced by wait_for_answer().

3723 {
3724  ast_verb(3, "Nobody picked up in %d ms\n", rnatime);
3725 
3726  /* Stop ringing, and resume MOH if specified */
3727  if (qe->ring_when_ringing) {
3728  ast_indicate(qe->chan, -1);
3729  ast_moh_start(qe->chan, qe->moh, NULL);
3730  }
3731 
3732  if (qe->parent->eventwhencalled) {
3733  char vars[2048];
3734 
3735  manager_event(EVENT_FLAG_AGENT, "AgentRingNoAnswer",
3736  "Queue: %s\r\n"
3737  "Uniqueid: %s\r\n"
3738  "Channel: %s\r\n"
3739  "Member: %s\r\n"
3740  "MemberName: %s\r\n"
3741  "Ringtime: %d\r\n"
3742  "%s",
3743  qe->parent->name,
3744  qe->chan->uniqueid,
3745  qe->chan->name,
3746  interface,
3747  membername,
3748  rnatime,
3749  qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
3750  }
3751  ast_queue_log(qe->parent->name, qe->chan->uniqueid, membername, "RINGNOANSWER", "%d", rnatime);
3752  if (qe->parent->autopause != QUEUE_AUTOPAUSE_OFF && pause) {
3753  if (qe->parent->autopause == QUEUE_AUTOPAUSE_ON) {
3754  if (!set_member_paused(qe->parent->name, interface, "Auto-Pause", 1)) {
3755  ast_verb(3, "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n",
3756  interface, qe->parent->name);
3757  } else {
3758  ast_verb(3, "Failed to pause Queue Member %s in queue %s!\n", interface, qe->parent->name);
3759  }
3760  } else {
3761  /* If queue autopause is mode all, just don't send any queue to stop.
3762  * the function will stop in all queues */
3763  if (!set_member_paused("", interface, "Auto-Pause", 1)) {
3764  ast_verb(3, "Auto-Pausing Queue Member %s in all queues since they failed to answer on queue %s.\n",
3765  interface, qe->parent->name);
3766  } else {
3767  ast_verb(3, "Failed to pause Queue Member %s in all queues!\n", interface);
3768  }
3769  }
3770  }
3771  return;
3772 }
3773 
struct call_queue * parent
Definition: app_queue.c:1144
char moh[80]
Definition: app_queue.c:1145
unsigned int eventwhencalled
Definition: app_queue.c:1270
struct ast_channel * chan
Definition: app_queue.c:1168
const ast_string_field uniqueid
Definition: channel.h:787
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
int autopause
Definition: app_queue.c:1312
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
char interface[256]
Definition: app_queue.c:1124
#define ast_verb(level,...)
Definition: logger.h:243
static char * vars2manager(struct ast_channel *chan, char *vars, size_t len)
convert &quot;\n&quot; to &quot;\nVariable: &quot; ready for manager to use
Definition: app_queue.c:3206
int ring_when_ringing
Definition: app_queue.c:1153
const ast_string_field name
Definition: app_queue.c:1266
const ast_string_field name
Definition: channel.h:787
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:8040
#define EVENT_FLAG_AGENT
Definition: manager.h:76
static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused)
Definition: app_queue.c:5814
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
#define QUEUE_EVENT_VARIABLES
Definition: app_queue.c:1210
static int rqm_exec ( struct ast_channel chan,
const char *  data 
)
static

RemoveQueueMember application.

Definition at line 6139 of file app_queue.c.

References args, AST_APP_ARG, ast_debug, AST_DECLARE_APP_ARGS, ast_log(), ast_queue_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), LOG_NOTICE, LOG_WARNING, ast_channel::name, parse(), pbx_builtin_setvar_helper(), remove_from_queue(), RES_EXISTS, RES_NOSUCHQUEUE, RES_NOT_DYNAMIC, RES_OKAY, and ast_channel::uniqueid.

Referenced by load_module().

6139 {
6140  int res=-1;
6141  char *parse, *temppos = NULL;
6143  AST_APP_ARG(queuename);
6145  );
6146 
6147 
6148  if (ast_strlen_zero(data)) {
6149  ast_log(LOG_WARNING, "RemoveQueueMember requires an argument (queuename[,interface])\n");
6150  return -1;
6151  }
6152 
6153  parse = ast_strdupa(data);
6154 
6155  AST_STANDARD_APP_ARGS(args, parse);
6156 
6157  if (ast_strlen_zero(args.interface)) {
6158  args.interface = ast_strdupa(chan->name);
6159  temppos = strrchr(args.interface, '-');
6160  if (temppos)
6161  *temppos = '\0';
6162  }
6163 
6164  ast_debug(1, "queue: %s, member: %s\n", args.queuename, args.interface);
6165 
6166  switch (remove_from_queue(args.queuename, args.interface)) {
6167  case RES_OKAY:
6168  ast_queue_log(args.queuename, chan->uniqueid, args.interface, "REMOVEMEMBER", "%s", "");
6169  ast_log(LOG_NOTICE, "Removed interface '%s' from queue '%s'\n", args.interface, args.queuename);
6170  pbx_builtin_setvar_helper(chan, "RQMSTATUS", "REMOVED");
6171  res = 0;
6172  break;
6173  case RES_EXISTS:
6174  ast_debug(1, "Unable to remove interface '%s' from queue '%s': Not there\n", args.interface, args.queuename);
6175  pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOTINQUEUE");
6176  res = 0;
6177  break;
6178  case RES_NOSUCHQUEUE:
6179  ast_log(LOG_WARNING, "Unable to remove interface from queue '%s': No such queue\n", args.queuename);
6180  pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOSUCHQUEUE");
6181  res = 0;
6182  break;
6183  case RES_NOT_DYNAMIC:
6184  ast_log(LOG_WARNING, "Unable to remove interface from queue '%s': '%s' is not a dynamic member\n", args.queuename, args.interface);
6185  pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOTDYNAMIC");
6186  res = 0;
6187  break;
6188  }
6189 
6190  return res;
6191 }
6192 
#define RES_OKAY
Definition: app_queue.c:1033
const ast_string_field uniqueid
Definition: channel.h:787
#define LOG_WARNING
Definition: logger.h:144
#define RES_NOT_DYNAMIC
Definition: app_queue.c:1037
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
char interface[256]
Definition: app_queue.c:1124
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static struct @350 args
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
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...
Definition: pbx.c:10546
#define RES_NOSUCHQUEUE
Definition: app_queue.c:1036
#define RES_EXISTS
Definition: app_queue.c:1034
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static int remove_from_queue(const char *queuename, const char *interface)
Remove member from queue.
Definition: app_queue.c:5715
static void rt_handle_member_record ( struct call_queue q,
char *  interface,
const char *  rt_uniqueid,
const char *  membername,
const char *  penalty_str,
const char *  paused_str,
const char *  state_interface 
)
static

Find rt member record to update otherwise create one.

Search for member in queue, if found update penalty/paused state, if no member exists create one flag it as a RT member and add to queue member list.

Definition at line 2328 of file app_queue.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_copy_string(), ast_log(), ast_queue_log(), ast_strlen_zero(), create_queue_member(), member::dead, member::interface, LOG_WARNING, member_add_to_queue(), call_queue::members, call_queue::name, member::paused, member::penalty, member::realtime, member::rt_uniqueid, S_OR, and member::state_interface.

Referenced by find_queue_by_name_rt(), and update_realtime_members().

2328 {
2329  struct member *m;
2330  struct ao2_iterator mem_iter;
2331  int penalty = 0;
2332  int paused = 0;
2333  int found = 0;
2334 
2335  if (ast_strlen_zero(rt_uniqueid)) {
2336  ast_log(LOG_WARNING, "Realtime field uniqueid is empty for member %s\n", S_OR(membername, "NULL"));
2337  return;
2338  }
2339 
2340  if (penalty_str) {
2341  penalty = atoi(penalty_str);
2342  if (penalty < 0)
2343  penalty = 0;
2344  }
2345 
2346  if (paused_str) {
2347  paused = atoi(paused_str);
2348  if (paused < 0)
2349  paused = 0;
2350  }
2351 
2352  /* Find member by realtime uniqueid and update */
2353  mem_iter = ao2_iterator_init(q->members, 0);
2354  while ((m = ao2_iterator_next(&mem_iter))) {
2355  if (!strcasecmp(m->rt_uniqueid, rt_uniqueid)) {
2356  m->dead = 0; /* Do not delete this one. */
2357  ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
2358  if (paused_str)
2359  m->paused = paused;
2360  if (strcasecmp(state_interface, m->state_interface)) {
2361  ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
2362  }
2363  m->penalty = penalty;
2364  found = 1;
2365  ao2_ref(m, -1);
2366  break;
2367  }
2368  ao2_ref(m, -1);
2369  }
2370  ao2_iterator_destroy(&mem_iter);
2371 
2372  /* Create a new member */
2373  if (!found) {
2374  if ((m = create_queue_member(interface, membername, penalty, paused, state_interface))) {
2375  m->dead = 0;
2376  m->realtime = 1;
2377  ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
2378  ast_queue_log(q->name, "REALTIME", m->interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
2379  member_add_to_queue(q, m);
2380  ao2_ref(m, -1);
2381  m = NULL;
2382  }
2383  }
2384 }
2385 
int paused
Definition: app_queue.c:1185
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
#define LOG_WARNING
Definition: logger.h:144
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
int realtime
Definition: app_queue.c:1183
char interface[80]
Definition: app_queue.c:1175
char state_interface[80]
Definition: app_queue.c:1178
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
unsigned int dead
Definition: app_queue.c:1189
struct ao2_container * members
Definition: app_queue.c:1320
static void member_add_to_queue(struct call_queue *queue, struct member *mem)
Definition: app_queue.c:2300
int penalty
Definition: app_queue.c:1180
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ao2_ref(o, delta)
Definition: astobj2.h:472
const ast_string_field name
Definition: app_queue.c:1266
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
static struct member * create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface)
allocate space for new queue member and set fields based on parameters passed
Definition: app_queue.c:1801
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
char rt_uniqueid[80]
Definition: app_queue.c:1193
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
static int say_periodic_announcement ( struct queue_ent qe,
int  ringing 
)
static

Playback announcement to queued members if period has elapsed.

Definition at line 3650 of file app_queue.c.

References AST_CONTROL_RINGING, ast_indicate(), ast_moh_start(), ast_moh_stop(), ast_random(), ast_str_buffer(), ast_str_strlen(), ast_verb, queue_ent::chan, queue_ent::last_periodic_announce_sound, queue_ent::last_periodic_announce_time, queue_ent::moh, call_queue::numperiodicannounce, queue_ent::parent, call_queue::periodicannouncefrequency, play_file(), call_queue::randomperiodicannounce, call_queue::relativeperiodicannounce, call_queue::sound_periodicannounce, and valid_exit().

Referenced by queue_exec(), wait_for_answer(), and wait_our_turn().

3650 {
3651  int res = 0;
3652  time_t now;
3653 
3654  /* Get the current time */
3655  time(&now);
3656 
3657  /* Check to see if it is time to announce */
3659  return 0;
3660 
3661  /* Stop the music on hold so we can play our own file */
3662  if (ringing)
3663  ast_indicate(qe->chan,-1);
3664  else
3665  ast_moh_stop(qe->chan);
3666 
3667  ast_verb(3, "Playing periodic announcement\n");
3668 
3670  qe->last_periodic_announce_sound = ((unsigned long) ast_random()) % qe->parent->numperiodicannounce;
3671  } else if (qe->last_periodic_announce_sound >= qe->parent->numperiodicannounce ||
3674  }
3675 
3676  /* play the announcement */
3678 
3679  if (res > 0 && !valid_exit(qe, res))
3680  res = 0;
3681 
3682  /* Resume Music on Hold if the caller is going to stay in the queue */
3683  if (!res) {
3684  if (ringing)
3686  else
3687  ast_moh_start(qe->chan, qe->moh, NULL);
3688  }
3689 
3690  /* update last_periodic_announce_time */
3692  time(&qe->last_periodic_announce_time);
3693  else
3694  qe->last_periodic_announce_time = now;
3695 
3696  /* Update the current periodic announcement to the next announcement */
3697  if (!qe->parent->randomperiodicannounce) {
3699  }
3700 
3701  return res;
3702 }
3703 
struct ast_str * sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS]
Definition: app_queue.c:1268
struct call_queue * parent
Definition: app_queue.c:1144
char moh[80]
Definition: app_queue.c:1145
struct ast_channel * chan
Definition: app_queue.c:1168
int last_periodic_announce_sound
Definition: app_queue.c:1155
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:8051
#define ast_verb(level,...)
Definition: logger.h:243
int periodicannouncefrequency
Definition: app_queue.c:1291
long int ast_random(void)
Definition: utils.c:1640
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:8040
static int play_file(struct ast_channel *chan, const char *filename)
Definition: app_queue.c:2787
int randomperiodicannounce
Definition: app_queue.c:1293
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:471
int numperiodicannounce
Definition: app_queue.c:1292
time_t last_periodic_announce_time
Definition: app_queue.c:1154
unsigned int relativeperiodicannounce
Definition: app_queue.c:1285
static int valid_exit(struct queue_ent *qe, char digit)
Check for valid exit from queue via goto.
Definition: app_queue.c:2815
static int say_position ( struct queue_ent qe,
int  ringing 
)
static

Definition at line 2849 of file app_queue.c.

References call_queue::announcefrequency, call_queue::announceholdtime, ANNOUNCEHOLDTIME_ONCE, call_queue::announceposition, ANNOUNCEPOSITION_LIMIT, ANNOUNCEPOSITION_MORE_THAN, ANNOUNCEPOSITION_YES, call_queue::announcepositionlimit, AST_CONTROL_RINGING, AST_DIGIT_ANY, ast_indicate(), ast_moh_start(), ast_moh_stop(), ast_say_number(), ast_verb, queue_ent::chan, call_queue::holdtime, ast_channel::language, queue_ent::last_pos, queue_ent::last_pos_said, call_queue::minannouncefrequency, queue_ent::moh, ast_channel::name, call_queue::name, queue_ent::parent, play_file(), queue_ent::pos, call_queue::queue_quantity1, call_queue::queue_quantity2, call_queue::roundingseconds, call_queue::sound_calls, call_queue::sound_holdtime, call_queue::sound_minute, call_queue::sound_minutes, call_queue::sound_next, call_queue::sound_seconds, call_queue::sound_thanks, call_queue::sound_thereare, queue_ent::start, and valid_exit().

Referenced by queue_exec(), wait_for_answer(), and wait_our_turn().

2849 {
2850  int res = 0, avgholdmins, avgholdsecs, announceposition = 0;
2851  int say_thanks = 1;
2852  time_t now;
2853 
2854  /* Let minannouncefrequency seconds pass between the start of each position announcement */
2855  time(&now);
2856  if ((now - qe->last_pos) < qe->parent->minannouncefrequency)
2857  return 0;
2858 
2859  /* If either our position has changed, or we are over the freq timer, say position */
2860  if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency))
2861  return 0;
2862 
2863  if (ringing) {
2864  ast_indicate(qe->chan,-1);
2865  } else {
2866  ast_moh_stop(qe->chan);
2867  }
2868 
2872  qe->pos <= qe->parent->announcepositionlimit))
2873  announceposition = 1;
2874 
2875 
2876  if (announceposition == 1) {
2877  /* Say we're next, if we are */
2878  if (qe->pos == 1) {
2879  res = play_file(qe->chan, qe->parent->sound_next);
2880  if (res)
2881  goto playout;
2882  else
2883  goto posout;
2884  } else {
2886  /* More than Case*/
2887  res = play_file(qe->chan, qe->parent->queue_quantity1);
2888  if (res)
2889  goto playout;
2890  res = ast_say_number(qe->chan, qe->parent->announcepositionlimit, AST_DIGIT_ANY, qe->chan->language, NULL); /* Needs gender */
2891  if (res)
2892  goto playout;
2893  } else {
2894  /* Normal Case */
2895  res = play_file(qe->chan, qe->parent->sound_thereare);
2896  if (res)
2897  goto playout;
2898  res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, qe->chan->language, NULL); /* Needs gender */
2899  if (res)
2900  goto playout;
2901  }
2903  /* More than Case*/
2904  res = play_file(qe->chan, qe->parent->queue_quantity2);
2905  if (res)
2906  goto playout;
2907  } else {
2908  res = play_file(qe->chan, qe->parent->sound_calls);
2909  if (res)
2910  goto playout;
2911  }
2912  }
2913  }
2914  /* Round hold time to nearest minute */
2915  avgholdmins = abs(((qe->parent->holdtime + 30) - (now - qe->start)) / 60);
2916 
2917  /* If they have specified a rounding then round the seconds as well */
2918  if (qe->parent->roundingseconds) {
2919  avgholdsecs = (abs(((qe->parent->holdtime + 30) - (now - qe->start))) - 60 * avgholdmins) / qe->parent->roundingseconds;
2920  avgholdsecs *= qe->parent->roundingseconds;
2921  } else {
2922  avgholdsecs = 0;
2923  }
2924 
2925  ast_verb(3, "Hold time for %s is %d minute(s) %d seconds\n", qe->parent->name, avgholdmins, avgholdsecs);
2926 
2927  /* If the hold time is >1 min, if it's enabled, and if it's not
2928  supposed to be only once and we have already said it, say it */
2929  if ((avgholdmins+avgholdsecs) > 0 && qe->parent->announceholdtime &&
2932  res = play_file(qe->chan, qe->parent->sound_holdtime);
2933  if (res)
2934  goto playout;
2935 
2936  if (avgholdmins >= 1) {
2937  res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, qe->chan->language, NULL);
2938  if (res)
2939  goto playout;
2940 
2941  if (avgholdmins == 1) {
2942  res = play_file(qe->chan, qe->parent->sound_minute);
2943  if (res)
2944  goto playout;
2945  } else {
2946  res = play_file(qe->chan, qe->parent->sound_minutes);
2947  if (res)
2948  goto playout;
2949  }
2950  }
2951  if (avgholdsecs >= 1) {
2952  res = ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, qe->chan->language, NULL);
2953  if (res)
2954  goto playout;
2955 
2956  res = play_file(qe->chan, qe->parent->sound_seconds);
2957  if (res)
2958  goto playout;
2959  }
2960  } else if (qe->parent->announceholdtime && !qe->parent->announceposition) {
2961  say_thanks = 0;
2962  }
2963 
2964 posout:
2965  if (qe->parent->announceposition) {
2966  ast_verb(3, "Told %s in %s their queue position (which was %d)\n",
2967  qe->chan->name, qe->parent->name, qe->pos);
2968  }
2969  if (say_thanks) {
2970  res = play_file(qe->chan, qe->parent->sound_thanks);
2971  }
2972 playout:
2973 
2974  if ((res > 0 && !valid_exit(qe, res)))
2975  res = 0;
2976 
2977  /* Set our last_pos indicators */
2978  qe->last_pos = now;
2979  qe->last_pos_said = qe->pos;
2980 
2981  /* Don't restart music on hold if we're about to exit the caller from the queue */
2982  if (!res) {
2983  if (ringing) {
2985  } else {
2986  ast_moh_start(qe->chan, qe->moh, NULL);
2987  }
2988  }
2989  return res;
2990 }
2991 
struct call_queue * parent
Definition: app_queue.c:1144
char moh[80]
Definition: app_queue.c:1145
const ast_string_field sound_holdtime
Definition: app_queue.c:1266
struct ast_channel * chan
Definition: app_queue.c:1168
#define AST_DIGIT_ANY
Definition: file.h:47
time_t start
Definition: app_queue.c:1165
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
int minannouncefrequency
Definition: app_queue.c:1290
int last_pos_said
Definition: app_queue.c:1152
unsigned int announceholdtime
Definition: app_queue.c:1279
const ast_string_field sound_thanks
Definition: app_queue.c:1266
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:8051
#define ast_verb(level,...)
Definition: logger.h:243
int announcepositionlimit
Definition: app_queue.c:1288
int holdtime
Definition: app_queue.c:1295
const ast_string_field sound_minute
Definition: app_queue.c:1266
const ast_string_field sound_thereare
Definition: app_queue.c:1266
const ast_string_field sound_next
Definition: app_queue.c:1266
#define ANNOUNCEPOSITION_MORE_THAN
Definition: app_queue.c:1223
#define ANNOUNCEPOSITION_YES
Definition: app_queue.c:1221
const ast_string_field name
Definition: app_queue.c:1266
const ast_string_field name
Definition: channel.h:787
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:8040
time_t last_pos
Definition: app_queue.c:1156
int roundingseconds
Definition: app_queue.c:1294
static int play_file(struct ast_channel *chan, const char *filename)
Definition: app_queue.c:2787
const ast_string_field sound_seconds
Definition: app_queue.c:1266
unsigned int announceposition
Definition: app_queue.c:1280
#define ANNOUNCEPOSITION_LIMIT
Definition: app_queue.c:1224
const ast_string_field sound_calls
Definition: app_queue.c:1266
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Definition: channel.c:8397
const ast_string_field sound_minutes
Definition: app_queue.c:1266
const ast_string_field queue_quantity2
Definition: app_queue.c:1266
#define ANNOUNCEHOLDTIME_ONCE
Definition: app_queue.c:1209
const ast_string_field queue_quantity1
Definition: app_queue.c:1266
static int valid_exit(struct queue_ent *qe, char digit)
Check for valid exit from queue via goto.
Definition: app_queue.c:2815
int announcefrequency
Definition: app_queue.c:1289
const ast_string_field language
Definition: channel.h:787
static void send_agent_complete ( const struct queue_ent qe,
const char *  queuename,
const struct ast_channel peer,
const struct member member,
time_t  callstart,
char *  vars,
size_t  vars_len,
enum agent_complete_reason  rsn 
)
static

Send out AMI message with member call completion status information.

Definition at line 4637 of file app_queue.c.

References AGENT, CALLER, queue_ent::chan, EVENT_FLAG_AGENT, call_queue::eventwhencalled, member::interface, manager_event, member::membername, ast_channel::name, queue_ent::parent, QUEUE_EVENT_VARIABLES, queue_ent::start, TRANSFER, ast_channel::uniqueid, and vars2manager().

Referenced by try_calling().

4639 {
4640  const char *reason = NULL; /* silence dumb compilers */
4641 
4642  if (!qe->parent->eventwhencalled)
4643  return;
4644 
4645  switch (rsn) {
4646  case CALLER:
4647  reason = "caller";
4648  break;
4649  case AGENT:
4650  reason = "agent";
4651  break;
4652  case TRANSFER:
4653  reason = "transfer";
4654  break;
4655  }
4656 
4657  manager_event(EVENT_FLAG_AGENT, "AgentComplete",
4658  "Queue: %s\r\n"
4659  "Uniqueid: %s\r\n"
4660  "Channel: %s\r\n"
4661  "Member: %s\r\n"
4662  "MemberName: %s\r\n"
4663  "HoldTime: %ld\r\n"
4664  "TalkTime: %ld\r\n"
4665  "Reason: %s\r\n"
4666  "%s",
4667  queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
4668  (long)(callstart - qe->start), (long)(time(NULL) - callstart), reason,
4669  qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, vars_len) : "");
4670 }
4671 
struct call_queue * parent
Definition: app_queue.c:1144
unsigned int eventwhencalled
Definition: app_queue.c:1270
struct ast_channel * chan
Definition: app_queue.c:1168
const ast_string_field uniqueid
Definition: channel.h:787
time_t start
Definition: app_queue.c:1165
char interface[80]
Definition: app_queue.c:1175
char membername[80]
Definition: app_queue.c:1179
static char * vars2manager(struct ast_channel *chan, char *vars, size_t len)
convert &quot;\n&quot; to &quot;\nVariable: &quot; ready for manager to use
Definition: app_queue.c:3206
const ast_string_field name
Definition: channel.h:787
#define EVENT_FLAG_AGENT
Definition: manager.h:76
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
#define QUEUE_EVENT_VARIABLES
Definition: app_queue.c:1210
static int set_member_paused ( const char *  queuename,
const char *  interface,
const char *  reason,
int  paused 
)
static

Definition at line 5814 of file app_queue.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_lock, ao2_ref, ao2_t_iterator_next, ao2_unlock, ast_debug, ast_log(), ast_queue_log(), ast_strlen_zero(), dump_queue_members(), EVENT_FLAG_AGENT, member::interface, interface_exists(), LOG_WARNING, manager_event, member::membername, call_queue::name, member::paused, queue_t_unref, queues, member::realtime, RESULT_FAILURE, RESULT_SUCCESS, S_OR, and update_realtime_member_field().

Referenced by handle_queue_pause_member(), manager_pause_queue_member(), pqm_exec(), rna(), and upqm_exec().

5814 {
5815  int found = 0;
5816  struct call_queue *q;
5817  struct member *mem;
5818  struct ao2_iterator queue_iter;
5819  int failed;
5820 
5821  /* Special event for when all queues are paused - individual events still generated */
5822  /* XXX In all other cases, we use the membername, but since this affects all queues, we cannot */
5823  if (ast_strlen_zero(queuename))
5824  ast_queue_log("NONE", "NONE", interface, (paused ? "PAUSEALL" : "UNPAUSEALL"), "%s", "");
5825 
5826  queue_iter = ao2_iterator_init(queues, 0);
5827  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate over queues"))) {
5828  ao2_lock(q);
5829  if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) {
5830  if ((mem = interface_exists(q, interface))) {
5831  if (mem->paused == paused) {
5832  ast_debug(1, "%spausing already-%spaused queue member %s:%s\n", (paused ? "" : "un"), (paused ? "" : "un"), q->name, interface);
5833  }
5834 
5835  failed = 0;
5836  if (mem->realtime) {
5837  failed = update_realtime_member_field(mem, q->name, "paused", paused ? "1" : "0");
5838  }
5839 
5840  if (failed) {
5841  ast_log(LOG_WARNING, "Failed %spausing realtime queue member %s:%s\n", (paused ? "" : "un"), q->name, interface);
5842  ao2_ref(mem, -1);
5843  ao2_unlock(q);
5844  queue_t_unref(q, "Done with iterator");
5845  continue;
5846  }
5847  found++;
5848  mem->paused = paused;
5849 
5851  dump_queue_members(q);
5852 
5853  ast_queue_log(q->name, "NONE", mem->membername, (paused ? "PAUSE" : "UNPAUSE"), "%s", S_OR(reason, ""));
5854 
5855  if (!ast_strlen_zero(reason)) {
5856  manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused",
5857  "Queue: %s\r\n"
5858  "Location: %s\r\n"
5859  "MemberName: %s\r\n"
5860  "Paused: %d\r\n"
5861  "Reason: %s\r\n",
5862  q->name, mem->interface, mem->membername, paused, reason);
5863  } else {
5864  manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused",
5865  "Queue: %s\r\n"
5866  "Location: %s\r\n"
5867  "MemberName: %s\r\n"
5868  "Paused: %d\r\n",
5869  q->name, mem->interface, mem->membername, paused);
5870  }
5871  ao2_ref(mem, -1);
5872  }
5873  }
5874 
5875  if (!ast_strlen_zero(queuename) && !strcasecmp(queuename, q->name)) {
5876  ao2_unlock(q);
5877  queue_t_unref(q, "Done with iterator");
5878  break;
5879  }
5880 
5881  ao2_unlock(q);
5882  queue_t_unref(q, "Done with iterator");
5883  }
5884  ao2_iterator_destroy(&queue_iter);
5885 
5886  return found ? RESULT_SUCCESS : RESULT_FAILURE;
5887 }
5888 
static int update_realtime_member_field(struct member *mem, const char *queue_name, const char *field, const char *value)
Definition: app_queue.c:2628
int paused
Definition: app_queue.c:1185
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
#define LOG_WARNING
Definition: logger.h:144
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
#define ao2_t_iterator_next(arg1, arg2)
Definition: astobj2.h:1125
int realtime
Definition: app_queue.c:1183
char interface[80]
Definition: app_queue.c:1175
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
char membername[80]
Definition: app_queue.c:1179
static struct member * interface_exists(struct call_queue *q, const char *interface)
Definition: app_queue.c:5637
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static struct ao2_container * queues
Definition: app_queue.c:1334
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
const ast_string_field name
Definition: app_queue.c:1266
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define EVENT_FLAG_AGENT
Definition: manager.h:76
static void dump_queue_members(struct call_queue *pm_queue)
Dump all members in a specific queue to the database.
Definition: app_queue.c:5663
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
#define RESULT_SUCCESS
Definition: cli.h:39
static int queue_persistent_members
queues.conf [general] option
Definition: app_queue.c:1058
#define RESULT_FAILURE
Definition: cli.h:41
static int set_member_penalty ( const char *  queuename,
const char *  interface,
int  penalty 
)
static

Definition at line 5891 of file app_queue.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_lock, ao2_ref, ao2_t_iterator_next, ao2_unlock, ast_log(), ast_queue_log(), ast_strlen_zero(), EVENT_FLAG_AGENT, member::interface, interface_exists(), LOG_ERROR, manager_event, call_queue::name, member::penalty, queue_t_unref, queues, RESULT_FAILURE, and RESULT_SUCCESS.

Referenced by handle_queue_set_member_penalty(), manager_queue_member_penalty(), and queue_function_memberpenalty_write().

5891 {
5892  int foundinterface = 0, foundqueue = 0;
5893  struct call_queue *q;
5894  struct member *mem;
5895  struct ao2_iterator queue_iter;
5896 
5897  if (penalty < 0) {
5898  ast_log(LOG_ERROR, "Invalid penalty (%d)\n", penalty);
5899  return RESULT_FAILURE;
5900  }
5901 
5902  queue_iter = ao2_iterator_init(queues, 0);
5903  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
5904  ao2_lock(q);
5905  if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) {
5906  foundqueue++;
5907  if ((mem = interface_exists(q, interface))) {
5908  foundinterface++;
5909  mem->penalty = penalty;
5910 
5911  ast_queue_log(q->name, "NONE", interface, "PENALTY", "%d", penalty);
5912  manager_event(EVENT_FLAG_AGENT, "QueueMemberPenalty",
5913  "Queue: %s\r\n"
5914  "Location: %s\r\n"
5915  "Penalty: %d\r\n",
5916  q->name, mem->interface, penalty);
5917  ao2_ref(mem, -1);
5918  }
5919  }
5920  ao2_unlock(q);
5921  queue_t_unref(q, "Done with iterator");
5922  }
5923  ao2_iterator_destroy(&queue_iter);
5924 
5925  if (foundinterface) {
5926  return RESULT_SUCCESS;
5927  } else if (!foundqueue) {
5928  ast_log (LOG_ERROR, "Invalid queuename\n");
5929  } else {
5930  ast_log (LOG_ERROR, "Invalid interface\n");
5931  }
5932 
5933  return RESULT_FAILURE;
5934 }
5935 
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
#define ao2_t_iterator_next(arg1, arg2)
Definition: astobj2.h:1125
char interface[80]
Definition: app_queue.c:1175
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
static struct member * interface_exists(struct call_queue *q, const char *interface)
Definition: app_queue.c:5637
static struct ao2_container * queues
Definition: app_queue.c:1334
int penalty
Definition: app_queue.c:1180
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
#define LOG_ERROR
Definition: logger.h:155
const ast_string_field name
Definition: app_queue.c:1266
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define EVENT_FLAG_AGENT
Definition: manager.h:76
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
#define RESULT_SUCCESS
Definition: cli.h:39
#define RESULT_FAILURE
Definition: cli.h:41
static void set_queue_result ( struct ast_channel chan,
enum queue_result  res 
)
static

sets the QUEUESTATUS channel variable

Definition at line 1341 of file app_queue.c.

References ARRAY_LEN, pbx_builtin_setvar_helper(), queue_results, and text.

Referenced by queue_exec().

1341 {
1342  int i;
1343 
1344  for (i = 0; i < ARRAY_LEN(queue_results); i++) {
1345  if (queue_results[i].id == res) {
1346  pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
1347  return;
1348  }
1349  }
1350 }
1351 
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
char * text
Definition: app_queue.c:1091
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...
Definition: pbx.c:10546
static struct @53 queue_results[]
static void set_queue_variables ( struct call_queue q,
struct ast_channel chan 
)
static

Set variables of queue.

Definition at line 1490 of file app_queue.c.

References ao2_lock, ao2_unlock, call_queue::callsabandoned, call_queue::callscompleted, call_queue::callscompletedinsl, call_queue::count, call_queue::holdtime, int2strat(), call_queue::maxlen, call_queue::name, pbx_builtin_setvar_multiple(), call_queue::servicelevel, call_queue::setqueuevar, call_queue::strategy, and call_queue::talktime.

Referenced by end_bridge_callback(), queue_exec(), record_abandoned(), and try_calling().

1490 {
1491  char interfacevar[256]="";
1492  float sl = 0;
1493 
1494  ao2_lock(q);
1495 
1496  if (q->setqueuevar) {
1497  sl = 0;
1498  if (q->callscompleted > 0)
1499  sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
1500 
1501  snprintf(interfacevar, sizeof(interfacevar),
1502  "QUEUENAME=%s,QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUETALKTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
1503  q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted, q->callsabandoned, q->servicelevel, sl);
1504 
1505  ao2_unlock(q);
1506 
1507  pbx_builtin_setvar_multiple(chan, interfacevar);
1508  } else {
1509  ao2_unlock(q);
1510  }
1511 }
1512 
int servicelevel
Definition: app_queue.c:1299
unsigned int setqueuevar
Definition: app_queue.c:1274
#define ao2_unlock(a)
Definition: astobj2.h:497
int callscompletedinsl
Definition: app_queue.c:1300
int holdtime
Definition: app_queue.c:1295
#define ao2_lock(a)
Definition: astobj2.h:488
int strategy
Definition: app_queue.c:1281
const ast_string_field name
Definition: app_queue.c:1266
int pbx_builtin_setvar_multiple(struct ast_channel *chan, const char *data)
Parse and set multiple channel variables, where the pairs are separated by the &#39;,&#39; character...
Definition: pbx.c:10633
int talktime
Definition: app_queue.c:1296
int callsabandoned
Definition: app_queue.c:1298
int callscompleted
Definition: app_queue.c:1297
static const char * int2strat(int strategy)
Definition: app_queue.c:1353
static struct ast_datastore* setup_transfer_datastore ( struct queue_ent qe,
struct member member,
time_t  starttime,
int  callcompletedinsl 
)
static

create a datastore for storing relevant info to log attended transfers in the queue_log

Definition at line 4742 of file app_queue.c.

References ast_calloc, ast_channel_datastore_add(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc(), ast_free, ast_log(), queue_transfer_ds::callcompletedinsl, queue_ent::chan, ast_datastore::data, LOG_WARNING, queue_transfer_ds::member, queue_transfer_ds::qe, queue_transfer_info, and queue_transfer_ds::starttime.

Referenced by try_calling().

4742 {
4743  struct ast_datastore *ds;
4744  struct queue_transfer_ds *qtds = ast_calloc(1, sizeof(*qtds));
4745 
4746  if (!qtds) {
4747  ast_log(LOG_WARNING, "Memory allocation error!\n");
4748  return NULL;
4749  }
4750 
4751  ast_channel_lock(qe->chan);
4752  if (!(ds = ast_datastore_alloc(&queue_transfer_info, NULL))) {
4753  ast_channel_unlock(qe->chan);
4754  ast_free(qtds);
4755  ast_log(LOG_WARNING, "Unable to create transfer datastore. queue_log will not show attended transfer\n");
4756  return NULL;
4757  }
4758 
4759  qtds->qe = qe;
4760  /* This member is refcounted in try_calling, so no need to add it here, too */
4761  qtds->member = member;
4762  qtds->starttime = starttime;
4764  ds->data = qtds;
4766  ast_channel_unlock(qe->chan);
4767  return ds;
4768 }
4769 
#define ast_channel_lock(chan)
Definition: channel.h:2466
struct ast_channel * chan
Definition: app_queue.c:1168
static struct ast_datastore_info queue_transfer_info
a datastore used to help correctly log attended transfers of queue callers
Definition: app_queue.c:4688
#define LOG_WARNING
Definition: logger.h:144
struct queue_ent * qe
Definition: app_queue.c:4674
Structure for a data store object.
Definition: datastore.h:54
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define ast_free(a)
Definition: astmm.h:97
struct member * member
Definition: app_queue.c:4675
void * data
Definition: datastore.h:56
#define ast_calloc(a, b)
Definition: astmm.h:82
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
static int store_next_lin ( struct queue_ent qe,
struct callattempt outgoing 
)
static

Search for best metric and add to Linear queue.

Definition at line 3626 of file app_queue.c.

References ast_debug, find_best(), callattempt::interface, queue_ent::linpos, queue_ent::linwrapped, and callattempt::metric.

Referenced by try_calling().

3626 {
3627  struct callattempt *best = find_best(outgoing);
3628 
3629  if (best) {
3630  /* Ring just the best channel */
3631  ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
3632  qe->linpos = best->metric % 1000;
3633  } else {
3634  /* Just increment rrpos */
3635  if (qe->linwrapped) {
3636  /* No more channels, start over */
3637  qe->linpos = 0;
3638  } else {
3639  /* Prioritize next entry */
3640  qe->linpos++;
3641  }
3642  }
3643  qe->linwrapped = 0;
3644 
3645  return 0;
3646 }
3647 
int linwrapped
Definition: app_queue.c:1164
char interface[256]
Definition: app_queue.c:1124
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static struct callattempt * find_best(struct callattempt *outgoing)
find the entry with the best metric, or NULL
Definition: app_queue.c:3540
int linpos
Definition: app_queue.c:1163
We define a custom &quot;local user&quot; structure because we use it not only for keeping track of what is i...
Definition: app_queue.c:1120
static int store_next_rr ( struct queue_ent qe,
struct callattempt outgoing 
)
static

Search for best metric and add to Round Robbin queue.

Definition at line 3602 of file app_queue.c.

References ast_debug, find_best(), callattempt::interface, callattempt::metric, queue_ent::parent, call_queue::rrpos, and call_queue::wrapped.

Referenced by try_calling().

3602 {
3603  struct callattempt *best = find_best(outgoing);
3604 
3605  if (best) {
3606  /* Ring just the best channel */
3607  ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
3608  qe->parent->rrpos = best->metric % 1000;
3609  } else {
3610  /* Just increment rrpos */
3611  if (qe->parent->wrapped) {
3612  /* No more channels, start over */
3613  qe->parent->rrpos = 0;
3614  } else {
3615  /* Prioritize next entry */
3616  qe->parent->rrpos++;
3617  }
3618  }
3619  qe->parent->wrapped = 0;
3620 
3621  return 0;
3622 }
3623 
struct call_queue * parent
Definition: app_queue.c:1144
char interface[256]
Definition: app_queue.c:1124
unsigned int wrapped
Definition: app_queue.c:1277
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static struct callattempt * find_best(struct callattempt *outgoing)
find the entry with the best metric, or NULL
Definition: app_queue.c:3540
We define a custom &quot;local user&quot; structure because we use it not only for keeping track of what is i...
Definition: app_queue.c:1120
static int strat2int ( const char *  strategy)
static

Definition at line 1365 of file app_queue.c.

References ARRAY_LEN, and strategies.

Referenced by find_queue_by_name_rt(), queue_set_param(), and reload_single_queue().

1365 {
1366  int x;
1367 
1368  for (x = 0; x < ARRAY_LEN(strategies); x++) {
1369  if (!strcasecmp(strategy, strategies[x].name))
1370  return strategies[x].strategy;
1371  }
1372 
1373  return -1;
1374 }
1375 
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static struct strategy strategies[]
static const char name[]
static int try_calling ( struct queue_ent qe,
const char *  options,
char *  announceoverride,
const char *  url,
int *  tries,
int *  noption,
const char *  agi,
const char *  macro,
const char *  gosub,
int  ringing 
)
static

A large function which calls members, updates statistics, and bridges the caller and a member.

Here is the process of this function

  1. Process any options passed to the Queue() application. Options here mean the third argument to Queue()
  2. Iterate trough the members of the queue, creating a callattempt corresponding to each member. During this iteration, we also check the dialed_interfaces datastore to see if we have already attempted calling this member. If we have, we do not create a callattempt. This is in place to prevent call forwarding loops. Also during each iteration, we call calc_metric to determine which members should be rung when.
  3. Call ring_one to place a call to the appropriate member(s)
  4. Call wait_for_answer to wait for an answer. If no one answers, return.
  5. Take care of any holdtime announcements, member delays, or other options which occur after a call has been answered.
  6. Start the monitor or mixmonitor if the option is set
  7. Remove the caller from the queue to allow other callers to advance
  8. Bridge the call.
  9. Do any post processing after the call has disconnected.
Parameters
[in]qethe queue_ent structure which corresponds to the caller attempting to reach members
[in]optionsthe options passed as the third parameter to the Queue() application
[in]announceoverridefilename to play to user when waiting
[in]urlthe url passed as the fourth parameter to the Queue() application
[in,out]triesthe number of times we have tried calling queue members
[out]noptionset if the call to Queue() has the 'n' option set.
[in]agithe agi passed as the fifth parameter to the Queue() application
[in]macrothe macro passed as the sixth parameter to the Queue() application
[in]gosubthe gosub passed as the seventh parameter to the Queue() application
[in]ringing1 if the 'r' option is set, otherwise 0

Definition at line 4823 of file app_queue.c.

References ast_channel::_softhangup, ast_channel::_state, AGENT, queue_ent::announce, ao2_alloc, ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_asprintf, ast_autoservice_start(), ast_autoservice_stop(), ast_bridge_call(), ast_calloc, ast_cdr_append(), ast_cdr_dup(), ast_cdr_failed(), AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POST_DISABLED, ast_cdr_init(), ast_cdr_isset_unanswered(), ast_cdr_reset(), ast_cdr_setdestchan(), ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_channel_lock, ast_channel_make_compatible(), ast_channel_sendurl(), ast_channel_setoption(), ast_channel_supports_html(), ast_channel_unlock, ast_check_hangup(), ast_clear_flag, ast_copy_string(), ast_datastore_alloc(), ast_datastore_free(), ast_debug, AST_DIGIT_ANY, ast_exists_extension(), AST_FEATURE_AUTOMIXMON, AST_FEATURE_AUTOMON, AST_FEATURE_DISCONNECT, AST_FEATURE_NO_H_EXTEN, AST_FEATURE_PARKCALL, AST_FEATURE_REDIRECT, AST_FLAG_ANSWERED_ELSEWHERE, ast_free, ast_hangup(), ast_indicate(), AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_moh_stop(), ast_monitor_setjoinfiles(), ast_monitor_start(), AST_OPTION_TONE_VERIFY, ast_party_connected_line_copy(), ast_pbx_run_args(), ast_queue_log(), ast_random(), ast_safe_sleep(), ast_say_number(), ast_set_flag, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, attended_transfer_occurred(), callattempt::block_connected_update, calc_metric(), callattempt_free(), ast_channel::caller, CALLER, member::calls, queue_ent::cancel_answered_elsewhere, ast_channel::cdr, callattempt::chan, queue_ent::chan, queue_end_bridge::chan, ast_channel::connected, callattempt::connected, ast_channel::context, ast_datastore::data, DATASTORE_INHERIT_FOREVER, di, dialed_interface_info, ast_cdr::dstchannel, member::dynamic, ast_bridge_config::end_bridge_callback, end_bridge_callback(), ast_bridge_config::end_bridge_callback_data, ast_bridge_config::end_bridge_callback_data_fixup, end_bridge_callback_data_fixup(), EVENT_FLAG_AGENT, call_queue::eventwhencalled, queue_ent::expire, ast_channel::exten, ast_bridge_config::features_callee, ast_bridge_config::features_caller, queue_ent::handled, hangupcalls(), ast_party_caller::id, ast_datastore::inheritance, ast_dialed_interface::interface, callattempt::interface, member::interface, ast_channel::language, callattempt::lastcall, member::lastcall, callattempt::lastqueue, member::lastqueue, leave_queue(), ast_cdr::linkedid, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, manager_event, callattempt::member, call_queue::memberdelay, call_queue::membergosub, call_queue::membermacro, member::membername, call_queue::members, call_queue::monfmt, call_queue::montype, ast_channel::name, call_queue::name, ast_cdr::next, ast_pbx_args::no_hangup_chan, ast_party_id::number, queue_ent::opos, option_debug, queue_ent::parent, pbx_builtin_getvar_helper(), pbx_builtin_setvar_multiple(), pbx_exec(), pbx_findapp(), pbx_substitute_variables_helper(), member::penalty, queue_ent::pending, play_file(), queue_ent::pos, ast_channel::priority, queue_end_bridge::q, callattempt::q_next, QUEUE_EVENT_VARIABLES, QUEUE_STRATEGY_LINEAR, QUEUE_STRATEGY_RRMEMORY, QUEUE_STRATEGY_RRORDERED, queue_t_ref, queue_transfer_info, member::realtime, recalc_holdtime(), record_abandoned(), call_queue::reportholdtime, ring_one(), member::ringcount, call_queue::ringlimit, S_COR, send_agent_complete(), call_queue::servicelevel, set_queue_variables(), call_queue::setinterfacevar, call_queue::setqueueentryvar, setup_transfer_datastore(), call_queue::sound_callerannounce, call_queue::sound_minutes, call_queue::sound_reporthold, call_queue::sound_seconds, queue_ent::start, callattempt::stillgoing, store_next_lin(), store_next_rr(), ast_party_number::str, call_queue::strategy, ast_channel::tech, call_queue::timeout, TIMEOUT_PRIORITY_APP, call_queue::timeoutpriority, TRANSFER, queue_ent::tries, ast_channel_tech::type, ast_cdr::uniqueid, ast_channel::uniqueid, update_queue(), ast_party_number::valid, vars2manager(), wait_for_answer(), X_REC_IN, and X_REC_OUT.

Referenced by queue_exec().

4823 {
4824  struct member *cur;
4825  struct callattempt *outgoing = NULL; /* the list of calls we are building */
4826  int to, orig;
4827  char oldexten[AST_MAX_EXTENSION]="";
4828  char oldcontext[AST_MAX_CONTEXT]="";
4829  char queuename[256]="";
4830  char interfacevar[256]="";
4831  struct ast_channel *peer;
4832  struct ast_channel *which;
4833  struct callattempt *lpeer;
4834  struct member *member;
4835  struct ast_app *application;
4836  int res = 0, bridge = 0;
4837  int numbusies = 0;
4838  int x=0;
4839  char *announce = NULL;
4840  char digit = 0;
4841  time_t callstart;
4842  time_t now = time(NULL);
4843  struct ast_bridge_config bridge_config;
4844  char nondataquality = 1;
4845  char *agiexec = NULL;
4846  char *macroexec = NULL;
4847  char *gosubexec = NULL;
4848  const char *monitorfilename;
4849  const char *monitor_exec;
4850  const char *monitor_options;
4851  char tmpid[256], tmpid2[256];
4852  char meid[1024], meid2[1024];
4853  char mixmonargs[1512];
4854  struct ast_app *mixmonapp = NULL;
4855  char *p;
4856  char vars[2048];
4857  int forwardsallowed = 1;
4858  int block_connected_line = 0;
4859  int callcompletedinsl;
4860  struct ao2_iterator memi;
4861  struct ast_datastore *datastore, *transfer_ds;
4862  struct queue_end_bridge *queue_end_bridge = NULL;
4863 
4864  ast_channel_lock(qe->chan);
4865  datastore = ast_channel_datastore_find(qe->chan, &dialed_interface_info, NULL);
4866  ast_channel_unlock(qe->chan);
4867 
4868  memset(&bridge_config, 0, sizeof(bridge_config));
4869  tmpid[0] = 0;
4870  meid[0] = 0;
4871  time(&now);
4872 
4873  /* If we've already exceeded our timeout, then just stop
4874  * This should be extremely rare. queue_exec will take care
4875  * of removing the caller and reporting the timeout as the reason.
4876  */
4877  if (qe->expire && now >= qe->expire) {
4878  res = 0;
4879  goto out;
4880  }
4881 
4882  for (; options && *options; options++)
4883  switch (*options) {
4884  case 't':
4885  ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
4886  break;
4887  case 'T':
4888  ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
4889  break;
4890  case 'w':
4891  ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMON);
4892  break;
4893  case 'W':
4894  ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMON);
4895  break;
4896  case 'c':
4897  ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_NO_H_EXTEN);
4898  break;
4899  case 'd':
4900  nondataquality = 0;
4901  break;
4902  case 'h':
4903  ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
4904  break;
4905  case 'H':
4906  ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
4907  break;
4908  case 'k':
4909  ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_PARKCALL);
4910  break;
4911  case 'K':
4912  ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_PARKCALL);
4913  break;
4914  case 'n':
4916  (*tries)++;
4917  else
4918  *tries = ao2_container_count(qe->parent->members);
4919  *noption = 1;
4920  break;
4921  case 'i':
4922  forwardsallowed = 0;
4923  break;
4924  case 'I':
4925  block_connected_line = 1;
4926  break;
4927  case 'x':
4928  ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMIXMON);
4929  break;
4930  case 'X':
4931  ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMIXMON);
4932  break;
4933  case 'C':
4934  qe->cancel_answered_elsewhere = 1;
4935  break;
4936  }
4937 
4938  /* if the calling channel has the ANSWERED_ELSEWHERE flag set, make sure this is inherited.
4939  (this is mainly to support chan_local)
4940  */
4942  qe->cancel_answered_elsewhere = 1;
4943  }
4944 
4945  ao2_lock(qe->parent);
4946  ast_debug(1, "%s is trying to call a queue member.\n",
4947  qe->chan->name);
4948  ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
4949  if (!ast_strlen_zero(qe->announce))
4950  announce = qe->announce;
4951  if (!ast_strlen_zero(announceoverride))
4952  announce = announceoverride;
4953 
4954  memi = ao2_iterator_init(qe->parent->members, 0);
4955  while ((cur = ao2_iterator_next(&memi))) {
4956  struct callattempt *tmp = ast_calloc(1, sizeof(*tmp));
4957  struct ast_dialed_interface *di;
4958  AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces;
4959  if (!tmp) {
4960  ao2_ref(cur, -1);
4961  ao2_iterator_destroy(&memi);
4962  ao2_unlock(qe->parent);
4963  goto out;
4964  }
4965  if (!datastore) {
4966  if (!(datastore = ast_datastore_alloc(&dialed_interface_info, NULL))) {
4967  callattempt_free(tmp);
4968  ao2_ref(cur, -1);
4969  ao2_iterator_destroy(&memi);
4970  ao2_unlock(qe->parent);
4971  goto out;
4972  }
4974  if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) {
4975  callattempt_free(tmp);
4976  ao2_ref(cur, -1);
4977  ao2_iterator_destroy(&memi);
4978  ao2_unlock(qe->parent);
4979  goto out;
4980  }
4981  datastore->data = dialed_interfaces;
4982  AST_LIST_HEAD_INIT(dialed_interfaces);
4983 
4984  ast_channel_lock(qe->chan);
4985  ast_channel_datastore_add(qe->chan, datastore);
4986  ast_channel_unlock(qe->chan);
4987  } else
4988  dialed_interfaces = datastore->data;
4989 
4990  AST_LIST_LOCK(dialed_interfaces);
4991  AST_LIST_TRAVERSE(dialed_interfaces, di, list) {
4992  if (!strcasecmp(cur->interface, di->interface)) {
4993  ast_debug(1, "Skipping dialing interface '%s' since it has already been dialed\n",
4994  di->interface);
4995  break;
4996  }
4997  }
4998  AST_LIST_UNLOCK(dialed_interfaces);
4999 
5000  if (di) {
5001  callattempt_free(tmp);
5002  ao2_ref(cur, -1);
5003  continue;
5004  }
5005 
5006  /* It is always ok to dial a Local interface. We only keep track of
5007  * which "real" interfaces have been dialed. The Local channel will
5008  * inherit this list so that if it ends up dialing a real interface,
5009  * it won't call one that has already been called. */
5010  if (strncasecmp(cur->interface, "Local/", 6)) {
5011  if (!(di = ast_calloc(1, sizeof(*di) + strlen(cur->interface)))) {
5012  callattempt_free(tmp);
5013  ao2_ref(cur, -1);
5014  ao2_iterator_destroy(&memi);
5015  ao2_unlock(qe->parent);
5016  goto out;
5017  }
5018  strcpy(di->interface, cur->interface);
5019 
5020  AST_LIST_LOCK(dialed_interfaces);
5021  AST_LIST_INSERT_TAIL(dialed_interfaces, di, list);
5022  AST_LIST_UNLOCK(dialed_interfaces);
5023  }
5024 
5025  /*
5026  * Seed the callattempt's connected line information with previously
5027  * acquired connected line info from the queued channel. The
5028  * previously acquired connected line info could have been set
5029  * through the CONNECTED_LINE dialplan function.
5030  */
5031  ast_channel_lock(qe->chan);
5033  ast_channel_unlock(qe->chan);
5034 
5035  tmp->block_connected_update = block_connected_line;
5036  tmp->stillgoing = 1;
5037  tmp->member = cur;/* Place the reference for cur into callattempt. */
5038  tmp->lastcall = cur->lastcall;
5039  tmp->lastqueue = cur->lastqueue;
5040  ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
5041  if (qe->tries == 0 && (cur->ringcount >= qe->parent->ringlimit)) {
5042  cur->ringcount = 0;
5043  }
5044  /* Special case: If we ring everyone, go ahead and ring them, otherwise
5045  just calculate their metric for the appropriate strategy */
5046  if (!calc_metric(qe->parent, cur, x++, qe, tmp)) {
5047  /* Put them in the list of outgoing thingies... We're ready now.
5048  XXX If we're forcibly removed, these outgoing calls won't get
5049  hung up XXX */
5050  tmp->q_next = outgoing;
5051  outgoing = tmp;
5052  /* If this line is up, don't try anybody else */
5053  if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
5054  break;
5055  } else {
5056  callattempt_free(tmp);
5057  }
5058  }
5059  ao2_iterator_destroy(&memi);
5060 
5062  /* Application arguments have higher timeout priority (behaviour for <=1.6) */
5063  if (qe->expire && (!qe->parent->timeout || (qe->expire - now) <= qe->parent->timeout))
5064  to = (qe->expire - now) * 1000;
5065  else
5066  to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;
5067  } else {
5068  /* Config timeout is higher priority thatn application timeout */
5069  if (qe->expire && qe->expire<=now) {
5070  to = 0;
5071  } else if (qe->parent->timeout) {
5072  to = qe->parent->timeout * 1000;
5073  } else {
5074  to = -1;
5075  }
5076  }
5077  orig = to;
5078  ++qe->pending;
5079  ++qe->tries;
5080  if (option_debug)
5081  ast_log(LOG_DEBUG, "%s is trying to ring one member from %s. This is try number %d\n",
5082  qe->chan->name, queuename, qe->tries);
5083  ao2_unlock(qe->parent);
5084  ring_one(qe, outgoing, &numbusies);
5085  lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies,
5086  ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT),
5087  forwardsallowed, ringing);
5088  /* The ast_channel_datastore_remove() function could fail here if the
5089  * datastore was moved to another channel during a masquerade. If this is
5090  * the case, don't free the datastore here because later, when the channel
5091  * to which the datastore was moved hangs up, it will attempt to free this
5092  * datastore again, causing a crash
5093  */
5094  ast_channel_lock(qe->chan);
5095  if (datastore && !ast_channel_datastore_remove(qe->chan, datastore)) {
5096  ast_datastore_free(datastore);
5097  }
5098  ast_channel_unlock(qe->chan);
5099  ao2_lock(qe->parent);
5101  store_next_rr(qe, outgoing);
5102 
5103  }
5104  if (qe->parent->strategy == QUEUE_STRATEGY_LINEAR) {
5105  store_next_lin(qe, outgoing);
5106  }
5107  ao2_unlock(qe->parent);
5108  peer = lpeer ? lpeer->chan : NULL;
5109  if (!peer) {
5110  qe->pending = 0;
5111  if (to) {
5112  /* Must gotten hung up */
5113  res = -1;
5114  } else {
5115  /* User exited by pressing a digit */
5116  res = digit;
5117  }
5118  if (option_debug && res == -1)
5119  ast_log(LOG_NOTICE, "%s: Nobody answered.\n", qe->chan->name);
5120  if (ast_cdr_isset_unanswered()) {
5121  /* channel contains the name of one of the outgoing channels
5122  in its CDR; zero out this CDR to avoid a dual-posting */
5123  struct callattempt *o;
5124  for (o = outgoing; o; o = o->q_next) {
5125  if (!o->chan) {
5126  continue;
5127  }
5128  if (strcmp(o->chan->cdr->dstchannel, qe->chan->cdr->dstchannel) == 0) {
5130  break;
5131  }
5132  }
5133  }
5134  } else { /* peer is valid */
5135  /* Ah ha! Someone answered within the desired timeframe. Of course after this
5136  we will always return with -1 so that it is hung up properly after the
5137  conversation. */
5138  if (!strcmp(qe->chan->tech->type, "DAHDI"))
5139  ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
5140  if (!strcmp(peer->tech->type, "DAHDI"))
5141  ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
5142  /* Update parameters for the queue */
5143  time(&now);
5144  recalc_holdtime(qe, (now - qe->start));
5145  ao2_lock(qe->parent);
5146  callcompletedinsl = ((now - qe->start) <= qe->parent->servicelevel);
5147  ao2_unlock(qe->parent);
5148  member = lpeer->member;
5149  /* Increment the refcount for this member, since we're going to be using it for awhile in here. */
5150  ao2_ref(member, 1);
5151  hangupcalls(outgoing, peer, qe->cancel_answered_elsewhere);
5152  outgoing = NULL;
5153  if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
5154  int res2;
5155 
5156  res2 = ast_autoservice_start(qe->chan);
5157  if (!res2) {
5158  if (qe->parent->memberdelay) {
5159  ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
5160  res2 = ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
5161  }
5162  if (!res2 && announce) {
5163  if (play_file(peer, announce) < 0) {
5164  ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", announce, peer->name);
5165  }
5166  }
5167  if (!res2 && qe->parent->reportholdtime) {
5168  if (!play_file(peer, qe->parent->sound_reporthold)) {
5169  int holdtime, holdtimesecs;
5170 
5171  time(&now);
5172  holdtime = abs((now - qe->start) / 60);
5173  holdtimesecs = abs((now - qe->start) % 60);
5174  if (holdtime > 0) {
5175  ast_say_number(peer, holdtime, AST_DIGIT_ANY, peer->language, NULL);
5176  if (play_file(peer, qe->parent->sound_minutes) < 0) {
5177  ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", qe->parent->sound_minutes, peer->name);
5178  }
5179  }
5180  if (holdtimesecs > 1) {
5181  ast_say_number(peer, holdtimesecs, AST_DIGIT_ANY, peer->language, NULL);
5182  if (play_file(peer, qe->parent->sound_seconds) < 0) {
5183  ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", qe->parent->sound_seconds, peer->name);
5184  }
5185  }
5186  }
5187  }
5189  }
5190  if (ast_check_hangup(peer)) {
5191  /* Agent must have hung up */
5192  ast_log(LOG_WARNING, "Agent on %s hungup on the customer.\n", peer->name);
5193  ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "AGENTDUMP", "%s", "");
5194  if (qe->parent->eventwhencalled)
5195  manager_event(EVENT_FLAG_AGENT, "AgentDump",
5196  "Queue: %s\r\n"
5197  "Uniqueid: %s\r\n"
5198  "Channel: %s\r\n"
5199  "Member: %s\r\n"
5200  "MemberName: %s\r\n"
5201  "%s",
5202  queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
5203  qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
5204  ast_hangup(peer);
5205  ao2_ref(member, -1);
5206  goto out;
5207  } else if (ast_check_hangup(qe->chan)) {
5208  /* Caller must have hung up just before being connected */
5209  ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", peer->name);
5210  ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
5211  record_abandoned(qe);
5212  ast_hangup(peer);
5213  ao2_ref(member, -1);
5214  return -1;
5215  }
5216  }
5217  /* Stop music on hold */
5218  if (ringing)
5219  ast_indicate(qe->chan,-1);
5220  else
5221  ast_moh_stop(qe->chan);
5222  /* If appropriate, log that we have a destination channel */
5223  if (qe->chan->cdr)
5224  ast_cdr_setdestchan(qe->chan->cdr, peer->name);
5225  /* Make sure channels are compatible */
5226  res = ast_channel_make_compatible(qe->chan, peer);
5227  if (res < 0) {
5228  ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "SYSCOMPAT", "%s", "");
5229  ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", qe->chan->name, peer->name);
5230  record_abandoned(qe);
5231  ast_cdr_failed(qe->chan->cdr);
5232  ast_hangup(peer);
5233  ao2_ref(member, -1);
5234  return -1;
5235  }
5236 
5237  /* Play announcement to the caller telling it's his turn if defined */
5239  if (play_file(qe->chan, qe->parent->sound_callerannounce))
5240  ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", qe->parent->sound_callerannounce);
5241  }
5242 
5243  ao2_lock(qe->parent);
5244  /* if setinterfacevar is defined, make member variables available to the channel */
5245  /* use pbx_builtin_setvar to set a load of variables with one call */
5246  if (qe->parent->setinterfacevar) {
5247  snprintf(interfacevar, sizeof(interfacevar), "MEMBERINTERFACE=%s,MEMBERNAME=%s,MEMBERCALLS=%d,MEMBERLASTCALL=%ld,MEMBERPENALTY=%d,MEMBERDYNAMIC=%d,MEMBERREALTIME=%d",
5248  member->interface, member->membername, member->calls, (long)member->lastcall, member->penalty, member->dynamic, member->realtime);
5249  pbx_builtin_setvar_multiple(qe->chan, interfacevar);
5250  pbx_builtin_setvar_multiple(peer, interfacevar);
5251  }
5252 
5253  /* if setqueueentryvar is defined, make queue entry (i.e. the caller) variables available to the channel */
5254  /* use pbx_builtin_setvar to set a load of variables with one call */
5255  if (qe->parent->setqueueentryvar) {
5256  snprintf(interfacevar, sizeof(interfacevar), "QEHOLDTIME=%ld,QEORIGINALPOS=%d",
5257  (long) time(NULL) - qe->start, qe->opos);
5258  pbx_builtin_setvar_multiple(qe->chan, interfacevar);
5259  pbx_builtin_setvar_multiple(peer, interfacevar);
5260  }
5261 
5262  ao2_unlock(qe->parent);
5263 
5264  /* try to set queue variables if configured to do so*/
5265  set_queue_variables(qe->parent, qe->chan);
5266  set_queue_variables(qe->parent, peer);
5267 
5268  ast_channel_lock(qe->chan);
5269  if ((monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME"))) {
5270  monitorfilename = ast_strdupa(monitorfilename);
5271  }
5272  ast_channel_unlock(qe->chan);
5273  /* Begin Monitoring */
5274  if (qe->parent->monfmt && *qe->parent->monfmt) {
5275  if (!qe->parent->montype) {
5276  const char *monexec;
5277  ast_debug(1, "Starting Monitor as requested.\n");
5278  ast_channel_lock(qe->chan);
5279  if ((monexec = pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC")) || pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC_ARGS")) {
5280  which = qe->chan;
5281  monexec = monexec ? ast_strdupa(monexec) : NULL;
5282  }
5283  else
5284  which = peer;
5285  ast_channel_unlock(qe->chan);
5286  if (monitorfilename) {
5287  ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1, X_REC_IN | X_REC_OUT);
5288  } else if (qe->chan->cdr) {
5289  ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1, X_REC_IN | X_REC_OUT);
5290  } else {
5291  /* Last ditch effort -- no CDR, make up something */
5292  snprintf(tmpid, sizeof(tmpid), "chan-%lx", (unsigned long)ast_random());
5293  ast_monitor_start(which, qe->parent->monfmt, tmpid, 1, X_REC_IN | X_REC_OUT);
5294  }
5295  if (!ast_strlen_zero(monexec)) {
5296  ast_monitor_setjoinfiles(which, 1);
5297  }
5298  } else {
5299  mixmonapp = pbx_findapp("MixMonitor");
5300 
5301  if (mixmonapp) {
5302  ast_debug(1, "Starting MixMonitor as requested.\n");
5303  if (!monitorfilename) {
5304  if (qe->chan->cdr)
5305  ast_copy_string(tmpid, qe->chan->cdr->uniqueid, sizeof(tmpid));
5306  else
5307  snprintf(tmpid, sizeof(tmpid), "chan-%lx", (unsigned long)ast_random());
5308  } else {
5309  const char *m = monitorfilename;
5310  for (p = tmpid2; p < tmpid2 + sizeof(tmpid2) - 1; p++, m++) {
5311  switch (*m) {
5312  case '^':
5313  if (*(m + 1) == '{')
5314  *p = '$';
5315  break;
5316  case ',':
5317  *p++ = '\\';
5318  /* Fall through */
5319  default:
5320  *p = *m;
5321  }
5322  if (*m == '\0')
5323  break;
5324  }
5325  if (p == tmpid2 + sizeof(tmpid2))
5326  tmpid2[sizeof(tmpid2) - 1] = '\0';
5327 
5328  pbx_substitute_variables_helper(qe->chan, tmpid2, tmpid, sizeof(tmpid) - 1);
5329  }
5330 
5331  ast_channel_lock(qe->chan);
5332  if ((monitor_exec = pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC"))) {
5333  monitor_exec = ast_strdupa(monitor_exec);
5334  }
5335  if ((monitor_options = pbx_builtin_getvar_helper(qe->chan, "MONITOR_OPTIONS"))) {
5336  monitor_options = ast_strdupa(monitor_options);
5337  } else {
5338  monitor_options = "";
5339  }
5340  ast_channel_unlock(qe->chan);
5341 
5342  if (monitor_exec) {
5343  const char *m = monitor_exec;
5344  for (p = meid2; p < meid2 + sizeof(meid2) - 1; p++, m++) {
5345  switch (*m) {
5346  case '^':
5347  if (*(m + 1) == '{')
5348  *p = '$';
5349  break;
5350  case ',':
5351  *p++ = '\\';
5352  /* Fall through */
5353  default:
5354  *p = *m;
5355  }
5356  if (*m == '\0')
5357  break;
5358  }
5359  if (p == meid2 + sizeof(meid2))
5360  meid2[sizeof(meid2) - 1] = '\0';
5361 
5362  pbx_substitute_variables_helper(qe->chan, meid2, meid, sizeof(meid) - 1);
5363  }
5364 
5365  snprintf(tmpid2, sizeof(tmpid2), "%s.%s", tmpid, qe->parent->monfmt);
5366 
5367  if (!ast_strlen_zero(monitor_exec))
5368  snprintf(mixmonargs, sizeof(mixmonargs), "%s,b%s,%s", tmpid2, monitor_options, monitor_exec);
5369  else
5370  snprintf(mixmonargs, sizeof(mixmonargs), "%s,b%s", tmpid2, monitor_options);
5371 
5372  ast_debug(1, "Arguments being passed to MixMonitor: %s\n", mixmonargs);
5373  /* We purposely lock the CDR so that pbx_exec does not update the application data */
5374  if (qe->chan->cdr)
5376  pbx_exec(qe->chan, mixmonapp, mixmonargs);
5377  if (qe->chan->cdr)
5379 
5380  } else {
5381  ast_log(LOG_WARNING, "Asked to run MixMonitor on this call, but cannot find the MixMonitor app!\n");
5382  }
5383  }
5384  }
5385  /* Drop out of the queue at this point, to prepare for next caller */
5386  leave_queue(qe);
5388  ast_debug(1, "app_queue: sendurl=%s.\n", url);
5389  ast_channel_sendurl(peer, url);
5390  }
5391 
5392  /* run a macro for this connection if defined. The macro simply returns, no action is taken on the result */
5393  /* use macro from dialplan if passed as a option, otherwise use the default queue macro */
5394  if (!ast_strlen_zero(macro)) {
5395  macroexec = ast_strdupa(macro);
5396  } else {
5397  if (qe->parent->membermacro)
5398  macroexec = ast_strdupa(qe->parent->membermacro);
5399  }
5400 
5401  if (!ast_strlen_zero(macroexec)) {
5402  ast_debug(1, "app_queue: macro=%s.\n", macroexec);
5403 
5404  res = ast_autoservice_start(qe->chan);
5405  if (res) {
5406  ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
5407  res = -1;
5408  }
5409 
5410  application = pbx_findapp("Macro");
5411 
5412  if (application) {
5413  res = pbx_exec(peer, application, macroexec);
5414  ast_debug(1, "Macro exited with status %d\n", res);
5415  res = 0;
5416  } else {
5417  ast_log(LOG_ERROR, "Could not find application Macro\n");
5418  res = -1;
5419  }
5420 
5421  if (ast_autoservice_stop(qe->chan) < 0) {
5422  ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
5423  res = -1;
5424  }
5425  }
5426 
5427  /* run a gosub for this connection if defined. The gosub simply returns, no action is taken on the result */
5428  /* use gosub from dialplan if passed as a option, otherwise use the default queue gosub */
5429  if (!ast_strlen_zero(gosub)) {
5430  gosubexec = ast_strdupa(gosub);
5431  } else {
5432  if (qe->parent->membergosub)
5433  gosubexec = ast_strdupa(qe->parent->membergosub);
5434  }
5435 
5436  if (!ast_strlen_zero(gosubexec)) {
5437  ast_debug(1, "app_queue: gosub=%s.\n", gosubexec);
5438 
5439  res = ast_autoservice_start(qe->chan);
5440  if (res) {
5441  ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
5442  res = -1;
5443  }
5444 
5445  application = pbx_findapp("Gosub");
5446 
5447  if (application) {
5448  char *gosub_args, *gosub_argstart;
5449 
5450  /* Set where we came from */
5451  ast_copy_string(peer->context, "app_queue_gosub_virtual_context", sizeof(peer->context));
5452  ast_copy_string(peer->exten, "s", sizeof(peer->exten));
5453  peer->priority = 0;
5454 
5455  gosub_argstart = strchr(gosubexec, ',');
5456  if (gosub_argstart) {
5457  const char *what_is_s = "s";
5458  *gosub_argstart = 0;
5459  if (!ast_exists_extension(peer, gosubexec, "s", 1, S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL)) &&
5460  ast_exists_extension(peer, gosubexec, "~~s~~", 1, S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL))) {
5461  what_is_s = "~~s~~";
5462  }
5463  if (ast_asprintf(&gosub_args, "%s,%s,1(%s)", gosubexec, what_is_s, gosub_argstart + 1) < 0) {
5464  gosub_args = NULL;
5465  }
5466  *gosub_argstart = ',';
5467  } else {
5468  const char *what_is_s = "s";
5469  if (!ast_exists_extension(peer, gosubexec, "s", 1, S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL)) &&
5470  ast_exists_extension(peer, gosubexec, "~~s~~", 1, S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL))) {
5471  what_is_s = "~~s~~";
5472  }
5473  if (ast_asprintf(&gosub_args, "%s,%s,1", gosubexec, what_is_s) < 0) {
5474  gosub_args = NULL;
5475  }
5476  }
5477  if (gosub_args) {
5478  res = pbx_exec(peer, application, gosub_args);
5479  if (!res) {
5480  struct ast_pbx_args args;
5481  memset(&args, 0, sizeof(args));
5482  args.no_hangup_chan = 1;
5483  ast_pbx_run_args(peer, &args);
5484  }
5485  ast_free(gosub_args);
5486  ast_debug(1, "Gosub exited with status %d\n", res);
5487  } else {
5488  ast_log(LOG_ERROR, "Could not Allocate string for Gosub arguments -- Gosub Call Aborted!\n");
5489  }
5490  } else {
5491  ast_log(LOG_ERROR, "Could not find application Gosub\n");
5492  res = -1;
5493  }
5494 
5495  if (ast_autoservice_stop(qe->chan) < 0) {
5496  ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
5497  res = -1;
5498  }
5499  }
5500 
5501  if (!ast_strlen_zero(agi)) {
5502  ast_debug(1, "app_queue: agi=%s.\n", agi);
5503  application = pbx_findapp("agi");
5504  if (application) {
5505  agiexec = ast_strdupa(agi);
5506  pbx_exec(qe->chan, application, agiexec);
5507  } else
5508  ast_log(LOG_WARNING, "Asked to execute an AGI on this channel, but could not find application (agi)!\n");
5509  }
5510  qe->handled++;
5511  ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "CONNECT", "%ld|%s|%ld", (long) time(NULL) - qe->start, peer->uniqueid,
5512  (long)(orig - to > 0 ? (orig - to) / 1000 : 0));
5513 
5514  if (qe->chan->cdr) {
5515  struct ast_cdr *cdr;
5516  struct ast_cdr *newcdr;
5517 
5518  /* Only work with the last CDR in the stack*/
5519  cdr = qe->chan->cdr;
5520  while (cdr->next) {
5521  cdr = cdr->next;
5522  }
5523 
5524  /* If this CDR is not related to us add new one*/
5525  if ((strcasecmp(cdr->uniqueid, qe->chan->uniqueid)) &&
5526  (strcasecmp(cdr->linkedid, qe->chan->uniqueid)) &&
5527  (newcdr = ast_cdr_dup(cdr))) {
5528  ast_channel_lock(qe->chan);
5529  ast_cdr_init(newcdr, qe->chan);
5530  ast_cdr_reset(newcdr, 0);
5531  cdr = ast_cdr_append(cdr, newcdr);
5532  cdr = cdr->next;
5533  ast_channel_unlock(qe->chan);
5534  }
5535 
5536  if (update_cdr) {
5537  ast_copy_string(cdr->dstchannel, member->membername, sizeof(cdr->dstchannel));
5538  }
5539  }
5540 
5541  if (qe->parent->eventwhencalled)
5542  manager_event(EVENT_FLAG_AGENT, "AgentConnect",
5543  "Queue: %s\r\n"
5544  "Uniqueid: %s\r\n"
5545  "Channel: %s\r\n"
5546  "Member: %s\r\n"
5547  "MemberName: %s\r\n"
5548  "Holdtime: %ld\r\n"
5549  "BridgedChannel: %s\r\n"
5550  "Ringtime: %ld\r\n"
5551  "%s",
5552  queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
5553  (long) time(NULL) - qe->start, peer->uniqueid, (long)(orig - to > 0 ? (orig - to) / 1000 : 0),
5554  qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
5555  ast_copy_string(oldcontext, qe->chan->context, sizeof(oldcontext));
5556  ast_copy_string(oldexten, qe->chan->exten, sizeof(oldexten));
5557 
5558  if ((queue_end_bridge = ao2_alloc(sizeof(*queue_end_bridge), NULL))) {
5559  queue_end_bridge->q = qe->parent;
5560  queue_end_bridge->chan = qe->chan;
5561  bridge_config.end_bridge_callback = end_bridge_callback;
5562  bridge_config.end_bridge_callback_data = queue_end_bridge;
5563  bridge_config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup;
5564  /* Since queue_end_bridge can survive beyond the life of this call to Queue, we need
5565  * to make sure to increase the refcount of this queue so it cannot be freed until we
5566  * are done with it. We remove this reference in end_bridge_callback.
5567  */
5568  queue_t_ref(qe->parent, "For bridge_config reference");
5569  }
5570 
5571  time(&callstart);
5572  transfer_ds = setup_transfer_datastore(qe, member, callstart, callcompletedinsl);
5573  bridge = ast_bridge_call(qe->chan, peer, &bridge_config);
5574 
5575  /* If the queue member did an attended transfer, then the TRANSFER already was logged in the queue_log
5576  * when the masquerade occurred. These other "ending" queue_log messages are unnecessary, except for
5577  * the AgentComplete manager event
5578  */
5579  ast_channel_lock(qe->chan);
5580  if (!attended_transfer_occurred(qe->chan)) {
5581  struct ast_datastore *tds;
5582 
5583  /* detect a blind transfer */
5584  if (!(qe->chan->_softhangup | peer->_softhangup) && (strcasecmp(oldcontext, qe->chan->context) || strcasecmp(oldexten, qe->chan->exten))) {
5585  ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "TRANSFER", "%s|%s|%ld|%ld|%d",
5586  qe->chan->exten, qe->chan->context, (long) (callstart - qe->start),
5587  (long) (time(NULL) - callstart), qe->opos);
5588  send_agent_complete(qe, queuename, peer, member, callstart, vars, sizeof(vars), TRANSFER);
5589  } else if (ast_check_hangup(qe->chan) && !ast_check_hangup(peer)) {
5590  ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "COMPLETECALLER", "%ld|%ld|%d",
5591  (long) (callstart - qe->start), (long) (time(NULL) - callstart), qe->opos);
5592  send_agent_complete(qe, queuename, peer, member, callstart, vars, sizeof(vars), CALLER);
5593  } else {
5594  ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "COMPLETEAGENT", "%ld|%ld|%d",
5595  (long) (callstart - qe->start), (long) (time(NULL) - callstart), qe->opos);
5596  send_agent_complete(qe, queuename, peer, member, callstart, vars, sizeof(vars), AGENT);
5597  }
5598  if ((tds = ast_channel_datastore_find(qe->chan, &queue_transfer_info, NULL))) {
5600  /* tds was added by setup_transfer_datastore() and is freed below. */
5601  }
5602  ast_channel_unlock(qe->chan);
5603  update_queue(qe->parent, member, callcompletedinsl, (time(NULL) - callstart));
5604  } else {
5605  ast_channel_unlock(qe->chan);
5606 
5607  /* We already logged the TRANSFER on the queue_log, but we still need to send the AgentComplete event */
5608  send_agent_complete(qe, queuename, peer, member, callstart, vars, sizeof(vars), TRANSFER);
5609  }
5610 
5611  if (transfer_ds) {
5612  ast_datastore_free(transfer_ds);
5613  }
5614  ast_hangup(peer);
5615  res = bridge ? bridge : 1;
5616  ao2_ref(member, -1);
5617  }
5618 out:
5619  hangupcalls(outgoing, NULL, qe->cancel_answered_elsewhere);
5620 
5621  return res;
5622 }
5623 
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: pbx.c:4676
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1916
struct callattempt * q_next
Definition: app_queue.c:1121
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
Options for ast_pbx_run()
Definition: pbx.h:336
int servicelevel
Definition: app_queue.c:1299
struct call_queue * parent
Definition: app_queue.c:1144
#define ast_channel_lock(chan)
Definition: channel.h:2466
#define X_REC_IN
Definition: monitor.h:35
int dynamic
Definition: app_queue.c:1182
int ast_cdr_isset_unanswered(void)
Definition: cdr.c:185
Main Channel structure associated with a channel.
Definition: channel.h:742
void ast_cdr_failed(struct ast_cdr *cdr)
Fail a call.
Definition: cdr.c:764
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
struct ast_party_connected_line connected
Channel Connected Line ID information.
Definition: channel.h:811
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static int store_next_rr(struct queue_ent *qe, struct callattempt *outgoing)
Search for best metric and add to Round Robbin queue.
Definition: app_queue.c:3602
const char *const type
Definition: channel.h:508
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
Definition: astobj2.c:470
time_t lastcall
Definition: app_queue.c:1126
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:172
static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator)
Definition: app_queue.c:4776
unsigned int eventwhencalled
Definition: app_queue.c:1270
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:179
struct ast_channel * chan
Definition: app_queue.c:1168
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: pbx.c:1537
int priority
Definition: channel.h:841
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx.c:1497
static struct ast_datastore_info queue_transfer_info
a datastore used to help correctly log attended transfers of queue callers
Definition: app_queue.c:4688
const ast_string_field membergosub
Definition: app_queue.c:1266
const ast_string_field uniqueid
Definition: channel.h:787
char dstchannel[AST_MAX_EXTENSION]
Definition: cdr.h:94
void ast_cdr_reset(struct ast_cdr *cdr, struct ast_flags *flags)
Reset the detail record, optionally posting it first.
Definition: cdr.c:1149
#define AST_DIGIT_ANY
Definition: file.h:47
time_t start
Definition: app_queue.c:1165
#define ast_test_flag(p, flag)
Definition: utils.h:63
int option_debug
Definition: asterisk.c:182
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
int ast_channel_supports_html(struct ast_channel *channel)
Checks for HTML support on a channel.
Definition: channel.c:5902
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:144
struct ast_cdr * next
Definition: cdr.h:132
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct call_queue * lastqueue
Definition: app_queue.c:1127
time_t expire
Definition: app_queue.c:1166
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
struct ast_cdr * ast_cdr_dup(struct ast_cdr *cdr)
Duplicate a record.
Definition: cdr.c:213
char uniqueid[150]
Definition: cdr.h:121
static struct callattempt * wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed, int ringing)
Wait for a member to answer the call.
Definition: app_queue.c:3789
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.
Definition: app_queue.c:4554
char interface[256]
Definition: app_queue.c:1124
int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
Bridge a call, optionally allowing redirection.
Definition: features.c:3960
static int attended_transfer_occurred(struct ast_channel *chan)
mechanism to tell if a queue caller was atxferred by a queue member.
Definition: app_queue.c:4735
static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl, int newtalktime)
update the queue status
Definition: app_queue.c:4506
#define AST_OPTION_TONE_VERIFY
Definition: frame.h:441
int realtime
Definition: app_queue.c:1183
char interface[80]
Definition: app_queue.c:1175
struct ast_cdr * cdr
Definition: channel.h:766
#define ao2_unlock(a)
Definition: astobj2.h:497
unsigned int setinterfacevar
Definition: app_queue.c:1273
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
Structure for a data store object.
Definition: datastore.h:54
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2604
int ringlimit
Definition: app_queue.c:1307
void ast_monitor_setjoinfiles(struct ast_channel *chan, int turnon)
Definition: res_monitor.c:867
#define LOG_DEBUG
Definition: logger.h:122
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
Definition: channel.c:7795
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:8051
struct ao2_container * members
Definition: app_queue.c:1320
char monfmt[8]
Definition: app_queue.c:1301
static void recalc_holdtime(struct queue_ent *qe, int newholdtime)
Definition: app_queue.c:2993
const ast_string_field membermacro
Definition: app_queue.c:1266
char membername[80]
Definition: app_queue.c:1179
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:65
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
#define X_REC_OUT
Definition: monitor.h:36
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
struct ast_cdr * ast_cdr_append(struct ast_cdr *cdr, struct ast_cdr *newcdr)
Definition: cdr.c:1216
#define ast_asprintf(a, b, c...)
Definition: astmm.h:121
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
struct ast_party_connected_line connected
Definition: app_queue.c:1130
static void end_bridge_callback(void *data)
Definition: app_queue.c:4783
static char * vars2manager(struct ast_channel *chan, char *vars, size_t len)
convert &quot;\n&quot; to &quot;\nVariable: &quot; ready for manager to use
Definition: app_queue.c:3206
int penalty
Definition: app_queue.c:1180
int memberdelay
Definition: app_queue.c:1317
struct call_queue * q
Definition: app_queue.c:4772
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
struct ast_datastore_info dialed_interface_info
unsigned int block_connected_update
Definition: app_queue.c:1134
enum ast_pbx_result ast_pbx_run_args(struct ast_channel *c, struct ast_pbx_args *args)
Execute the PBX in the current thread.
Definition: pbx.c:5906
char linkedid[32]
Definition: cdr.h:123
#define AST_MAX_EXTENSION
Definition: channel.h:135
bridge configuration
Definition: channel.h:974
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
long int ast_random(void)
Definition: utils.c:1640
static void hangupcalls(struct callattempt *outgoing, struct ast_channel *exception, int cancel_answered_elsewhere)
Hang up a list of outgoing calls.
Definition: app_queue.c:3090
#define ao2_lock(a)
Definition: astobj2.h:488
struct member * member
Definition: app_queue.c:1128
int ast_monitor_start(struct ast_channel *chan, const char *format_spec, const char *fname_base, int need_lock, int stream_action)
Start monitoring a channel.
Definition: res_monitor.c:290
int strategy
Definition: app_queue.c:1281
struct call_queue * lastqueue
Definition: app_queue.c:1188
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:5400
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:238
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
static void leave_queue(struct queue_ent *qe)
Caller leaving queue.
Definition: app_queue.c:3012
We define a custom &quot;local user&quot; structure because we use it not only for keeping track of what is i...
Definition: app_queue.c:1120
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
Responsible for call detail data.
Definition: cdr.h:82
#define LOG_ERROR
Definition: logger.h:155
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
static struct @350 args
const ast_string_field name
Definition: app_queue.c:1266
static struct ast_datastore * setup_transfer_datastore(struct queue_ent *qe, struct member *member, time_t starttime, int callcompletedinsl)
create a datastore for storing relevant info to log attended transfers in the queue_log ...
Definition: app_queue.c:4742
unsigned int reportholdtime
Definition: app_queue.c:1276
struct ast_channel * chan
Definition: app_queue.c:4773
enum ast_channel_state _state
Definition: channel.h:839
const ast_string_field name
Definition: channel.h:787
int pbx_builtin_setvar_multiple(struct ast_channel *chan, const char *data)
Parse and set multiple channel variables, where the pairs are separated by the &#39;,&#39; character...
Definition: pbx.c:10633
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static float di[4]
Definition: tdd.c:59
int _softhangup
Definition: channel.h:832
#define EVENT_FLAG_AGENT
Definition: manager.h:76
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:430
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
#define LOG_NOTICE
Definition: logger.h:133
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct ast_dialed_interface::@174 list
int ast_channel_sendurl(struct ast_channel *channel, const char *url)
Sends a URL on a given link Send URL on link.
Definition: channel.c:5914
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define AST_MAX_CONTEXT
Definition: channel.h:136
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:611
#define ast_free(a)
Definition: astmm.h:97
static int play_file(struct ast_channel *chan, const char *filename)
Definition: app_queue.c:2787
#define queue_t_ref(a, b)
Definition: app_queue.c:1472
#define DATASTORE_INHERIT_FOREVER
Definition: channel.h:156
int timeoutpriority
Definition: app_queue.c:1313
unsigned int inheritance
Definition: datastore.h:58
const ast_string_field sound_seconds
Definition: app_queue.c:1266
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
#define ast_clear_flag(p, flag)
Definition: utils.h:77
int pending
Definition: app_queue.c:1160
int calls
Definition: app_queue.c:1181
unsigned int setqueueentryvar
Definition: app_queue.c:1275
const ast_string_field sound_reporthold
Definition: app_queue.c:1266
static void callattempt_free(struct callattempt *doomed)
Definition: app_queue.c:3080
void * data
Definition: datastore.h:56
static int store_next_lin(struct queue_ent *qe, struct callattempt *outgoing)
Search for best metric and add to Linear queue.
Definition: app_queue.c:3626
void ast_party_connected_line_copy(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src)
Copy the source connected line information to the destination connected line.
Definition: channel.c:2316
static void record_abandoned(struct queue_ent *qe)
Record that a caller gave up on waiting in queue.
Definition: app_queue.c:3706
static void send_agent_complete(const struct queue_ent *qe, const char *queuename, const struct ast_channel *peer, const struct member *member, time_t callstart, char *vars, size_t vars_len, enum agent_complete_reason rsn)
Send out AMI message with member call completion status information.
Definition: app_queue.c:4637
int ast_channel_make_compatible(struct ast_channel *c0, struct ast_channel *c1)
Makes two channel formats compatible.
Definition: channel.c:5970
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Definition: channel.c:8397
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
ast_app: A registered application
Definition: pbx.c:971
static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
Set variables of queue.
Definition: app_queue.c:1490
const ast_string_field sound_minutes
Definition: app_queue.c:1266
int handled
Definition: app_queue.c:1158
int cancel_answered_elsewhere
Definition: app_queue.c:1167
static char url[512]
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
struct ast_channel * chan
Definition: app_queue.c:1123
struct ast_channel_tech * tech
Definition: channel.h:743
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
void ast_cdr_setdestchan(struct ast_cdr *cdr, const char *chan)
Set the destination channel, if there was one.
Definition: cdr.c:812
const ast_string_field sound_callerannounce
Definition: app_queue.c:1266
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
#define QUEUE_EVENT_VARIABLES
Definition: app_queue.c:1210
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2599
int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *chan)
Initialize based on a channel.
Definition: cdr.c:897
time_t lastcall
Definition: app_queue.c:1187
const ast_string_field language
Definition: channel.h:787
unsigned int stillgoing
Definition: app_queue.c:1138
char announce[PATH_MAX]
Definition: app_queue.c:1146
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
Place a call to a queue member.
Definition: app_queue.c:3565
int ringcount
Definition: app_queue.c:1190
static int update_cdr
queues.conf [general] option
Definition: app_queue.c:1076
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int unload_module ( void  )
static

Definition at line 9075 of file app_queue.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_ref, ao2_t_iterator_next, ARRAY_LEN, ast_cli_unregister_multiple(), ast_context_destroy(), ast_context_find(), ast_context_remove_extension2(), ast_custom_function_unregister(), ast_data_unregister, ast_event_unsubscribe(), ast_extension_state_del(), ast_manager_unregister(), ast_taskprocessor_unreference(), ast_unload_realtime(), ast_unregister_application(), cli_queue, extension_state_cb(), queue_t_unref, queueexists_function, queuemembercount_dep, queuemembercount_function, queuememberlist_function, queuememberpaused_function, queuememberpenalty_function, queuememberstatus_function, queues, queues_t_unlink, queuevar_function, and queuewaitingcount_function.

9075 {
9076  int res;
9077  struct ast_context *con;
9078  struct ao2_iterator q_iter;
9079  struct call_queue *q = NULL;
9080 
9082  res = ast_manager_unregister("QueueStatus");
9083  res |= ast_manager_unregister("Queues");
9084  res |= ast_manager_unregister("QueueRule");
9085  res |= ast_manager_unregister("QueueSummary");
9086  res |= ast_manager_unregister("QueueAdd");
9087  res |= ast_manager_unregister("QueueRemove");
9088  res |= ast_manager_unregister("QueuePause");
9089  res |= ast_manager_unregister("QueueLog");
9090  res |= ast_manager_unregister("QueuePenalty");
9091  res |= ast_manager_unregister("QueueReload");
9092  res |= ast_manager_unregister("QueueReset");
9108 
9109  res |= ast_data_unregister(NULL);
9110 
9111  if (device_state_sub)
9113 
9115 
9116  if ((con = ast_context_find("app_queue_gosub_virtual_context"))) {
9117  ast_context_remove_extension2(con, "s", 1, NULL, 0);
9118  ast_context_destroy(con, "app_queue"); /* leave no trace */
9119  }
9120 
9121  q_iter = ao2_iterator_init(queues, 0);
9122  while ((q = ao2_t_iterator_next(&q_iter, "Iterate through queues"))) {
9123  queues_t_unlink(queues, q, "Remove queue from container due to unload");
9124  queue_t_unref(q, "Done with iterator");
9125  }
9126  ao2_iterator_destroy(&q_iter);
9128  ao2_ref(queues, -1);
9129  ast_unload_realtime("queue_members");
9130  return res;
9131 }
9132 
static struct ast_custom_function queuewaitingcount_function
Definition: app_queue.c:7112
static char * app_ql
Definition: app_queue.c:1049
static struct ast_custom_function queuememberstatus_function
Definition: app_queue.c:7128
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
static char * app_aqm
Definition: app_queue.c:1041
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
int ast_unload_realtime(const char *family)
Release any resources cached for a realtime family.
Definition: config.c:2630
int ast_extension_state_del(int id, ast_state_cb_type change_cb)
Deletes a registered state change callback by ID.
Definition: pbx.c:5157
static struct ast_custom_function queuemembercount_dep
Definition: app_queue.c:7107
#define ao2_t_iterator_next(arg1, arg2)
Definition: astobj2.h:1125
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
static char * app_rqm
Definition: app_queue.c:1043
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
static struct ast_custom_function queueexists_function
Definition: app_queue.c:7092
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Definition: pbx.c:3814
static char * app
Definition: app_queue.c:1039
static struct ast_taskprocessor * devicestate_tps
Definition: app_queue.c:1022
static struct ast_custom_function queuemembercount_function
Definition: app_queue.c:7102
static struct ao2_container * queues
Definition: app_queue.c:1334
static struct ast_custom_function queuememberpenalty_function
Definition: app_queue.c:7122
#define ast_data_unregister(path)
Definition: data.h:394
#define ao2_ref(o, delta)
Definition: astobj2.h:472
static struct ast_custom_function queuememberlist_function
Definition: app_queue.c:7117
static char * app_pqm
Definition: app_queue.c:1045
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
static struct ast_custom_function queuememberpaused_function
Definition: app_queue.c:7133
static struct ast_cli_entry cli_queue[]
Definition: app_queue.c:8793
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
static struct ast_custom_function queuevar_function
Definition: app_queue.c:7097
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
static struct ast_event_sub * device_state_sub
Subscription to device state change events.
Definition: app_queue.c:1073
int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
This functionc locks given context, search for the right extension and fires out all peer in this ext...
Definition: pbx.c:6144
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context (or ANY context if NULL)
Definition: pbx.c:9875
static int extension_state_cb(char *context, char *exten, enum ast_extension_states state, void *data)
Definition: app_queue.c:1757
#define queues_t_unlink(c, q, tag)
Definition: app_queue.c:1475
struct ast_event_sub * ast_event_unsubscribe(struct ast_event_sub *event_sub)
Un-subscribe from events.
Definition: event.c:987
ast_context: An extension context
Definition: pbx.c:955
static char * app_upqm
Definition: app_queue.c:1047
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: pbx.c:2971
int ast_manager_unregister(char *action)
Unregister a registered manager command.
Definition: manager.c:5355
static void update_qe_rule ( struct queue_ent qe)
static

update rules for queues

Calculate min/max penalties making sure if relative they stay within bounds. Update queues penalty and set dialplan vars, goto next list entry.

Definition at line 4367 of file app_queue.c.

References ast_debug, AST_LIST_NEXT, queue_ent::chan, queue_ent::max_penalty, penalty_rule::max_relative, penalty_rule::max_value, queue_ent::min_penalty, penalty_rule::min_relative, penalty_rule::min_value, ast_channel::name, pbx_builtin_setvar_helper(), queue_ent::pr, and penalty_rule::time.

Referenced by queue_exec(), and wait_our_turn().

4367 {
4368  int max_penalty = INT_MAX;
4369 
4370  if (qe->max_penalty != INT_MAX) {
4371  char max_penalty_str[20];
4372 
4373  if (qe->pr->max_relative) {
4374  max_penalty = qe->max_penalty + qe->pr->max_value;
4375  } else {
4376  max_penalty = qe->pr->max_value;
4377  }
4378 
4379  /* a relative change to the penalty could put it below 0 */
4380  if (max_penalty < 0) {
4381  max_penalty = 0;
4382  }
4383 
4384  snprintf(max_penalty_str, sizeof(max_penalty_str), "%d", max_penalty);
4385  pbx_builtin_setvar_helper(qe->chan, "QUEUE_MAX_PENALTY", max_penalty_str);
4386  qe->max_penalty = max_penalty;
4387  ast_debug(3, "Setting max penalty to %d for caller %s since %d seconds have elapsed\n",
4388  qe->max_penalty, qe->chan->name, qe->pr->time);
4389  }
4390 
4391  if (qe->min_penalty != INT_MAX) {
4392  char min_penalty_str[20];
4393  int min_penalty;
4394 
4395  if (qe->pr->min_relative) {
4396  min_penalty = qe->min_penalty + qe->pr->min_value;
4397  } else {
4398  min_penalty = qe->pr->min_value;
4399  }
4400 
4401  if (min_penalty < 0) {
4402  min_penalty = 0;
4403  }
4404 
4405  if (max_penalty != INT_MAX && min_penalty > max_penalty) {
4406  min_penalty = max_penalty;
4407  }
4408 
4409  snprintf(min_penalty_str, sizeof(min_penalty_str), "%d", min_penalty);
4410  pbx_builtin_setvar_helper(qe->chan, "QUEUE_MIN_PENALTY", min_penalty_str);
4411  qe->min_penalty = min_penalty;
4412  ast_debug(3, "Setting min penalty to %d for caller %s since %d seconds have elapsed\n",
4413  qe->min_penalty, qe->chan->name, qe->pr->time);
4414  }
4415 
4416  qe->pr = AST_LIST_NEXT(qe->pr, list);
4417 }
4418 
struct ast_channel * chan
Definition: app_queue.c:1168
int min_penalty
Definition: app_queue.c:1162
int max_relative
Definition: app_queue.c:1216
int max_penalty
Definition: app_queue.c:1161
int min_relative
Definition: app_queue.c:1217
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
struct call_queue::@56 list
const ast_string_field name
Definition: channel.h:787
struct penalty_rule * pr
Definition: app_queue.c:1170
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...
Definition: pbx.c:10546
static int update_queue ( struct call_queue q,
struct member member,
int  callcompletedinsl,
int  newtalktime 
)
static

update the queue status

Return values
Always0

Definition at line 4506 of file app_queue.c.

References ao2_find, ao2_iterator_destroy(), ao2_iterator_init(), ao2_lock, ao2_ref, ao2_t_iterator_next, ao2_unlock, member::calls, call_queue::callscompleted, call_queue::callscompletedinsl, member::lastcall, member::lastqueue, call_queue::members, OBJ_POINTER, queue_t_unref, queues, and call_queue::talktime.

Referenced by queue_transfer_fixup(), and try_calling().

4506 {
4507  int oldtalktime;
4508 
4509  struct member *mem;
4510  struct call_queue *qtmp;
4511  struct ao2_iterator queue_iter;
4512 
4513  if (shared_lastcall) {
4514  queue_iter = ao2_iterator_init(queues, 0);
4515  while ((qtmp = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
4516  ao2_lock(qtmp);
4517  if ((mem = ao2_find(qtmp->members, member, OBJ_POINTER))) {
4518  time(&mem->lastcall);
4519  mem->calls++;
4520  mem->lastqueue = q;
4521  ao2_ref(mem, -1);
4522  }
4523  ao2_unlock(qtmp);
4524  queue_t_unref(qtmp, "Done with iterator");
4525  }
4526  ao2_iterator_destroy(&queue_iter);
4527  } else {
4528  ao2_lock(q);
4529  time(&member->lastcall);
4530  member->calls++;
4531  member->lastqueue = q;
4532  ao2_unlock(q);
4533  }
4534  ao2_lock(q);
4535  q->callscompleted++;
4536  if (callcompletedinsl)
4537  q->callscompletedinsl++;
4538  /* Calculate talktime using the same exponential average as holdtime code*/
4539  oldtalktime = q->talktime;
4540  q->talktime = (((oldtalktime << 2) - oldtalktime) + newtalktime) >> 2;
4541  ao2_unlock(q);
4542  return 0;
4543 }
4544 
#define queue_t_unref(a, b)
Definition: app_queue.c:1473
#define ao2_t_iterator_next(arg1, arg2)
Definition: astobj2.h:1125
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
struct ao2_container * members
Definition: app_queue.c:1320
int callscompletedinsl
Definition: app_queue.c:1300
static struct ao2_container * queues
Definition: app_queue.c:1334
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
struct call_queue * lastqueue
Definition: app_queue.c:1188
int talktime
Definition: app_queue.c:1296
#define ao2_find(arg1, arg2, arg3)
Definition: astobj2.h:964
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
int calls
Definition: app_queue.c:1181
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
int callscompleted
Definition: app_queue.c:1297
static int shared_lastcall
queues.conf [general] option
Definition: app_queue.c:1070
time_t lastcall
Definition: app_queue.c:1187
static int update_realtime_member_field ( struct member mem,
const char *  queue_name,
const char *  field,
const char *  value 
)
static

Definition at line 2628 of file app_queue.c.

References ast_strlen_zero(), ast_update_realtime(), member::rt_uniqueid, and SENTINEL.

Referenced by set_member_paused().

2628 {
2629  int ret = -1;
2630 
2631  if (ast_strlen_zero(mem->rt_uniqueid))
2632  return ret;
2633 
2634  if ((ast_update_realtime("queue_members", "uniqueid", mem->rt_uniqueid, field, value, SENTINEL)) > 0)
2635  ret = 0;
2636 
2637  return ret;
2638 }
2639 
int value
Definition: syslog.c:39
int ast_update_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Update realtime configuration.
Definition: config.c:2679
#define SENTINEL
Definition: compiler.h:75
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char rt_uniqueid[80]
Definition: app_queue.c:1193
static void update_realtime_members ( struct call_queue q)
static

Definition at line 2642 of file app_queue.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_category_browse(), ast_config_destroy(), ast_debug, ast_load_realtime_multientry(), ast_queue_log(), ast_variable_retrieve(), member::dead, member::interface, member_remove_from_queue(), call_queue::members, call_queue::name, member::realtime, rt_handle_member_record(), S_OR, and SENTINEL.

Referenced by load_realtime_queue(), and queue_exec().

2642 {
2643  struct ast_config *member_config = NULL;
2644  struct member *m;
2645  char *interface = NULL;
2646  struct ao2_iterator mem_iter;
2647 
2648  if (!(member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", q->name , SENTINEL))) {
2649  /* This queue doesn't have realtime members. If the queue still has any realtime
2650  * members in memory, they need to be removed.
2651  */
2652  ao2_lock(q);
2653  mem_iter = ao2_iterator_init(q->members, 0);
2654  while ((m = ao2_iterator_next(&mem_iter))) {
2655  if (m->realtime) {
2657  }
2658  ao2_ref(m, -1);
2659  }
2660  ast_debug(3, "Queue %s has no realtime members defined. No need for update\n", q->name);
2661  ao2_unlock(q);
2662  return;
2663  }
2664 
2665  ao2_lock(q);
2666 
2667  /* Temporarily set realtime members dead so we can detect deleted ones.*/
2668  mem_iter = ao2_iterator_init(q->members, 0);
2669  while ((m = ao2_iterator_next(&mem_iter))) {
2670  if (m->realtime)
2671  m->dead = 1;
2672  ao2_ref(m, -1);
2673  }
2674  ao2_iterator_destroy(&mem_iter);
2675 
2676  while ((interface = ast_category_browse(member_config, interface))) {
2677  rt_handle_member_record(q, interface,
2678  ast_variable_retrieve(member_config, interface, "uniqueid"),
2679  S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface),
2680  ast_variable_retrieve(member_config, interface, "penalty"),
2681  ast_variable_retrieve(member_config, interface, "paused"),
2682  S_OR(ast_variable_retrieve(member_config, interface, "state_interface"), interface));
2683  }
2684 
2685  /* Delete all realtime members that have been deleted in DB. */
2686  mem_iter = ao2_iterator_init(q->members, 0);
2687  while ((m = ao2_iterator_next(&mem_iter))) {
2688  if (m->dead) {
2689  ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
2691  }
2692  ao2_ref(m, -1);
2693  }
2694  ao2_iterator_destroy(&mem_iter);
2695  ao2_unlock(q);
2696  ast_config_destroy(member_config);
2697 }
2698 
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
static void member_remove_from_queue(struct call_queue *queue, struct member *mem)
Definition: app_queue.c:2314
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
int realtime
Definition: app_queue.c:1183
char interface[80]
Definition: app_queue.c:1175
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
unsigned int dead
Definition: app_queue.c:1189
struct ao2_container * members
Definition: app_queue.c:1320
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define SENTINEL
Definition: compiler.h:75
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
const ast_string_field name
Definition: app_queue.c:1266
static void rt_handle_member_record(struct call_queue *q, char *interface, const char *rt_uniqueid, const char *membername, const char *penalty_str, const char *paused_str, const char *state_interface)
Find rt member record to update otherwise create one.
Definition: app_queue.c:2328
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: config.c:2650
static int update_status ( struct call_queue q,
struct member m,
const int  status 
)
static

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

Lock interface list find sc, iterate through each queues queue_member list for member to update state inside queues

Definition at line 1630 of file app_queue.c.

References EVENT_FLAG_AGENT, manager_event, and status.

Referenced by extension_state_cb(), and handle_statechange().

1630 {
1631  m->status = status;
1632 
1633  if (q->maskmemberstatus)
1634  return 0;
1635 
1636  manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
1637  "Queue: %s\r\n"
1638  "Location: %s\r\n"
1639  "MemberName: %s\r\n"
1640  "Membership: %s\r\n"
1641  "Penalty: %d\r\n"
1642  "CallsTaken: %d\r\n"
1643  "LastCall: %d\r\n"
1644  "Status: %d\r\n"
1645  "Paused: %d\r\n",
1646  q->name, m->interface, m->membername, m->dynamic ? "dynamic" : m->realtime ? "realtime" : "static",
1647  m->penalty, m->calls, (int)m->lastcall, m->status, m->paused
1648  );
1649 
1650  return 0;
1651 }
1652 
int dynamic
Definition: app_queue.c:1182
int paused
Definition: app_queue.c:1185
unsigned int maskmemberstatus
Definition: app_queue.c:1282
int realtime
Definition: app_queue.c:1183
char interface[80]
Definition: app_queue.c:1175
char membername[80]
Definition: app_queue.c:1179
int penalty
Definition: app_queue.c:1180
const ast_string_field name
Definition: app_queue.c:1266
#define EVENT_FLAG_AGENT
Definition: manager.h:76
int calls
Definition: app_queue.c:1181
int status
Definition: app_queue.c:1184
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
time_t lastcall
Definition: app_queue.c:1187
jack_status_t status
Definition: app_jack.c:143
static int upqm_exec ( struct ast_channel chan,
const char *  data 
)
static

UnPauseQueueMember application.

Definition at line 6103 of file app_queue.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), LOG_WARNING, parse(), pbx_builtin_setvar_helper(), and set_member_paused().

Referenced by load_module().

6103 {
6104  char *parse;
6106  AST_APP_ARG(queuename);
6107  AST_APP_ARG(interface);
6108  AST_APP_ARG(options);
6109  AST_APP_ARG(reason);
6110  );
6111 
6112  if (ast_strlen_zero(data)) {
6113  ast_log(LOG_WARNING, "UnpauseQueueMember requires an argument ([queuename],interface[,options[,reason]])\n");
6114  return -1;
6115  }
6116 
6117  parse = ast_strdupa(data);
6118 
6119  AST_STANDARD_APP_ARGS(args, parse);
6120 
6121  if (ast_strlen_zero(args.interface)) {
6122  ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename],interface[,options[,reason]])\n");
6123  return -1;
6124  }
6125 
6126  if (set_member_paused(args.queuename, args.interface, args.reason, 0)) {
6127  ast_log(LOG_WARNING, "Attempt to unpause interface %s, not found\n", args.interface);
6128  pbx_builtin_setvar_helper(chan, "UPQMSTATUS", "NOTFOUND");
6129  return 0;
6130  }
6131 
6132  pbx_builtin_setvar_helper(chan, "UPQMSTATUS", "UNPAUSED");
6133 
6134  return 0;
6135 }
6136 
#define LOG_WARNING
Definition: logger.h:144
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static struct @350 args
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused)
Definition: app_queue.c:5814
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
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...
Definition: pbx.c:10546
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static int valid_exit ( struct queue_ent qe,
char  digit 
)
static

Check for valid exit from queue via goto.

Return values
0if failure
1if successful

Definition at line 2815 of file app_queue.c.

References ast_canmatch_extension(), ast_goto_if_exists(), ast_strlen_zero(), ast_channel::caller, queue_ent::chan, queue_ent::context, queue_ent::digits, ast_party_caller::id, ast_party_id::number, S_COR, ast_party_number::str, ast_party_number::valid, and queue_ent::valid_digits.

Referenced by say_periodic_announcement(), say_position(), wait_a_bit(), wait_for_answer(), and wait_our_turn().

2815 {
2816  int digitlen = strlen(qe->digits);
2817 
2818  /* Prevent possible buffer overflow */
2819  if (digitlen < sizeof(qe->digits) - 2) {
2820  qe->digits[digitlen] = digit;
2821  qe->digits[digitlen + 1] = '\0';
2822  } else {
2823  qe->digits[0] = '\0';
2824  return 0;
2825  }
2826 
2827  /* If there's no context to goto, short-circuit */
2828  if (ast_strlen_zero(qe->context))
2829  return 0;
2830 
2831  /* If the extension is bad, then reset the digits to blank */
2832  if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1,
2833  S_COR(qe->chan->caller.id.number.valid, qe->chan->caller.id.number.str, NULL))) {
2834  qe->digits[0] = '\0';
2835  return 0;
2836  }
2837 
2838  /* We have an exact match */
2839  if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) {
2840  qe->valid_digits = 1;
2841  /* Return 1 on a successful goto */
2842  return 1;
2843  }
2844 
2845  return 0;
2846 }
2847 
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
char digits[AST_MAX_EXTENSION]
Definition: app_queue.c:1148
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
struct ast_channel * chan
Definition: app_queue.c:1168
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
Definition: pbx.c:5415
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
int valid_digits
Definition: app_queue.c:1149
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:11261
char context[AST_MAX_CONTEXT]
Definition: app_queue.c:1147
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static char* vars2manager ( struct ast_channel chan,
char *  vars,
size_t  len 
)
static

convert "\n" to "\nVariable: " ready for manager to use

Definition at line 3206 of file app_queue.c.

References ast_copy_string(), ast_str_buffer(), ast_str_thread_get(), and pbx_builtin_serialize_variables().

Referenced by ring_entry(), rna(), send_agent_complete(), and try_calling().

3206 {
3207  struct ast_str *buf = ast_str_thread_get(&ast_str_thread_global_buf, len + 1);
3208  const char *tmp;
3209 
3210  if (pbx_builtin_serialize_variables(chan, &buf)) {
3211  int i, j;
3212 
3213  /* convert "\n" to "\nVariable: " */
3214  strcpy(vars, "Variable: ");
3215  tmp = ast_str_buffer(buf);
3216 
3217  for (i = 0, j = 10; (i < len - 1) && (j < len - 1); i++, j++) {
3218  vars[j] = tmp[i];
3219 
3220  if (tmp[i + 1] == '\0')
3221  break;
3222  if (tmp[i] == '\n') {
3223  vars[j++] = '\r';
3224  vars[j++] = '\n';
3225 
3226  ast_copy_string(&(vars[j]), "Variable: ", len - j);
3227  j += 9;
3228  }
3229  }
3230  if (j > len - 3)
3231  j = len - 3;
3232  vars[j++] = '\r';
3233  vars[j++] = '\n';
3234  vars[j] = '\0';
3235  } else {
3236  /* there are no channel variables; leave it blank */
3237  *vars = '\0';
3238  }
3239  return vars;
3240 }
3241 
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:669
int pbx_builtin_serialize_variables(struct ast_channel *chan, struct ast_str **buf)
Create a human-readable string, specifying all variables and their corresponding values.
Definition: pbx.c:10444
static int wait_a_bit ( struct queue_ent qe)
static

Definition at line 5625 of file app_queue.c.

References ast_waitfordigit(), queue_ent::chan, queue_ent::parent, call_queue::retry, and valid_exit().

Referenced by queue_exec().

5625 {
5626  /* Don't need to hold the lock while we setup the outgoing calls */
5627  int retrywait = qe->parent->retry * 1000;
5628 
5629  int res = ast_waitfordigit(qe->chan, retrywait);
5630  if (res > 0 && !valid_exit(qe, res))
5631  res = 0;
5632 
5633  return res;
5634 }
5635 
struct call_queue * parent
Definition: app_queue.c:1144
struct ast_channel * chan
Definition: app_queue.c:1168
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3552
static int valid_exit(struct queue_ent *qe, char digit)
Check for valid exit from queue via goto.
Definition: app_queue.c:2815
static struct callattempt* wait_for_answer ( struct queue_ent qe,
struct callattempt outgoing,
int *  to,
char *  digit,
int  prebusies,
int  caller_disconnect,
int  forwardsallowed,
int  ringing 
)
static

Wait for a member to answer the call.

Parameters
[in]qethe queue_ent corresponding to the caller in the queue
[in]outgoingthe list of callattempts. Relevant ones will have their chan and stillgoing parameters non-zero
[in]tothe amount of time (in milliseconds) to wait for a response
[out]digitif a user presses a digit to exit the queue, this is the digit the caller pressed
[in]prebusiesnumber of busy members calculated prior to calling wait_for_answer
[in]caller_disconnectif the 'H' option is used when calling Queue(), this is used to detect if the caller pressed * to disconnect the call
[in]forwardsallowedused to detect if we should allow call forwarding, based on the 'i' option to Queue()
Todo:
eventually all call forward logic should be intergerated into and replaced by ast_call_forward()

Definition at line 3789 of file app_queue.c.

References ast_channel::_state, accountcode, ast_channel::accountcode, call_queue::announce_to_first_user, call_queue::announcefrequency, callattempt::aoc_s_rate_list, ast_aoc_decode(), ast_aoc_destroy_decoded(), ast_aoc_destroy_encoded(), ast_aoc_encode(), ast_aoc_get_msg_type(), AST_AOC_S, ast_call(), ast_cdr_failed(), ast_cdr_noanswer(), AST_CEL_FORWARD, ast_cel_report_event(), ast_channel_connected_line_macro(), ast_channel_datastore_inherit(), ast_channel_inherit_variables(), ast_channel_lock, ast_channel_lock_both, AST_CHANNEL_NAME, ast_channel_redirecting_macro(), ast_channel_unlock, ast_channel_update_connected_line(), ast_channel_update_redirecting(), ast_check_hangup(), ast_connected_line_copy_from_caller(), ast_connected_line_parse_data(), AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, AST_CONTROL_ANSWER, AST_CONTROL_AOC, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_HANGUP, AST_CONTROL_OFFHOOK, AST_CONTROL_REDIRECTING, AST_CONTROL_RINGING, ast_copy_string(), ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_hangup(), ast_indicate(), ast_indicate_data(), ast_log(), AST_MAX_WATCHERS, ast_moh_stop(), ast_party_connected_line_copy(), ast_party_connected_line_free(), ast_party_connected_line_init(), ast_party_connected_line_set(), ast_party_connected_line_set_init(), ast_party_number_free(), ast_party_number_init(), ast_party_redirecting_copy(), ast_party_redirecting_free(), ast_party_redirecting_init(), ast_poll_channel_add(), ast_poll_channel_del(), ast_read(), ast_remaining_ms(), ast_request(), AST_STATE_UP, ast_strdup, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_tvnow(), ast_verb, ast_waitfor_n(), callattempt::block_connected_update, ast_channel::call_forward, callattempt::call_next, ast_channel::caller, ast_channel::cdr, callattempt::chan, queue_ent::chan, ast_channel::connected, callattempt::connected, ast_channel::context, ast_frame::data, ast_frame::datalen, callattempt::dial_callerid_absent, ast_channel::dialed, do_hang(), ast_channel::exten, f, ast_frame::frametype, ast_party_redirecting::from, ast_channel::hangupcause, ast_party_caller::id, ast_frame_subclass::integer, callattempt::interface, member::interface, LOG_NOTICE, ast_channel::macroexten, callattempt::member, member::membername, ast_channel::name, call_queue::name, ast_channel::nativeformats, ast_party_id::number, queue_ent::parent, callattempt::pending_connected_update, call_queue::periodicannouncefrequency, queue_ent::pos, ast_frame::ptr, callattempt::q_next, QUEUE_STRATEGY_RINGALL, ast_channel::redirecting, ring_one(), queue_ent::ring_when_ringing, rna(), S_OR, say_periodic_announcement(), say_position(), ast_party_connected_line::source, queue_ent::start, status, callattempt::stillgoing, ast_party_number::str, call_queue::strategy, ast_frame::subclass, ast_channel::tech, call_queue::timeoutrestart, ast_party_dialed::transit_network_select, ast_frame::uint32, ast_party_number::valid, and valid_exit().

Referenced by try_calling().

3789 {
3790  const char *queue = qe->parent->name;
3791  struct callattempt *o, *start = NULL, *prev = NULL;
3792  int status;
3793  int numbusies = prebusies;
3794  int numnochan = 0;
3795  int stillgoing = 0;
3796  int orig = *to;
3797  struct ast_frame *f;
3798  struct callattempt *peer = NULL;
3799  struct ast_channel *winner;
3800  struct ast_channel *in = qe->chan;
3801  char on[80] = "";
3802  char membername[80] = "";
3803  long starttime = 0;
3804  long endtime = 0;
3805 #ifdef HAVE_EPOLL
3806  struct callattempt *epollo;
3807 #endif
3808  struct ast_party_connected_line connected_caller;
3809  char *inchan_name;
3810  struct timeval start_time_tv = ast_tvnow();
3811 
3812  ast_party_connected_line_init(&connected_caller);
3813 
3814  ast_channel_lock(qe->chan);
3815  inchan_name = ast_strdupa(qe->chan->name);
3816  ast_channel_unlock(qe->chan);
3817 
3818  starttime = (long) time(NULL);
3819 #ifdef HAVE_EPOLL
3820  for (epollo = outgoing; epollo; epollo = epollo->q_next) {
3821  if (epollo->chan)
3822  ast_poll_channel_add(in, epollo->chan);
3823  }
3824 #endif
3825 
3826  while ((*to = ast_remaining_ms(start_time_tv, orig)) && !peer) {
3827  int numlines, retry, pos = 1;
3828  struct ast_channel *watchers[AST_MAX_WATCHERS];
3829  watchers[0] = in;
3830  start = NULL;
3831 
3832  for (retry = 0; retry < 2; retry++) {
3833  numlines = 0;
3834  for (o = outgoing; o; o = o->q_next) { /* Keep track of important channels */
3835  if (o->stillgoing) { /* Keep track of important channels */
3836  stillgoing = 1;
3837  if (o->chan) {
3838  if (pos < AST_MAX_WATCHERS) {
3839  watchers[pos++] = o->chan;
3840  }
3841  if (!start)
3842  start = o;
3843  else
3844  prev->call_next = o;
3845  prev = o;
3846  }
3847  }
3848  numlines++;
3849  }
3850  if (pos > 1 /* found */ || !stillgoing /* nobody listening */ ||
3851  (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) /* ring would not be delivered */)
3852  break;
3853  /* On "ringall" strategy we only move to the next penalty level
3854  when *all* ringing phones are done in the current penalty level */
3855  ring_one(qe, outgoing, &numbusies);
3856  /* and retry... */
3857  }
3858  if (pos == 1 /* not found */) {
3859  if (numlines == (numbusies + numnochan)) {
3860  ast_debug(1, "Everyone is busy at this time\n");
3861  //if (in->cdr && in->_state != AST_STATE_UP) {
3862  // ast_cdr_busy(in->cdr);
3863  //}
3864  } else {
3865  ast_debug(3, "No one is answering queue '%s' (%d numlines / %d busies / %d failed channels)\n", queue, numlines, numbusies, numnochan);
3866  if (in->cdr && in->_state != AST_STATE_UP) {
3867  ast_cdr_failed(in->cdr);
3868  }
3869  }
3870  *to = 0;
3871  return NULL;
3872  }
3873 
3874  /* Poll for events from both the incoming channel as well as any outgoing channels */
3875  winner = ast_waitfor_n(watchers, pos, to);
3876 
3877  /* Service all of the outgoing channels */
3878  for (o = start; o; o = o->call_next) {
3879  /* We go with a fixed buffer here instead of using ast_strdupa. Using
3880  * ast_strdupa in a loop like this one can cause a stack overflow
3881  */
3882  char ochan_name[AST_CHANNEL_NAME];
3883 
3884  if (o->chan) {
3885  ast_channel_lock(o->chan);
3886  ast_copy_string(ochan_name, o->chan->name, sizeof(ochan_name));
3888  }
3889  if (o->stillgoing && (o->chan) && (o->chan->_state == AST_STATE_UP)) {
3890  if (!peer) {
3891  ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
3892  if (!o->block_connected_update) {
3893  if (o->pending_connected_update) {
3894  if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
3896  }
3897  } else if (!o->dial_callerid_absent) {
3898  ast_channel_lock(o->chan);
3899  ast_connected_line_copy_from_caller(&connected_caller, &o->chan->caller);
3901  connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
3902  if (ast_channel_connected_line_macro(o->chan, in, &connected_caller, 1, 0)) {
3903  ast_channel_update_connected_line(in, &connected_caller, NULL);
3904  }
3905  ast_party_connected_line_free(&connected_caller);
3906  }
3907  }
3908  if (o->aoc_s_rate_list) {
3909  size_t encoded_size;
3910  struct ast_aoc_encoded *encoded;
3911  if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
3912  ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
3913  ast_aoc_destroy_encoded(encoded);
3914  }
3915  }
3916  peer = o;
3917  }
3918  } else if (o->chan && (o->chan == winner)) {
3919 
3920  ast_copy_string(on, o->member->interface, sizeof(on));
3921  ast_copy_string(membername, o->member->membername, sizeof(membername));
3922 
3923  /* Before processing channel, go ahead and check for forwarding */
3924  if (!ast_strlen_zero(o->chan->call_forward) && !forwardsallowed) {
3925  ast_verb(3, "Forwarding %s to '%s' prevented.\n", inchan_name, o->chan->call_forward);
3926  numnochan++;
3927  do_hang(o);
3928  winner = NULL;
3929  continue;
3930  } else if (!ast_strlen_zero(o->chan->call_forward)) {
3931  struct ast_channel *original = o->chan;
3932  char tmpchan[256];
3933  char *stuff;
3934  char *tech;
3935 
3936  ast_copy_string(tmpchan, o->chan->call_forward, sizeof(tmpchan));
3937  if ((stuff = strchr(tmpchan, '/'))) {
3938  *stuff++ = '\0';
3939  tech = tmpchan;
3940  } else {
3941  snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
3942  stuff = tmpchan;
3943  tech = "Local";
3944  }
3945  if (!strcasecmp(tech, "Local")) {
3946  /*
3947  * Drop the connected line update block for local channels since
3948  * this is going to run dialplan and the user can change his
3949  * mind about what connected line information he wants to send.
3950  */
3951  o->block_connected_update = 0;
3952  }
3953 
3954  ast_cel_report_event(in, AST_CEL_FORWARD, NULL, o->chan->call_forward, NULL);
3955 
3956  ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", inchan_name, tech, stuff, ochan_name);
3957  /* Setup parameters */
3958  o->chan = ast_request(tech, in->nativeformats, in, stuff, &status);
3959  if (!o->chan) {
3961  "Forwarding failed to create channel to dial '%s/%s'\n",
3962  tech, stuff);
3963  o->stillgoing = 0;
3964  numnochan++;
3965  } else {
3966  ast_channel_lock_both(o->chan, original);
3969  ast_channel_unlock(original);
3970 
3971  ast_channel_lock_both(o->chan, in);
3974 
3975  if (o->pending_connected_update) {
3976  /*
3977  * Re-seed the callattempt's connected line information with
3978  * previously acquired connected line info from the queued
3979  * channel. The previously acquired connected line info could
3980  * have been set through the CONNECTED_LINE dialplan function.
3981  */
3982  o->pending_connected_update = 0;
3984  }
3985 
3987 
3988  if (!o->chan->redirecting.from.number.valid
3990  /*
3991  * The call was not previously redirected so it is
3992  * now redirected from this number.
3993  */
3996  o->chan->redirecting.from.number.valid = 1;
3998  ast_strdup(S_OR(in->macroexten, in->exten));
3999  }
4000 
4002 
4006 
4007  ast_channel_unlock(in);
4009  && !o->block_connected_update) {
4010  struct ast_party_redirecting redirecting;
4011 
4012  /*
4013  * Redirecting updates to the caller make sense only on single
4014  * call at a time strategies.
4015  *
4016  * We must unlock o->chan before calling
4017  * ast_channel_redirecting_macro, because we put o->chan into
4018  * autoservice there. That is pretty much a guaranteed
4019  * deadlock. This is why the handling of o->chan's lock may
4020  * seem a bit unusual here.
4021  */
4022  ast_party_redirecting_init(&redirecting);
4023  ast_party_redirecting_copy(&redirecting, &o->chan->redirecting);
4025  if (ast_channel_redirecting_macro(o->chan, in, &redirecting, 1, 0)) {
4026  ast_channel_update_redirecting(in, &redirecting, NULL);
4027  }
4028  ast_party_redirecting_free(&redirecting);
4029  } else {
4031  }
4032 
4033  if (ast_call(o->chan, stuff, 0)) {
4034  ast_log(LOG_NOTICE, "Forwarding failed to dial '%s/%s'\n",
4035  tech, stuff);
4036  do_hang(o);
4037  numnochan++;
4038  }
4039  }
4040  /* Hangup the original channel now, in case we needed it */
4041  ast_hangup(winner);
4042  continue;
4043  }
4044  f = ast_read(winner);
4045  if (f) {
4046  if (f->frametype == AST_FRAME_CONTROL) {
4047  switch (f->subclass.integer) {
4048  case AST_CONTROL_ANSWER:
4049  /* This is our guy if someone answered. */
4050  if (!peer) {
4051  ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
4052  if (!o->block_connected_update) {
4053  if (o->pending_connected_update) {
4054  if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
4056  }
4057  } else if (!o->dial_callerid_absent) {
4058  ast_channel_lock(o->chan);
4059  ast_connected_line_copy_from_caller(&connected_caller, &o->chan->caller);
4061  connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
4062  if (ast_channel_connected_line_macro(o->chan, in, &connected_caller, 1, 0)) {
4063  ast_channel_update_connected_line(in, &connected_caller, NULL);
4064  }
4065  ast_party_connected_line_free(&connected_caller);
4066  }
4067  }
4068  if (o->aoc_s_rate_list) {
4069  size_t encoded_size;
4070  struct ast_aoc_encoded *encoded;
4071  if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
4072  ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
4073  ast_aoc_destroy_encoded(encoded);
4074  }
4075  }
4076  peer = o;
4077  }
4078  break;
4079  case AST_CONTROL_BUSY:
4080  ast_verb(3, "%s is busy\n", ochan_name);
4081  //if (in->cdr)
4082  // ast_cdr_busy(in->cdr);
4083  do_hang(o);
4084  endtime = (long) time(NULL);
4085  endtime -= starttime;
4086  rna(endtime * 1000, qe, on, membername, 0);
4087  if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
4088  if (qe->parent->timeoutrestart) {
4089  start_time_tv = ast_tvnow();
4090  }
4091  /* Have enough time for a queue member to answer? */
4092  if (ast_remaining_ms(start_time_tv, orig) > 500) {
4093  ring_one(qe, outgoing, &numbusies);
4094  starttime = (long) time(NULL);
4095  }
4096  }
4097  numbusies++;
4098  break;
4100  ast_verb(3, "%s is circuit-busy\n", ochan_name);
4101  if (in->cdr)
4102  ast_cdr_failed(in->cdr);
4103  endtime = (long) time(NULL);
4104  endtime -= starttime;
4105  rna(endtime * 1000, qe, on, membername, 0);
4106  do_hang(o);
4107  if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
4108  if (qe->parent->timeoutrestart) {
4109  start_time_tv = ast_tvnow();
4110  }
4111  if (ast_remaining_ms(start_time_tv, orig) > 500) {
4112  ring_one(qe, outgoing, &numbusies);
4113  starttime = (long) time(NULL);
4114  }
4115  }
4116  numbusies++;
4117  break;
4118  case AST_CONTROL_RINGING:
4119  ast_verb(3, "%s is ringing\n", ochan_name);
4120 
4121  /* Start ring indication when the channel is ringing, if specified */
4122  if (qe->ring_when_ringing) {
4123  ast_moh_stop(qe->chan);
4125  }
4126  break;
4127  case AST_CONTROL_OFFHOOK:
4128  /* Ignore going off hook */
4129  break;
4131  if (o->block_connected_update) {
4132  ast_verb(3, "Connected line update to %s prevented.\n", inchan_name);
4133  break;
4134  }
4135  if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
4137 
4138  ast_verb(3, "%s connected line has changed. Saving it until answer for %s\n", ochan_name, inchan_name);
4143  o->pending_connected_update = 1;
4144  break;
4145  }
4146 
4147  /*
4148  * Prevent using the CallerID from the outgoing channel since we
4149  * got a connected line update from it.
4150  */
4151  o->dial_callerid_absent = 1;
4152 
4153  if (ast_channel_connected_line_macro(o->chan, in, f, 1, 1)) {
4155  }
4156  break;
4157  case AST_CONTROL_AOC:
4158  {
4159  struct ast_aoc_decoded *decoded = ast_aoc_decode(f->data.ptr, f->datalen, o->chan);
4160  if (decoded && (ast_aoc_get_msg_type(decoded) == AST_AOC_S)) {
4162  o->aoc_s_rate_list = decoded;
4163  } else {
4164  ast_aoc_destroy_decoded(decoded);
4165  }
4166  }
4167  break;
4169  if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
4170  /*
4171  * Redirecting updates to the caller make sense only on single
4172  * call at a time strategies.
4173  */
4174  break;
4175  }
4176  if (o->block_connected_update) {
4177  ast_verb(3, "Redirecting update to %s prevented\n",
4178  inchan_name);
4179  break;
4180  }
4181  ast_verb(3, "%s redirecting info has changed, passing it to %s\n",
4182  ochan_name, inchan_name);
4183  if (ast_channel_redirecting_macro(o->chan, in, f, 1, 1)) {
4185  }
4186  break;
4187  default:
4188  ast_debug(1, "Dunno what to do with control type %d\n", f->subclass.integer);
4189  break;
4190  }
4191  }
4192  ast_frfree(f);
4193  } else { /* ast_read() returned NULL */
4194  endtime = (long) time(NULL) - starttime;
4195  rna(endtime * 1000, qe, on, membername, 1);
4196  do_hang(o);
4197  if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
4198  if (qe->parent->timeoutrestart) {
4199  start_time_tv = ast_tvnow();
4200  }
4201  if (ast_remaining_ms(start_time_tv, orig) > 500) {
4202  ring_one(qe, outgoing, &numbusies);
4203  starttime = (long) time(NULL);
4204  }
4205  }
4206  }
4207  }
4208  }
4209 
4210  /* If we received an event from the caller, deal with it. */
4211  if (winner == in) {
4212  f = ast_read(in);
4213  if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_HANGUP))) {
4214  /* Got hung up */
4215  *to = -1;
4216  if (f) {
4217  if (f->data.uint32) {
4218  in->hangupcause = f->data.uint32;
4219  }
4220  ast_frfree(f);
4221  }
4222  return NULL;
4223  }
4224 
4225  if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass.integer == '*')) {
4226  ast_verb(3, "User hit %c to disconnect call.\n", f->subclass.integer);
4227  *to = 0;
4228  ast_frfree(f);
4229  if (in->cdr && in->_state != AST_STATE_UP) {
4230  ast_cdr_noanswer(in->cdr);
4231  }
4232  return NULL;
4233  }
4234  if ((f->frametype == AST_FRAME_DTMF) && valid_exit(qe, f->subclass.integer)) {
4235  ast_verb(3, "User pressed digit: %c\n", f->subclass.integer);
4236  *to = 0;
4237  *digit = f->subclass.integer;
4238  ast_frfree(f);
4239  if (in->cdr && in->_state != AST_STATE_UP) {
4240  ast_cdr_noanswer(in->cdr);
4241  }
4242  return NULL;
4243  }
4244 
4245  /* Send the frame from the in channel to all outgoing channels. */
4246  for (o = start; o; o = o->call_next) {
4247  if (!o->stillgoing || !o->chan) {
4248  /* This outgoing channel has died so don't send the frame to it. */
4249  continue;
4250  }
4251  switch (f->frametype) {
4252  case AST_FRAME_CONTROL:
4253  switch (f->subclass.integer) {
4255  if (ast_channel_connected_line_macro(in, o->chan, f, 0, 1)) {
4257  }
4258  break;
4260  if (ast_channel_redirecting_macro(in, o->chan, f, 0, 1)) {
4262  }
4263  break;
4264  default:
4265  /* We are not going to do anything with this frame. */
4266  goto skip_frame;
4267  }
4268  break;
4269  default:
4270  /* We are not going to do anything with this frame. */
4271  goto skip_frame;
4272  }
4273  }
4274 skip_frame:;
4275 
4276  ast_frfree(f);
4277  }
4278  }
4279 
4280  /* Make a position announcement, if enabled */
4282  say_position(qe, ringing);
4283  }
4284 
4285  /* Make a periodic announcement, if enabled */
4287  say_periodic_announcement(qe, ringing);
4288  }
4289 
4290  if (!*to) {
4291  for (o = start; o; o = o->call_next) {
4292  rna(orig, qe, o->interface, o->member->membername, 1);
4293  }
4294  }
4295 
4296  if (in->cdr
4297  && in->_state != AST_STATE_UP
4298  && (!*to || ast_check_hangup(in))) {
4299  ast_cdr_noanswer(in->cdr);
4300  }
4301 
4302 #ifdef HAVE_EPOLL
4303  for (epollo = outgoing; epollo; epollo = epollo->q_next) {
4304  if (epollo->chan)
4305  ast_poll_channel_del(in, epollo->chan);
4306  }
4307 #endif
4308 
4309  return peer;
4310 }
4311 
struct ast_channel * ast_waitfor_n(struct ast_channel **chan, int n, int *ms)
Waits for input on a group of channels Wait for input on an array of channels for a given # of millis...
Definition: channel.c:3534
union ast_frame_subclass subclass
Definition: frame.h:146
struct callattempt * q_next
Definition: app_queue.c:1121
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
Definition: channel.c:2308
static char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_iax2.c:383
static int say_position(struct queue_ent *qe, int ringing)
Definition: app_queue.c:2849
struct call_queue * parent
Definition: app_queue.c:1144
#define ast_channel_lock(chan)
Definition: channel.h:2466
Main Channel structure associated with a channel.
Definition: channel.h:742
void ast_cdr_failed(struct ast_cdr *cdr)
Fail a call.
Definition: cdr.c:764
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
struct ast_party_connected_line connected
Channel Connected Line ID information.
Definition: channel.h:811
void ast_poll_channel_add(struct ast_channel *chan0, struct ast_channel *chan1)
Definition: channel.c:2665
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
struct ast_channel * chan
Definition: app_queue.c:1168
#define ast_strdup(a)
Definition: astmm.h:109
void ast_party_connected_line_set_init(struct ast_party_connected_line *init, const struct ast_party_connected_line *guide)
Initialize the given connected line structure using the given guide for a set update operation...
Definition: channel.c:2329
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:449
void * ptr
Definition: frame.h:160
void ast_channel_update_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update)
Indicate that the redirecting id has changed.
Definition: channel.c:9592
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
int ast_cel_report_event(struct ast_channel *chan, enum ast_cel_event_type event_type, const char *userdefevname, const char *extra, struct ast_channel *peer2)
Report a channel event.
Definition: cel.c:645
#define AST_MAX_WATCHERS
Definition: app_queue.c:3775
void ast_channel_update_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Indicate that the connected line information has changed.
Definition: channel.c:9085
#define AST_FRAME_DTMF
Definition: frame.h:128
unsigned int timeoutrestart
Definition: app_queue.c:1278
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
struct ast_party_redirecting redirecting
Redirecting/Diversion information.
Definition: channel.h:814
void * ast_aoc_destroy_decoded(struct ast_aoc_decoded *decoded)
free an ast_aoc_decoded object
Definition: aoc.c:176
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4447
char interface[256]
Definition: app_queue.c:1124
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
char interface[80]
Definition: app_queue.c:1175
struct ast_cdr * cdr
Definition: channel.h:766
format_t nativeformats
Definition: channel.h:852
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2353
int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int caller, int frame)
Run a connected line interception macro and update a channel&#39;s connected line information.
Definition: channel.c:9618
struct ast_aoc_decoded * aoc_s_rate_list
Definition: app_queue.c:1139
static int say_periodic_announcement(struct queue_ent *qe, int ringing)
Playback announcement to queued members if period has elapsed.
Definition: app_queue.c:3650
unsigned int announce_to_first_user
Definition: app_queue.c:1272
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:8051
#define ast_verb(level,...)
Definition: logger.h:243
char membername[80]
Definition: app_queue.c:1179
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition: channel.c:2573
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
struct ast_party_connected_line connected
Definition: app_queue.c:1130
struct ast_aoc_decoded * ast_aoc_decode(struct ast_aoc_encoded *encoded, size_t size, struct ast_channel *chan)
decodes an encoded aoc payload.
Definition: aoc.c:318
int periodicannouncefrequency
Definition: app_queue.c:1291
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
struct ast_aoc_encoded * ast_aoc_encode(struct ast_aoc_decoded *decoded, size_t *out_size, struct ast_channel *chan)
encodes a decoded aoc structure so it can be passed on the wire
Definition: aoc.c:519
unsigned int block_connected_update
Definition: app_queue.c:1134
int ring_when_ringing
Definition: app_queue.c:1153
int datalen
Definition: frame.h:148
void ast_party_number_init(struct ast_party_number *init)
Initialize the given number structure.
Definition: channel.c:1981
struct member * member
Definition: app_queue.c:1128
int strategy
Definition: app_queue.c:1281
void ast_party_number_free(struct ast_party_number *doomed)
Destroy the party number contents.
Definition: channel.c:2028
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
struct ast_party_dialed dialed
Dialed/Called information.
Definition: channel.h:797
We define a custom &quot;local user&quot; structure because we use it not only for keeping track of what is i...
Definition: app_queue.c:1120
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, struct ast_party_connected_line *connected)
Parse connected line indication frame data.
Definition: channel.c:8886
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:1615
const ast_string_field name
Definition: app_queue.c:1266
const ast_string_field call_forward
Definition: channel.h:787
void ast_party_connected_line_set(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src, const struct ast_set_party_connected_line *update)
Set the connected line information based on another connected line source.
Definition: channel.c:2337
enum ast_channel_state _state
Definition: channel.h:839
Connected Line/Party information.
Definition: channel.h:401
const ast_string_field name
Definition: channel.h:787
unsigned int pending_connected_update
Definition: app_queue.c:1132
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
Redirecting Line information. RDNIS (Redirecting Directory Number Information Service) Where a call d...
Definition: channel.h:447
#define LOG_NOTICE
Definition: logger.h:133
#define ast_channel_unlock(chan)
Definition: channel.h:2467
void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child)
Inherits channel variable from parent to child channel.
Definition: channel.c:6241
#define AST_CHANNEL_NAME
Definition: channel.h:137
static struct ast_format f[]
Definition: format_g726.c:181
void * ast_aoc_destroy_encoded(struct ast_aoc_encoded *encoded)
free an ast_aoc_encoded object
Definition: aoc.c:182
int ast_call(struct ast_channel *chan, char *addr, int timeout)
Make a call.
Definition: channel.c:5761
char macroexten[AST_MAX_EXTENSION]
Definition: channel.h:871
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2473
void ast_poll_channel_del(struct ast_channel *chan0, struct ast_channel *chan1)
Definition: channel.c:2688
int transit_network_select
Transit Network Select.
Definition: channel.h:347
void ast_party_redirecting_free(struct ast_party_redirecting *doomed)
Destroy the redirecting information contents.
Definition: channel.c:2396
void ast_party_connected_line_copy(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src)
Copy the source connected line information to the destination connected line.
Definition: channel.c:2316
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
Copy the caller information to the connected line information.
Definition: channel.c:8443
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
void ast_cdr_noanswer(struct ast_cdr *cdr)
A call wasn&#39;t answered.
Definition: cdr.c:776
void ast_party_redirecting_init(struct ast_party_redirecting *init)
Initialize the given redirecting structure.
Definition: channel.c:2359
const ast_string_field accountcode
Definition: channel.h:787
Data structure associated with a single frame of data.
Definition: frame.h:142
int hangupcause
Definition: channel.h:849
Definition: aoc.h:64
static int connected
Definition: cdr_pgsql.c:57
enum ast_aoc_type ast_aoc_get_msg_type(struct ast_aoc_decoded *decoded)
get the message type, AOC-D, AOC-E, or AOC Request
Definition: aoc.c:761
uint32_t uint32
Definition: frame.h:160
enum ast_frame_type frametype
Definition: frame.h:144
static void rna(int rnatime, struct queue_ent *qe, char *interface, char *membername, int pause)
RNA == Ring No Answer. Common code that is executed when we try a queue member and they don&#39;t answer...
Definition: app_queue.c:3723
#define ast_frfree(fr)
Definition: frame.h:583
static void do_hang(struct callattempt *o)
common hangup actions
Definition: app_queue.c:3198
struct callattempt * call_next
Definition: app_queue.c:1122
unsigned int dial_callerid_absent
Definition: app_queue.c:1136
struct ast_channel * chan
Definition: app_queue.c:1123
struct ast_channel * ast_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *status)
Requests a channel.
Definition: channel.c:5695
union ast_frame::@172 data
struct ast_channel_tech * tech
Definition: channel.h:743
static int valid_exit(struct queue_ent *qe, char digit)
Check for valid exit from queue via goto.
Definition: app_queue.c:2815
int announcefrequency
Definition: app_queue.c:1289
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
this call was forwarded somewhere else
Definition: cel.h:98
unsigned int stillgoing
Definition: app_queue.c:1138
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src)
Copy the source redirecting information to the destination redirecting.
Definition: channel.c:2367
static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
Place a call to a queue member.
Definition: app_queue.c:3565
jack_status_t status
Definition: app_jack.c:143
int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *redirecting_info, int is_caller, int is_frame)
Run a redirecting interception macro and update a channel&#39;s redirecting information.
Definition: channel.c:9663
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int wait_our_turn ( struct queue_ent qe,
int  ringing,
enum queue_result reason 
)
static

The waiting areas for callers who are not actively calling members.

This function is one large loop. This function will return if a caller either exits the queue or it becomes that caller's turn to attempt calling queue members. Inside the loop, we service the caller with periodic announcements, holdtime announcements, etc. as configured in queues.conf

Return values
0if the caller's turn has arrived
-1if the caller should exit the queue.

Definition at line 4430 of file app_queue.c.

References call_queue::announcefrequency, ast_queue_log(), ast_waitfordigit(), queue_ent::chan, queue_ent::expire, get_member_status(), is_our_turn(), leave_queue(), call_queue::leavewhenempty, queue_ent::max_penalty, queue_ent::min_penalty, call_queue::name, queue_ent::opos, queue_ent::parent, call_queue::periodicannouncefrequency, queue_ent::pos, queue_ent::pr, QUEUE_LEAVEEMPTY, QUEUE_TIMEOUT, RECHECK, say_periodic_announcement(), say_position(), queue_ent::start, status, penalty_rule::time, ast_channel::uniqueid, update_qe_rule(), and valid_exit().

Referenced by queue_exec().

4430 {
4431  int res = 0;
4432 
4433  /* This is the holding pen for callers 2 through maxlen */
4434  for (;;) {
4435 
4436  if (is_our_turn(qe))
4437  break;
4438 
4439  /* If we have timed out, break out */
4440  if (qe->expire && (time(NULL) >= qe->expire)) {
4441  *reason = QUEUE_TIMEOUT;
4442  break;
4443  }
4444 
4445  if (qe->parent->leavewhenempty) {
4446  int status = 0;
4447 
4448  if ((status = get_member_status(qe->parent, qe->max_penalty, qe->min_penalty, qe->parent->leavewhenempty, 0))) {
4449  *reason = QUEUE_LEAVEEMPTY;
4450  ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
4451  leave_queue(qe);
4452  break;
4453  }
4454  }
4455 
4456  /* Make a position announcement, if enabled */
4457  if (qe->parent->announcefrequency &&
4458  (res = say_position(qe,ringing)))
4459  break;
4460 
4461  /* If we have timed out, break out */
4462  if (qe->expire && (time(NULL) >= qe->expire)) {
4463  *reason = QUEUE_TIMEOUT;
4464  break;
4465  }
4466 
4467  /* Make a periodic announcement, if enabled */
4468  if (qe->parent->periodicannouncefrequency &&
4469  (res = say_periodic_announcement(qe,ringing)))
4470  break;
4471 
4472  /* see if we need to move to the next penalty level for this queue */
4473  while (qe->pr && ((time(NULL) - qe->start) >= qe->pr->time)) {
4474  update_qe_rule(qe);
4475  }
4476 
4477  /* If we have timed out, break out */
4478  if (qe->expire && (time(NULL) >= qe->expire)) {
4479  *reason = QUEUE_TIMEOUT;
4480  break;
4481  }
4482 
4483  /* Wait a second before checking again */
4484  if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000))) {
4485  if (res > 0 && !valid_exit(qe, res))
4486  res = 0;
4487  else
4488  break;
4489  }
4490 
4491  /* If we have timed out, break out */
4492  if (qe->expire && (time(NULL) >= qe->expire)) {
4493  *reason = QUEUE_TIMEOUT;
4494  break;
4495  }
4496  }
4497 
4498  return res;
4499 }
4500 
static int say_position(struct queue_ent *qe, int ringing)
Definition: app_queue.c:2849
struct call_queue * parent
Definition: app_queue.c:1144
struct ast_channel * chan
Definition: app_queue.c:1168
static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, enum empty_conditions conditions, int devstate)
Check if members are available.
Definition: app_queue.c:1545
int min_penalty
Definition: app_queue.c:1162
const ast_string_field uniqueid
Definition: channel.h:787
int max_penalty
Definition: app_queue.c:1161
time_t start
Definition: app_queue.c:1165
time_t expire
Definition: app_queue.c:1166
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
static int say_periodic_announcement(struct queue_ent *qe, int ringing)
Playback announcement to queued members if period has elapsed.
Definition: app_queue.c:3650
int periodicannouncefrequency
Definition: app_queue.c:1291
static void leave_queue(struct queue_ent *qe)
Caller leaving queue.
Definition: app_queue.c:3012
const ast_string_field name
Definition: app_queue.c:1266
struct penalty_rule * pr
Definition: app_queue.c:1170
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3552
enum empty_conditions leavewhenempty
Definition: app_queue.c:1287
#define RECHECK
Definition: app_queue.c:1026
static void update_qe_rule(struct queue_ent *qe)
update rules for queues
Definition: app_queue.c:4367
static int is_our_turn(struct queue_ent *qe)
Check if we should start attempting to call queue members.
Definition: app_queue.c:4324
static int valid_exit(struct queue_ent *qe, char digit)
Check for valid exit from queue via goto.
Definition: app_queue.c:2815
int announcefrequency
Definition: app_queue.c:1289
jack_status_t status
Definition: app_jack.c:143
static int word_in_list ( const char *  list,
const char *  word 
)
static

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

Parameters
listSpace delimited list of words
wordThe word used to search the list
Note
This function will not return 1 if the word is at the very end of the list (followed immediately by a \0, not a space) since it is used for checking tab-completion and a word at the end is still being tab-completed.
Returns
Returns 1 if the word is found
Returns 0 if the word is not found

Definition at line 7748 of file app_queue.c.

Referenced by complete_queue().

7752  {
7753  list++;
7754  }
7755 
7756  while ((find = strstr(list, word))) {
7757  /* beginning of find starts inside another word? */
7758  if (find != list && *(find - 1) != ' ') {
7759  list = find;
7760  /* strip word from front */
7761  while (!isspace(*list) && *list != '\0') {
7762  list++;
7763  }
7764  /* strip whitespace from front */
7765  while (isspace(*list)) {
7766  list++;
7767  }
7768  continue;
7769  }
7770 
7771  /* end of find ends inside another word or at very end of list? */
7772  list_len = strlen(list);
7773  end_find = find + word_len;
7774  end_list = list + list_len;
7775  if (end_find == end_list || *end_find != ' ') {
7776  list = find;
7777  /* strip word from front */
7778  while (!isspace(*list) && *list != '\0') {
7779  list++;
7780  }
7781  /* strip whitespace from front */
7782  while (isspace(*list)) {
7783  list++;
7784  }
7785  continue;
7786  }
7787 
7788  /* terminating conditions satisfied, word at beginning or separated by ' ' */
7789  return 1;
7790  }
7791 
7792  return 0;
7793 }
7794 
Definition: ael.tab.c:203

Variable Documentation

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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_CONSUMER, .nonoptreq = "res_monitor", }
static

Definition at line 9216 of file app_queue.c.

char* app = "Queue"
static

Definition at line 1039 of file app_queue.c.

char* app_aqm = "AddQueueMember"
static

Definition at line 1041 of file app_queue.c.

char* app_pqm = "PauseQueueMember"
static

Definition at line 1045 of file app_queue.c.

char* app_ql = "QueueLog"
static

Definition at line 1049 of file app_queue.c.

char* app_rqm = "RemoveQueueMember"
static

Definition at line 1043 of file app_queue.c.

char* app_upqm = "UnpauseQueueMember"
static

Definition at line 1047 of file app_queue.c.

Definition at line 9216 of file app_queue.c.

int autofill_default = 1
static

queues.conf [general] option

Definition at line 1064 of file app_queue.c.

Referenced by init_queue().

struct autopause autopausesmodes[]
static
struct ast_cli_entry cli_queue[]
static

Definition at line 8793 of file app_queue.c.

Referenced by load_module(), and unload_module().

struct ast_event_sub* device_state_sub
static

Subscription to device state change events.

Definition at line 1073 of file app_queue.c.

struct ast_taskprocessor* devicestate_tps
static

Definition at line 1022 of file app_queue.c.

int montype_default = 0
static

queues.conf [general] option

Definition at line 1067 of file app_queue.c.

Referenced by init_queue().

const char* const pm_family = "Queue/PersistentMembers"
static

Persistent Members astdb family.

Definition at line 1052 of file app_queue.c.

const char qpm_cmd_usage[]
static
Initial value:
=
"Usage: queue pause member <channel> in <queue> reason <reason>\n"

Definition at line 8784 of file app_queue.c.

const char qsmp_cmd_usage[]
static
Initial value:
=
"Usage: queue set member penalty <channel> from <queue> <penalty>\n"

Definition at line 8790 of file app_queue.c.

struct ast_data_entry queue_data_providers[]
static
Initial value:
= {
AST_DATA_ENTRY("asterisk/application/queue/list", &queues_data_provider),
}
#define AST_DATA_ENTRY(__path, __handler)
Definition: data.h:260
static struct ast_data_handler queues_data_provider
Definition: app_queue.c:9066

Definition at line 9071 of file app_queue.c.

Referenced by load_module().

int queue_debug = 0
static

queues.conf [general] extra debug option

Definition at line 1055 of file app_queue.c.

int queue_persistent_members = 0
static

queues.conf [general] option

Definition at line 1058 of file app_queue.c.

struct { ... } queue_results[]

Referenced by set_queue_result().

struct ast_datastore_info queue_transfer_info
static
Initial value:
= {
.type = "queue_transfer",
.chan_fixup = queue_transfer_fixup,
}
static void queue_transfer_destroy(void *data)
Definition: app_queue.c:4680
static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
Log an attended transfer when a queue caller channel is masqueraded.
Definition: app_queue.c:4703

a datastore used to help correctly log attended transfers of queue callers

Definition at line 4688 of file app_queue.c.

Referenced by attended_transfer_occurred(), queue_transfer_fixup(), setup_transfer_datastore(), and try_calling().

struct ast_custom_function queueexists_function
static
Initial value:
= {
.name = "QUEUE_EXISTS",
}
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.
Definition: app_queue.c:6678

Definition at line 7092 of file app_queue.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function queuemembercount_dep
static
Initial value:
= {
.name = "QUEUE_MEMBER_COUNT",
}
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)
Definition: app_queue.c:6781

Definition at line 7107 of file app_queue.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function queuemembercount_function
static
Initial value:
= {
.name = "QUEUE_MEMBER",
}
static int queue_function_qac(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.
Definition: app_queue.c:6702

Definition at line 7102 of file app_queue.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function queuememberlist_function
static
Initial value:
= {
.name = "QUEUE_MEMBER_LIST",
}
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.
Definition: app_queue.c:6857

Definition at line 7117 of file app_queue.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function queuememberpaused_function
static
Initial value:
= {
.name = "QUEUE_MEMBER_PAUSED",
}
static int queue_function_queuememberpaused(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: app_queue.c:7033

Definition at line 7133 of file app_queue.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function queuememberpenalty_function
static
Initial value:
= {
.name = "QUEUE_MEMBER_PENALTY",
}
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.
Definition: app_queue.c:6907
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.
Definition: app_queue.c:6938

Definition at line 7122 of file app_queue.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function queuememberstatus_function
static
Initial value:
= {
.name = "QUEUE_MEMBER_STATUS",
}
static int queue_function_queuememberstatus(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: app_queue.c:6974

Definition at line 7128 of file app_queue.c.

Referenced by load_module(), and unload_module().

struct ast_data_handler queues_data_provider
static
Initial value:
= {
}
#define AST_DATA_HANDLER_VERSION
The Data API structures version.
Definition: data.h:204
static int queues_data_provider_get(const struct ast_data_search *search, struct ast_data *data_root)
Definition: app_queue.c:9022

Definition at line 9066 of file app_queue.c.

struct ast_custom_function queuevar_function
static
Initial value:
= {
.name = "QUEUE_VARIABLES",
}
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.
Definition: app_queue.c:6631

Definition at line 7097 of file app_queue.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function queuewaitingcount_function
static
Initial value:
= {
.name = "QUEUE_WAITING_COUNT",
}
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.
Definition: app_queue.c:6821

Definition at line 7112 of file app_queue.c.

Referenced by load_module(), and unload_module().

const char qum_cmd_usage[]
static
Initial value:
=
"Usage: queue unpause member <channel> in <queue> reason <reason>\n"

Definition at line 8787 of file app_queue.c.

struct rule_lists rule_lists = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } , }
static
int shared_lastcall = 1
static

queues.conf [general] option

Definition at line 1070 of file app_queue.c.

struct strategy strategies[]
static

Referenced by int2strat(), and strat2int().

int update_cdr = 0
static

queues.conf [general] option

Definition at line 1076 of file app_queue.c.

Referenced by login_exec().

int use_weight = 0
static

queues.conf per-queue weight option

Definition at line 1061 of file app_queue.c.