#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/options.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"
Go to the source code of this file.
Data Structures | |
struct | call_queue |
struct | localuser |
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 | member_interface |
struct | queue_ent |
struct | statechange |
struct | strategy |
Defines | |
#define | ANNOUNCEHOLDTIME_ALWAYS 1 |
#define | ANNOUNCEHOLDTIME_ONCE 2 |
#define | AST_MAX_WATCHERS 256 |
#define | BUILD_WATCHERS |
#define | DEFAULT_RETRY 5 |
#define | DEFAULT_TIMEOUT 15 |
#define | PM_MAX_LEN 2048 |
#define | QUEUE_EMPTY_NORMAL 1 |
#define | QUEUE_EMPTY_STRICT 2 |
#define | QUEUE_STRATEGY_FEWESTCALLS 3 |
#define | QUEUE_STRATEGY_LEASTRECENT 2 |
#define | QUEUE_STRATEGY_RANDOM 4 |
#define | QUEUE_STRATEGY_RINGALL 0 |
#define | QUEUE_STRATEGY_ROUNDROBIN 1 |
#define | QUEUE_STRATEGY_RRMEMORY 5 |
#define | RECHECK 1 |
#define | RES_EXISTS (-1) |
#define | RES_NOSUCHQUEUE (-3) |
#define | RES_OKAY 0 |
#define | RES_OUTOFMEMORY (-2) |
Enumerations | |
enum | queue_member_status { QUEUE_NO_MEMBERS, QUEUE_NO_REACHABLE_MEMBERS, QUEUE_NORMAL } |
enum | queue_result { QUEUE_UNKNOWN = 0, QUEUE_TIMEOUT = 1, QUEUE_JOINEMPTY = 2, QUEUE_LEAVEEMPTY = 3, QUEUE_JOINUNAVAIL = 4, QUEUE_LEAVEUNAVAIL = 5, QUEUE_FULL = 6 } |
Functions | |
static int | __queues_show (int manager, int fd, int argc, char **argv, int queue_show) |
static int | add_to_interfaces (char *interface) |
static int | add_to_queue (char *queuename, char *interface, int penalty, int paused, int dump) |
static struct call_queue * | alloc_queue (const char *queuename) |
static int | aqm_exec (struct ast_channel *chan, void *data) |
static | AST_LIST_HEAD_STATIC (interfaces, member_interface) |
AST_MUTEX_DEFINE_STATIC (qlock) | |
static int | background_file (struct queue_ent *qe, struct ast_channel *chan, char *filename) |
static int | calc_metric (struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct localuser *tmp) |
static void * | changethread (void *data) |
static void | clear_and_free_interfaces (void) |
static void | clear_queue (struct call_queue *q) |
static int | compare_weight (struct call_queue *rq, struct member *member) |
static char * | complete_add_queue_member (char *line, char *word, int pos, int state) |
static char * | complete_queue (char *line, char *word, int pos, int state) |
static char * | complete_remove_queue_member (char *line, char *word, int pos, int state) |
static struct member * | create_queue_member (char *interface, int penalty, int paused) |
char * | description (void) |
Provides a description of the module. | |
static void | destroy_queue (struct call_queue *q) |
static void | dump_queue_members (struct call_queue *pm_queue) |
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. | |
static void | free_members (struct call_queue *q, int all) |
static enum queue_member_status | get_member_status (struct call_queue *q) |
static int | handle_add_queue_member (int fd, int argc, char *argv[]) |
static int | handle_remove_queue_member (int fd, int argc, char *argv[]) |
static void | hangupcalls (struct localuser *outgoing, struct ast_channel *exception) |
static void | init_queue (struct call_queue *q) |
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'. | |
static char * | int2strat (int strategy) |
static struct member * | interface_exists (struct call_queue *q, char *interface) |
static int | interface_exists_global (char *interface) |
static int | is_our_turn (struct queue_ent *qe) |
static int | join_queue (char *queuename, struct queue_ent *qe, enum queue_result *reason) |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
static void | leave_queue (struct queue_ent *qe) |
int | load_module (void) |
Initialize the module. | |
static struct call_queue * | load_realtime_queue (char *queuename) |
static int | manager_add_queue_member (struct mansession *s, struct message *m) |
static int | manager_pause_queue_member (struct mansession *s, struct message *m) |
static int | manager_queues_show (struct mansession *s, struct message *m) |
static int | manager_queues_status (struct mansession *s, struct message *m) |
static int | manager_remove_queue_member (struct mansession *s, struct message *m) |
static int | play_file (struct ast_channel *chan, char *filename) |
static int | pqm_exec (struct ast_channel *chan, void *data) |
static int | queue_exec (struct ast_channel *chan, void *data) |
static char * | queue_function_qac (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) |
static void | queue_set_param (struct call_queue *q, const char *param, const char *val, int linenum, int failunknown) |
Configure a queue parameter. | |
static int | queue_show (int fd, int argc, char **argv) |
static int | queues_show (int fd, int argc, char **argv) |
static void | recalc_holdtime (struct queue_ent *qe) |
static void | record_abandoned (struct queue_ent *qe) |
int | reload (void) |
Reload stuff. | |
static void | reload_queue_members (void) |
static void | reload_queues (void) |
static int | remove_from_interfaces (char *interface) |
static int | remove_from_queue (char *queuename, char *interface) |
static void | remove_queue (struct call_queue *q) |
static int | ring_entry (struct queue_ent *qe, struct localuser *tmp, int *busies) |
static int | ring_one (struct queue_ent *qe, struct localuser *outgoing, int *busies) |
static int | rqm_exec (struct ast_channel *chan, void *data) |
static void | rt_handle_member_record (struct call_queue *q, char *interface, const char *penalty_str) |
static int | say_periodic_announcement (struct queue_ent *qe) |
static int | say_position (struct queue_ent *qe) |
static int | set_member_paused (char *queuename, char *interface, int paused) |
static void | set_queue_result (struct ast_channel *chan, enum queue_result res) |
static int | statechange_queue (const char *dev, int state, void *ign) |
static int | store_next (struct queue_ent *qe, struct localuser *outgoing) |
static int | strat2int (const char *strategy) |
static int | try_calling (struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *go_on) |
int | unload_module (void) |
Cleanup all module structures, sockets, etc. | |
static int | update_dial_status (struct call_queue *q, struct member *member, int status) |
static int | update_queue (struct call_queue *q, struct member *member) |
static int | update_status (struct call_queue *q, struct member *member, int status) |
static int | upqm_exec (struct ast_channel *chan, void *data) |
int | usecount (void) |
Provides a usecount. | |
static int | valid_exit (struct queue_ent *qe, char digit) |
static int | wait_a_bit (struct queue_ent *qe) |
static struct localuser * | wait_for_answer (struct queue_ent *qe, struct localuser *outgoing, int *to, char *digit, int prebusies, int caller_disconnect) |
static int | wait_our_turn (struct queue_ent *qe, int ringing, enum queue_result *reason) |
Variables | |
static char * | app = "Queue" |
static char * | app_aqm = "AddQueueMember" |
static char * | app_aqm_descrip |
static char * | app_aqm_synopsis = "Dynamically adds queue members" |
static char * | app_pqm = "PauseQueueMember" |
static char * | app_pqm_descrip |
static char * | app_pqm_synopsis = "Pauses a queue member" |
static char * | app_rqm = "RemoveQueueMember" |
static char * | app_rqm_descrip |
static char * | app_rqm_synopsis = "Dynamically removes queue members" |
static char * | app_upqm = "UnpauseQueueMember" |
static char * | app_upqm_descrip |
static char * | app_upqm_synopsis = "Unpauses a queue member" |
static char | aqm_cmd_usage [] |
static struct ast_cli_entry | cli_add_queue_member |
static struct ast_cli_entry | cli_remove_queue_member |
static struct ast_cli_entry | cli_show_queue |
static struct ast_cli_entry | cli_show_queues |
static char * | descrip |
LOCAL_USER_DECL | |
static const char * | pm_family = "/Queue/PersistentMembers" |
Persistent Members astdb family. | |
static int | queue_persistent_members = 0 |
queues.conf [general] option | |
struct { | |
int alarm | |
char * description | |
unsigned int event_log:1 | |
enum queue_result id | |
char * name | |
char * name | |
char * name | |
rtpPayloadType payloadType | |
unsigned int queue_log:1 | |
char * subtype | |
char * text | |
char * type | |
int val | |
} | queue_results [] |
static struct ast_custom_function | queueagentcount_function |
static struct call_queue * | queues = NULL |
static char | rqm_cmd_usage [] |
static char | show_queue_usage [] |
static char | show_queues_usage [] |
static struct strategy | strategies [] |
static char * | synopsis = "Queue a call for a call queue" |
static char * | tdesc = "True Call Queueing" |
static int | use_weight = 0 |
queues.conf per-queue weight option |
These features added by David C. Troy <dave@toad.net>:
Added servicelevel statistic by Michiel Betel <michiel@betel.nl> Added Priority jumping code for adding and removing queue members by Jonathan Stanton <asterisk@doilooklikeicare.com>
Fixed to work with CVS as of 2004-02-25 and released as 1.07a by Matthew Enger <m.enger@xi.com.au>
Definition in file app_queue.c.
|
Definition at line 316 of file app_queue.c. Referenced by queue_set_param(). |
|
Definition at line 317 of file app_queue.c. Referenced by queue_set_param(), and say_position(). |
|
Definition at line 1755 of file app_queue.c. |
|
Definition at line 1757 of file app_queue.c. Referenced by wait_for_answer(). |
|
Definition at line 112 of file app_queue.c. Referenced by init_queue(), and queue_set_param(). |
|
Definition at line 113 of file app_queue.c. Referenced by queue_set_param(). |
|
Definition at line 225 of file app_queue.c. Referenced by dump_queue_members(), and reload_queue_members(). |
|
Definition at line 314 of file app_queue.c. Referenced by queue_set_param(). |
|
Definition at line 315 of file app_queue.c. Referenced by join_queue(), and queue_set_param(). |
|
Definition at line 96 of file app_queue.c. Referenced by calc_metric(). |
|
Definition at line 95 of file app_queue.c. Referenced by calc_metric(). |
|
Definition at line 97 of file app_queue.c. Referenced by calc_metric(). |
|
Definition at line 93 of file app_queue.c. Referenced by calc_metric(). |
|
Definition at line 94 of file app_queue.c. Referenced by calc_metric(). |
|
Definition at line 98 of file app_queue.c. Referenced by calc_metric(). |
|
Definition at line 114 of file app_queue.c. |
|
Definition at line 117 of file app_queue.c. Referenced by add_to_queue(), aqm_exec(), handle_add_queue_member(), handle_remove_queue_member(), manager_add_queue_member(), manager_remove_queue_member(), and rqm_exec(). |
|
Definition at line 119 of file app_queue.c. Referenced by add_to_queue(), aqm_exec(), handle_add_queue_member(), handle_remove_queue_member(), manager_add_queue_member(), manager_remove_queue_member(), remove_from_queue(), and rqm_exec(). |
|
Definition at line 116 of file app_queue.c. Referenced by add_to_queue(), aqm_exec(), handle_add_queue_member(), handle_remove_queue_member(), manager_add_queue_member(), manager_remove_queue_member(), and rqm_exec(). |
|
Definition at line 118 of file app_queue.c. Referenced by add_to_queue(), aqm_exec(), handle_add_queue_member(), handle_remove_queue_member(), manager_add_queue_member(), manager_remove_queue_member(), and rqm_exec(). |
|
Definition at line 429 of file app_queue.c. 00429 { 00430 QUEUE_NO_MEMBERS, 00431 QUEUE_NO_REACHABLE_MEMBERS, 00432 QUEUE_NORMAL 00433 };
|
|
Definition at line 233 of file app_queue.c. 00233 { 00234 QUEUE_UNKNOWN = 0, 00235 QUEUE_TIMEOUT = 1, 00236 QUEUE_JOINEMPTY = 2, 00237 QUEUE_LEAVEEMPTY = 3, 00238 QUEUE_JOINUNAVAIL = 4, 00239 QUEUE_LEAVEUNAVAIL = 5, 00240 QUEUE_FULL = 6, 00241 };
|
|
Definition at line 3463 of file app_queue.c. References ast_build_string(), ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), member::calls, call_queue::callsabandoned, call_queue::callscompleted, call_queue::callscompletedinsl, queue_ent::chan, call_queue::count, devstate2str(), member::dynamic, call_queue::head, call_queue::holdtime, int2strat(), member::interface, member::lastcall, load_realtime_queue(), call_queue::lock, call_queue::maxlen, call_queue::members, ast_channel::name, call_queue::name, queue_ent::next, member::next, call_queue::next, member::paused, member::penalty, queue_ent::prio, queues, RESULT_SHOWUSAGE, RESULT_SUCCESS, call_queue::servicelevel, queue_ent::start, member::status, call_queue::strategy, and call_queue::weight. Referenced by manager_queues_show(), queue_show(), and queues_show(). 03464 { 03465 struct call_queue *q; 03466 struct queue_ent *qe; 03467 struct member *mem; 03468 int pos; 03469 time_t now; 03470 char max_buf[80]; 03471 char *max; 03472 size_t max_left; 03473 float sl = 0; 03474 char *term = manager ? "\r\n" : "\n"; 03475 03476 time(&now); 03477 if ((!queue_show && argc != 2) || (queue_show && argc != 3)) 03478 return RESULT_SHOWUSAGE; 03479 03480 /* We only want to load realtime queues when a specific queue is asked for. */ 03481 if (queue_show) 03482 load_realtime_queue(argv[2]); 03483 03484 ast_mutex_lock(&qlock); 03485 03486 q = queues; 03487 if (!q) { 03488 ast_mutex_unlock(&qlock); 03489 if (queue_show) 03490 ast_cli(fd, "No such queue: %s.%s",argv[2], term); 03491 else 03492 ast_cli(fd, "No queues.%s", term); 03493 return RESULT_SUCCESS; 03494 } 03495 while (q) { 03496 ast_mutex_lock(&q->lock); 03497 if (queue_show) { 03498 if (strcasecmp(q->name, argv[2]) != 0) { 03499 ast_mutex_unlock(&q->lock); 03500 q = q->next; 03501 if (!q) { 03502 ast_cli(fd, "No such queue: %s.%s",argv[2], term); 03503 break; 03504 } 03505 continue; 03506 } 03507 } 03508 max_buf[0] = '\0'; 03509 max = max_buf; 03510 max_left = sizeof(max_buf); 03511 if (q->maxlen) 03512 ast_build_string(&max, &max_left, "%d", q->maxlen); 03513 else 03514 ast_build_string(&max, &max_left, "unlimited"); 03515 sl = 0; 03516 if(q->callscompleted > 0) 03517 sl = 100*((float)q->callscompletedinsl/(float)q->callscompleted); 03518 ast_cli(fd, "%-12.12s has %d calls (max %s) in '%s' strategy (%ds holdtime), W:%d, C:%d, A:%d, SL:%2.1f%% within %ds%s", 03519 q->name, q->count, max_buf, int2strat(q->strategy), q->holdtime, q->weight, q->callscompleted, q->callsabandoned,sl,q->servicelevel, term); 03520 if (q->members) { 03521 ast_cli(fd, " Members: %s", term); 03522 for (mem = q->members; mem; mem = mem->next) { 03523 max_buf[0] = '\0'; 03524 max = max_buf; 03525 max_left = sizeof(max_buf); 03526 if (mem->penalty) 03527 ast_build_string(&max, &max_left, " with penalty %d", mem->penalty); 03528 if (mem->dynamic) 03529 ast_build_string(&max, &max_left, " (dynamic)"); 03530 if (mem->paused) 03531 ast_build_string(&max, &max_left, " (paused)"); 03532 ast_build_string(&max, &max_left, " (%s)", devstate2str(mem->status)); 03533 if (mem->calls) { 03534 ast_build_string(&max, &max_left, " has taken %d calls (last was %ld secs ago)", 03535 mem->calls, (long)(time(NULL) - mem->lastcall)); 03536 } else 03537 ast_build_string(&max, &max_left, " has taken no calls yet"); 03538 ast_cli(fd, " %s%s%s", mem->interface, max_buf, term); 03539 } 03540 } else 03541 ast_cli(fd, " No Members%s", term); 03542 if (q->head) { 03543 pos = 1; 03544 ast_cli(fd, " Callers: %s", term); 03545 for (qe = q->head; qe; qe = qe->next) 03546 ast_cli(fd, " %d. %s (wait: %ld:%2.2ld, prio: %d)%s", pos++, qe->chan->name, 03547 (long)(now - qe->start) / 60, (long)(now - qe->start) % 60, qe->prio, term); 03548 } else 03549 ast_cli(fd, " No Callers%s", term); 03550 ast_cli(fd, "%s", term); 03551 ast_mutex_unlock(&q->lock); 03552 q = q->next; 03553 if (queue_show) 03554 break; 03555 } 03556 ast_mutex_unlock(&qlock); 03557 return RESULT_SUCCESS; 03558 }
|
|
Definition at line 639 of file app_queue.c. References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), member_interface::interface, list, LOG_DEBUG, malloc, and option_debug. Referenced by add_to_queue(), reload_queues(), and rt_handle_member_record(). 00640 { 00641 struct member_interface *curint; 00642 00643 if (!interface) 00644 return 0; 00645 00646 AST_LIST_LOCK(&interfaces); 00647 AST_LIST_TRAVERSE(&interfaces, curint, list) { 00648 if (!strcasecmp(curint->interface, interface)) 00649 break; 00650 } 00651 00652 if (curint) { 00653 AST_LIST_UNLOCK(&interfaces); 00654 return 0; 00655 } 00656 00657 if (option_debug) 00658 ast_log(LOG_DEBUG, "Adding %s to the list of interfaces that make up all of our queue members.\n", interface); 00659 00660 if ((curint = malloc(sizeof(*curint)))) { 00661 memset(curint, 0, sizeof(*curint)); 00662 ast_copy_string(curint->interface, interface, sizeof(curint->interface)); 00663 AST_LIST_INSERT_HEAD(&interfaces, curint, list); 00664 } 00665 AST_LIST_UNLOCK(&interfaces); 00666 00667 return 0; 00668 }
|
|
Definition at line 2567 of file app_queue.c. References add_to_interfaces(), ast_mutex_lock(), ast_mutex_unlock(), member::calls, create_queue_member(), dump_queue_members(), member::dynamic, EVENT_FLAG_AGENT, member::interface, interface_exists(), member::lastcall, load_realtime_queue(), call_queue::lock, manager_event(), call_queue::members, call_queue::name, member::next, member::paused, member::penalty, RES_EXISTS, RES_NOSUCHQUEUE, RES_OKAY, RES_OUTOFMEMORY, and member::status. Referenced by aqm_exec(), handle_add_queue_member(), and manager_add_queue_member(). 02568 { 02569 struct call_queue *q; 02570 struct member *new_member; 02571 int res = RES_NOSUCHQUEUE; 02572 02573 /* \note Ensure the appropriate realtime queue is loaded. Note that this 02574 * short-circuits if the queue is already in memory. */ 02575 q = load_realtime_queue(queuename); 02576 02577 ast_mutex_lock(&qlock); 02578 02579 if (q) { 02580 ast_mutex_lock(&q->lock); 02581 if (interface_exists(q, interface) == NULL) { 02582 02583 add_to_interfaces(interface); 02584 02585 new_member = create_queue_member(interface, penalty, paused); 02586 02587 if (new_member != NULL) { 02588 new_member->dynamic = 1; 02589 new_member->next = q->members; 02590 q->members = new_member; 02591 manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded", 02592 "Queue: %s\r\n" 02593 "Location: %s\r\n" 02594 "Membership: %s\r\n" 02595 "Penalty: %d\r\n" 02596 "CallsTaken: %d\r\n" 02597 "LastCall: %d\r\n" 02598 "Status: %d\r\n" 02599 "Paused: %d\r\n", 02600 q->name, new_member->interface, new_member->dynamic ? "dynamic" : "static", 02601 new_member->penalty, new_member->calls, (int)new_member->lastcall, new_member->status, new_member->paused); 02602 02603 if (dump) 02604 dump_queue_members(q); 02605 02606 res = RES_OKAY; 02607 } else { 02608 res = RES_OUTOFMEMORY; 02609 } 02610 } else { 02611 res = RES_EXISTS; 02612 } 02613 ast_mutex_unlock(&q->lock); 02614 } 02615 ast_mutex_unlock(&qlock); 02616 return res; 02617 }
|
|
Definition at line 590 of file app_queue.c. References ast_mutex_init(), and malloc. Referenced by reload_queues(). 00591 { 00592 struct call_queue *q; 00593 00594 q = malloc(sizeof(*q)); 00595 if (q) { 00596 memset(q, 0, sizeof(*q)); 00597 ast_mutex_init(&q->lock); 00598 ast_copy_string(q->name, queuename, sizeof(q->name)); 00599 } 00600 return q; 00601 }
|
|
Definition at line 2931 of file app_queue.c. References add_to_queue(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_goto_if_exists(), ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), localuser::chan, ast_channel::context, localuser::interface, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_channel::name, option_priority_jumping, parse(), pbx_builtin_setvar_helper(), queue_persistent_members, RES_EXISTS, RES_NOSUCHQUEUE, RES_OKAY, and RES_OUTOFMEMORY. Referenced by load_module(). 02932 { 02933 int res=-1; 02934 struct localuser *u; 02935 char *parse, *temppos = NULL; 02936 int priority_jump = 0; 02937 AST_DECLARE_APP_ARGS(args, 02938 AST_APP_ARG(queuename); 02939 AST_APP_ARG(interface); 02940 AST_APP_ARG(penalty); 02941 AST_APP_ARG(options); 02942 ); 02943 int penalty = 0; 02944 02945 if (ast_strlen_zero(data)) { 02946 ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename[|[interface]|[penalty][|options]])\n"); 02947 return -1; 02948 } 02949 02950 LOCAL_USER_ADD(u); 02951 02952 if (!(parse = ast_strdupa(data))) { 02953 ast_log(LOG_WARNING, "Memory Error!\n"); 02954 LOCAL_USER_REMOVE(u); 02955 return -1; 02956 } 02957 02958 AST_STANDARD_APP_ARGS(args, parse); 02959 02960 if (ast_strlen_zero(args.interface)) { 02961 args.interface = ast_strdupa(chan->name); 02962 temppos = strrchr(args.interface, '-'); 02963 if (temppos) 02964 *temppos = '\0'; 02965 } 02966 02967 if (!ast_strlen_zero(args.penalty)) { 02968 if ((sscanf(args.penalty, "%d", &penalty) != 1) || penalty < 0) { 02969 ast_log(LOG_WARNING, "Penalty '%s' is invalid, must be an integer >= 0\n", args.penalty); 02970 penalty = 0; 02971 } 02972 } 02973 02974 if (args.options) { 02975 if (strchr(args.options, 'j')) 02976 priority_jump = 1; 02977 } 02978 02979 02980 switch (add_to_queue(args.queuename, args.interface, penalty, 0, queue_persistent_members)) { 02981 case RES_OKAY: 02982 ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", args.interface, args.queuename); 02983 pbx_builtin_setvar_helper(chan, "AQMSTATUS", "ADDED"); 02984 res = 0; 02985 break; 02986 case RES_EXISTS: 02987 ast_log(LOG_WARNING, "Unable to add interface '%s' to queue '%s': Already there\n", args.interface, args.queuename); 02988 if (priority_jump || option_priority_jumping) 02989 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101); 02990 pbx_builtin_setvar_helper(chan, "AQMSTATUS", "MEMBERALREADY"); 02991 res = 0; 02992 break; 02993 case RES_NOSUCHQUEUE: 02994 ast_log(LOG_WARNING, "Unable to add interface to queue '%s': No such queue\n", args.queuename); 02995 pbx_builtin_setvar_helper(chan, "AQMSTATUS", "NOSUCHQUEUE"); 02996 res = 0; 02997 break; 02998 case RES_OUTOFMEMORY: 02999 ast_log(LOG_ERROR, "Out of memory adding member %s to queue %s\n", args.interface, args.queuename); 03000 break; 03001 } 03002 03003 LOCAL_USER_REMOVE(u); 03004 return res; 03005 }
|
|
|
|
|
|
Definition at line 1689 of file app_queue.c. References AST_DIGIT_ANY, ast_stopstream(), ast_streamfile(), ast_waitstream(), localuser::chan, ast_channel::language, and valid_exit(). Referenced by say_periodic_announcement(). 01690 { 01691 int res; 01692 01693 ast_stopstream(chan); 01694 res = ast_streamfile(chan, filename, chan->language); 01695 01696 if (!res) { 01697 /* Wait for a keypress */ 01698 res = ast_waitstream(chan, AST_DIGIT_ANY); 01699 if (res < 0 || !valid_exit(qe, res)) 01700 res = 0; 01701 01702 /* Stop playback */ 01703 ast_stopstream(chan); 01704 } else { 01705 res = 0; 01706 } 01707 01708 /*if (res) { 01709 ast_log(LOG_WARNING, "ast_streamfile failed on %s \n", chan->name); 01710 res = 0; 01711 }*/ 01712 01713 return res; 01714 }
|
|
Definition at line 2101 of file app_queue.c. References ast_log(), member::calls, member::lastcall, LOG_WARNING, localuser::metric, member::penalty, QUEUE_STRATEGY_FEWESTCALLS, QUEUE_STRATEGY_LEASTRECENT, QUEUE_STRATEGY_RANDOM, QUEUE_STRATEGY_RINGALL, QUEUE_STRATEGY_ROUNDROBIN, QUEUE_STRATEGY_RRMEMORY, call_queue::rrpos, call_queue::strategy, and call_queue::wrapped. 02102 { 02103 switch (q->strategy) { 02104 case QUEUE_STRATEGY_RINGALL: 02105 /* Everyone equal, except for penalty */ 02106 tmp->metric = mem->penalty * 1000000; 02107 break; 02108 case QUEUE_STRATEGY_ROUNDROBIN: 02109 if (!pos) { 02110 if (!q->wrapped) { 02111 /* No more channels, start over */ 02112 q->rrpos = 0; 02113 } else { 02114 /* Prioritize next entry */ 02115 q->rrpos++; 02116 } 02117 q->wrapped = 0; 02118 } 02119 /* Fall through */ 02120 case QUEUE_STRATEGY_RRMEMORY: 02121 if (pos < q->rrpos) { 02122 tmp->metric = 1000 + pos; 02123 } else { 02124 if (pos > q->rrpos) 02125 /* Indicate there is another priority */ 02126 q->wrapped = 1; 02127 tmp->metric = pos; 02128 } 02129 tmp->metric += mem->penalty * 1000000; 02130 break; 02131 case QUEUE_STRATEGY_RANDOM: 02132 tmp->metric = rand() % 1000; 02133 tmp->metric += mem->penalty * 1000000; 02134 break; 02135 case QUEUE_STRATEGY_FEWESTCALLS: 02136 tmp->metric = mem->calls; 02137 tmp->metric += mem->penalty * 1000000; 02138 break; 02139 case QUEUE_STRATEGY_LEASTRECENT: 02140 if (!mem->lastcall) 02141 tmp->metric = 0; 02142 else 02143 tmp->metric = 1000000 - (time(NULL) - mem->lastcall); 02144 tmp->metric += mem->penalty * 1000000; 02145 break; 02146 default: 02147 ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy); 02148 break; 02149 } 02150 return 0; 02151 }
|
|
Definition at line 466 of file app_queue.c. References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_strdupa, member::calls, statechange::dev, devstate2str(), member::dynamic, EVENT_FLAG_AGENT, free, member::interface, member_interface::interface, member::lastcall, list, call_queue::lock, LOG_DEBUG, manager_event(), call_queue::maskmemberstatus, call_queue::members, call_queue::name, member::next, call_queue::next, option_debug, member::paused, member::penalty, queues, statechange::state, and member::status. Referenced by statechange_queue(). 00467 { 00468 struct call_queue *q; 00469 struct statechange *sc = data; 00470 struct member *cur; 00471 struct member_interface *curint; 00472 char *loc; 00473 char *technology; 00474 00475 technology = ast_strdupa(sc->dev); 00476 loc = strchr(technology, '/'); 00477 if (loc) { 00478 *loc++ = '\0'; 00479 } else { 00480 free(sc); 00481 return NULL; 00482 } 00483 00484 AST_LIST_LOCK(&interfaces); 00485 AST_LIST_TRAVERSE(&interfaces, curint, list) { 00486 char *interface; 00487 char *slash_pos; 00488 interface = ast_strdupa(curint->interface); 00489 if ((slash_pos = strchr(interface, '/'))) 00490 if ((slash_pos = strchr(slash_pos + 1, '/'))) 00491 *slash_pos = '\0'; 00492 00493 if (!strcasecmp(interface, sc->dev)) 00494 break; 00495 } 00496 AST_LIST_UNLOCK(&interfaces); 00497 00498 if (!curint) { 00499 if (option_debug) 00500 ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n", technology, loc, sc->state, devstate2str(sc->state)); 00501 free(sc); 00502 return NULL; 00503 } 00504 00505 if (option_debug) 00506 ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d' (%s)\n", technology, loc, sc->state, devstate2str(sc->state)); 00507 ast_mutex_lock(&qlock); 00508 for (q = queues; q; q = q->next) { 00509 ast_mutex_lock(&q->lock); 00510 for (cur = q->members; cur; cur = cur->next) { 00511 char *interface; 00512 char *slash_pos; 00513 interface = ast_strdupa(cur->interface); 00514 if ((slash_pos = strchr(interface, '/'))) 00515 if ((slash_pos = strchr(slash_pos + 1, '/'))) 00516 *slash_pos = '\0'; 00517 00518 if (strcasecmp(sc->dev, interface)) 00519 continue; 00520 00521 if (cur->status != sc->state) { 00522 cur->status = sc->state; 00523 if (q->maskmemberstatus) 00524 continue; 00525 00526 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus", 00527 "Queue: %s\r\n" 00528 "Location: %s\r\n" 00529 "Membership: %s\r\n" 00530 "Penalty: %d\r\n" 00531 "CallsTaken: %d\r\n" 00532 "LastCall: %d\r\n" 00533 "Status: %d\r\n" 00534 "Paused: %d\r\n", 00535 q->name, cur->interface, cur->dynamic ? "dynamic" : "static", 00536 cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused); 00537 } 00538 } 00539 ast_mutex_unlock(&q->lock); 00540 } 00541 ast_mutex_unlock(&qlock); 00542 00543 return NULL; 00544 }
|
|
Definition at line 718 of file app_queue.c. References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, free, and list. Referenced by unload_module(). 00719 { 00720 struct member_interface *curint; 00721 00722 AST_LIST_LOCK(&interfaces); 00723 while ((curint = AST_LIST_REMOVE_HEAD(&interfaces, list))) 00724 free(curint); 00725 AST_LIST_UNLOCK(&interfaces); 00726 }
|
|
Definition at line 630 of file app_queue.c. References call_queue::callsabandoned, call_queue::callscompleted, call_queue::callscompletedinsl, call_queue::holdtime, and call_queue::wrapuptime. Referenced by reload_queues(). 00631 { 00632 q->holdtime = 0; 00633 q->callscompleted = 0; 00634 q->callsabandoned = 0; 00635 q->callscompletedinsl = 0; 00636 q->wrapuptime = 0; 00637 }
|
|
Definition at line 1456 of file app_queue.c. References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), call_queue::count, member::interface, call_queue::lock, LOG_DEBUG, call_queue::members, call_queue::name, member::next, call_queue::next, queues, and call_queue::weight. Referenced by ring_entry(). 01457 { 01458 struct call_queue *q; 01459 struct member *mem; 01460 int found = 0; 01461 01462 /* &qlock and &rq->lock already set by try_calling() 01463 * to solve deadlock */ 01464 for (q = queues; q; q = q->next) { 01465 if (q == rq) /* don't check myself, could deadlock */ 01466 continue; 01467 ast_mutex_lock(&q->lock); 01468 if (q->count && q->members) { 01469 for (mem = q->members; mem; mem = mem->next) { 01470 if (!strcmp(mem->interface, member->interface)) { 01471 ast_log(LOG_DEBUG, "Found matching member %s in queue '%s'\n", mem->interface, q->name); 01472 if (q->weight > rq->weight) { 01473 ast_log(LOG_DEBUG, "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); 01474 found = 1; 01475 break; 01476 } 01477 } 01478 } 01479 } 01480 ast_mutex_unlock(&q->lock); 01481 if (found) 01482 break; 01483 } 01484 ast_mutex_unlock(&qlock); 01485 return found; 01486 }
|
|
Definition at line 3839 of file app_queue.c. References complete_queue(), malloc, and strdup. 03840 { 03841 /* 0 - add; 1 - queue; 2 - member; 3 - <member>; 4 - to; 5 - <queue>; 6 - penalty; 7 - <penalty> */ 03842 switch (pos) { 03843 case 3: 03844 /* Don't attempt to complete name of member (infinite possibilities) */ 03845 return NULL; 03846 case 4: 03847 if (state == 0) { 03848 return strdup("to"); 03849 } else { 03850 return NULL; 03851 } 03852 case 5: 03853 /* No need to duplicate code */ 03854 return complete_queue(line, word, pos, state); 03855 case 6: 03856 if (state == 0) { 03857 return strdup("penalty"); 03858 } else { 03859 return NULL; 03860 } 03861 case 7: 03862 if (state < 100) { /* 0-99 */ 03863 char *num = malloc(3); 03864 if (num) { 03865 sprintf(num, "%d", state); 03866 } 03867 return num; 03868 } else { 03869 return NULL; 03870 } 03871 default: 03872 return NULL; 03873 } 03874 }
|
|
Definition at line 3570 of file app_queue.c. References ast_mutex_lock(), call_queue::name, call_queue::next, and queues. Referenced by complete_add_queue_member(), and complete_remove_queue_member(). 03571 { 03572 struct call_queue *q; 03573 int which=0; 03574 03575 ast_mutex_lock(&qlock); 03576 for (q = queues; q; q = q->next) { 03577 if (!strncasecmp(word, q->name, strlen(word))) { 03578 if (++which > state) 03579 break; 03580 } 03581 } 03582 ast_mutex_unlock(&qlock); 03583 return q ? strdup(q->name) : NULL; 03584 }
|
|
Definition at line 3907 of file app_queue.c. References ast_mutex_lock(), ast_mutex_unlock(), complete_queue(), member::interface, call_queue::lock, call_queue::members, member::next, call_queue::next, queues, and strdup. 03908 { 03909 int which = 0; 03910 struct call_queue *q; 03911 struct member *m; 03912 03913 /* 0 - add; 1 - queue; 2 - member; 3 - <member>; 4 - to; 5 - <queue> */ 03914 if ((pos > 5) || (pos < 3)) { 03915 return NULL; 03916 } 03917 if (pos == 4) { 03918 if (state == 0) { 03919 return strdup("from"); 03920 } else { 03921 return NULL; 03922 } 03923 } 03924 03925 if (pos == 5) { 03926 /* No need to duplicate code */ 03927 return complete_queue(line, word, pos, state); 03928 } 03929 03930 if (queues != NULL) { 03931 for (q = queues ; q ; q = q->next) { 03932 ast_mutex_lock(&q->lock); 03933 for (m = q->members ; m ; m = m->next) { 03934 if (++which > state) { 03935 ast_mutex_unlock(&q->lock); 03936 return strdup(m->interface); 03937 } 03938 } 03939 ast_mutex_unlock(&q->lock); 03940 } 03941 } 03942 return NULL; 03943 }
|
|
Definition at line 569 of file app_queue.c. References ast_device_state(), ast_log(), LOG_WARNING, and malloc. Referenced by add_to_queue(), reload_queues(), and rt_handle_member_record(). 00570 { 00571 struct member *cur; 00572 00573 /* Add a new member */ 00574 00575 cur = malloc(sizeof(struct member)); 00576 00577 if (cur) { 00578 memset(cur, 0, sizeof(struct member)); 00579 cur->penalty = penalty; 00580 cur->paused = paused; 00581 ast_copy_string(cur->interface, interface, sizeof(cur->interface)); 00582 if (!strchr(cur->interface, '/')) 00583 ast_log(LOG_WARNING, "No location at interface '%s'\n", interface); 00584 cur->status = ast_device_state(interface); 00585 } 00586 00587 return cur; 00588 }
|
|
Provides a description of the module.
Definition at line 4039 of file app_queue.c. References tdesc. 04040 { 04041 return tdesc; 04042 }
|
|
Definition at line 910 of file app_queue.c. References ast_mutex_destroy(), free, free_members(), and call_queue::lock. Referenced by leave_queue(), and reload_queues(). 00911 { 00912 free_members(q, 1); 00913 ast_mutex_destroy(&q->lock); 00914 free(q); 00915 }
|
|
Definition at line 2486 of file app_queue.c. References ast_db_del(), ast_db_put(), ast_log(), member::dynamic, member::interface, LOG_WARNING, call_queue::members, call_queue::name, member::next, member::paused, member::penalty, pm_family, and PM_MAX_LEN. Referenced by add_to_queue(), and set_member_paused(). 02487 { 02488 struct member *cur_member; 02489 char value[PM_MAX_LEN]; 02490 int value_len = 0; 02491 int res; 02492 02493 memset(value, 0, sizeof(value)); 02494 02495 if (!pm_queue) 02496 return; 02497 02498 for (cur_member = pm_queue->members; cur_member; cur_member = cur_member->next) { 02499 if (!cur_member->dynamic) 02500 continue; 02501 02502 res = snprintf(value + value_len, sizeof(value) - value_len, "%s;%d;%d%s", 02503 cur_member->interface, cur_member->penalty, cur_member->paused, 02504 cur_member->next ? "|" : ""); 02505 if (res != strlen(value + value_len)) { 02506 ast_log(LOG_WARNING, "Could not create persistent member string, out of space\n"); 02507 break; 02508 } 02509 value_len += res; 02510 } 02511 02512 if (value_len && !cur_member) { 02513 if (ast_db_put(pm_family, pm_queue->name, value)) 02514 ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n"); 02515 } else 02516 /* Delete the entry if the queue is empty or there is an error */ 02517 ast_db_del(pm_family, pm_queue->name); 02518 }
|
|
Reload a single queue via realtime.
Definition at line 938 of file app_queue.c. References member::interface, call_queue::name, call_queue::next, and queues. 00939 { 00940 struct ast_variable *v; 00941 struct call_queue *q, *prev_q = NULL; 00942 struct member *m, *prev_m, *next_m; 00943 char *interface; 00944 char *tmp, *tmp_name; 00945 char tmpbuf[64]; /* Must be longer than the longest queue param name. */ 00946 00947 /* Find the queue in the in-core list (we will create a new one if not found). */ 00948 for (q = queues; q; q = q->next) { 00949 if (!strcasecmp(q->name, queuename)) { 00950 break; 00951 } 00952 prev_q = q; 00953 } 00954 00955 /* Static queues override realtime. */ 00956 if (q) { 00957 ast_mutex_lock(&q->lock); 00958 if (!q->realtime) { 00959 if (q->dead) { 00960 ast_mutex_unlock(&q->lock); 00961 return NULL; 00962 } else { 00963 ast_mutex_unlock(&q->lock); 00964 return q; 00965 } 00966 } 00967 } else if (!member_config) 00968 /* Not found in the list, and it's not realtime ... */ 00969 return NULL; 00970 00971 /* Check if queue is defined in realtime. */ 00972 if (!queue_vars) { 00973 /* Delete queue from in-core list if it has been deleted in realtime. */ 00974 if (q) { 00975 /*! \note Hmm, can't seem to distinguish a DB failure from a not 00976 found condition... So we might delete an in-core queue 00977 in case of DB failure. */ 00978 ast_log(LOG_DEBUG, "Queue %s not found in realtime.\n", queuename); 00979 00980 q->dead = 1; 00981 /* Delete if unused (else will be deleted when last caller leaves). */ 00982 if (!q->count) { 00983 /* Delete. */ 00984 if (!prev_q) { 00985 queues = q->next; 00986 } else { 00987 prev_q->next = q->next; 00988 } 00989 ast_mutex_unlock(&q->lock); 00990 destroy_queue(q); 00991 } else 00992 ast_mutex_unlock(&q->lock); 00993 } 00994 return NULL; 00995 } 00996 00997 /* Create a new queue if an in-core entry does not exist yet. */ 00998 if (!q) { 00999 q = alloc_queue(queuename); 01000 if (!q) 01001 return NULL; 01002 ast_mutex_lock(&q->lock); 01003 clear_queue(q); 01004 q->realtime = 1; 01005 q->next = queues; 01006 queues = q; 01007 } 01008 init_queue(q); /* Ensure defaults for all parameters not set explicitly. */ 01009 01010 v = queue_vars; 01011 memset(tmpbuf, 0, sizeof(tmpbuf)); 01012 while(v) { 01013 /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */ 01014 if((tmp = strchr(v->name, '_')) != NULL) { 01015 ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf)); 01016 tmp_name = tmpbuf; 01017 tmp = tmp_name; 01018 while((tmp = strchr(tmp, '_')) != NULL) 01019 *tmp++ = '-'; 01020 } else 01021 tmp_name = v->name; 01022 queue_set_param(q, tmp_name, v->value, -1, 0); 01023 v = v->next; 01024 } 01025 01026 /* Temporarily set non-dynamic members dead so we can detect deleted ones. */ 01027 m = q->members; 01028 while (m) { 01029 if (!m->dynamic) 01030 m->dead = 1; 01031 m = m->next; 01032 } 01033 01034 interface = ast_category_browse(member_config, NULL); 01035 while (interface) { 01036 rt_handle_member_record(q, interface, ast_variable_retrieve(member_config, interface, "penalty")); 01037 interface = ast_category_browse(member_config, interface); 01038 } 01039 01040 /* Delete all realtime members that have been deleted in DB. */ 01041 m = q->members; 01042 prev_m = NULL; 01043 while (m) { 01044 next_m = m->next; 01045 if (m->dead) { 01046 if (prev_m) { 01047 prev_m->next = next_m; 01048 } else { 01049 q->members = next_m; 01050 } 01051 remove_from_interfaces(m->interface); 01052 free(m); 01053 } else { 01054 prev_m = m; 01055 } 01056 m = next_m; 01057 } 01058 01059 ast_mutex_unlock(&q->lock); 01060 01061 return q; 01062 }
|
|
Definition at line 891 of file app_queue.c. References member::dynamic, free, member::interface, call_queue::members, member::next, and remove_from_interfaces(). Referenced by destroy_queue(). 00892 { 00893 /* Free non-dynamic members */ 00894 struct member *curm, *next, *prev = NULL; 00895 00896 for (curm = q->members; curm; curm = next) { 00897 next = curm->next; 00898 if (all || !curm->dynamic) { 00899 if (prev) 00900 prev->next = next; 00901 else 00902 q->members = next; 00903 remove_from_interfaces(curm->interface); 00904 free(curm); 00905 } else 00906 prev = curm; 00907 } 00908 }
|
|
Definition at line 435 of file app_queue.c. References AST_DEVICE_INVALID, AST_DEVICE_UNAVAILABLE, ast_mutex_lock(), ast_mutex_unlock(), call_queue::lock, call_queue::members, member::next, member::paused, QUEUE_NO_MEMBERS, QUEUE_NO_REACHABLE_MEMBERS, QUEUE_NORMAL, result, and member::status. Referenced by join_queue(). 00436 { 00437 struct member *member; 00438 enum queue_member_status result = QUEUE_NO_MEMBERS; 00439 00440 ast_mutex_lock(&q->lock); 00441 for (member = q->members; member; member = member->next) { 00442 if (member->paused) continue; 00443 00444 switch (member->status) { 00445 case AST_DEVICE_INVALID: 00446 /* nothing to do */ 00447 break; 00448 case AST_DEVICE_UNAVAILABLE: 00449 result = QUEUE_NO_REACHABLE_MEMBERS; 00450 break; 00451 default: 00452 ast_mutex_unlock(&q->lock); 00453 return QUEUE_NORMAL; 00454 } 00455 } 00456 00457 ast_mutex_unlock(&q->lock); 00458 return result; 00459 }
|
|
Definition at line 3792 of file app_queue.c. References add_to_queue(), ast_cli(), member::interface, member::penalty, queue_persistent_members, RES_EXISTS, RES_NOSUCHQUEUE, RES_OKAY, RES_OUTOFMEMORY, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS. 03793 { 03794 char *queuename, *interface; 03795 int penalty; 03796 03797 if ((argc != 6) && (argc != 8)) { 03798 return RESULT_SHOWUSAGE; 03799 } else if (strcmp(argv[4], "to")) { 03800 return RESULT_SHOWUSAGE; 03801 } else if ((argc == 8) && strcmp(argv[6], "penalty")) { 03802 return RESULT_SHOWUSAGE; 03803 } 03804 03805 queuename = argv[5]; 03806 interface = argv[3]; 03807 if (argc == 8) { 03808 if (sscanf(argv[7], "%d", &penalty) == 1) { 03809 if (penalty < 0) { 03810 ast_cli(fd, "Penalty must be >= 0\n"); 03811 penalty = 0; 03812 } 03813 } else { 03814 ast_cli(fd, "Penalty must be an integer >= 0\n"); 03815 penalty = 0; 03816 } 03817 } else { 03818 penalty = 0; 03819 } 03820 03821 switch (add_to_queue(queuename, interface, penalty, 0, queue_persistent_members)) { 03822 case RES_OKAY: 03823 ast_cli(fd, "Added interface '%s' to queue '%s'\n", interface, queuename); 03824 return RESULT_SUCCESS; 03825 case RES_EXISTS: 03826 ast_cli(fd, "Unable to add interface '%s' to queue '%s': Already there\n", interface, queuename); 03827 return RESULT_FAILURE; 03828 case RES_NOSUCHQUEUE: 03829 ast_cli(fd, "Unable to add interface to queue '%s': No such queue\n", queuename); 03830 return RESULT_FAILURE; 03831 case RES_OUTOFMEMORY: 03832 ast_cli(fd, "Out of memory\n"); 03833 return RESULT_FAILURE; 03834 default: 03835 return RESULT_FAILURE; 03836 } 03837 }
|
|
Definition at line 3876 of file app_queue.c. References ast_cli(), member::interface, remove_from_queue(), RES_EXISTS, RES_NOSUCHQUEUE, RES_OKAY, RES_OUTOFMEMORY, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS. 03877 { 03878 char *queuename, *interface; 03879 03880 if (argc != 6) { 03881 return RESULT_SHOWUSAGE; 03882 } else if (strcmp(argv[4], "from")) { 03883 return RESULT_SHOWUSAGE; 03884 } 03885 03886 queuename = argv[5]; 03887 interface = argv[3]; 03888 03889 switch (remove_from_queue(queuename, interface)) { 03890 case RES_OKAY: 03891 ast_cli(fd, "Removed interface '%s' from queue '%s'\n", interface, queuename); 03892 return RESULT_SUCCESS; 03893 case RES_EXISTS: 03894 ast_cli(fd, "Unable to remove interface '%s' from queue '%s': Not there\n", interface, queuename); 03895 return RESULT_FAILURE; 03896 case RES_NOSUCHQUEUE: 03897 ast_cli(fd, "Unable to remove interface from queue '%s': No such queue\n", queuename); 03898 return RESULT_FAILURE; 03899 case RES_OUTOFMEMORY: 03900 ast_cli(fd, "Out of memory\n"); 03901 return RESULT_FAILURE; 03902 default: 03903 return RESULT_FAILURE; 03904 } 03905 }
|
|
Definition at line 1395 of file app_queue.c. References ast_hangup(), localuser::chan, free, and localuser::next. 01396 { 01397 struct localuser *oo; 01398 01399 while(outgoing) { 01400 /* Hangup any existing lines we have open */ 01401 if (outgoing->chan && (outgoing->chan != exception)) 01402 ast_hangup(outgoing->chan); 01403 oo = outgoing; 01404 outgoing=outgoing->next; 01405 free(oo); 01406 } 01407 }
|
|
|
Insert the 'new' entry after the 'prev' entry of queue 'q'.
Definition at line 410 of file app_queue.c. References call_queue::head, queue_ent::next, and queue_ent::parent. Referenced by join_queue(). 00411 { 00412 struct queue_ent *cur; 00413 00414 if (!q || !new) 00415 return; 00416 if (prev) { 00417 cur = prev->next; 00418 prev->next = new; 00419 } else { 00420 cur = q->head; 00421 q->head = new; 00422 } 00423 new->next = cur; 00424 new->parent = q; 00425 new->pos = ++(*pos); 00426 new->opos = *pos; 00427 }
|
|
Definition at line 389 of file app_queue.c. References name, and strategies. Referenced by __queues_show(). 00390 { 00391 int x; 00392 for (x=0;x<sizeof(strategies) / sizeof(strategies[0]);x++) { 00393 if (strategy == strategies[x].strategy) 00394 return strategies[x].name; 00395 } 00396 return "<unknown>"; 00397 }
|
|
Definition at line 2468 of file app_queue.c. References member::interface, call_queue::members, and member::next. Referenced by add_to_queue(), remove_from_queue(), and set_member_paused(). 02469 { 02470 struct member *mem; 02471 02472 if (q) 02473 for (mem = q->members; mem; mem = mem->next) 02474 if (!strcasecmp(interface, mem->interface)) 02475 return mem; 02476 02477 return NULL; 02478 }
|
|
Definition at line 670 of file app_queue.c. References ast_mutex_lock(), member::interface, call_queue::lock, call_queue::members, member::next, call_queue::next, and queues. Referenced by remove_from_interfaces(). 00671 { 00672 struct call_queue *q; 00673 struct member *mem; 00674 int ret = 0; 00675 00676 if (!interface) 00677 return ret; 00678 00679 ast_mutex_lock(&qlock); 00680 for (q = queues; q && !ret; q = q->next) { 00681 ast_mutex_lock(&q->lock); 00682 for (mem = q->members; mem && !ret; mem = mem->next) { 00683 if (!strcasecmp(interface, mem->interface)) 00684 ret = 1; 00685 } 00686 ast_mutex_unlock(&q->lock); 00687 } 00688 ast_mutex_unlock(&qlock); 00689 00690 return ret; 00691 }
|
|
Definition at line 2010 of file app_queue.c. References ast_log(), queue_ent::chan, call_queue::head, LOG_DEBUG, ast_channel::name, option_debug, and queue_ent::parent. Referenced by wait_our_turn(). 02011 { 02012 struct queue_ent *ch; 02013 int res; 02014 02015 /* Atomically read the parent head -- does not need a lock */ 02016 ch = qe->parent->head; 02017 /* If we are now at the top of the head, break out */ 02018 if (ch == qe) { 02019 if (option_debug) 02020 ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name); 02021 res = 1; 02022 } else { 02023 if (option_debug) 02024 ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name); 02025 res = 0; 02026 } 02027 return res; 02028 }
|
|
Definition at line 1111 of file app_queue.c. References queue_ent::announce, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), queue_ent::chan, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, queue_ent::context, call_queue::count, EVENT_FLAG_CALL, get_member_status(), call_queue::head, insert_entry(), call_queue::joinempty, load_realtime_queue(), call_queue::lock, LOG_DEBUG, manager_event(), call_queue::maxlen, queue_ent::moh, ast_channel::name, queue_ent::next, option_debug, queue_ent::pos, queue_ent::prio, QUEUE_EMPTY_STRICT, QUEUE_FULL, QUEUE_JOINEMPTY, QUEUE_JOINUNAVAIL, QUEUE_NO_MEMBERS, and QUEUE_NO_REACHABLE_MEMBERS. Referenced by queue_exec(). 01112 { 01113 struct call_queue *q; 01114 struct queue_ent *cur, *prev = NULL; 01115 int res = -1; 01116 int pos = 0; 01117 int inserted = 0; 01118 enum queue_member_status stat; 01119 01120 q = load_realtime_queue(queuename); 01121 if (!q) 01122 return res; 01123 01124 ast_mutex_lock(&qlock); 01125 ast_mutex_lock(&q->lock); 01126 01127 /* This is our one */ 01128 stat = get_member_status(q); 01129 if (!q->joinempty && (stat == QUEUE_NO_MEMBERS)) 01130 *reason = QUEUE_JOINEMPTY; 01131 else if ((q->joinempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) 01132 *reason = QUEUE_JOINUNAVAIL; 01133 else if (q->maxlen && (q->count >= q->maxlen)) 01134 *reason = QUEUE_FULL; 01135 else { 01136 /* There's space for us, put us at the right position inside 01137 * the queue. 01138 * Take into account the priority of the calling user */ 01139 inserted = 0; 01140 prev = NULL; 01141 cur = q->head; 01142 while(cur) { 01143 /* We have higher priority than the current user, enter 01144 * before him, after all the other users with priority 01145 * higher or equal to our priority. */ 01146 if ((!inserted) && (qe->prio > cur->prio)) { 01147 insert_entry(q, prev, qe, &pos); 01148 inserted = 1; 01149 } 01150 cur->pos = ++pos; 01151 prev = cur; 01152 cur = cur->next; 01153 } 01154 /* No luck, join at the end of the queue */ 01155 if (!inserted) 01156 insert_entry(q, prev, qe, &pos); 01157 ast_copy_string(qe->moh, q->moh, sizeof(qe->moh)); 01158 ast_copy_string(qe->announce, q->announce, sizeof(qe->announce)); 01159 ast_copy_string(qe->context, q->context, sizeof(qe->context)); 01160 q->count++; 01161 res = 0; 01162 manager_event(EVENT_FLAG_CALL, "Join", 01163 "Channel: %s\r\nCallerID: %s\r\nCallerIDName: %s\r\nQueue: %s\r\nPosition: %d\r\nCount: %d\r\n", 01164 qe->chan->name, 01165 qe->chan->cid.cid_num ? qe->chan->cid.cid_num : "unknown", 01166 qe->chan->cid.cid_name ? qe->chan->cid.cid_name : "unknown", 01167 q->name, qe->pos, q->count ); 01168 01169 if (option_debug) 01170 ast_log(LOG_DEBUG, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos ); 01171 } 01172 ast_mutex_unlock(&q->lock); 01173 ast_mutex_unlock(&qlock); 01174 return res; 01175 }
|
|
Returns the ASTERISK_GPL_KEY. This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 4051 of file app_queue.c. References ASTERISK_GPL_KEY. 04052 { 04053 return ASTERISK_GPL_KEY; 04054 }
|
|
Definition at line 1350 of file app_queue.c. References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), queue_ent::chan, call_queue::count, call_queue::dead, destroy_queue(), EVENT_FLAG_CALL, call_queue::head, call_queue::lock, LOG_NOTICE, manager_event(), call_queue::name, ast_channel::name, queue_ent::next, queue_ent::parent, queue_ent::pos, and remove_queue(). 01351 { 01352 struct call_queue *q; 01353 struct queue_ent *cur, *prev = NULL; 01354 int pos = 0; 01355 01356 q = qe->parent; 01357 if (!q) 01358 return; 01359 ast_mutex_lock(&q->lock); 01360 01361 prev = NULL; 01362 cur = q->head; 01363 while(cur) { 01364 if (cur == qe) { 01365 q->count--; 01366 01367 /* Take us out of the queue */ 01368 manager_event(EVENT_FLAG_CALL, "Leave", 01369 "Channel: %s\r\nQueue: %s\r\nCount: %d\r\n", 01370 qe->chan->name, q->name, q->count); 01371 #if 0 01372 ast_log(LOG_NOTICE, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name ); 01373 #endif 01374 /* Take us out of the queue */ 01375 if (prev) 01376 prev->next = cur->next; 01377 else 01378 q->head = cur->next; 01379 } else { 01380 /* Renumber the people after us in the queue based on a new count */ 01381 cur->pos = ++pos; 01382 prev = cur; 01383 } 01384 cur = cur->next; 01385 } 01386 ast_mutex_unlock(&q->lock); 01387 if (q->dead && !q->count) { 01388 /* It's dead and nobody is in it, so kill it */ 01389 remove_queue(q); 01390 destroy_queue(q); 01391 } 01392 }
|
|
|
Definition at line 1064 of file app_queue.c. References ast_mutex_lock(), call_queue::name, call_queue::next, and queues. Referenced by __queues_show(), add_to_queue(), and join_queue(). 01065 { 01066 struct ast_variable *queue_vars = NULL; 01067 struct ast_config *member_config = NULL; 01068 struct call_queue *q; 01069 01070 /* Find the queue in the in-core list first. */ 01071 ast_mutex_lock(&qlock); 01072 for (q = queues; q; q = q->next) { 01073 if (!strcasecmp(q->name, queuename)) { 01074 break; 01075 } 01076 } 01077 ast_mutex_unlock(&qlock); 01078 01079 if (!q || q->realtime) { 01080 /*! \note Load from realtime before taking the global qlock, to avoid blocking all 01081 queue operations while waiting for the DB. 01082 01083 This will be two separate database transactions, so we might 01084 see queue parameters as they were before another process 01085 changed the queue and member list as it was after the change. 01086 Thus we might see an empty member list when a queue is 01087 deleted. In practise, this is unlikely to cause a problem. */ 01088 01089 queue_vars = ast_load_realtime("queues", "name", queuename, NULL); 01090 if (queue_vars) { 01091 member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, NULL); 01092 if (!member_config) { 01093 ast_log(LOG_ERROR, "no queue_members defined in your config (extconfig.conf).\n"); 01094 return NULL; 01095 } 01096 } 01097 01098 ast_mutex_lock(&qlock); 01099 01100 q = find_queue_by_name_rt(queuename, queue_vars, member_config); 01101 if (member_config) 01102 ast_config_destroy(member_config); 01103 if (queue_vars) 01104 ast_variables_destroy(queue_vars); 01105 01106 ast_mutex_unlock(&qlock); 01107 } 01108 return q; 01109 }
|
|
Definition at line 3688 of file app_queue.c. References add_to_queue(), ast_strlen_zero(), ast_true(), astman_get_header(), astman_send_ack(), astman_send_error(), member::interface, member::paused, member::penalty, queue_persistent_members, RES_EXISTS, RES_NOSUCHQUEUE, RES_OKAY, RES_OUTOFMEMORY, and s. Referenced by load_module(). 03689 { 03690 char *queuename, *interface, *penalty_s, *paused_s; 03691 int paused, penalty = 0; 03692 03693 queuename = astman_get_header(m, "Queue"); 03694 interface = astman_get_header(m, "Interface"); 03695 penalty_s = astman_get_header(m, "Penalty"); 03696 paused_s = astman_get_header(m, "Paused"); 03697 03698 if (ast_strlen_zero(queuename)) { 03699 astman_send_error(s, m, "'Queue' not specified."); 03700 return 0; 03701 } 03702 03703 if (ast_strlen_zero(interface)) { 03704 astman_send_error(s, m, "'Interface' not specified."); 03705 return 0; 03706 } 03707 03708 if (ast_strlen_zero(penalty_s)) 03709 penalty = 0; 03710 else if (sscanf(penalty_s, "%d", &penalty) != 1) { 03711 penalty = 0; 03712 } 03713 03714 if (ast_strlen_zero(paused_s)) 03715 paused = 0; 03716 else 03717 paused = abs(ast_true(paused_s)); 03718 03719 switch (add_to_queue(queuename, interface, penalty, paused, queue_persistent_members)) { 03720 case RES_OKAY: 03721 astman_send_ack(s, m, "Added interface to queue"); 03722 break; 03723 case RES_EXISTS: 03724 astman_send_error(s, m, "Unable to add interface: Already there"); 03725 break; 03726 case RES_NOSUCHQUEUE: 03727 astman_send_error(s, m, "Unable to add interface to queue: No such queue"); 03728 break; 03729 case RES_OUTOFMEMORY: 03730 astman_send_error(s, m, "Out of memory"); 03731 break; 03732 } 03733 return 0; 03734 }
|
|
Definition at line 3765 of file app_queue.c. References ast_strlen_zero(), ast_true(), astman_get_header(), astman_send_ack(), astman_send_error(), member::interface, member::paused, s, and set_member_paused(). Referenced by load_module(). 03766 { 03767 char *queuename, *interface, *paused_s; 03768 int paused; 03769 03770 interface = astman_get_header(m, "Interface"); 03771 paused_s = astman_get_header(m, "Paused"); 03772 queuename = astman_get_header(m, "Queue"); /* Optional - if not supplied, pause the given Interface in all queues */ 03773 03774 if (ast_strlen_zero(interface) || ast_strlen_zero(paused_s)) { 03775 astman_send_error(s, m, "Need 'Interface' and 'Paused' parameters."); 03776 return 0; 03777 } 03778 03779 paused = abs(ast_true(paused_s)); 03780 03781 if (set_member_paused(queuename, interface, paused)) 03782 astman_send_error(s, m, "Interface not found"); 03783 else 03784 if (paused) 03785 astman_send_ack(s, m, "Interface paused successfully"); 03786 else 03787 astman_send_ack(s, m, "Interface unpaused successfully"); 03788 03789 return 0; 03790 }
|
|
Definition at line 3589 of file app_queue.c. References __queues_show(), ast_cli(), RESULT_SUCCESS, and s. Referenced by load_module(). 03590 { 03591 char *a[] = { "show", "queues" }; 03592 __queues_show(1, s->fd, 2, a, 0); 03593 ast_cli(s->fd, "\r\n\r\n"); /* Properly terminate Manager output */ 03594 03595 return RESULT_SUCCESS; 03596 }
|
|
Definition at line 3599 of file app_queue.c. References ast_cli(), ast_mutex_lock(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), member::calls, call_queue::callsabandoned, call_queue::callscompleted, call_queue::callscompletedinsl, call_queue::count, member::dynamic, call_queue::holdtime, member::interface, member::lastcall, call_queue::lock, call_queue::maxlen, call_queue::members, call_queue::name, member::next, call_queue::next, member::paused, member::penalty, queues, s, call_queue::servicelevel, member::status, and call_queue::weight. Referenced by load_module(). 03600 { 03601 time_t now; 03602 int pos; 03603 char *id = astman_get_header(m,"ActionID"); 03604 char *queuefilter = astman_get_header(m,"Queue"); 03605 char *memberfilter = astman_get_header(m,"Member"); 03606 char idText[256] = ""; 03607 struct call_queue *q; 03608 struct queue_ent *qe; 03609 float sl = 0; 03610 struct member *mem; 03611 03612 astman_send_ack(s, m, "Queue status will follow"); 03613 time(&now); 03614 ast_mutex_lock(&qlock); 03615 if (!ast_strlen_zero(id)) { 03616 snprintf(idText,256,"ActionID: %s\r\n",id); 03617 } 03618 for (q = queues; q; q = q->next) { 03619 ast_mutex_lock(&q->lock); 03620 03621 /* List queue properties */ 03622 if (ast_strlen_zero(queuefilter) || !strcmp(q->name, queuefilter)) { 03623 if(q->callscompleted > 0) 03624 sl = 100*((float)q->callscompletedinsl/(float)q->callscompleted); 03625 ast_cli(s->fd, "Event: QueueParams\r\n" 03626 "Queue: %s\r\n" 03627 "Max: %d\r\n" 03628 "Calls: %d\r\n" 03629 "Holdtime: %d\r\n" 03630 "Completed: %d\r\n" 03631 "Abandoned: %d\r\n" 03632 "ServiceLevel: %d\r\n" 03633 "ServicelevelPerf: %2.1f\r\n" 03634 "Weight: %d\r\n" 03635 "%s" 03636 "\r\n", 03637 q->name, q->maxlen, q->count, q->holdtime, q->callscompleted, 03638 q->callsabandoned, q->servicelevel, sl, q->weight, idText); 03639 /* List Queue Members */ 03640 for (mem = q->members; mem; mem = mem->next) { 03641 if (ast_strlen_zero(memberfilter) || !strcmp(mem->interface, memberfilter)) { 03642 ast_cli(s->fd, "Event: QueueMember\r\n" 03643 "Queue: %s\r\n" 03644 "Location: %s\r\n" 03645 "Membership: %s\r\n" 03646 "Penalty: %d\r\n" 03647 "CallsTaken: %d\r\n" 03648 "LastCall: %d\r\n" 03649 "Status: %d\r\n" 03650 "Paused: %d\r\n" 03651 "%s" 03652 "\r\n", 03653 q->name, mem->interface, mem->dynamic ? "dynamic" : "static", 03654 mem->penalty, mem->calls, (int)mem->lastcall, mem->status, mem->paused, idText); 03655 } 03656 } 03657 /* List Queue Entries */ 03658 pos = 1; 03659 for (qe = q->head; qe; qe = qe->next) { 03660 ast_cli(s->fd, "Event: QueueEntry\r\n" 03661 "Queue: %s\r\n" 03662 "Position: %d\r\n" 03663 "Channel: %s\r\n" 03664 "CallerID: %s\r\n" 03665 "CallerIDName: %s\r\n" 03666 "Wait: %ld\r\n" 03667 "%s" 03668 "\r\n", 03669 q->name, pos++, qe->chan->name, 03670 qe->chan->cid.cid_num ? qe->chan->cid.cid_num : "unknown", 03671 qe->chan->cid.cid_name ? qe->chan->cid.cid_name : "unknown", 03672 (long)(now - qe->start), idText); 03673 } 03674 } 03675 ast_mutex_unlock(&q->lock); 03676 } 03677 03678 ast_cli(s->fd, 03679 "Event: QueueStatusComplete\r\n" 03680 "%s" 03681 "\r\n",idText); 03682 03683 ast_mutex_unlock(&qlock); 03684 03685 return RESULT_SUCCESS; 03686 }
|
|
Definition at line 3736 of file app_queue.c. References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), member::interface, remove_from_queue(), RES_EXISTS, RES_NOSUCHQUEUE, RES_OKAY, RES_OUTOFMEMORY, and s. Referenced by load_module(). 03737 { 03738 char *queuename, *interface; 03739 03740 queuename = astman_get_header(m, "Queue"); 03741 interface = astman_get_header(m, "Interface"); 03742 03743 if (ast_strlen_zero(queuename) || ast_strlen_zero(interface)) { 03744 astman_send_error(s, m, "Need 'Queue' and 'Interface' parameters."); 03745 return 0; 03746 } 03747 03748 switch (remove_from_queue(queuename, interface)) { 03749 case RES_OKAY: 03750 astman_send_ack(s, m, "Removed interface from queue"); 03751 break; 03752 case RES_EXISTS: 03753 astman_send_error(s, m, "Unable to remove interface: Not there"); 03754 break; 03755 case RES_NOSUCHQUEUE: 03756 astman_send_error(s, m, "Unable to remove interface from queue: No such queue"); 03757 break; 03758 case RES_OUTOFMEMORY: 03759 astman_send_error(s, m, "Out of memory"); 03760 break; 03761 } 03762 return 0; 03763 }
|
|
Definition at line 1177 of file app_queue.c. References AST_DIGIT_ANY, ast_stopstream(), ast_streamfile(), ast_waitstream(), queue_ent::chan, and ast_channel::language. Referenced by say_position(). 01178 { 01179 int res; 01180 01181 ast_stopstream(chan); 01182 res = ast_streamfile(chan, filename, chan->language); 01183 01184 if (!res) 01185 res = ast_waitstream(chan, AST_DIGIT_ANY); 01186 else 01187 res = 0; 01188 01189 ast_stopstream(chan); 01190 01191 return res; 01192 }
|
|
Definition at line 2752 of file app_queue.c. References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_goto_if_exists(), ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), localuser::chan, ast_channel::context, localuser::interface, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_WARNING, option_priority_jumping, parse(), pbx_builtin_setvar_helper(), and set_member_paused(). Referenced by load_module(). 02753 { 02754 struct localuser *u; 02755 char *parse; 02756 int priority_jump = 0; 02757 AST_DECLARE_APP_ARGS(args, 02758 AST_APP_ARG(queuename); 02759 AST_APP_ARG(interface); 02760 AST_APP_ARG(options); 02761 ); 02762 02763 if (ast_strlen_zero(data)) { 02764 ast_log(LOG_WARNING, "PauseQueueMember requires an argument ([queuename]|interface[|options])\n"); 02765 return -1; 02766 } 02767 02768 LOCAL_USER_ADD(u); 02769 02770 if (!(parse = ast_strdupa(data))) { 02771 ast_log(LOG_WARNING, "Memory Error!\n"); 02772 LOCAL_USER_REMOVE(u); 02773 return -1; 02774 } 02775 02776 AST_STANDARD_APP_ARGS(args, parse); 02777 02778 if (args.options) { 02779 if (strchr(args.options, 'j')) 02780 priority_jump = 1; 02781 } 02782 02783 if (ast_strlen_zero(args.interface)) { 02784 ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename]|interface[|options])\n"); 02785 LOCAL_USER_REMOVE(u); 02786 return -1; 02787 } 02788 02789 if (set_member_paused(args.queuename, args.interface, 1)) { 02790 ast_log(LOG_WARNING, "Attempt to pause interface %s, not found\n", args.interface); 02791 if (priority_jump || option_priority_jumping) { 02792 if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) { 02793 pbx_builtin_setvar_helper(chan, "PQMSTATUS", "NOTFOUND"); 02794 LOCAL_USER_REMOVE(u); 02795 return 0; 02796 } 02797 } 02798 LOCAL_USER_REMOVE(u); 02799 pbx_builtin_setvar_helper(chan, "PQMSTATUS", "NOTFOUND"); 02800 return -1; 02801 } 02802 02803 LOCAL_USER_REMOVE(u); 02804 pbx_builtin_setvar_helper(chan, "PQMSTATUS", "PAUSED"); 02805 return 0; 02806 }
|
|
Definition at line 3007 of file app_queue.c. References AST_CONTROL_RINGING, ast_indicate(), ast_log(), ast_moh_start(), ast_queue_log(), ast_strlen_zero(), ast_verbose(), queue_ent::chan, ast_channel::cid, ast_callerid::cid_num, join_queue(), LOCAL_USER_ADD, LOG_DEBUG, LOG_WARNING, ast_channel::name, option_debug, option_verbose, pbx_builtin_getvar_helper(), QUEUE_UNKNOWN, record_abandoned(), strsep(), ast_channel::uniqueid, valid_exit(), VERBOSE_PREFIX_3, and wait_our_turn(). Referenced by load_module(). 03008 { 03009 int res=-1; 03010 int ringing=0; 03011 struct localuser *u; 03012 char *queuename; 03013 char info[512]; 03014 char *info_ptr = info; 03015 char *options = NULL; 03016 char *url = NULL; 03017 char *announceoverride = NULL; 03018 char *user_priority; 03019 int prio; 03020 char *queuetimeoutstr = NULL; 03021 enum queue_result reason = QUEUE_UNKNOWN; 03022 03023 /* whether to exit Queue application after the timeout hits */ 03024 int go_on = 0; 03025 03026 /* Our queue entry */ 03027 struct queue_ent qe; 03028 03029 if (ast_strlen_zero(data)) { 03030 ast_log(LOG_WARNING, "Queue requires an argument: queuename[|options[|URL][|announceoverride][|timeout]]\n"); 03031 return -1; 03032 } 03033 03034 LOCAL_USER_ADD(u); 03035 03036 /* Setup our queue entry */ 03037 memset(&qe, 0, sizeof(qe)); 03038 qe.start = time(NULL); 03039 03040 /* Parse our arguments XXX Check for failure XXX */ 03041 ast_copy_string(info, (char *) data, sizeof(info)); 03042 queuename = strsep(&info_ptr, "|"); 03043 options = strsep(&info_ptr, "|"); 03044 url = strsep(&info_ptr, "|"); 03045 announceoverride = strsep(&info_ptr, "|"); 03046 queuetimeoutstr = info_ptr; 03047 03048 /* set the expire time based on the supplied timeout; */ 03049 if (!ast_strlen_zero(queuetimeoutstr)) 03050 qe.expire = qe.start + atoi(queuetimeoutstr); 03051 else 03052 qe.expire = 0; 03053 03054 /* Get the priority from the variable ${QUEUE_PRIO} */ 03055 user_priority = pbx_builtin_getvar_helper(chan, "QUEUE_PRIO"); 03056 if (user_priority) { 03057 if (sscanf(user_priority, "%d", &prio) == 1) { 03058 if (option_debug) 03059 ast_log(LOG_DEBUG, "%s: Got priority %d from ${QUEUE_PRIO}.\n", 03060 chan->name, prio); 03061 } else { 03062 ast_log(LOG_WARNING, "${QUEUE_PRIO}: Invalid value (%s), channel %s.\n", 03063 user_priority, chan->name); 03064 prio = 0; 03065 } 03066 } else { 03067 if (option_debug > 2) 03068 ast_log(LOG_DEBUG, "NO QUEUE_PRIO variable found. Using default.\n"); 03069 prio = 0; 03070 } 03071 03072 if (options && (strchr(options, 'r'))) 03073 ringing = 1; 03074 03075 if (option_debug) 03076 ast_log(LOG_DEBUG, "queue: %s, options: %s, url: %s, announce: %s, expires: %ld, priority: %d\n", 03077 queuename, options, url, announceoverride, (long)qe.expire, (int)prio); 03078 03079 qe.chan = chan; 03080 qe.prio = (int)prio; 03081 qe.last_pos_said = 0; 03082 qe.last_pos = 0; 03083 qe.last_periodic_announce_time = time(NULL); 03084 if (!join_queue(queuename, &qe, &reason)) { 03085 ast_queue_log(queuename, chan->uniqueid, "NONE", "ENTERQUEUE", "%s|%s", url ? url : "", 03086 chan->cid.cid_num ? chan->cid.cid_num : ""); 03087 check_turns: 03088 if (ringing) { 03089 ast_indicate(chan, AST_CONTROL_RINGING); 03090 } else { 03091 ast_moh_start(chan, qe.moh); 03092 } 03093 for (;;) { 03094 /* This is the wait loop for callers 2 through maxlen */ 03095 03096 res = wait_our_turn(&qe, ringing, &reason); 03097 /* If they hungup, return immediately */ 03098 if (res < 0) { 03099 /* Record this abandoned call */ 03100 record_abandoned(&qe); 03101 ast_queue_log(queuename, chan->uniqueid, "NONE", "ABANDON", "%d|%d|%ld", qe.pos, qe.opos, (long)time(NULL) - qe.start); 03102 if (option_verbose > 2) { 03103 ast_verbose(VERBOSE_PREFIX_3 "User disconnected from queue %s while waiting their turn\n", queuename); 03104 } 03105 res = -1; 03106 break; 03107 } 03108 if (!res) 03109 break; 03110 if (valid_exit(&qe, res)) { 03111 ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%s|%d", qe.digits, qe.pos); 03112 break; 03113 } 03114 } 03115 if (!res) { 03116 int makeannouncement = 0; 03117 for (;;) { 03118 /* This is the wait loop for the head caller*/ 03119 /* To exit, they may get their call answered; */ 03120 /* they may dial a digit from the queue context; */ 03121 /* or, they may timeout. */ 03122 03123 enum queue_member_status stat; 03124 03125 /* Leave if we have exceeded our queuetimeout */ 03126 if (qe.expire && (time(NULL) > qe.expire)) { 03127 record_abandoned(&qe); 03128 reason = QUEUE_TIMEOUT; 03129 res = 0; 03130 ast_queue_log(queuename, chan->uniqueid,"NONE", "EXITWITHTIMEOUT", "%d", qe.pos); 03131 break; 03132 } 03133 03134 if (makeannouncement) { 03135 /* Make a position announcement, if enabled */ 03136 if (qe.parent->announcefrequency && !ringing && 03137 (res = say_position(&qe))) { 03138 ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%s|%d", qe.digits, qe.pos); 03139 break; 03140 } 03141 03142 } 03143 makeannouncement = 1; 03144 03145 /* Make a periodic announcement, if enabled */ 03146 if (qe.parent->periodicannouncefrequency && !ringing && 03147 (res = say_periodic_announcement(&qe))) { 03148 ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%c|%d", res, qe.pos); 03149 break; 03150 } 03151 03152 /* Try calling all queue members for 'timeout' seconds */ 03153 res = try_calling(&qe, options, announceoverride, url, &go_on); 03154 if (res) { 03155 if (res < 0) { 03156 if (!qe.handled) { 03157 record_abandoned(&qe); 03158 ast_queue_log(queuename, chan->uniqueid, "NONE", "ABANDON", "%d|%d|%ld", qe.pos, qe.opos, (long)time(NULL) - qe.start); 03159 } 03160 } else if (valid_exit(&qe, res)) { 03161 ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%s|%d", qe.digits, qe.pos); 03162 } 03163 break; 03164 } 03165 03166 stat = get_member_status(qe.parent); 03167 03168 /* leave the queue if no agents, if enabled */ 03169 if (qe.parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) { 03170 record_abandoned(&qe); 03171 reason = QUEUE_LEAVEEMPTY; 03172 res = 0; 03173 break; 03174 } 03175 03176 /* leave the queue if no reachable agents, if enabled */ 03177 if ((qe.parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) { 03178 record_abandoned(&qe); 03179 reason = QUEUE_LEAVEUNAVAIL; 03180 res = 0; 03181 break; 03182 } 03183 03184 /* Leave if we have exceeded our queuetimeout */ 03185 if (qe.expire && (time(NULL) > qe.expire)) { 03186 record_abandoned(&qe); 03187 reason = QUEUE_TIMEOUT; 03188 res = 0; 03189 ast_queue_log(queuename, chan->uniqueid,"NONE", "EXITWITHTIMEOUT", "%d", qe.pos); 03190 break; 03191 } 03192 03193 /* OK, we didn't get anybody; wait for 'retry' seconds; may get a digit to exit with */ 03194 res = wait_a_bit(&qe); 03195 if (res < 0) { 03196 record_abandoned(&qe); 03197 ast_queue_log(queuename, chan->uniqueid, "NONE", "ABANDON", "%d|%d|%ld", qe.pos, qe.opos, (long)time(NULL) - qe.start); 03198 if (option_verbose > 2) { 03199 ast_verbose(VERBOSE_PREFIX_3 "User disconnected from queue %s when they almost made it\n", queuename); 03200 } 03201 res = -1; 03202 break; 03203 } 03204 if (res && valid_exit(&qe, res)) { 03205 ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%s|%d", qe.digits, qe.pos); 03206 break; 03207 } 03208 /* exit after 'timeout' cycle if 'n' option enabled */ 03209 if (go_on) { 03210 if (option_verbose > 2) 03211 ast_verbose(VERBOSE_PREFIX_3 "Exiting on time-out cycle\n"); 03212 ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHTIMEOUT", "%d", qe.pos); 03213 record_abandoned(&qe); 03214 reason = QUEUE_TIMEOUT; 03215 res = 0; 03216 break; 03217 } 03218 /* Since this is a priority queue and 03219 * it is not sure that we are still at the head 03220 * of the queue, go and check for our turn again. 03221 */ 03222 if (!is_our_turn(&qe)) { 03223 if (option_debug) 03224 ast_log(LOG_DEBUG, "Darn priorities, going back in queue (%s)!\n", 03225 qe.chan->name); 03226 goto check_turns; 03227 } 03228 } 03229 } 03230 /* Don't allow return code > 0 */ 03231 if (res >= 0 && res != AST_PBX_KEEPALIVE) { 03232 res = 0; 03233 if (ringing) { 03234 ast_indicate(chan, -1); 03235 } else { 03236 ast_moh_stop(chan); 03237 } 03238 ast_stopstream(chan); 03239 } 03240 leave_queue(&qe); 03241 if (reason != QUEUE_UNKNOWN) 03242 set_queue_result(chan, reason); 03243 } else { 03244 ast_log(LOG_WARNING, "Unable to join queue '%s'\n", queuename); 03245 set_queue_result(chan, reason); 03246 res = 0; 03247 } 03248 LOCAL_USER_REMOVE(u); 03249 return res; 03250 }
|
|
Definition at line 3252 of file app_queue.c. References ast_log(), ast_mutex_lock(), ast_strlen_zero(), LOCAL_USER_ACF_ADD, LOCAL_USER_REMOVE, call_queue::lock, LOG_ERROR, call_queue::name, call_queue::next, and queues. 03253 { 03254 int count = 0; 03255 struct call_queue *q; 03256 struct localuser *u; 03257 struct member *m; 03258 03259 LOCAL_USER_ACF_ADD(u); 03260 03261 ast_copy_string(buf, "0", len); 03262 03263 if (ast_strlen_zero(data)) { 03264 ast_log(LOG_ERROR, "QUEUEAGENTCOUNT requires an argument: queuename\n"); 03265 LOCAL_USER_REMOVE(u); 03266 return buf; 03267 } 03268 03269 ast_mutex_lock(&qlock); 03270 03271 /* Find the right queue */ 03272 for (q = queues; q; q = q->next) { 03273 if (!strcasecmp(q->name, data)) { 03274 ast_mutex_lock(&q->lock); 03275 break; 03276 } 03277 } 03278 03279 ast_mutex_unlock(&qlock); 03280 03281 if (q) { 03282 for (m = q->members; m; m = m->next) { 03283 /* Count the agents who are logged in and presently answering calls */ 03284 if ((m->status != AST_DEVICE_UNAVAILABLE) && (m->status != AST_DEVICE_INVALID)) { 03285 count++; 03286 } 03287 } 03288 ast_mutex_unlock(&q->lock); 03289 } 03290 03291 snprintf(buf, len, "%d", count); 03292 LOCAL_USER_REMOVE(u); 03293 return buf; 03294 }
|
|
Configure a queue parameter.
Definition at line 735 of file app_queue.c. References call_queue::announce, call_queue::announcefrequency, call_queue::announceholdtime, ANNOUNCEHOLDTIME_ALWAYS, ANNOUNCEHOLDTIME_ONCE, ast_log(), ast_true(), call_queue::context, DEFAULT_RETRY, DEFAULT_TIMEOUT, call_queue::eventwhencalled, call_queue::joinempty, call_queue::leavewhenempty, LOG_WARNING, call_queue::maskmemberstatus, call_queue::maxlen, call_queue::memberdelay, call_queue::moh, call_queue::monfmt, call_queue::monjoin, call_queue::name, call_queue::periodicannouncefrequency, QUEUE_EMPTY_NORMAL, QUEUE_EMPTY_STRICT, call_queue::reportholdtime, call_queue::retry, call_queue::roundingseconds, call_queue::servicelevel, call_queue::sound_calls, call_queue::sound_holdtime, call_queue::sound_lessthan, call_queue::sound_minutes, call_queue::sound_next, call_queue::sound_periodicannounce, call_queue::sound_reporthold, call_queue::sound_seconds, call_queue::sound_thanks, call_queue::sound_thereare, strat2int(), call_queue::strategy, call_queue::timeout, call_queue::timeoutrestart, use_weight, call_queue::weight, and call_queue::wrapuptime. Referenced by reload_queues(). 00736 { 00737 if (!strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) { 00738 ast_copy_string(q->moh, val, sizeof(q->moh)); 00739 } else if (!strcasecmp(param, "announce")) { 00740 ast_copy_string(q->announce, val, sizeof(q->announce)); 00741 } else if (!strcasecmp(param, "context")) { 00742 ast_copy_string(q->context, val, sizeof(q->context)); 00743 } else if (!strcasecmp(param, "timeout")) { 00744 q->timeout = atoi(val); 00745 if (q->timeout < 0) 00746 q->timeout = DEFAULT_TIMEOUT; 00747 } else if (!strcasecmp(param, "monitor-join")) { 00748 q->monjoin = ast_true(val); 00749 } else if (!strcasecmp(param, "monitor-format")) { 00750 ast_copy_string(q->monfmt, val, sizeof(q->monfmt)); 00751 } else if (!strcasecmp(param, "queue-youarenext")) { 00752 ast_copy_string(q->sound_next, val, sizeof(q->sound_next)); 00753 } else if (!strcasecmp(param, "queue-thereare")) { 00754 ast_copy_string(q->sound_thereare, val, sizeof(q->sound_thereare)); 00755 } else if (!strcasecmp(param, "queue-callswaiting")) { 00756 ast_copy_string(q->sound_calls, val, sizeof(q->sound_calls)); 00757 } else if (!strcasecmp(param, "queue-holdtime")) { 00758 ast_copy_string(q->sound_holdtime, val, sizeof(q->sound_holdtime)); 00759 } else if (!strcasecmp(param, "queue-minutes")) { 00760 ast_copy_string(q->sound_minutes, val, sizeof(q->sound_minutes)); 00761 } else if (!strcasecmp(param, "queue-seconds")) { 00762 ast_copy_string(q->sound_seconds, val, sizeof(q->sound_seconds)); 00763 } else if (!strcasecmp(param, "queue-lessthan")) { 00764 ast_copy_string(q->sound_lessthan, val, sizeof(q->sound_lessthan)); 00765 } else if (!strcasecmp(param, "queue-thankyou")) { 00766 ast_copy_string(q->sound_thanks, val, sizeof(q->sound_thanks)); 00767 } else if (!strcasecmp(param, "queue-reporthold")) { 00768 ast_copy_string(q->sound_reporthold, val, sizeof(q->sound_reporthold)); 00769 } else if (!strcasecmp(param, "announce-frequency")) { 00770 q->announcefrequency = atoi(val); 00771 } else if (!strcasecmp(param, "announce-round-seconds")) { 00772 q->roundingseconds = atoi(val); 00773 if (q->roundingseconds>60 || q->roundingseconds<0) { 00774 if (linenum >= 0) { 00775 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s " 00776 "using 0 instead for queue '%s' at line %d of queues.conf\n", 00777 val, param, q->name, linenum); 00778 } else { 00779 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s " 00780 "using 0 instead for queue '%s'\n", val, param, q->name); 00781 } 00782 q->roundingseconds=0; 00783 } 00784 } else if (!strcasecmp(param, "announce-holdtime")) { 00785 if (!strcasecmp(val, "once")) 00786 q->announceholdtime = ANNOUNCEHOLDTIME_ONCE; 00787 else if (ast_true(val)) 00788 q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS; 00789 else 00790 q->announceholdtime = 0; 00791 } else if (!strcasecmp(param, "periodic-announce")) { 00792 ast_copy_string(q->sound_periodicannounce, val, sizeof(q->sound_periodicannounce)); 00793 } else if (!strcasecmp(param, "periodic-announce-frequency")) { 00794 q->periodicannouncefrequency = atoi(val); 00795 } else if (!strcasecmp(param, "retry")) { 00796 q->retry = atoi(val); 00797 if (q->retry <= 0) 00798 q->retry = DEFAULT_RETRY; 00799 } else if (!strcasecmp(param, "wrapuptime")) { 00800 q->wrapuptime = atoi(val); 00801 } else if (!strcasecmp(param, "maxlen")) { 00802 q->maxlen = atoi(val); 00803 if (q->maxlen < 0) 00804 q->maxlen = 0; 00805 } else if (!strcasecmp(param, "servicelevel")) { 00806 q->servicelevel= atoi(val); 00807 } else if (!strcasecmp(param, "strategy")) { 00808 q->strategy = strat2int(val); 00809 if (q->strategy < 0) { 00810 ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n", 00811 val, q->name); 00812 q->strategy = 0; 00813 } 00814 } else if (!strcasecmp(param, "joinempty")) { 00815 if (!strcasecmp(val, "strict")) 00816 q->joinempty = QUEUE_EMPTY_STRICT; 00817 else if (ast_true(val)) 00818 q->joinempty = QUEUE_EMPTY_NORMAL; 00819 else 00820 q->joinempty = 0; 00821 } else if (!strcasecmp(param, "leavewhenempty")) { 00822 if (!strcasecmp(val, "strict")) 00823 q->leavewhenempty = QUEUE_EMPTY_STRICT; 00824 else if (ast_true(val)) 00825 q->leavewhenempty = QUEUE_EMPTY_NORMAL; 00826 else 00827 q->leavewhenempty = 0; 00828 } else if (!strcasecmp(param, "eventmemberstatus")) { 00829 q->maskmemberstatus = !ast_true(val); 00830 } else if (!strcasecmp(param, "eventwhencalled")) { 00831 q->eventwhencalled = ast_true(val); 00832 } else if (!strcasecmp(param, "reportholdtime")) { 00833 q->reportholdtime = ast_true(val); 00834 } else if (!strcasecmp(param, "memberdelay")) { 00835 q->memberdelay = atoi(val); 00836 } else if (!strcasecmp(param, "weight")) { 00837 q->weight = atoi(val); 00838 if (q->weight) 00839 use_weight++; 00840 /* With Realtime queues, if the last queue using weights is deleted in realtime, 00841 we will not see any effect on use_weight until next reload. */ 00842 } else if (!strcasecmp(param, "timeoutrestart")) { 00843 q->timeoutrestart = ast_true(val); 00844 } else if(failunknown) { 00845 if (linenum >= 0) { 00846 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n", 00847 q->name, param, linenum); 00848 } else { 00849 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s\n", q->name, param); 00850 } 00851 } 00852 }
|
|
Definition at line 3565 of file app_queue.c. References __queues_show(). 03566 { 03567 return __queues_show(0, fd, argc, argv, 1); 03568 }
|
|
Definition at line 3560 of file app_queue.c. References __queues_show(). 03561 { 03562 return __queues_show(0, fd, argc, argv, 0); 03563 }
|
|
Definition at line 1331 of file app_queue.c. References ast_mutex_lock(), ast_mutex_unlock(), call_queue::callscompletedinsl, call_queue::holdtime, call_queue::lock, queue_ent::parent, call_queue::servicelevel, and queue_ent::start. 01332 { 01333 int oldvalue, newvalue; 01334 01335 /* Calculate holdtime using a recursive boxcar filter */ 01336 /* Thanks to SRT for this contribution */ 01337 /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */ 01338 01339 newvalue = time(NULL) - qe->start; 01340 01341 ast_mutex_lock(&qe->parent->lock); 01342 if (newvalue <= qe->parent->servicelevel) 01343 qe->parent->callscompletedinsl++; 01344 oldvalue = qe->parent->holdtime; 01345 qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newvalue) >> 2; 01346 ast_mutex_unlock(&qe->parent->lock); 01347 }
|
|
Definition at line 1747 of file app_queue.c. References ast_mutex_lock(), ast_mutex_unlock(), call_queue::callsabandoned, call_queue::lock, and queue_ent::parent. Referenced by queue_exec(). 01748 { 01749 ast_mutex_lock(&qe->parent->lock); 01750 qe->parent->callsabandoned++; 01751 ast_mutex_unlock(&qe->parent->lock); 01752 }
|
|
Reload stuff. This function is where any reload routines take place. Re-read config files, change signalling, whatever is appropriate on a reload.
Definition at line 4033 of file app_queue.c. References reload_queues(). 04034 { 04035 reload_queues(); 04036 return 0; 04037 }
|
|
Definition at line 2663 of file app_queue.c. References ast_db_gettree(), ast_mutex_lock(), ast_mutex_unlock(), member::interface, ast_db_entry::key, call_queue::lock, call_queue::name, call_queue::next, ast_db_entry::next, member::paused, member::penalty, pm_family, PM_MAX_LEN, and queues. Referenced by load_module(). 02664 { 02665 char *cur_ptr; 02666 char *queue_name; 02667 char *member; 02668 char *interface; 02669 char *penalty_tok; 02670 int penalty = 0; 02671 char *paused_tok; 02672 int paused = 0; 02673 struct ast_db_entry *db_tree; 02674 struct ast_db_entry *entry; 02675 struct call_queue *cur_queue; 02676 char queue_data[PM_MAX_LEN]; 02677 02678 ast_mutex_lock(&qlock); 02679 02680 /* Each key in 'pm_family' is the name of a queue */ 02681 db_tree = ast_db_gettree(pm_family, NULL); 02682 for (entry = db_tree; entry; entry = entry->next) { 02683 02684 queue_name = entry->key + strlen(pm_family) + 2; 02685 02686 cur_queue = queues; 02687 while (cur_queue) { 02688 ast_mutex_lock(&cur_queue->lock); 02689 if (!strcmp(queue_name, cur_queue->name)) 02690 break; 02691 ast_mutex_unlock(&cur_queue->lock); 02692 cur_queue = cur_queue->next; 02693 } 02694 02695 if (!cur_queue) { 02696 /* If the queue no longer exists, remove it from the 02697 * database */ 02698 ast_db_del(pm_family, queue_name); 02699 continue; 02700 } else 02701 ast_mutex_unlock(&cur_queue->lock); 02702 02703 if (ast_db_get(pm_family, queue_name, queue_data, PM_MAX_LEN)) 02704 continue; 02705 02706 cur_ptr = queue_data; 02707 while ((member = strsep(&cur_ptr, "|"))) { 02708 if (ast_strlen_zero(member)) 02709 continue; 02710 02711 interface = strsep(&member, ";"); 02712 penalty_tok = strsep(&member, ";"); 02713 paused_tok = strsep(&member, ";"); 02714 02715 if (!penalty_tok) { 02716 ast_log(LOG_WARNING, "Error parsing persisent member string for '%s' (penalty)\n", queue_name); 02717 break; 02718 } 02719 penalty = strtol(penalty_tok, NULL, 10); 02720 if (errno == ERANGE) { 02721 ast_log(LOG_WARNING, "Error converting penalty: %s: Out of range.\n", penalty_tok); 02722 break; 02723 } 02724 02725 if (!paused_tok) { 02726 ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (paused)\n", queue_name); 02727 break; 02728 } 02729 paused = strtol(paused_tok, NULL, 10); 02730 if ((errno == ERANGE) || paused < 0 || paused > 1) { 02731 ast_log(LOG_WARNING, "Error converting paused: %s: Expected 0 or 1.\n", paused_tok); 02732 break; 02733 } 02734 02735 if (option_debug) 02736 ast_log(LOG_DEBUG, "Reload Members: Queue: %s Member: %s Penalty: %d Paused: %d\n", queue_name, interface, penalty, paused); 02737 02738 if (add_to_queue(queue_name, interface, penalty, paused, 0) == RES_OUTOFMEMORY) { 02739 ast_log(LOG_ERROR, "Out of Memory when reloading persistent queue member\n"); 02740 break; 02741 } 02742 } 02743 } 02744 02745 ast_mutex_unlock(&qlock); 02746 if (db_tree) { 02747 ast_log(LOG_NOTICE, "Queue members sucessfully reloaded from database.\n"); 02748 ast_db_freetree(db_tree); 02749 } 02750 }
|
|
Definition at line 3303 of file app_queue.c. References add_to_interfaces(), alloc_queue(), ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_device_state(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), cfg, clear_queue(), call_queue::count, create_queue_member(), call_queue::dead, member::delme, destroy_queue(), member::dynamic, free, init_queue(), member::interface, call_queue::lock, LOG_NOTICE, LOG_WARNING, call_queue::members, call_queue::name, call_queue::next, member::next, member::paused, member::penalty, queue_persistent_members, queue_set_param(), queues, remove_from_interfaces(), member::status, and var. Referenced by load_module(), and reload(). 03304 { 03305 struct call_queue *q, *ql, *qn; 03306 struct ast_config *cfg; 03307 char *cat, *tmp; 03308 struct ast_variable *var; 03309 struct member *prev, *cur, *newm, *next; 03310 int new; 03311 char *general_val = NULL; 03312 char interface[80]; 03313 int penalty; 03314 03315 cfg = ast_config_load("queues.conf"); 03316 if (!cfg) { 03317 ast_log(LOG_NOTICE, "No call queueing config file (queues.conf), so no call queues\n"); 03318 return; 03319 } 03320 memset(interface, 0, sizeof(interface)); 03321 ast_mutex_lock(&qlock); 03322 use_weight=0; 03323 /* Mark all queues as dead for the moment */ 03324 q = queues; 03325 while(q) { 03326 q->dead = 1; 03327 q = q->next; 03328 } 03329 /* Chug through config file */ 03330 cat = ast_category_browse(cfg, NULL); 03331 while(cat) { 03332 if (!strcasecmp(cat, "general")) { 03333 /* Initialize global settings */ 03334 queue_persistent_members = 0; 03335 if ((general_val = ast_variable_retrieve(cfg, "general", "persistentmembers"))) 03336 queue_persistent_members = ast_true(general_val); 03337 } else { /* Define queue */ 03338 /* Look for an existing one */ 03339 q = queues; 03340 while(q) { 03341 if (!strcmp(q->name, cat)) 03342 break; 03343 q = q->next; 03344 } 03345 if (!q) { 03346 /* Make one then */ 03347 q = alloc_queue(cat); 03348 new = 1; 03349 } else 03350 new = 0; 03351 if (q) { 03352 if (!new) 03353 ast_mutex_lock(&q->lock); 03354 /* Re-initialize the queue, and clear statistics */ 03355 init_queue(q); 03356 clear_queue(q); 03357 for (cur = q->members; cur; cur = cur->next) { 03358 if (!cur->dynamic) { 03359 cur->delme = 1; 03360 } 03361 } 03362 var = ast_variable_browse(cfg, cat); 03363 while (var) { 03364 if (!strcasecmp(var->name, "member")) { 03365 /* Add a new member */ 03366 ast_copy_string(interface, var->value, sizeof(interface)); 03367 if ((tmp = strchr(interface, ','))) { 03368 *tmp = '\0'; 03369 tmp++; 03370 penalty = atoi(tmp); 03371 if (penalty < 0) { 03372 penalty = 0; 03373 } 03374 } else 03375 penalty = 0; 03376 03377 /* Find the old position in the list */ 03378 for (prev = NULL, cur = q->members; cur; prev = cur, cur = cur->next) { 03379 if (!strcmp(cur->interface, interface)) { 03380 break; 03381 } 03382 } 03383 03384 newm = create_queue_member(interface, penalty, cur ? cur->paused : 0); 03385 03386 if (cur) { 03387 /* Delete it now */ 03388 newm->next = cur->next; 03389 if (prev) { 03390 prev->next = newm; 03391 } else { 03392 q->members = newm; 03393 } 03394 free(cur); 03395 } else { 03396 /* Add them to the master int list if necessary */ 03397 add_to_interfaces(interface); 03398 newm->next = q->members; 03399 q->members = newm; 03400 } 03401 } else { 03402 queue_set_param(q, var->name, var->value, var->lineno, 1); 03403 } 03404 var = var->next; 03405 } 03406 03407 /* Free remaining members marked as delme */ 03408 for (prev = NULL, cur = q->members; 03409 cur; 03410 cur = next) { 03411 next = cur->next; 03412 03413 if (!cur->delme) { 03414 prev = cur; 03415 continue; 03416 } 03417 03418 if (prev) 03419 prev->next = next; 03420 else 03421 q->members = next; 03422 03423 remove_from_interfaces(cur->interface); 03424 free(cur); 03425 } 03426 03427 if (!new) 03428 ast_mutex_unlock(&q->lock); 03429 if (new) { 03430 q->next = queues; 03431 queues = q; 03432 } 03433 } 03434 } 03435 cat = ast_category_browse(cfg, cat); 03436 } 03437 ast_config_destroy(cfg); 03438 q = queues; 03439 ql = NULL; 03440 while(q) { 03441 qn = q->next; 03442 if (q->dead) { 03443 if (ql) 03444 ql->next = q->next; 03445 else 03446 queues = q->next; 03447 if (!q->count) { 03448 destroy_queue(q); 03449 } else 03450 ast_log(LOG_WARNING, "XXX Leaking a little memory :( XXX\n"); 03451 } else { 03452 ast_mutex_lock(&q->lock); 03453 for (cur = q->members; cur; cur = cur->next) 03454 cur->status = ast_device_state(cur->interface); 03455 ql = q; 03456 ast_mutex_unlock(&q->lock); 03457 } 03458 q = qn; 03459 } 03460 ast_mutex_unlock(&qlock); 03461 }
|
|
Definition at line 693 of file app_queue.c. References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), free, member_interface::interface, interface_exists_global(), list, LOG_DEBUG, and option_debug. Referenced by free_members(), and reload_queues(). 00694 { 00695 struct member_interface *curint; 00696 00697 if (!interface) 00698 return 0; 00699 00700 AST_LIST_LOCK(&interfaces); 00701 AST_LIST_TRAVERSE_SAFE_BEGIN(&interfaces, curint, list) { 00702 if (!strcasecmp(curint->interface, interface)) { 00703 if (!interface_exists_global(interface)) { 00704 if (option_debug) 00705 ast_log(LOG_DEBUG, "Removing %s from the list of interfaces that make up all of our queue members.\n", interface); 00706 AST_LIST_REMOVE_CURRENT(&interfaces, list); 00707 free(curint); 00708 } 00709 break; 00710 } 00711 } 00712 AST_LIST_TRAVERSE_SAFE_END; 00713 AST_LIST_UNLOCK(&interfaces); 00714 00715 return 0; 00716 }
|
|
Definition at line 2520 of file app_queue.c. References ast_mutex_lock(), interface_exists(), call_queue::lock, call_queue::members, call_queue::name, member::next, call_queue::next, queues, and RES_NOSUCHQUEUE. Referenced by handle_remove_queue_member(), manager_remove_queue_member(), and rqm_exec(). 02521 { 02522 struct call_queue *q; 02523 struct member *last_member, *look; 02524 int res = RES_NOSUCHQUEUE; 02525 02526 ast_mutex_lock(&qlock); 02527 for (q = queues ; q ; q = q->next) { 02528 ast_mutex_lock(&q->lock); 02529 if (!strcmp(q->name, queuename)) { 02530 if ((last_member = interface_exists(q, interface))) { 02531 if ((look = q->members) == last_member) { 02532 q->members = last_member->next; 02533 } else { 02534 while (look != NULL) { 02535 if (look->next == last_member) { 02536 look->next = last_member->next; 02537 break; 02538 } else { 02539 look = look->next; 02540 } 02541 } 02542 } 02543 manager_event(EVENT_FLAG_AGENT, "QueueMemberRemoved", 02544 "Queue: %s\r\n" 02545 "Location: %s\r\n", 02546 q->name, last_member->interface); 02547 free(last_member); 02548 02549 if (queue_persistent_members) 02550 dump_queue_members(q); 02551 02552 res = RES_OKAY; 02553 } else { 02554 res = RES_EXISTS; 02555 } 02556 ast_mutex_unlock(&q->lock); 02557 break; 02558 } 02559 ast_mutex_unlock(&q->lock); 02560 } 02561 if (res == RES_OKAY) 02562 remove_from_interfaces(interface); 02563 ast_mutex_unlock(&qlock); 02564 return res; 02565 }
|
|
Definition at line 917 of file app_queue.c. References ast_mutex_lock(), call_queue::next, and queues. Referenced by leave_queue(). 00918 { 00919 struct call_queue *cur, *prev = NULL; 00920 00921 ast_mutex_lock(&qlock); 00922 for (cur = queues; cur; cur = cur->next) { 00923 if (cur == q) { 00924 if (prev) 00925 prev->next = cur->next; 00926 else 00927 queues = cur->next; 00928 } else { 00929 prev = cur; 00930 } 00931 } 00932 ast_mutex_unlock(&qlock); 00933 }
|
|
Definition at line 1488 of file app_queue.c. References ast_channel::adsicpe, ast_channel::appl, ast_call(), ast_cdr_busy(), ast_channel_inherit_variables(), ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_request(), ast_verbose(), ast_channel::cdr, localuser::chan, queue_ent::chan, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, compare_weight(), ast_channel::context, ast_channel::data, EVENT_FLAG_AGENT, call_queue::eventwhencalled, ast_channel::exten, free, localuser::interface, localuser::lastcall, call_queue::lock, LOG_DEBUG, LOG_NOTICE, manager_event(), localuser::member, ast_channel::name, call_queue::name, ast_channel::nativeformats, localuser::oldstatus, option_debug, option_verbose, queue_ent::parent, member::paused, ast_channel::priority, call_queue::rrpos, member::status, localuser::stillgoing, strdup, update_dial_status(), use_weight, VERBOSE_PREFIX_3, ast_channel::whentohangup, and call_queue::wrapuptime. Referenced by ring_one(). 01489 { 01490 int res; 01491 int status; 01492 char tech[256]; 01493 char *location; 01494 01495 if (qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime)) { 01496 if (option_debug) 01497 ast_log(LOG_DEBUG, "Wrapuptime not yet expired for %s\n", tmp->interface); 01498 if (qe->chan->cdr) 01499 ast_cdr_busy(qe->chan->cdr); 01500 tmp->stillgoing = 0; 01501 (*busies)++; 01502 return 0; 01503 } 01504 01505 if (tmp->member->paused) { 01506 if (option_debug) 01507 ast_log(LOG_DEBUG, "%s paused, can't receive call\n", tmp->interface); 01508 if (qe->chan->cdr) 01509 ast_cdr_busy(qe->chan->cdr); 01510 tmp->stillgoing = 0; 01511 return 0; 01512 } 01513 if (use_weight && compare_weight(qe->parent,tmp->member)) { 01514 ast_log(LOG_DEBUG, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface); 01515 if (qe->chan->cdr) 01516 ast_cdr_busy(qe->chan->cdr); 01517 tmp->stillgoing = 0; 01518 (*busies)++; 01519 return 0; 01520 } 01521 01522 ast_copy_string(tech, tmp->interface, sizeof(tech)); 01523 if ((location = strchr(tech, '/'))) 01524 *location++ = '\0'; 01525 else 01526 location = ""; 01527 01528 /* Request the peer */ 01529 tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status); 01530 if (!tmp->chan) { /* If we can't, just go on to the next call */ 01531 #if 0 01532 ast_log(LOG_NOTICE, "Unable to create channel of type '%s' for Queue\n", cur->tech); 01533 #endif 01534 if (qe->chan->cdr) 01535 ast_cdr_busy(qe->chan->cdr); 01536 tmp->stillgoing = 0; 01537 update_dial_status(qe->parent, tmp->member, status); 01538 01539 ast_mutex_lock(&qe->parent->lock); 01540 qe->parent->rrpos++; 01541 ast_mutex_unlock(&qe->parent->lock); 01542 01543 (*busies)++; 01544 return 0; 01545 } else if (status != tmp->oldstatus) 01546 update_dial_status(qe->parent, tmp->member, status); 01547 01548 tmp->chan->appl = "AppQueue"; 01549 tmp->chan->data = "(Outgoing Line)"; 01550 tmp->chan->whentohangup = 0; 01551 if (tmp->chan->cid.cid_num) 01552 free(tmp->chan->cid.cid_num); 01553 tmp->chan->cid.cid_num = NULL; 01554 if (tmp->chan->cid.cid_name) 01555 free(tmp->chan->cid.cid_name); 01556 tmp->chan->cid.cid_name = NULL; 01557 if (tmp->chan->cid.cid_ani) 01558 free(tmp->chan->cid.cid_ani); 01559 tmp->chan->cid.cid_ani = NULL; 01560 if (qe->chan->cid.cid_num) 01561 tmp->chan->cid.cid_num = strdup(qe->chan->cid.cid_num); 01562 if (qe->chan->cid.cid_name) 01563 tmp->chan->cid.cid_name = strdup(qe->chan->cid.cid_name); 01564 if (qe->chan->cid.cid_ani) 01565 tmp->chan->cid.cid_ani = strdup(qe->chan->cid.cid_ani); 01566 01567 /* Inherit specially named variables from parent channel */ 01568 ast_channel_inherit_variables(qe->chan, tmp->chan); 01569 01570 /* Presense of ADSI CPE on outgoing channel follows ours */ 01571 tmp->chan->adsicpe = qe->chan->adsicpe; 01572 01573 /* Place the call, but don't wait on the answer */ 01574 res = ast_call(tmp->chan, location, 0); 01575 if (res) { 01576 /* Again, keep going even if there's an error */ 01577 if (option_debug) 01578 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res); 01579 if (option_verbose > 2) 01580 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", tmp->interface); 01581 ast_hangup(tmp->chan); 01582 tmp->chan = NULL; 01583 tmp->stillgoing = 0; 01584 (*busies)++; 01585 return 0; 01586 } else { 01587 if (qe->parent->eventwhencalled) { 01588 manager_event(EVENT_FLAG_AGENT, "AgentCalled", 01589 "AgentCalled: %s\r\n" 01590 "ChannelCalling: %s\r\n" 01591 "CallerID: %s\r\n" 01592 "CallerIDName: %s\r\n" 01593 "Context: %s\r\n" 01594 "Extension: %s\r\n" 01595 "Priority: %d\r\n", 01596 tmp->interface, qe->chan->name, 01597 tmp->chan->cid.cid_num ? tmp->chan->cid.cid_num : "unknown", 01598 tmp->chan->cid.cid_name ? tmp->chan->cid.cid_name : "unknown", 01599 qe->chan->context, qe->chan->exten, qe->chan->priority); 01600 } 01601 if (option_verbose > 2) 01602 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", tmp->interface); 01603 } 01604 return 1; 01605 }
|
|
Definition at line 1607 of file app_queue.c. References ast_log(), localuser::chan, localuser::interface, LOG_DEBUG, localuser::metric, localuser::next, option_debug, queue_ent::parent, ring_entry(), localuser::stillgoing, and call_queue::strategy. Referenced by wait_for_answer(). 01608 { 01609 struct localuser *cur; 01610 struct localuser *best; 01611 int bestmetric=0; 01612 01613 do { 01614 best = NULL; 01615 cur = outgoing; 01616 while(cur) { 01617 if (cur->stillgoing && /* Not already done */ 01618 !cur->chan && /* Isn't already going */ 01619 (!best || (cur->metric < bestmetric))) { /* We haven't found one yet, or it's better */ 01620 bestmetric = cur->metric; 01621 best = cur; 01622 } 01623 cur = cur->next; 01624 } 01625 if (best) { 01626 if (!qe->parent->strategy) { 01627 /* Ring everyone who shares this best metric (for ringall) */ 01628 cur = outgoing; 01629 while(cur) { 01630 if (cur->stillgoing && !cur->chan && (cur->metric <= bestmetric)) { 01631 if (option_debug) 01632 ast_log(LOG_DEBUG, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric); 01633 ring_entry(qe, cur, busies); 01634 } 01635 cur = cur->next; 01636 } 01637 } else { 01638 /* Ring just the best channel */ 01639 if (option_debug) 01640 ast_log(LOG_DEBUG, "Trying '%s' with metric %d\n", best->interface, best->metric); 01641 ring_entry(qe, best, busies); 01642 } 01643 } 01644 } while (best && !best->chan); 01645 if (!best) { 01646 if (option_debug) 01647 ast_log(LOG_DEBUG, "Nobody left to try ringing in queue\n"); 01648 return 0; 01649 } 01650 return 1; 01651 }
|
|
Definition at line 2864 of file app_queue.c. References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_goto_if_exists(), ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), localuser::chan, ast_channel::context, localuser::interface, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_channel::name, option_priority_jumping, parse(), pbx_builtin_setvar_helper(), remove_from_queue(), RES_EXISTS, RES_NOSUCHQUEUE, RES_OKAY, and RES_OUTOFMEMORY. Referenced by load_module(). 02865 { 02866 int res=-1; 02867 struct localuser *u; 02868 char *parse, *temppos = NULL; 02869 int priority_jump = 0; 02870 AST_DECLARE_APP_ARGS(args, 02871 AST_APP_ARG(queuename); 02872 AST_APP_ARG(interface); 02873 AST_APP_ARG(options); 02874 ); 02875 02876 02877 if (ast_strlen_zero(data)) { 02878 ast_log(LOG_WARNING, "RemoveQueueMember requires an argument (queuename[|interface[|options]])\n"); 02879 return -1; 02880 } 02881 02882 LOCAL_USER_ADD(u); 02883 02884 if (!(parse = ast_strdupa(data))) { 02885 ast_log(LOG_WARNING, "Memory Error!\n"); 02886 LOCAL_USER_REMOVE(u); 02887 return -1; 02888 } 02889 02890 AST_STANDARD_APP_ARGS(args, parse); 02891 02892 if (ast_strlen_zero(args.interface)) { 02893 args.interface = ast_strdupa(chan->name); 02894 temppos = strrchr(args.interface, '-'); 02895 if (temppos) 02896 *temppos = '\0'; 02897 } 02898 02899 if (args.options) { 02900 if (strchr(args.options, 'j')) 02901 priority_jump = 1; 02902 } 02903 02904 switch (remove_from_queue(args.queuename, args.interface)) { 02905 case RES_OKAY: 02906 ast_log(LOG_NOTICE, "Removed interface '%s' from queue '%s'\n", args.interface, args.queuename); 02907 pbx_builtin_setvar_helper(chan, "RQMSTATUS", "REMOVED"); 02908 res = 0; 02909 break; 02910 case RES_EXISTS: 02911 ast_log(LOG_WARNING, "Unable to remove interface '%s' from queue '%s': Not there\n", args.interface, args.queuename); 02912 if (priority_jump || option_priority_jumping) 02913 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101); 02914 pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOTINQUEUE"); 02915 res = 0; 02916 break; 02917 case RES_NOSUCHQUEUE: 02918 ast_log(LOG_WARNING, "Unable to remove interface from queue '%s': No such queue\n", args.queuename); 02919 pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOSUCHQUEUE"); 02920 res = 0; 02921 break; 02922 case RES_OUTOFMEMORY: 02923 ast_log(LOG_ERROR, "Out of memory\n"); 02924 break; 02925 } 02926 02927 LOCAL_USER_REMOVE(u); 02928 return res; 02929 }
|
|
Definition at line 854 of file app_queue.c. References add_to_interfaces(), create_queue_member(), member::dead, member::interface, call_queue::members, member::next, and member::penalty. 00855 { 00856 struct member *m, *prev_m; 00857 int penalty = 0; 00858 00859 if(penalty_str) { 00860 penalty = atoi(penalty_str); 00861 if(penalty < 0) 00862 penalty = 0; 00863 } 00864 00865 /* Find the member, or the place to put a new one. */ 00866 prev_m = NULL; 00867 m = q->members; 00868 while (m && strcmp(m->interface, interface)) { 00869 prev_m = m; 00870 m = m->next; 00871 } 00872 00873 /* Create a new one if not found, else update penalty */ 00874 if (!m) { 00875 m = create_queue_member(interface, penalty, 0); 00876 if (m) { 00877 m->dead = 0; 00878 add_to_interfaces(interface); 00879 if (prev_m) { 00880 prev_m->next = m; 00881 } else { 00882 q->members = m; 00883 } 00884 } 00885 } else { 00886 m->dead = 0; /* Do not delete this one. */ 00887 m->penalty = penalty; 00888 } 00889 }
|
|
Definition at line 1716 of file app_queue.c. References ast_moh_start(), ast_moh_stop(), ast_verbose(), background_file(), queue_ent::chan, queue_ent::last_periodic_announce_time, queue_ent::moh, option_verbose, queue_ent::parent, call_queue::periodicannouncefrequency, call_queue::sound_periodicannounce, and VERBOSE_PREFIX_3. 01717 { 01718 int res = 0; 01719 time_t now; 01720 01721 /* Get the current time */ 01722 time(&now); 01723 01724 /* Check to see if it is time to announce */ 01725 if ((now - qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency) 01726 return 0; 01727 01728 /* Stop the music on hold so we can play our own file */ 01729 ast_moh_stop(qe->chan); 01730 01731 if (option_verbose > 2) 01732 ast_verbose(VERBOSE_PREFIX_3 "Playing periodic announcement\n"); 01733 01734 /* play the announcement */ 01735 res = background_file(qe, qe->chan, qe->parent->sound_periodicannounce); 01736 01737 /* Resume Music on Hold if the caller is going to stay in the queue */ 01738 if (!res) 01739 ast_moh_start(qe->chan, qe->moh); 01740 01741 /* update last_periodic_announce_time */ 01742 qe->last_periodic_announce_time = now; 01743 01744 return res; 01745 }
|
|
Definition at line 1225 of file app_queue.c. References call_queue::announcefrequency, call_queue::announceholdtime, ANNOUNCEHOLDTIME_ONCE, AST_DIGIT_ANY, ast_moh_start(), ast_moh_stop(), ast_say_number(), ast_verbose(), queue_ent::chan, call_queue::holdtime, ast_channel::language, queue_ent::last_pos, queue_ent::last_pos_said, queue_ent::moh, ast_channel::name, call_queue::name, option_verbose, queue_ent::parent, play_file(), queue_ent::pos, call_queue::roundingseconds, call_queue::sound_calls, call_queue::sound_holdtime, call_queue::sound_lessthan, call_queue::sound_minutes, call_queue::sound_next, call_queue::sound_seconds, call_queue::sound_thanks, call_queue::sound_thereare, queue_ent::start, valid_exit(), and VERBOSE_PREFIX_3. 01226 { 01227 int res = 0, avgholdmins, avgholdsecs; 01228 time_t now; 01229 01230 /* Check to see if this is ludicrous -- if we just announced position, don't do it again*/ 01231 time(&now); 01232 if ( (now - qe->last_pos) < 15 ) 01233 return 0; 01234 01235 /* If either our position has changed, or we are over the freq timer, say position */ 01236 if ( (qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency) ) 01237 return 0; 01238 01239 ast_moh_stop(qe->chan); 01240 /* Say we're next, if we are */ 01241 if (qe->pos == 1) { 01242 res = play_file(qe->chan, qe->parent->sound_next); 01243 if (res && valid_exit(qe, res)) 01244 goto playout; 01245 else 01246 goto posout; 01247 } else { 01248 res = play_file(qe->chan, qe->parent->sound_thereare); 01249 if (res && valid_exit(qe, res)) 01250 goto playout; 01251 res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, qe->chan->language, (char *) NULL); /* Needs gender */ 01252 if (res && valid_exit(qe, res)) 01253 goto playout; 01254 res = play_file(qe->chan, qe->parent->sound_calls); 01255 if (res && valid_exit(qe, res)) 01256 goto playout; 01257 } 01258 /* Round hold time to nearest minute */ 01259 avgholdmins = abs(( (qe->parent->holdtime + 30) - (now - qe->start) ) / 60); 01260 01261 /* If they have specified a rounding then round the seconds as well */ 01262 if(qe->parent->roundingseconds) { 01263 avgholdsecs = (abs(( (qe->parent->holdtime + 30) - (now - qe->start) )) - 60 * avgholdmins) / qe->parent->roundingseconds; 01264 avgholdsecs*= qe->parent->roundingseconds; 01265 } else { 01266 avgholdsecs=0; 01267 } 01268 01269 if (option_verbose > 2) 01270 ast_verbose(VERBOSE_PREFIX_3 "Hold time for %s is %d minutes %d seconds\n", qe->parent->name, avgholdmins, avgholdsecs); 01271 01272 /* If the hold time is >1 min, if it's enabled, and if it's not 01273 supposed to be only once and we have already said it, say it */ 01274 if ((avgholdmins+avgholdsecs) > 0 && (qe->parent->announceholdtime) && 01275 (!(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE) && qe->last_pos)) { 01276 res = play_file(qe->chan, qe->parent->sound_holdtime); 01277 if (res && valid_exit(qe, res)) 01278 goto playout; 01279 01280 if (avgholdmins>0) { 01281 if (avgholdmins < 2) { 01282 res = play_file(qe->chan, qe->parent->sound_lessthan); 01283 if (res && valid_exit(qe, res)) 01284 goto playout; 01285 01286 res = ast_say_number(qe->chan, 2, AST_DIGIT_ANY, qe->chan->language, (char *)NULL); 01287 if (res && valid_exit(qe, res)) 01288 goto playout; 01289 } else { 01290 res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, qe->chan->language, (char*) NULL); 01291 if (res && valid_exit(qe, res)) 01292 goto playout; 01293 } 01294 01295 res = play_file(qe->chan, qe->parent->sound_minutes); 01296 if (res && valid_exit(qe, res)) 01297 goto playout; 01298 } 01299 if (avgholdsecs>0) { 01300 res = ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, qe->chan->language, (char*) NULL); 01301 if (res && valid_exit(qe, res)) 01302 goto playout; 01303 01304 res = play_file(qe->chan, qe->parent->sound_seconds); 01305 if (res && valid_exit(qe, res)) 01306 goto playout; 01307 } 01308 01309 } 01310 01311 posout: 01312 if (option_verbose > 2) 01313 ast_verbose(VERBOSE_PREFIX_3 "Told %s in %s their queue position (which was %d)\n", 01314 qe->chan->name, qe->parent->name, qe->pos); 01315 res = play_file(qe->chan, qe->parent->sound_thanks); 01316 if (res && !valid_exit(qe, res)) 01317 res = 0; 01318 01319 playout: 01320 /* Set our last_pos indicators */ 01321 qe->last_pos = now; 01322 qe->last_pos_said = qe->pos; 01323 01324 /* Don't restart music on hold if we're about to exit the caller from the queue */ 01325 if (!res) 01326 ast_moh_start(qe->chan, qe->moh); 01327 01328 return res; 01329 }
|
|
Definition at line 2619 of file app_queue.c. References ast_log(), ast_mutex_lock(), ast_queue_log(), ast_strlen_zero(), dump_queue_members(), EVENT_FLAG_AGENT, member::interface, interface_exists(), call_queue::lock, LOG_DEBUG, manager_event(), call_queue::name, call_queue::next, member::paused, queue_persistent_members, and queues. Referenced by manager_pause_queue_member(), pqm_exec(), and upqm_exec(). 02620 { 02621 int found = 0; 02622 struct call_queue *q; 02623 struct member *mem; 02624 02625 /* Special event for when all queues are paused - individual events still generated */ 02626 02627 if (ast_strlen_zero(queuename)) 02628 ast_queue_log("NONE", "NONE", interface, (paused ? "PAUSEALL" : "UNPAUSEALL"), "%s", ""); 02629 02630 ast_mutex_lock(&qlock); 02631 for (q = queues ; q ; q = q->next) { 02632 ast_mutex_lock(&q->lock); 02633 if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) { 02634 if ((mem = interface_exists(q, interface))) { 02635 found++; 02636 if (mem->paused == paused) 02637 ast_log(LOG_DEBUG, "%spausing already-%spaused queue member %s:%s\n", (paused ? "" : "un"), (paused ? "" : "un"), q->name, interface); 02638 mem->paused = paused; 02639 02640 if (queue_persistent_members) 02641 dump_queue_members(q); 02642 02643 ast_queue_log(q->name, "NONE", interface, (paused ? "PAUSE" : "UNPAUSE"), "%s", ""); 02644 02645 manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused", 02646 "Queue: %s\r\n" 02647 "Location: %s\r\n" 02648 "Paused: %d\r\n", 02649 q->name, mem->interface, paused); 02650 } 02651 } 02652 ast_mutex_unlock(&q->lock); 02653 } 02654 ast_mutex_unlock(&qlock); 02655 02656 if (found) 02657 return RESULT_SUCCESS; 02658 else 02659 return RESULT_FAILURE; 02660 }
|
|
Definition at line 377 of file app_queue.c. References pbx_builtin_setvar_helper(), queue_results, and text. 00378 { 00379 int i; 00380 00381 for (i = 0; i < sizeof(queue_results) / sizeof(queue_results[0]); i++) { 00382 if (queue_results[i].id == res) { 00383 pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text); 00384 return; 00385 } 00386 } 00387 }
|
|
Definition at line 546 of file app_queue.c. References ast_log(), ast_pthread_create, changethread(), free, LOG_WARNING, malloc, and t. Referenced by load_module(), and unload_module(). 00547 { 00548 /* Avoid potential for deadlocks by spawning a new thread to handle 00549 the event */ 00550 struct statechange *sc; 00551 pthread_t t; 00552 pthread_attr_t attr; 00553 00554 if (!(sc = malloc(sizeof(*sc) + strlen(dev) + 1))) 00555 return 0; 00556 00557 sc->state = state; 00558 strcpy(sc->dev, dev); 00559 pthread_attr_init(&attr); 00560 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 00561 if (ast_pthread_create(&t, &attr, changethread, sc)) { 00562 ast_log(LOG_WARNING, "Failed to create update thread!\n"); 00563 free(sc); 00564 } 00565 00566 return 0; 00567 }
|
|
Definition at line 1653 of file app_queue.c. References ast_log(), localuser::chan, localuser::interface, LOG_DEBUG, localuser::metric, localuser::next, option_debug, queue_ent::parent, call_queue::rrpos, localuser::stillgoing, and call_queue::wrapped. 01654 { 01655 struct localuser *cur; 01656 struct localuser *best; 01657 int bestmetric=0; 01658 01659 best = NULL; 01660 cur = outgoing; 01661 while(cur) { 01662 if (cur->stillgoing && /* Not already done */ 01663 !cur->chan && /* Isn't already going */ 01664 (!best || (cur->metric < bestmetric))) { /* We haven't found one yet, or it's better */ 01665 bestmetric = cur->metric; 01666 best = cur; 01667 } 01668 cur = cur->next; 01669 } 01670 if (best) { 01671 /* Ring just the best channel */ 01672 if (option_debug) 01673 ast_log(LOG_DEBUG, "Next is '%s' with metric %d\n", best->interface, best->metric); 01674 qe->parent->rrpos = best->metric % 1000; 01675 } else { 01676 /* Just increment rrpos */ 01677 if (qe->parent->wrapped) { 01678 /* No more channels, start over */ 01679 qe->parent->rrpos = 0; 01680 } else { 01681 /* Prioritize next entry */ 01682 qe->parent->rrpos++; 01683 } 01684 } 01685 qe->parent->wrapped = 0; 01686 return 0; 01687 }
|
|
Definition at line 399 of file app_queue.c. References name, and strategies. Referenced by queue_set_param(). 00400 { 00401 int x; 00402 for (x=0;x<sizeof(strategies) / sizeof(strategies[0]);x++) { 00403 if (!strcasecmp(strategy, strategies[x].name)) 00404 return strategies[x].strategy; 00405 } 00406 return -1; 00407 }
|
|
Definition at line 2153 of file app_queue.c. References AST_FEATURE_AUTOMON, AST_FEATURE_DISCONNECT, AST_FEATURE_REDIRECT, AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_set_flag, queue_ent::parent, queue_ent::start, and call_queue::timeout. 02154 { 02155 struct member *cur; 02156 struct localuser *outgoing=NULL, *tmp = NULL; 02157 int to; 02158 char restofit[AST_MAX_EXTENSION]; 02159 char oldexten[AST_MAX_EXTENSION]=""; 02160 char oldcontext[AST_MAX_CONTEXT]=""; 02161 char queuename[256]=""; 02162 char *newnum; 02163 char *monitorfilename; 02164 struct ast_channel *peer; 02165 struct ast_channel *which; 02166 struct localuser *lpeer; 02167 struct member *member; 02168 int res = 0, bridge = 0; 02169 int numbusies = 0; 02170 int x=0; 02171 char *announce = NULL; 02172 char digit = 0; 02173 time_t callstart; 02174 time_t now = time(NULL); 02175 struct ast_bridge_config bridge_config; 02176 char nondataquality = 1; 02177 02178 memset(&bridge_config, 0, sizeof(bridge_config)); 02179 time(&now); 02180 02181 for (; options && *options; options++) 02182 switch (*options) { 02183 case 't': 02184 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT); 02185 break; 02186 case 'T': 02187 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT); 02188 break; 02189 case 'w': 02190 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMON); 02191 break; 02192 case 'W': 02193 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMON); 02194 break; 02195 case 'd': 02196 nondataquality = 0; 02197 break; 02198 case 'h': 02199 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT); 02200 break; 02201 case 'H': 02202 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT); 02203 break; 02204 case 'n': 02205 if ((now - qe->start >= qe->parent->timeout)) 02206 *go_on = 1; 02207 break; 02208 } 02209 02210 /* Hold the lock while we setup the outgoing calls */ 02211 if (use_weight) 02212 ast_mutex_lock(&qlock); 02213 ast_mutex_lock(&qe->parent->lock); 02214 if (option_debug) 02215 ast_log(LOG_DEBUG, "%s is trying to call a queue member.\n", 02216 qe->chan->name); 02217 ast_copy_string(queuename, qe->parent->name, sizeof(queuename)); 02218 cur = qe->parent->members; 02219 if (!ast_strlen_zero(qe->announce)) 02220 announce = qe->announce; 02221 if (!ast_strlen_zero(announceoverride)) 02222 announce = announceoverride; 02223 02224 while(cur) { 02225 tmp = malloc(sizeof(*tmp)); 02226 if (!tmp) { 02227 ast_mutex_unlock(&qe->parent->lock); 02228 if (use_weight) 02229 ast_mutex_unlock(&qlock); 02230 ast_log(LOG_WARNING, "Out of memory\n"); 02231 goto out; 02232 } 02233 memset(tmp, 0, sizeof(*tmp)); 02234 tmp->stillgoing = -1; 02235 if (option_debug) { 02236 if (url) 02237 ast_log(LOG_DEBUG, "Queue with URL=%s_\n", url); 02238 else 02239 ast_log(LOG_DEBUG, "Simple queue (no URL)\n"); 02240 } 02241 02242 tmp->member = cur; /* Never directly dereference! Could change on reload */ 02243 tmp->oldstatus = cur->status; 02244 tmp->lastcall = cur->lastcall; 02245 ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface)); 02246 /* If we're dialing by extension, look at the extension to know what to dial */ 02247 if ((newnum = strstr(tmp->interface, "/BYEXTENSION"))) { 02248 newnum++; 02249 strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit) - 1); 02250 snprintf(newnum, sizeof(tmp->interface) - (newnum - tmp->interface), "%s%s", qe->chan->exten, restofit); 02251 if (option_debug) 02252 ast_log(LOG_DEBUG, "Dialing by extension %s\n", tmp->interface); 02253 } 02254 /* Special case: If we ring everyone, go ahead and ring them, otherwise 02255 just calculate their metric for the appropriate strategy */ 02256 calc_metric(qe->parent, cur, x++, qe, tmp); 02257 /* Put them in the list of outgoing thingies... We're ready now. 02258 XXX If we're forcibly removed, these outgoing calls won't get 02259 hung up XXX */ 02260 tmp->next = outgoing; 02261 outgoing = tmp; 02262 /* If this line is up, don't try anybody else */ 02263 if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP)) 02264 break; 02265 02266 cur = cur->next; 02267 } 02268 if (qe->expire && (!qe->parent->timeout || (qe->expire - now) <= qe->parent->timeout)) 02269 to = (qe->expire - now) * 1000; 02270 else 02271 to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1; 02272 ring_one(qe, outgoing, &numbusies); 02273 ast_mutex_unlock(&qe->parent->lock); 02274 if (use_weight) 02275 ast_mutex_unlock(&qlock); 02276 lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT)); 02277 ast_mutex_lock(&qe->parent->lock); 02278 if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) { 02279 store_next(qe, outgoing); 02280 } 02281 ast_mutex_unlock(&qe->parent->lock); 02282 if (lpeer) 02283 peer = lpeer->chan; 02284 else 02285 peer = NULL; 02286 if (!peer) { 02287 if (to) { 02288 /* Musta gotten hung up */ 02289 res = -1; 02290 } else { 02291 res = digit; 02292 } 02293 if (option_debug) 02294 ast_log(LOG_DEBUG, "%s: Nobody answered.\n", qe->chan->name); 02295 goto out; 02296 } 02297 if (peer) { 02298 /* Ah ha! Someone answered within the desired timeframe. Of course after this 02299 we will always return with -1 so that it is hung up properly after the 02300 conversation. */ 02301 qe->handled++; 02302 if (!strcmp(qe->chan->type,"Zap")) 02303 ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0); 02304 if (!strcmp(peer->type,"Zap")) 02305 ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0); 02306 /* Update parameters for the queue */ 02307 recalc_holdtime(qe); 02308 member = lpeer->member; 02309 hangupcalls(outgoing, peer); 02310 outgoing = NULL; 02311 if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) { 02312 int res2; 02313 res2 = ast_autoservice_start(qe->chan); 02314 if (!res2) { 02315 if (qe->parent->memberdelay) { 02316 ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay); 02317 res2 |= ast_safe_sleep(peer, qe->parent->memberdelay * 1000); 02318 } 02319 if (!res2 && announce) { 02320 if (play_file(peer, announce)) 02321 ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", announce); 02322 } 02323 if (!res2 && qe->parent->reportholdtime) { 02324 if (!play_file(peer, qe->parent->sound_reporthold)) { 02325 int holdtime; 02326 02327 time(&now); 02328 holdtime = abs((now - qe->start) / 60); 02329 if (holdtime < 2) { 02330 play_file(peer, qe->parent->sound_lessthan); 02331 ast_say_number(peer, 2, AST_DIGIT_ANY, peer->language, NULL); 02332 } else 02333 ast_say_number(peer, holdtime, AST_DIGIT_ANY, peer->language, NULL); 02334 play_file(peer, qe->parent->sound_minutes); 02335 } 02336 } 02337 } 02338 res2 |= ast_autoservice_stop(qe->chan); 02339 if (peer->_softhangup) { 02340 /* Agent must have hung up */ 02341 ast_log(LOG_WARNING, "Agent on %s hungup on the customer. They're going to be pissed.\n", peer->name); 02342 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "AGENTDUMP", "%s", ""); 02343 record_abandoned(qe); 02344 if (qe->parent->eventwhencalled) { 02345 manager_event(EVENT_FLAG_AGENT, "AgentDump", 02346 "Queue: %s\r\n" 02347 "Uniqueid: %s\r\n" 02348 "Channel: %s\r\n" 02349 "Member: %s\r\n", 02350 queuename, qe->chan->uniqueid, peer->name, member->interface); 02351 } 02352 ast_hangup(peer); 02353 goto out; 02354 } else if (res2) { 02355 /* Caller must have hung up just before being connected*/ 02356 ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", peer->name); 02357 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long)time(NULL) - qe->start); 02358 record_abandoned(qe); 02359 ast_hangup(peer); 02360 return -1; 02361 } 02362 } 02363 /* Stop music on hold */ 02364 ast_moh_stop(qe->chan); 02365 /* If appropriate, log that we have a destination channel */ 02366 if (qe->chan->cdr) 02367 ast_cdr_setdestchan(qe->chan->cdr, peer->name); 02368 /* Make sure channels are compatible */ 02369 res = ast_channel_make_compatible(qe->chan, peer); 02370 if (res < 0) { 02371 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "SYSCOMPAT", "%s", ""); 02372 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", qe->chan->name, peer->name); 02373 record_abandoned(qe); 02374 ast_hangup(peer); 02375 return -1; 02376 } 02377 /* Begin Monitoring */ 02378 if (qe->parent->monfmt && *qe->parent->monfmt) { 02379 monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME"); 02380 if (pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC") || pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC_ARGS")) 02381 which = qe->chan; 02382 else 02383 which = peer; 02384 if (monitorfilename) 02385 ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1 ); 02386 else if (qe->chan->cdr) 02387 ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1 ); 02388 else { 02389 /* Last ditch effort -- no CDR, make up something */ 02390 char tmpid[256]; 02391 snprintf(tmpid, sizeof(tmpid), "chan-%x", rand()); 02392 ast_monitor_start(which, qe->parent->monfmt, tmpid, 1 ); 02393 } 02394 if (qe->parent->monjoin) 02395 ast_monitor_setjoinfiles(which, 1); 02396 } 02397 /* Drop out of the queue at this point, to prepare for next caller */ 02398 leave_queue(qe); 02399 if (!ast_strlen_zero(url) && ast_channel_supports_html(peer)) { 02400 if (option_debug) 02401 ast_log(LOG_DEBUG, "app_queue: sendurl=%s.\n", url); 02402 ast_channel_sendurl(peer, url); 02403 } 02404 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "CONNECT", "%ld", (long)time(NULL) - qe->start); 02405 if (qe->parent->eventwhencalled) 02406 manager_event(EVENT_FLAG_AGENT, "AgentConnect", 02407 "Queue: %s\r\n" 02408 "Uniqueid: %s\r\n" 02409 "Channel: %s\r\n" 02410 "Member: %s\r\n" 02411 "Holdtime: %ld\r\n", 02412 queuename, qe->chan->uniqueid, peer->name, member->interface, 02413 (long)time(NULL) - qe->start); 02414 ast_copy_string(oldcontext, qe->chan->context, sizeof(oldcontext)); 02415 ast_copy_string(oldexten, qe->chan->exten, sizeof(oldexten)); 02416 time(&callstart); 02417 02418 bridge = ast_bridge_call(qe->chan,peer, &bridge_config); 02419 02420 if (strcasecmp(oldcontext, qe->chan->context) || strcasecmp(oldexten, qe->chan->exten)) { 02421 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "TRANSFER", "%s|%s", qe->chan->exten, qe->chan->context); 02422 } else if (qe->chan->_softhangup) { 02423 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETECALLER", "%ld|%ld", 02424 (long)(callstart - qe->start), (long)(time(NULL) - callstart)); 02425 if (qe->parent->eventwhencalled) 02426 manager_event(EVENT_FLAG_AGENT, "AgentComplete", 02427 "Queue: %s\r\n" 02428 "Uniqueid: %s\r\n" 02429 "Channel: %s\r\n" 02430 "Member: %s\r\n" 02431 "HoldTime: %ld\r\n" 02432 "TalkTime: %ld\r\n" 02433 "Reason: caller\r\n", 02434 queuename, qe->chan->uniqueid, peer->name, member->interface, 02435 (long)(callstart - qe->start), (long)(time(NULL) - callstart)); 02436 } else { 02437 ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETEAGENT", "%ld|%ld", (long)(callstart - qe->start), (long)(time(NULL) - callstart)); 02438 if (qe->parent->eventwhencalled) 02439 manager_event(EVENT_FLAG_AGENT, "AgentComplete", 02440 "Queue: %s\r\n" 02441 "Uniqueid: %s\r\n" 02442 "Channel: %s\r\n" 02443 "HoldTime: %ld\r\n" 02444 "TalkTime: %ld\r\n" 02445 "Reason: agent\r\n", 02446 queuename, qe->chan->uniqueid, peer->name, (long)(callstart - qe->start), 02447 (long)(time(NULL) - callstart)); 02448 } 02449 02450 if (bridge != AST_PBX_NO_HANGUP_PEER) 02451 ast_hangup(peer); 02452 update_queue(qe->parent, member); 02453 res = bridge ? bridge : 1; 02454 } 02455 out: 02456 hangupcalls(outgoing, NULL); 02457 return res; 02458 }
|
|
|
Definition at line 1441 of file app_queue.c. References AST_CAUSE_BUSY, AST_CAUSE_NOSUCHDRIVER, AST_CAUSE_UNREGISTERED, AST_DEVICE_BUSY, AST_DEVICE_INVALID, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, and update_status(). Referenced by ring_entry(), and wait_for_answer(). 01442 { 01443 if (status == AST_CAUSE_BUSY) 01444 status = AST_DEVICE_BUSY; 01445 else if (status == AST_CAUSE_UNREGISTERED) 01446 status = AST_DEVICE_UNAVAILABLE; 01447 else if (status == AST_CAUSE_NOSUCHDRIVER) 01448 status = AST_DEVICE_INVALID; 01449 else 01450 status = AST_DEVICE_UNKNOWN; 01451 return update_status(q, member, status); 01452 }
|
|
Definition at line 2080 of file app_queue.c. References ast_mutex_lock(), ast_mutex_unlock(), member::calls, call_queue::callscompleted, member::lastcall, call_queue::lock, call_queue::members, and member::next. 02081 { 02082 struct member *cur; 02083 02084 /* Since a reload could have taken place, we have to traverse the list to 02085 be sure it's still valid */ 02086 ast_mutex_lock(&q->lock); 02087 cur = q->members; 02088 while(cur) { 02089 if (member == cur) { 02090 time(&cur->lastcall); 02091 cur->calls++; 02092 break; 02093 } 02094 cur = cur->next; 02095 } 02096 q->callscompleted++; 02097 ast_mutex_unlock(&q->lock); 02098 return 0; 02099 }
|
|
Definition at line 1409 of file app_queue.c. References ast_mutex_lock(), ast_mutex_unlock(), member::calls, member::dynamic, EVENT_FLAG_AGENT, member::interface, member::lastcall, call_queue::lock, manager_event(), call_queue::maskmemberstatus, call_queue::members, call_queue::name, member::next, member::paused, member::penalty, and member::status. Referenced by update_dial_status(). 01410 { 01411 struct member *cur; 01412 01413 /* Since a reload could have taken place, we have to traverse the list to 01414 be sure it's still valid */ 01415 ast_mutex_lock(&q->lock); 01416 cur = q->members; 01417 while(cur) { 01418 if (member == cur) { 01419 cur->status = status; 01420 if (!q->maskmemberstatus) { 01421 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus", 01422 "Queue: %s\r\n" 01423 "Location: %s\r\n" 01424 "Membership: %s\r\n" 01425 "Penalty: %d\r\n" 01426 "CallsTaken: %d\r\n" 01427 "LastCall: %d\r\n" 01428 "Status: %d\r\n" 01429 "Paused: %d\r\n", 01430 q->name, cur->interface, cur->dynamic ? "dynamic" : "static", 01431 cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused); 01432 } 01433 break; 01434 } 01435 cur = cur->next; 01436 } 01437 ast_mutex_unlock(&q->lock); 01438 return 0; 01439 }
|
|
Definition at line 2808 of file app_queue.c. References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_goto_if_exists(), ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), localuser::chan, ast_channel::context, localuser::interface, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_WARNING, option_priority_jumping, parse(), pbx_builtin_setvar_helper(), and set_member_paused(). Referenced by load_module(). 02809 { 02810 struct localuser *u; 02811 char *parse; 02812 int priority_jump = 0; 02813 AST_DECLARE_APP_ARGS(args, 02814 AST_APP_ARG(queuename); 02815 AST_APP_ARG(interface); 02816 AST_APP_ARG(options); 02817 ); 02818 02819 if (ast_strlen_zero(data)) { 02820 ast_log(LOG_WARNING, "UnpauseQueueMember requires an argument ([queuename]|interface[|options])\n"); 02821 return -1; 02822 } 02823 02824 LOCAL_USER_ADD(u); 02825 02826 if (!(parse = ast_strdupa(data))) { 02827 ast_log(LOG_WARNING, "Memory Error!\n"); 02828 LOCAL_USER_REMOVE(u); 02829 return -1; 02830 } 02831 02832 AST_STANDARD_APP_ARGS(args, parse); 02833 02834 if (args.options) { 02835 if (strchr(args.options, 'j')) 02836 priority_jump = 1; 02837 } 02838 02839 if (ast_strlen_zero(args.interface)) { 02840 ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename]|interface[|options])\n"); 02841 LOCAL_USER_REMOVE(u); 02842 return -1; 02843 } 02844 02845 if (set_member_paused(args.queuename, args.interface, 0)) { 02846 ast_log(LOG_WARNING, "Attempt to unpause interface %s, not found\n", args.interface); 02847 if (priority_jump || option_priority_jumping) { 02848 if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) { 02849 pbx_builtin_setvar_helper(chan, "UPQMSTATUS", "NOTFOUND"); 02850 LOCAL_USER_REMOVE(u); 02851 return 0; 02852 } 02853 } 02854 LOCAL_USER_REMOVE(u); 02855 pbx_builtin_setvar_helper(chan, "UPQMSTATUS", "NOTFOUND"); 02856 return -1; 02857 } 02858 02859 LOCAL_USER_REMOVE(u); 02860 pbx_builtin_setvar_helper(chan, "UPQMSTATUS", "UNPAUSED"); 02861 return 0; 02862 }
|
|
Provides a usecount. This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 4044 of file app_queue.c. References STANDARD_USECOUNT. 04045 { 04046 int res; 04047 STANDARD_USECOUNT(res); 04048 return res; 04049 }
|
|
Definition at line 1194 of file app_queue.c. References ast_canmatch_extension(), ast_goto_if_exists(), ast_strlen_zero(), queue_ent::chan, ast_channel::cid, ast_callerid::cid_num, queue_ent::context, and queue_ent::digits. Referenced by background_file(), queue_exec(), say_position(), and wait_for_answer(). 01195 { 01196 int digitlen = strlen(qe->digits); 01197 01198 /* Prevent possible buffer overflow */ 01199 if (digitlen < sizeof(qe->digits) - 2) { 01200 qe->digits[digitlen] = digit; 01201 qe->digits[digitlen + 1] = '\0'; 01202 } else { 01203 qe->digits[0] = '\0'; 01204 return 0; 01205 } 01206 01207 /* If there's no context to goto, short-circuit */ 01208 if (ast_strlen_zero(qe->context)) 01209 return 0; 01210 01211 /* If the extension is bad, then reset the digits to blank */ 01212 if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1, qe->chan->cid.cid_num)) { 01213 qe->digits[0] = '\0'; 01214 return 0; 01215 } 01216 01217 /* We have an exact match */ 01218 if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) { 01219 /* Return 1 on a successful goto */ 01220 return 1; 01221 } 01222 return 0; 01223 }
|
|
Definition at line 2460 of file app_queue.c. References ast_waitfordigit(), queue_ent::chan, queue_ent::parent, and call_queue::retry. 02461 { 02462 /* Don't need to hold the lock while we setup the outgoing calls */ 02463 int retrywait = qe->parent->retry * 1000; 02464 02465 return ast_waitfordigit(qe->chan, retrywait); 02466 }
|
|
Definition at line 1777 of file app_queue.c. References ast_channel::_state, ast_channel::accountcode, ast_call(), ast_cdr_busy(), ast_channel_inherit_variables(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_OFFHOOK, AST_CONTROL_RINGING, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree(), ast_hangup(), ast_indicate(), ast_log(), AST_MAX_WATCHERS, ast_read(), ast_request(), AST_STATE_UP, ast_strlen_zero(), ast_verbose(), ast_waitfor_n(), BUILD_WATCHERS, ast_channel::call_forward, ast_channel::cdr, ast_channel::cdrflags, localuser::chan, queue_ent::chan, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_rdnis, ast_channel::context, ast_channel::exten, ast_frame::frametype, free, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::macroexten, malloc, localuser::member, ast_channel::name, call_queue::name, ast_channel::nativeformats, localuser::next, localuser::oldstatus, option_verbose, queue_ent::parent, ring_one(), localuser::stillgoing, call_queue::strategy, strdup, ast_frame::subclass, ast_channel::tech, call_queue::timeoutrestart, update_dial_status(), valid_exit(), and VERBOSE_PREFIX_3. 01778 { 01779 char *queue = qe->parent->name; 01780 struct localuser *o; 01781 int found; 01782 int numlines; 01783 int status; 01784 int sentringing = 0; 01785 int numbusies = prebusies; 01786 int numnochan = 0; 01787 int stillgoing = 0; 01788 int orig = *to; 01789 struct ast_frame *f; 01790 struct localuser *peer = NULL; 01791 struct ast_channel *watchers[AST_MAX_WATCHERS]; 01792 int pos; 01793 struct ast_channel *winner; 01794 struct ast_channel *in = qe->chan; 01795 01796 while(*to && !peer) { 01797 BUILD_WATCHERS; 01798 if ((found < 0) && stillgoing && !qe->parent->strategy) { 01799 /* On "ringall" strategy we only move to the next penalty level 01800 when *all* ringing phones are done in the current penalty level */ 01801 ring_one(qe, outgoing, &numbusies); 01802 BUILD_WATCHERS; 01803 } 01804 if (found < 0) { 01805 if (numlines == (numbusies + numnochan)) { 01806 ast_log(LOG_DEBUG, "Everyone is busy at this time\n"); 01807 } else { 01808 ast_log(LOG_NOTICE, "No one is answering queue '%s' (%d/%d/%d)\n", queue, numlines, numbusies, numnochan); 01809 } 01810 *to = 0; 01811 return NULL; 01812 } 01813 winner = ast_waitfor_n(watchers, pos, to); 01814 o = outgoing; 01815 while(o) { 01816 if (o->stillgoing && (o->chan) && (o->chan->_state == AST_STATE_UP)) { 01817 if (!peer) { 01818 if (option_verbose > 2) 01819 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name); 01820 peer = o; 01821 } 01822 } else if (o->chan && (o->chan == winner)) { 01823 if (!ast_strlen_zero(o->chan->call_forward)) { 01824 char tmpchan[256]=""; 01825 char *stuff; 01826 char *tech; 01827 ast_copy_string(tmpchan, o->chan->call_forward, sizeof(tmpchan)); 01828 if ((stuff = strchr(tmpchan, '/'))) { 01829 *stuff = '\0'; 01830 stuff++; 01831 tech = tmpchan; 01832 } else { 01833 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context); 01834 stuff = tmpchan; 01835 tech = "Local"; 01836 } 01837 /* Before processing channel, go ahead and check for forwarding */ 01838 if (option_verbose > 2) 01839 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name); 01840 /* Setup parameters */ 01841 o->chan = ast_request(tech, in->nativeformats, stuff, &status); 01842 if (status != o->oldstatus) 01843 update_dial_status(qe->parent, o->member, status); 01844 if (!o->chan) { 01845 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff); 01846 o->stillgoing = 0; 01847 numnochan++; 01848 } else { 01849 ast_channel_inherit_variables(in, o->chan); 01850 if (o->chan->cid.cid_num) 01851 free(o->chan->cid.cid_num); 01852 o->chan->cid.cid_num = NULL; 01853 if (o->chan->cid.cid_name) 01854 free(o->chan->cid.cid_name); 01855 o->chan->cid.cid_name = NULL; 01856 01857 if (in->cid.cid_num) { 01858 o->chan->cid.cid_num = strdup(in->cid.cid_num); 01859 if (!o->chan->cid.cid_num) 01860 ast_log(LOG_WARNING, "Out of memory\n"); 01861 } 01862 if (in->cid.cid_name) { 01863 o->chan->cid.cid_name = strdup(in->cid.cid_name); 01864 if (!o->chan->cid.cid_name) 01865 ast_log(LOG_WARNING, "Out of memory\n"); 01866 } 01867 ast_copy_string(o->chan->accountcode, in->accountcode, sizeof(o->chan->accountcode)); 01868 o->chan->cdrflags = in->cdrflags; 01869 01870 if (in->cid.cid_ani) { 01871 if (o->chan->cid.cid_ani) 01872 free(o->chan->cid.cid_ani); 01873 o->chan->cid.cid_ani = malloc(strlen(in->cid.cid_ani) + 1); 01874 if (o->chan->cid.cid_ani) 01875 strncpy(o->chan->cid.cid_ani, in->cid.cid_ani, strlen(in->cid.cid_ani) + 1); 01876 else 01877 ast_log(LOG_WARNING, "Out of memory\n"); 01878 } 01879 if (o->chan->cid.cid_rdnis) 01880 free(o->chan->cid.cid_rdnis); 01881 if (!ast_strlen_zero(in->macroexten)) 01882 o->chan->cid.cid_rdnis = strdup(in->macroexten); 01883 else 01884 o->chan->cid.cid_rdnis = strdup(in->exten); 01885 if (ast_call(o->chan, tmpchan, 0)) { 01886 ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan); 01887 o->stillgoing = 0; 01888 ast_hangup(o->chan); 01889 o->chan = NULL; 01890 numnochan++; 01891 } 01892 } 01893 /* Hangup the original channel now, in case we needed it */ 01894 ast_hangup(winner); 01895 continue; 01896 } 01897 f = ast_read(winner); 01898 if (f) { 01899 if (f->frametype == AST_FRAME_CONTROL) { 01900 switch(f->subclass) { 01901 case AST_CONTROL_ANSWER: 01902 /* This is our guy if someone answered. */ 01903 if (!peer) { 01904 if (option_verbose > 2) 01905 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name); 01906 peer = o; 01907 } 01908 break; 01909 case AST_CONTROL_BUSY: 01910 if (option_verbose > 2) 01911 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name); 01912 o->stillgoing = 0; 01913 if (in->cdr) 01914 ast_cdr_busy(in->cdr); 01915 ast_hangup(o->chan); 01916 o->chan = NULL; 01917 if (qe->parent->strategy) { 01918 if (qe->parent->timeoutrestart) 01919 *to = orig; 01920 ring_one(qe, outgoing, &numbusies); 01921 } 01922 numbusies++; 01923 break; 01924 case AST_CONTROL_CONGESTION: 01925 if (option_verbose > 2) 01926 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name); 01927 o->stillgoing = 0; 01928 if (in->cdr) 01929 ast_cdr_busy(in->cdr); 01930 ast_hangup(o->chan); 01931 o->chan = NULL; 01932 if (qe->parent->strategy) { 01933 if (qe->parent->timeoutrestart) 01934 *to = orig; 01935 ring_one(qe, outgoing, &numbusies); 01936 } 01937 numbusies++; 01938 break; 01939 case AST_CONTROL_RINGING: 01940 if (option_verbose > 2) 01941 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name); 01942 if (!sentringing) { 01943 #if 0 01944 ast_indicate(in, AST_CONTROL_RINGING); 01945 #endif 01946 sentringing++; 01947 } 01948 break; 01949 case AST_CONTROL_OFFHOOK: 01950 /* Ignore going off hook */ 01951 break; 01952 default: 01953 ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass); 01954 } 01955 } 01956 ast_frfree(f); 01957 } else { 01958 o->stillgoing = 0; 01959 ast_hangup(o->chan); 01960 o->chan = NULL; 01961 if (qe->parent->strategy) { 01962 if (qe->parent->timeoutrestart) 01963 *to = orig; 01964 ring_one(qe, outgoing, &numbusies); 01965 } 01966 } 01967 } 01968 o = o->next; 01969 } 01970 if (winner == in) { 01971 f = ast_read(in); 01972 #if 0 01973 if (f && (f->frametype != AST_FRAME_VOICE)) 01974 printf("Frame type: %d, %d\n", f->frametype, f->subclass); 01975 else if (!f || (f->frametype != AST_FRAME_VOICE)) 01976 printf("Hangup received on %s\n", in->name); 01977 #endif 01978 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) { 01979 /* Got hung up */ 01980 *to=-1; 01981 if (f) 01982 ast_frfree(f); 01983 return NULL; 01984 } 01985 if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass == '*')) { 01986 if (option_verbose > 3) 01987 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass); 01988 *to=0; 01989 ast_frfree(f); 01990 return NULL; 01991 } 01992 if ((f->frametype == AST_FRAME_DTMF) && (f->subclass != '*') && valid_exit(qe, f->subclass)) { 01993 if (option_verbose > 3) 01994 ast_verbose(VERBOSE_PREFIX_3 "User pressed digit: %c\n", f->subclass); 01995 *to=0; 01996 *digit=f->subclass; 01997 ast_frfree(f); 01998 return NULL; 01999 } 02000 ast_frfree(f); 02001 } 02002 if (!*to && (option_verbose > 2)) 02003 ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig); 02004 } 02005 02006 return peer; 02007 02008 }
|
|
Definition at line 2030 of file app_queue.c. References is_our_turn(), and QUEUE_TIMEOUT. Referenced by queue_exec(). 02031 { 02032 int res = 0; 02033 02034 /* This is the holding pen for callers 2 through maxlen */ 02035 for (;;) { 02036 enum queue_member_status stat; 02037 02038 if (is_our_turn(qe)) 02039 break; 02040 02041 /* If we have timed out, break out */ 02042 if (qe->expire && (time(NULL) > qe->expire)) { 02043 *reason = QUEUE_TIMEOUT; 02044 break; 02045 } 02046 02047 stat = get_member_status(qe->parent); 02048 02049 /* leave the queue if no agents, if enabled */ 02050 if (qe->parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) { 02051 *reason = QUEUE_LEAVEEMPTY; 02052 leave_queue(qe); 02053 break; 02054 } 02055 02056 /* leave the queue if no reachable agents, if enabled */ 02057 if ((qe->parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) { 02058 *reason = QUEUE_LEAVEUNAVAIL; 02059 leave_queue(qe); 02060 break; 02061 } 02062 02063 /* Make a position announcement, if enabled */ 02064 if (qe->parent->announcefrequency && !ringing && 02065 (res = say_position(qe))) 02066 break; 02067 02068 /* Make a periodic announcement, if enabled */ 02069 if (qe->parent->periodicannouncefrequency && !ringing && 02070 (res = say_periodic_announcement(qe))) 02071 break; 02072 02073 /* Wait a second before checking again */ 02074 if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000))) 02075 break; 02076 } 02077 return res; 02078 }
|
|
Definition at line 123 of file app_queue.c. |
|
Definition at line 153 of file app_queue.c. Referenced by load_module(), and unload_module(). |
|
Definition at line 155 of file app_queue.c. Referenced by load_module(). |
|
Definition at line 154 of file app_queue.c. Referenced by load_module(). |
|
Definition at line 185 of file app_queue.c. Referenced by load_module(), and unload_module(). |
|
Definition at line 187 of file app_queue.c. Referenced by load_module(). |
|
Definition at line 186 of file app_queue.c. Referenced by load_module(). |
|
Definition at line 169 of file app_queue.c. Referenced by load_module(), and unload_module(). |
|
Definition at line 171 of file app_queue.c. Referenced by load_module(). |
|
Definition at line 170 of file app_queue.c. Referenced by load_module(). |
|
Definition at line 207 of file app_queue.c. Referenced by load_module(), and unload_module(). |
|
Definition at line 209 of file app_queue.c. Referenced by load_module(). |
|
Definition at line 208 of file app_queue.c. Referenced by load_module(). |
|
Initial value:
"Usage: add queue member <channel> to <queue> [penalty <penalty>]\n"
Definition at line 3961 of file app_queue.c. |
|
Initial value: { { "add", "queue", "member", NULL }, handle_add_queue_member, "Add a channel to a specified queue", aqm_cmd_usage, complete_add_queue_member } Definition at line 3964 of file app_queue.c. Referenced by load_module(), and unload_module(). |
|
Initial value: { { "remove", "queue", "member", NULL }, handle_remove_queue_member, "Removes a channel from a specified queue", rqm_cmd_usage, complete_remove_queue_member } Definition at line 3971 of file app_queue.c. Referenced by load_module(), and unload_module(). |
|
Initial value: { { "show", "queue", NULL }, queue_show, "Show status of a specified queue", show_queue_usage, complete_queue } Definition at line 3957 of file app_queue.c. Referenced by load_module(), and unload_module(). |
|
Initial value: { { "show", "queues", NULL }, queues_show, "Show status of queues", show_queues_usage, NULL } Definition at line 3949 of file app_queue.c. Referenced by load_module(), and unload_module(). |
|
Definition at line 127 of file app_queue.c. |
|
Definition at line 244 of file app_queue.c. Referenced by _sip_show_peers(), aPGSQL_clear(), aPGSQL_connect(), aPGSQL_disconnect(), aPGSQL_fetch(), aPGSQL_query(), aPGSQL_reset(), config_odbc(), and manager_iax2_show_peers(). |
|
Definition at line 271 of file app_queue.c. |
|
Persistent Members astdb family.
Definition at line 223 of file app_queue.c. Referenced by dump_queue_members(), and reload_queue_members(). |
|
queues.conf [general] option
Definition at line 228 of file app_queue.c. Referenced by aqm_exec(), handle_add_queue_member(), load_module(), manager_add_queue_member(), reload_queues(), and set_member_paused(). |
|
Referenced by set_queue_result(). |
|
Definition at line 3296 of file app_queue.c. Referenced by load_module(), and unload_module(). |
|
Definition at line 374 of file app_queue.c. Referenced by __queues_show(), changethread(), compare_weight(), complete_queue(), complete_remove_queue_member(), find_queue_by_name_rt(), interface_exists_global(), load_realtime_queue(), manager_queues_status(), queue_function_qac(), reload_queue_members(), reload_queues(), remove_from_queue(), remove_queue(), and set_member_paused(). |
|
Initial value:
"Usage: remove queue member <channel> from <queue>\n"
Definition at line 3968 of file app_queue.c. |
|
Initial value: "Usage: show queue\n" " Provides summary information on a specified queue.\n" Definition at line 3953 of file app_queue.c. |
|
Initial value: "Usage: show queues\n" " Provides summary information on call queues.\n" Definition at line 3945 of file app_queue.c. |
|
Referenced by int2strat(), and strat2int(). |
|
Definition at line 125 of file app_queue.c. |
|
Definition at line 121 of file app_queue.c. |
|
Definition at line 245 of file app_queue.c. Referenced by _sip_show_peer(), build_reply_digest(), check_auth(), find_sip_method(), handle_response(), parse_sip_options(), reqprep(), sendtext_exec(), set_queue_result(), sip_alloc(), and sip_show_channel(). |
|
queues.conf per-queue weight option
Definition at line 231 of file app_queue.c. Referenced by queue_set_param(), and ring_entry(). |