69 #include <sys/signal.h>
70 #include <netinet/in.h>
1024 #define DEFAULT_RETRY 5
1025 #define DEFAULT_TIMEOUT 15
1027 #define MAX_PERIODIC_ANNOUNCEMENTS 10
1028 #define DEFAULT_MIN_ANNOUNCE_FREQUENCY 15
1030 #define MAX_QUEUE_BUCKETS 53
1033 #define RES_EXISTS (-1)
1034 #define RES_OUTOFMEMORY (-2)
1035 #define RES_NOSUCHQUEUE (-3)
1036 #define RES_NOT_DYNAMIC (-4)
1038 static char *
app =
"Queue";
1040 static char *
app_aqm =
"AddQueueMember" ;
1042 static char *
app_rqm =
"RemoveQueueMember" ;
1044 static char *
app_pqm =
"PauseQueueMember" ;
1046 static char *
app_upqm =
"UnpauseQueueMember" ;
1048 static char *
app_ql =
"QueueLog" ;
1051 static const char *
const pm_family =
"Queue/PersistentMembers";
1088 static const struct {
1177 char state_interface[80];
1178 char membername[80];
1190 unsigned int delme:1;
1191 unsigned int call_pending:1;
1192 char rt_uniqueid[80];
1207 #define ANNOUNCEHOLDTIME_ALWAYS 1
1208 #define ANNOUNCEHOLDTIME_ONCE 2
1209 #define QUEUE_EVENT_VARIABLES 3
1220 #define ANNOUNCEPOSITION_YES 1
1221 #define ANNOUNCEPOSITION_NO 2
1222 #define ANNOUNCEPOSITION_MORE_THAN 3
1223 #define ANNOUNCEPOSITION_LIMIT 4
1268 unsigned int dead:1;
1269 unsigned int eventwhencalled:2;
1270 unsigned int ringinuse:1;
1271 unsigned int announce_to_first_user:1;
1272 unsigned int setinterfacevar:1;
1273 unsigned int setqueuevar:1;
1274 unsigned int setqueueentryvar:1;
1275 unsigned int reportholdtime:1;
1276 unsigned int wrapped:1;
1277 unsigned int timeoutrestart:1;
1278 unsigned int announceholdtime:2;
1279 unsigned int announceposition:3;
1281 unsigned int maskmemberstatus:1;
1282 unsigned int realtime:1;
1283 unsigned int found:1;
1284 unsigned int relativeperiodicannounce:1;
1287 int announcepositionlimit;
1288 int announcefrequency;
1289 int minannouncefrequency;
1290 int periodicannouncefrequency;
1291 int numperiodicannounce;
1292 int randomperiodicannounce;
1293 int roundingseconds;
1299 int callscompletedinsl;
1305 int penaltymemberslimit;
1312 int timeoutpriority;
1336 static
int set_member_paused(const
char *queuename, const
char *interface, const
char *reason,
int paused);
1369 if (!strcasecmp(strategy,
strategies[x].name))
1403 static int queue_cmp_cb(
void *obj,
void *arg,
int flags)
1416 struct member *mem = obj;
1417 int *decrement_followers_after = arg;
1419 if (mem->
queuepos > *decrement_followers_after) {
1434 struct member *mem = obj;
1456 if (pos < queue->
rrpos) {
1463 #ifdef REF_DEBUG_ONLY_QUEUES
1464 #define queue_ref(a) __ao2_ref_debug(a,1,"",__FILE__,__LINE__,__PRETTY_FUNCTION__)
1465 #define queue_unref(a) __ao2_ref_debug(a,-1,"",__FILE__,__LINE__,__PRETTY_FUNCTION__)
1466 #define queue_t_ref(a,b) __ao2_ref_debug(a,1,b,__FILE__,__LINE__,__PRETTY_FUNCTION__)
1467 #define queue_t_unref(a,b) __ao2_ref_debug(a,-1,b,__FILE__,__LINE__,__PRETTY_FUNCTION__)
1468 #define queues_t_link(c,q,tag) __ao2_link_debug(c,q,tag,__FILE__,__LINE__,__PRETTY_FUNCTION__)
1469 #define queues_t_unlink(c,q,tag) __ao2_unlink_debug(c,q,tag,__FILE__,__LINE__,__PRETTY_FUNCTION__)
1471 #define queue_t_ref(a,b) queue_ref(a)
1472 #define queue_t_unref(a,b) queue_unref(a)
1473 #define queues_t_link(c,q,tag) ao2_t_link(c,q,tag)
1474 #define queues_t_unlink(c,q,tag) ao2_t_unlink(c,q,tag)
1491 char interfacevar[256]=
"";
1501 snprintf(interfacevar,
sizeof(interfacevar),
1502 "QUEUENAME=%s,QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUETALKTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
1534 new->pos = ++(*pos);
1552 if ((max_penalty != INT_MAX && member->
penalty > max_penalty) || (min_penalty != INT_MAX && member->
penalty <
min_penalty)) {
1554 ast_debug(4,
"%s is unavailable because his penalty is not between %d and %d\n", member->
membername, min_penalty, max_penalty);
1562 ast_debug(4,
"%s is unavailable because his device state is 'invalid'\n", member->
membername);
1568 ast_debug(4,
"%s is unavailable because his device state is 'unavailable'\n", member->
membername);
1574 ast_debug(4,
"%s is unavailable because his device state is 'inuse'\n", member->
membername);
1580 ast_debug(4,
"%s is unavailable because his device state is 'ringing'\n", member->
membername);
1586 ast_debug(4,
"%s is unavailable because his device state is 'unknown'\n", member->
membername);
1596 ast_debug(4,
"%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n", member->
membername, (
int) (time(NULL) - member->
lastcall), q->
wrapuptime);
1633 if (q->maskmemberstatus)
1639 "MemberName: %s\r\n"
1640 "Membership: %s\r\n"
1642 "CallsTaken: %d\r\n"
1646 q->name, m->interface, m->membername, m->dynamic ?
"dynamic" : m->realtime ?
"realtime" :
"static",
1647 m->penalty, m->calls, (
int)m->lastcall, m->status, m->paused
1660 char interface[80], *slash_pos;
1671 if ((slash_pos = strchr(interface,
'/')))
1672 if (!strncasecmp(interface,
"Local/", 6) && (slash_pos = strchr(slash_pos + 1,
'/')))
1675 if (!strcasecmp(interface, sc->
dev)) {
1712 datapsize =
sizeof(*sc) + strlen(device) + 1;
1718 strcpy(sc->
dev, device);
1784 ast_debug(1,
"Extension '%s@%s' changed to state '%d' (%s)\n", exten, context, device_state,
ast_devstate2str(device_state));
1786 ast_debug(3,
"Extension '%s@%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n",
1804 if ((cur =
ao2_alloc(
sizeof(*cur), NULL))) {
1844 const struct member *mem = obj;
1845 const char *chname = strchr(mem->
interface,
'/');
1849 for (i = 0; i < 5 && chname[i]; i++)
1856 struct member *mem1 = obj1, *mem2 = obj2;
1973 char *timestr, *maxstr, *minstr, *contentdup;
1975 struct rule_list *rl_iter;
1976 int penaltychangetime, inserted = 0;
1978 if (!(rule =
ast_calloc(1,
sizeof(*rule)))) {
1984 if (!(maxstr = strchr(contentdup,
','))) {
1985 ast_log(
LOG_WARNING,
"Improperly formatted penaltychange rule at line %d. Ignoring.\n", linenum);
1991 timestr = contentdup;
1993 if ((penaltychangetime = atoi(timestr)) < 0) {
1994 ast_log(
LOG_WARNING,
"Improper time parameter specified for penaltychange rule at line %d. Ignoring.\n", linenum);
1999 rule->
time = penaltychangetime;
2001 if ((minstr = strchr(maxstr,
',')))
2006 if (*maxstr ==
'+' || *maxstr ==
'-' || *maxstr ==
'\0') {
2013 if (*minstr ==
'+' || *minstr ==
'-')
2021 if (strcasecmp(rl_iter->
name, list_name))
2025 if (rule->
time < rule_iter->time) {
2052 char *option = NULL;
2053 while ((option =
strsep(&value_copy,
","))) {
2054 if (!strcasecmp(option,
"paused")) {
2056 }
else if (!strcasecmp(option,
"penalty")) {
2058 }
else if (!strcasecmp(option,
"inuse")) {
2060 }
else if (!strcasecmp(option,
"ringing")) {
2062 }
else if (!strcasecmp(option,
"invalid")) {
2064 }
else if (!strcasecmp(option,
"wrapup")) {
2066 }
else if (!strcasecmp(option,
"unavailable")) {
2068 }
else if (!strcasecmp(option,
"unknown")) {
2070 }
else if (!strcasecmp(option,
"loose")) {
2072 }
else if (!strcasecmp(option,
"strict")) {
2074 }
else if ((
ast_false(option) && joinempty) || (
ast_true(option) && !joinempty)) {
2076 }
else if ((
ast_false(option) && !joinempty) || (
ast_true(option) && joinempty)) {
2079 ast_log(
LOG_WARNING,
"Unknown option %s for '%s'\n", option, joinempty ?
"joinempty" :
"leavewhenempty");
2094 if (!strcasecmp(param,
"musicclass") ||
2095 !strcasecmp(param,
"music") || !strcasecmp(param,
"musiconhold")) {
2097 }
else if (!strcasecmp(param,
"announce")) {
2099 }
else if (!strcasecmp(param,
"context")) {
2101 }
else if (!strcasecmp(param,
"timeout")) {
2105 }
else if (!strcasecmp(param,
"ringinuse")) {
2107 }
else if (!strcasecmp(param,
"setinterfacevar")) {
2109 }
else if (!strcasecmp(param,
"setqueuevar")) {
2111 }
else if (!strcasecmp(param,
"setqueueentryvar")) {
2113 }
else if (!strcasecmp(param,
"monitor-format")) {
2115 }
else if (!strcasecmp(param,
"membermacro")) {
2117 }
else if (!strcasecmp(param,
"membergosub")) {
2119 }
else if (!strcasecmp(param,
"queue-youarenext")) {
2121 }
else if (!strcasecmp(param,
"queue-thereare")) {
2123 }
else if (!strcasecmp(param,
"queue-callswaiting")) {
2125 }
else if (!strcasecmp(param,
"queue-quantity1")) {
2127 }
else if (!strcasecmp(param,
"queue-quantity2")) {
2129 }
else if (!strcasecmp(param,
"queue-holdtime")) {
2131 }
else if (!strcasecmp(param,
"queue-minutes")) {
2133 }
else if (!strcasecmp(param,
"queue-minute")) {
2135 }
else if (!strcasecmp(param,
"queue-seconds")) {
2137 }
else if (!strcasecmp(param,
"queue-thankyou")) {
2139 }
else if (!strcasecmp(param,
"queue-callerannounce")) {
2141 }
else if (!strcasecmp(param,
"queue-reporthold")) {
2143 }
else if (!strcasecmp(param,
"announce-frequency")) {
2145 }
else if (!strcasecmp(param,
"announce-to-first-user")) {
2147 }
else if (!strcasecmp(param,
"min-announce-frequency")) {
2149 ast_debug(1,
"%s=%s for queue '%s'\n", param, val, q->
name);
2150 }
else if (!strcasecmp(param,
"announce-round-seconds")) {
2157 "using 0 instead for queue '%s' at line %d of queues.conf\n",
2158 val, param, q->
name, linenum);
2161 "using 0 instead for queue '%s'\n", val, param, q->
name);
2165 }
else if (!strcasecmp(param,
"announce-holdtime")) {
2166 if (!strcasecmp(val,
"once"))
2172 }
else if (!strcasecmp(param,
"announce-position")) {
2173 if (!strcasecmp(val,
"limit"))
2175 else if (!strcasecmp(val,
"more"))
2181 }
else if (!strcasecmp(param,
"announce-position-limit")) {
2183 }
else if (!strcasecmp(param,
"periodic-announce")) {
2184 if (strchr(val,
',')) {
2188 while ((s =
strsep(&buf,
",|"))) {
2201 }
else if (!strcasecmp(param,
"periodic-announce-frequency")) {
2203 }
else if (!strcasecmp(param,
"relative-periodic-announce")) {
2205 }
else if (!strcasecmp(param,
"random-periodic-announce")) {
2207 }
else if (!strcasecmp(param,
"retry")) {
2208 q->
retry = atoi(val);
2211 }
else if (!strcasecmp(param,
"wrapuptime")) {
2213 }
else if (!strcasecmp(param,
"penaltymemberslimit")) {
2217 }
else if (!strcasecmp(param,
"autofill")) {
2219 }
else if (!strcasecmp(param,
"monitor-type")) {
2220 if (!strcasecmp(val,
"mixmonitor"))
2222 }
else if (!strcasecmp(param,
"autopause")) {
2224 }
else if (!strcasecmp(param,
"maxlen")) {
2228 }
else if (!strcasecmp(param,
"ringlimit")) {
2232 }
else if (!strcasecmp(param,
"servicelevel")) {
2234 }
else if (!strcasecmp(param,
"strategy")) {
2243 ast_log(
LOG_WARNING,
"'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
2251 ast_log(
LOG_WARNING,
"Changing to the linear strategy currently requires asterisk to be restarted.\n");
2255 }
else if (!strcasecmp(param,
"joinempty")) {
2257 }
else if (!strcasecmp(param,
"leavewhenempty")) {
2259 }
else if (!strcasecmp(param,
"eventmemberstatus")) {
2261 }
else if (!strcasecmp(param,
"eventwhencalled")) {
2262 if (!strcasecmp(val,
"vars")) {
2267 }
else if (!strcasecmp(param,
"reportholdtime")) {
2269 }
else if (!strcasecmp(param,
"memberdelay")) {
2271 }
else if (!strcasecmp(param,
"weight")) {
2273 }
else if (!strcasecmp(param,
"timeoutrestart")) {
2275 }
else if (!strcasecmp(param,
"defaultrule")) {
2277 }
else if (!strcasecmp(param,
"timeoutpriority")) {
2278 if (!strcasecmp(val,
"conf")) {
2283 }
else if (failunknown) {
2285 ast_log(
LOG_WARNING,
"Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
2286 q->
name, param, linenum);
2327 static void rt_handle_member_record(
struct call_queue *q,
char *interface,
const char *rt_uniqueid,
const char *membername,
const char *penalty_str,
const char *paused_str,
const char* state_interface)
2341 penalty = atoi(penalty_str);
2347 paused = atoi(paused_str);
2449 char *
interface = NULL;
2450 const char *tmp_name;
2468 }
else if (!member_config)
2479 ast_debug(1,
"Queue %s not found in realtime.\n", queuename);
2501 for (tmpvar = queue_vars; tmpvar; tmpvar = tmpvar->
next) {
2502 if (!strcasecmp(tmpvar->
name,
"strategy")) {
2505 ast_log(
LOG_WARNING,
"'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
2519 memset(tmpbuf, 0,
sizeof(tmpbuf));
2520 for (v = queue_vars; v; v = v->
next) {
2522 if (strchr(v->
name,
'_')) {
2526 while ((tmp = strchr(tmp,
'_')))
2579 int prev_weight = 0;
2597 if (!member_config) {
2598 ast_debug(1,
"No queue_members defined in config extconfig.conf\n");
2603 prev_weight = q->
weight ? 1 : 0;
2613 if (!q->
weight && prev_weight) {
2616 if (q->
weight && !prev_weight) {
2645 char *
interface = NULL;
2660 ast_debug(3,
"Queue %s has no realtime members defined. No need for update\n", q->
name);
2735 if ((!inserted) && (qe->
prio > cur->
prio)) {
2742 if (!inserted && (qe->
prio >= cur->
prio) && position && (position <= pos + 1)) {
2746 if (position < pos) {
2747 ast_log(
LOG_NOTICE,
"Asked to be inserted at position %d but forced into position %d due to higher priority callers\n", position, pos);
2764 "CallerIDNum: %s\r\n"
2765 "CallerIDName: %s\r\n"
2766 "ConnectedLineNum: %s\r\n"
2767 "ConnectedLineName: %s\r\n"
2816 int digitlen = strlen(qe->
digits);
2819 if (digitlen <
sizeof(qe->
digits) - 2) {
2820 qe->
digits[digitlen] = digit;
2821 qe->
digits[digitlen + 1] =
'\0';
2850 int res = 0, avgholdmins, avgholdsecs, announceposition = 0;
2873 announceposition = 1;
2876 if (announceposition == 1) {
2925 ast_verb(3,
"Hold time for %s is %d minute(s) %d seconds\n", qe->
parent->
name, avgholdmins, avgholdsecs);
2936 if (avgholdmins >= 1) {
2941 if (avgholdmins == 1) {
2951 if (avgholdsecs >= 1) {
2966 ast_verb(3,
"Told %s in %s their queue position (which was %d)\n",
3002 qe->
parent->
holdtime = (((oldvalue << 2) - oldvalue) + newholdtime) >> 2;
3014 struct queue_ent *current, *prev = NULL;
3020 queue_t_ref(q,
"Copy queue pointer from queue entry");
3024 for (current = q->
head; current; current = current->
next) {
3025 if (current == qe) {
3031 "Channel: %s\r\nQueue: %s\r\nCount: %d\r\nPosition: %d\r\nUniqueid: %s\r\n",
3042 snprintf(posstr,
sizeof(posstr),
"%d", qe->
pos);
3096 if (outgoing->
chan && (outgoing->
chan != exception)) {
3097 if (exception || cancel_answered_elsewhere)
3102 outgoing = outgoing->
q_next;
3214 strcpy(vars,
"Variable: ");
3217 for (i = 0, j = 10; (i < len - 1) && (j < len - 1); i++, j++) {
3220 if (tmp[i + 1] ==
'\0')
3222 if (tmp[i] ==
'\n') {
3343 ast_debug(1,
"%s actually not available, can't receive call\n",
3372 char *location, *location2;
3373 const char *macrocontext, *macroexten;
3374 char pickupmark[256],
chan[128];
3385 if ((location = strchr(tech,
'/')))
3416 tmp->
chan->
data =
"(Outgoing Line)";
3481 if (!strncasecmp(tech,
"dahdi", 5)) {
3482 if((chan[0] >
'0') && (chan[0] <=
'9')) {
3483 if ((location2 = strchr(chan,
'r')))
3484 *location2++ =
'\0';
3487 snprintf(pickupmark,
sizeof(pickupmark),
"%s/%s", tech, chan);
3507 "AgentCalled: %s\r\n"
3509 "ChannelCalling: %s\r\n"
3510 "DestinationChannel: %s\r\n"
3511 "CallerIDNum: %s\r\n"
3512 "CallerIDName: %s\r\n"
3513 "ConnectedLineNum: %s\r\n"
3514 "ConnectedLineName: %s\r\n"
3543 for (cur = outgoing; cur; cur = cur->
q_next) {
3544 if (cur->stillgoing &&
3571 ast_debug(1,
"Nobody left to try ringing in queue\n");
3577 for (cur = outgoing; cur; cur = cur->
q_next) {
3591 ast_debug(1,
"Queue timed out while ringing members.\n");
3667 ast_verb(3,
"Playing periodic announcement\n");
3713 "OriginalPosition: %d\r\n"
3724 ast_verb(3,
"Nobody picked up in %d ms\n", rnatime);
3740 "MemberName: %s\r\n"
3755 ast_verb(3,
"Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n",
3758 ast_verb(3,
"Failed to pause Queue Member %s in queue %s!\n", interface, qe->
parent->
name);
3764 ast_verb(3,
"Auto-Pausing Queue Member %s in all queues since they failed to answer on queue %s.\n",
3767 ast_verb(3,
"Failed to pause Queue Member %s in all queues!\n", interface);
3774 #define AST_MAX_WATCHERS 256
3793 int numbusies = prebusies;
3802 char membername[80] =
"";
3810 struct timeval start_time_tv =
ast_tvnow();
3818 starttime = (long) time(NULL);
3820 for (epollo = outgoing; epollo; epollo = epollo->
q_next) {
3827 int numlines, retry,
pos = 1;
3832 for (retry = 0; retry < 2; retry++) {
3834 for (o = outgoing; o; o = o->
q_next) {
3839 watchers[pos++] = o->
chan;
3850 if (pos > 1 || !stillgoing ||
3855 ring_one(qe, outgoing, &numbusies);
3859 if (numlines == (numbusies + numnochan)) {
3860 ast_debug(1,
"Everyone is busy at this time\n");
3865 ast_debug(3,
"No one is answering queue '%s' (%d numlines / %d busies / %d failed channels)\n", queue, numlines, numbusies, numnochan);
3891 ast_verb(3,
"%s answered %s\n", ochan_name, inchan_name);
3909 size_t encoded_size;
3918 }
else if (o->
chan && (o->
chan == winner)) {
3937 if ((stuff = strchr(tmpchan,
'/'))) {
3945 if (!strcasecmp(tech,
"Local")) {
3956 ast_verb(3,
"Now forwarding %s to '%s/%s' (thanks to %s)\n", inchan_name, tech, stuff, ochan_name);
3961 "Forwarding failed to create channel to dial '%s/%s'\n",
4051 ast_verb(3,
"%s answered %s\n", ochan_name, inchan_name);
4069 size_t encoded_size;
4080 ast_verb(3,
"%s is busy\n", ochan_name);
4084 endtime = (long) time(NULL);
4085 endtime -= starttime;
4086 rna(endtime * 1000, qe, on, membername, 0);
4093 ring_one(qe, outgoing, &numbusies);
4094 starttime = (long) time(NULL);
4100 ast_verb(3,
"%s is circuit-busy\n", ochan_name);
4103 endtime = (long) time(NULL);
4104 endtime -= starttime;
4105 rna(endtime * 1000, qe, on, membername, 0);
4112 ring_one(qe, outgoing, &numbusies);
4113 starttime = (long) time(NULL);
4119 ast_verb(3,
"%s is ringing\n", ochan_name);
4132 ast_verb(3,
"Connected line update to %s prevented.\n", inchan_name);
4138 ast_verb(3,
"%s connected line has changed. Saving it until answer for %s\n", ochan_name, inchan_name);
4177 ast_verb(3,
"Redirecting update to %s prevented\n",
4181 ast_verb(3,
"%s redirecting info has changed, passing it to %s\n",
4182 ochan_name, inchan_name);
4194 endtime = (long) time(NULL) - starttime;
4195 rna(endtime * 1000, qe, on, membername, 1);
4202 ring_one(qe, outgoing, &numbusies);
4203 starttime = (long) time(NULL);
4303 for (epollo = outgoing; epollo; epollo = epollo->
q_next) {
4336 ast_debug(1,
"There %s %d available %s.\n", avl != 1 ?
"are" :
"is", avl, avl != 1 ?
"members" :
"member");
4338 while ((idx < avl) && (ch) && (ch != qe)) {
4371 char max_penalty_str[20];
4380 if (max_penalty < 0) {
4384 snprintf(max_penalty_str,
sizeof(max_penalty_str),
"%d", max_penalty);
4387 ast_debug(3,
"Setting max penalty to %d for caller %s since %d seconds have elapsed\n",
4392 char min_penalty_str[20];
4401 if (min_penalty < 0) {
4405 if (max_penalty != INT_MAX && min_penalty > max_penalty) {
4409 snprintf(min_penalty_str,
sizeof(min_penalty_str),
"%d", min_penalty);
4412 ast_debug(3,
"Setting min penalty to %d for caller %s since %d seconds have elapsed\n",
4473 while (qe->
pr && ((time(NULL) - qe->
start) >= qe->
pr->
time)) {
4513 if (shared_lastcall) {
4536 if (callcompletedinsl)
4540 q->
talktime = (((oldtalktime << 2) - oldtalktime) + newtalktime) >> 2;
4565 ast_debug(1,
"Disregarding penalty, %d members and %d in penaltymemberslimit.\n",
4588 if (pos < q->rrpos) {
4624 ast_log(
LOG_DEBUG,
"New metric %d for member %s with %d rings (limit %d)\n",
4640 const char *reason = NULL;
4653 reason =
"transfer";
4662 "MemberName: %s\r\n"
4668 (
long)(callstart - qe->
start), (
long)(time(NULL) - callstart), reason,
4676 int callcompletedinsl;
4713 (
long) (time(NULL) - callstart), qe->
opos);
4755 ast_log(
LOG_WARNING,
"Unable to create transfer datastore. queue_log will not show attended transfer\n");
4779 qeb->
chan = originator;
4822 static int try_calling(
struct queue_ent *qe,
const char *options,
char *announceoverride,
const char *
url,
int *
tries,
int *noption,
const char *agi,
const char *macro,
const char *gosub,
int ringing)
4829 char queuename[256]=
"";
4830 char interfacevar[256]=
"";
4836 int res = 0, bridge = 0;
4842 time_t now = time(NULL);
4844 char nondataquality = 1;
4845 char *agiexec = NULL;
4846 char *macroexec = NULL;
4847 char *gosubexec = NULL;
4848 const char *monitorfilename;
4849 const char *monitor_exec;
4850 const char *monitor_options;
4851 char tmpid[256], tmpid2[256];
4852 char meid[1024], meid2[1024];
4853 char mixmonargs[1512];
4854 struct ast_app *mixmonapp = NULL;
4857 int forwardsallowed = 1;
4858 int block_connected_line = 0;
4859 int callcompletedinsl;
4868 memset(&bridge_config, 0,
sizeof(bridge_config));
4882 for (; options && *options; options++)
4922 forwardsallowed = 0;
4925 block_connected_line = 1;
4946 ast_debug(1,
"%s is trying to call a queue member.\n",
4952 announce = announceoverride;
4974 if (!(dialed_interfaces =
ast_calloc(1,
sizeof(*dialed_interfaces)))) {
4981 datastore->
data = dialed_interfaces;
4988 dialed_interfaces = datastore->
data;
4993 ast_debug(1,
"Skipping dialing interface '%s' since it has already been dialed\n",
5010 if (strncasecmp(cur->
interface,
"Local/", 6)) {
5064 to = (qe->
expire - now) * 1000;
5081 ast_log(
LOG_DEBUG,
"%s is trying to ring one member from %s. This is try number %d\n",
5084 ring_one(qe, outgoing, &numbusies);
5087 forwardsallowed, ringing);
5108 peer = lpeer ? lpeer->
chan : NULL;
5124 for (o = outgoing; o; o = o->
q_next) {
5140 if (!strcmp(peer->
tech->
type,
"DAHDI"))
5162 if (!res2 && announce) {
5169 int holdtime, holdtimesecs;
5172 holdtime = abs((now - qe->
start) / 60);
5173 holdtimesecs = abs((now - qe->
start) % 60);
5180 if (holdtimesecs > 1) {
5200 "MemberName: %s\r\n"
5209 ast_log(
LOG_NOTICE,
"Caller was about to talk to agent on %s but the caller hungup.\n", peer->
name);
5247 snprintf(interfacevar,
sizeof(interfacevar),
"MEMBERINTERFACE=%s,MEMBERNAME=%s,MEMBERCALLS=%d,MEMBERLASTCALL=%ld,MEMBERPENALTY=%d,MEMBERDYNAMIC=%d,MEMBERREALTIME=%d",
5256 snprintf(interfacevar,
sizeof(interfacevar),
"QEHOLDTIME=%ld,QEORIGINALPOS=%d",
5257 (
long) time(NULL) - qe->
start, qe->
opos);
5276 const char *monexec;
5277 ast_debug(1,
"Starting Monitor as requested.\n");
5286 if (monitorfilename) {
5292 snprintf(tmpid,
sizeof(tmpid),
"chan-%lx", (
unsigned long)
ast_random());
5302 ast_debug(1,
"Starting MixMonitor as requested.\n");
5303 if (!monitorfilename) {
5307 snprintf(tmpid,
sizeof(tmpid),
"chan-%lx", (
unsigned long)
ast_random());
5309 const char *m = monitorfilename;
5310 for (p = tmpid2; p < tmpid2 +
sizeof(tmpid2) - 1; p++, m++) {
5313 if (*(m + 1) ==
'{')
5325 if (p == tmpid2 +
sizeof(tmpid2))
5326 tmpid2[
sizeof(tmpid2) - 1] =
'\0';
5338 monitor_options =
"";
5343 const char *m = monitor_exec;
5344 for (p = meid2; p < meid2 +
sizeof(meid2) - 1; p++, m++) {
5347 if (*(m + 1) ==
'{')
5359 if (p == meid2 +
sizeof(meid2))
5360 meid2[
sizeof(meid2) - 1] =
'\0';
5365 snprintf(tmpid2,
sizeof(tmpid2),
"%s.%s", tmpid, qe->
parent->
monfmt);
5368 snprintf(mixmonargs,
sizeof(mixmonargs),
"%s,b%s,%s", tmpid2, monitor_options, monitor_exec);
5370 snprintf(mixmonargs,
sizeof(mixmonargs),
"%s,b%s", tmpid2, monitor_options);
5372 ast_debug(1,
"Arguments being passed to MixMonitor: %s\n", mixmonargs);
5381 ast_log(
LOG_WARNING,
"Asked to run MixMonitor on this call, but cannot find the MixMonitor app!\n");
5388 ast_debug(1,
"app_queue: sendurl=%s.\n", url);
5402 ast_debug(1,
"app_queue: macro=%s.\n", macroexec);
5413 res =
pbx_exec(peer, application, macroexec);
5414 ast_debug(1,
"Macro exited with status %d\n", res);
5437 ast_debug(1,
"app_queue: gosub=%s.\n", gosubexec);
5448 char *gosub_args, *gosub_argstart;
5455 gosub_argstart = strchr(gosubexec,
',');
5456 if (gosub_argstart) {
5457 const char *what_is_s =
"s";
5458 *gosub_argstart = 0;
5461 what_is_s =
"~~s~~";
5463 if (
ast_asprintf(&gosub_args,
"%s,%s,1(%s)", gosubexec, what_is_s, gosub_argstart + 1) < 0) {
5466 *gosub_argstart =
',';
5468 const char *what_is_s =
"s";
5471 what_is_s =
"~~s~~";
5473 if (
ast_asprintf(&gosub_args,
"%s,%s,1", gosubexec, what_is_s) < 0) {
5478 res =
pbx_exec(peer, application, gosub_args);
5481 memset(&args, 0,
sizeof(args));
5486 ast_debug(1,
"Gosub exited with status %d\n", res);
5488 ast_log(
LOG_ERROR,
"Could not Allocate string for Gosub arguments -- Gosub Call Aborted!\n");
5502 ast_debug(1,
"app_queue: agi=%s.\n", agi);
5508 ast_log(
LOG_WARNING,
"Asked to execute an AGI on this channel, but could not find application (agi)!\n");
5512 (
long)(orig - to > 0 ? (orig - to) / 1000 : 0));
5547 "MemberName: %s\r\n"
5549 "BridgedChannel: %s\r\n"
5553 (
long) time(NULL) - qe->
start, peer->
uniqueid, (
long)(orig - to > 0 ? (orig - to) / 1000 : 0),
5558 if ((queue_end_bridge =
ao2_alloc(
sizeof(*queue_end_bridge), NULL))) {
5559 queue_end_bridge->
q = qe->
parent;
5587 (
long) (time(NULL) - callstart), qe->
opos);
5591 (
long) (callstart - qe->
start), (
long) (time(NULL) - callstart), qe->
opos);
5595 (
long) (callstart - qe->
start), (
long) (time(NULL) - callstart), qe->
opos);
5615 res = bridge ? bridge : 1;
5646 if (!strcasecmp(interface, mem->
interface)) {
5664 struct member *cur_member;
5719 struct member *mem, tmpmem;
5730 queue_t_unref(q,
"Interface wasn't dynamic, expiring temporary reference");
5736 "MemberName: %s\r\n",
5741 if (queue_persistent_members)
5765 struct member *new_member, *old_member;
5775 if ((new_member =
create_queue_member(interface, membername, penalty, paused, state_interface))) {
5781 "MemberName: %s\r\n"
5782 "Membership: %s\r\n"
5784 "CallsTaken: %d\r\n"
5824 ast_queue_log(
"NONE",
"NONE", interface, (paused ?
"PAUSEALL" :
"UNPAUSEALL"),
"%s",
"");
5831 if (mem->
paused == paused) {
5832 ast_debug(1,
"%spausing already-%spaused queue member %s:%s\n", (paused ?
"" :
"un"), (paused ?
"" :
"un"), q->
name, interface);
5841 ast_log(
LOG_WARNING,
"Failed %spausing realtime queue member %s:%s\n", (paused ?
"" :
"un"), q->
name, interface);
5850 if (queue_persistent_members)
5859 "MemberName: %s\r\n"
5867 "MemberName: %s\r\n"
5890 static int set_member_penalty(
const char *queuename,
const char *interface,
int penalty)
5892 int foundinterface = 0, foundqueue = 0;
5925 if (foundinterface) {
5927 }
else if (!foundqueue) {
5941 int foundqueue = 0, penalty;
5974 const char *queue_name;
5990 for (entry = db_tree; entry; entry = entry->
next) {
5992 queue_name = entry->
key + strlen(pm_family) + 2;
6007 ast_log(
LOG_WARNING,
"Error loading persistent queue: '%s': it does not exist\n", queue_name);
6017 cur_ptr = queue_data;
6018 while ((member =
strsep(&cur_ptr,
",|"))) {
6022 interface =
strsep(&member,
";");
6023 penalty_tok =
strsep(&member,
";");
6024 paused_tok =
strsep(&member,
";");
6025 membername =
strsep(&member,
";");
6026 state_interface =
strsep(&member,
";");
6029 ast_log(
LOG_WARNING,
"Error parsing persistent member string for '%s' (penalty)\n", queue_name);
6032 penalty = strtol(penalty_tok, NULL, 10);
6033 if (
errno == ERANGE) {
6039 ast_log(
LOG_WARNING,
"Error parsing persistent member string for '%s' (paused)\n", queue_name);
6042 paused = strtol(paused_tok, NULL, 10);
6043 if ((
errno == ERANGE) || paused < 0 || paused > 1) {
6048 ast_debug(1,
"Reload Members: Queue: %s Member: %s Name: %s Penalty: %d Paused: %d\n", queue_name, interface, membername, penalty, paused);
6051 ast_log(
LOG_ERROR,
"Out of Memory when reloading persistent queue member\n");
6077 ast_log(
LOG_WARNING,
"PauseQueueMember requires an argument ([queuename],interface[,options][,reason])\n");
6086 ast_log(
LOG_WARNING,
"Missing interface argument to PauseQueueMember ([queuename],interface[,options[,reason]])\n");
6113 ast_log(
LOG_WARNING,
"UnpauseQueueMember requires an argument ([queuename],interface[,options[,reason]])\n");
6122 ast_log(
LOG_WARNING,
"Missing interface argument to PauseQueueMember ([queuename],interface[,options[,reason]])\n");
6141 char *
parse, *temppos = NULL;
6149 ast_log(
LOG_WARNING,
"RemoveQueueMember requires an argument (queuename[,interface])\n");
6159 temppos = strrchr(
args.interface,
'-');
6174 ast_debug(1,
"Unable to remove interface '%s' from queue '%s': Not there\n",
args.interface,
args.queuename);
6184 ast_log(
LOG_WARNING,
"Unable to remove interface from queue '%s': '%s' is not a dynamic member\n",
args.queuename,
args.interface);
6197 char *
parse, *temppos = NULL;
6209 ast_log(
LOG_WARNING,
"AddQueueMember requires an argument (queuename[,interface[,penalty[,options[,membername[,stateinterface]]]]])\n");
6219 temppos = strrchr(
args.interface,
'-');
6225 if ((sscanf(
args.penalty,
"%30d", &penalty) != 1) || penalty < 0) {
6270 ast_log(
LOG_WARNING,
"QueueLog requires arguments (queuename,uniqueid,membername,event[,additionalinfo]\n");
6280 ast_log(
LOG_WARNING,
"QueueLog requires arguments (queuename,uniqueid,membername,event[,additionalinfo])\n");
6285 "%s",
args.params ?
args.params :
"");
6294 struct rule_list *rl_iter;
6298 if (!strcasecmp(rl_iter->
name, tmp))
6305 ast_log(
LOG_ERROR,
"Memory allocation error when copying penalty rules! Aborting!\n");
6335 const char *user_priority;
6336 const char *max_penalty_str;
6337 const char *min_penalty_str;
6346 int makeannouncement = 0;
6364 ast_log(
LOG_WARNING,
"Queue requires an argument: queuename[,options[,URL[,announceoverride[,timeout[,agi[,macro[,gosub[,rule[,position]]]]]]]]]\n");
6372 qe.
start = time(NULL);
6383 if (user_priority) {
6384 if (sscanf(user_priority,
"%30d", &prio) == 1) {
6385 ast_debug(1,
"%s: Got priority %d from ${QUEUE_PRIO}.\n", chan->
name, prio);
6388 user_priority, chan->
name);
6392 ast_debug(3,
"NO QUEUE_PRIO variable found. Using default.\n");
6399 if (sscanf(max_penalty_str,
"%30d", &max_penalty) == 1) {
6400 ast_debug(1,
"%s: Got max penalty %d from ${QUEUE_MAX_PENALTY}.\n", chan->
name, max_penalty);
6403 max_penalty_str, chan->
name);
6404 max_penalty = INT_MAX;
6407 max_penalty = INT_MAX;
6411 if (sscanf(min_penalty_str,
"%30d", &min_penalty) == 1) {
6412 ast_debug(1,
"%s: Got min penalty %d from ${QUEUE_MIN_PENALTY}.\n", chan->
name, min_penalty);
6415 min_penalty_str, chan->
name);
6416 min_penalty = INT_MAX;
6419 min_penalty = INT_MAX;
6423 if (
args.options && (strchr(
args.options,
'r')))
6426 if (ringing != 1 &&
args.options && (strchr(
args.options,
'R'))) {
6430 if (
args.options && (strchr(
args.options,
'c')))
6433 if (
args.position) {
6434 position = atoi(
args.position);
6436 ast_log(
LOG_WARNING,
"Invalid position '%s' given for call to queue '%s'. Assuming no preference for position\n",
args.position,
args.queuename);
6441 ast_debug(1,
"queue: %s, options: %s, url: %s, announce: %s, expires: %ld, priority: %d\n",
6479 makeannouncement = 0;
6497 if (makeannouncement) {
6503 makeannouncement = 1;
6543 ast_verb(3,
"Exiting on time-out cycle\n");
6585 (
long) time(NULL) - qe.
start);
6587 }
else if (qcontinue) {
6637 char interfacevar[256] =
"";
6655 snprintf(interfacevar,
sizeof(interfacevar),
6656 "QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUETALKTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
6668 snprintf(buf, len,
"%d", res);
6688 snprintf(buf, len,
"%d", q != NULL? 1 : 0);
6690 queue_t_unref(q,
"Done with temporary reference in QUEUE_EXISTS()");
6714 if ((option = strchr(data,
',')))
6720 if (!strcasecmp(option,
"logged")) {
6730 }
else if (!strcasecmp(option,
"free")) {
6740 }
else if (!strcasecmp(option,
"ready")) {
6753 }
else if (!strcasecmp(option,
"paused")) {
6766 queue_t_unref(q,
"Done with temporary reference in QUEUE_MEMBER()");
6770 snprintf(buf, len,
"%d", count);
6786 static int depflag = 1;
6790 ast_log(
LOG_NOTICE,
"The function QUEUE_MEMBER_COUNT has been deprecated in favor of the QUEUE_MEMBER function and will not be in further releases.\n");
6810 queue_t_unref(q,
"Done with temporary reference in QUEUE_MEMBER_COUNT");
6814 snprintf(buf, len,
"%d", count);
6831 ast_log(
LOG_ERROR,
"QUEUE_WAITING_COUNT requires an argument: queuename\n");
6839 queue_t_unref(q,
"Done with reference in QUEUE_WAITING_COUNT()");
6850 snprintf(buf, len,
"%d", count);
6872 int buflen = 0, count = 0;
6880 strncat(buf + buflen,
",", len - buflen - 1);
6883 strncat(buf + buflen, m->
interface, len - buflen - 1);
6886 if (buflen >= len - 2) {
6900 buf[len - 1] =
'\0';
6917 ast_log(
LOG_ERROR,
"Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
6923 if (
args.argc < 2) {
6924 ast_log(
LOG_ERROR,
"Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
6931 snprintf (buf, len,
"%d", penalty);
6946 ast_log(
LOG_ERROR,
"Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
6952 if (
args.argc < 2) {
6953 ast_log(
LOG_ERROR,
"Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
6957 penalty = atoi(value);
7012 strncat(buffer, tmp,
sizeof(tmp));
7071 strncat(buffer, tmp,
sizeof(tmp));
7146 struct rule_list *rl_iter, *new_rl;
7148 char *rulecat = NULL;
7153 ast_log(
LOG_NOTICE,
"No queuerules.conf file found, queues will not follow penalty rules\n");
7156 ast_log(
LOG_NOTICE,
"queuerules.conf has not changed since it was last loaded. Not taking any action.\n");
7159 ast_log(
LOG_ERROR,
"Config file queuerules.conf is in an invalid format. Aborting.\n");
7170 if (!(new_rl =
ast_calloc(1,
sizeof(*new_rl)))) {
7178 if(!strcasecmp(rulevar->
name,
"penaltychange"))
7194 const char *general_val = NULL;
7197 queue_debug =
ast_true(general_val);
7198 queue_persistent_members = 0;
7200 queue_persistent_members =
ast_true(general_val);
7201 autofill_default = 0;
7203 autofill_default =
ast_true(general_val);
7204 montype_default = 0;
7206 if (!strcasecmp(general_val,
"mixmonitor"))
7207 montype_default = 1;
7211 update_cdr =
ast_true(general_val);
7212 shared_lastcall = 0;
7214 shared_lastcall =
ast_true(general_val);
7227 char *membername, *interface, *state_interface, *tmp;
7229 struct member *cur, *newm;
7249 interface =
args.interface;
7253 penalty = atoi(tmp);
7262 membername =
args.membername;
7265 membername = interface;
7269 state_interface =
args.state_interface;
7272 state_interface = interface;
7313 if (!member->
delme) {
7343 int prev_weight = 0;
7364 prev_weight = q->
weight ? 1 : 0;
7385 ast_log(
LOG_WARNING,
"'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
7394 if (member_reload) {
7399 if (member_reload && !strcasecmp(var->
name,
"member")) {
7401 }
else if (queue_reload) {
7408 if (!q->
weight && prev_weight) {
7411 else if (q->
weight && !prev_weight) {
7416 if (member_reload) {
7434 char *queuename = arg;
7445 char *queuename = arg;
7456 char *queuename = arg;
7485 ast_log(
LOG_NOTICE,
"No call queueing config file (queues.conf), so no call queues\n");
7490 ast_log(
LOG_ERROR,
"Config file queues.conf is in an invalid format. Aborting.\n");
7504 if (member_reload) {
7511 if (!strcasecmp(cat,
"general") && queue_reload) {
7607 time_t now = time(NULL);
7611 if (argc != 2 && argc != 3)
7648 if (!realtime_queue) {
7653 queue_t_unref(realtime_queue,
"Queue is already in memory");
7656 if (argc == 3 && strcasecmp(q->
name, argv[2])) {
7671 ast_str_append(&out, 0,
") in '%s' strategy (%ds holdtime, %ds talktime), R:%d, W:%d, C:%d, A:%d, SL:%2.1f%% within %ds",
7690 mem->
dynamic ?
" (dynamic)" :
"",
7691 mem->
realtime ?
" (realtime)" :
"",
7692 mem->
paused ?
" (paused)" :
"",
7695 ast_str_append(&out, 0,
" has taken %d calls (last was %ld secs ago)",
7711 for (qe = q->
head; qe; qe = qe->
next) {
7712 ast_str_set(&out, 0,
" %d. %s (wait: %ld:%2.2ld, prio: %d)",
7714 (
long) (now - qe->
start) % 60, qe->
prio);
7726 ast_str_set(&out, 0,
"No such queue: %s.", argv[2]);
7748 int list_len, word_len = strlen(word);
7749 const char *find, *end_find, *end_list;
7752 while (isspace(*list)) {
7756 while ((find = strstr(list, word))) {
7758 if (find != list && *(find - 1) !=
' ') {
7761 while (!isspace(*list) && *list !=
'\0') {
7765 while (isspace(*list)) {
7772 list_len = strlen(list);
7773 end_find = find + word_len;
7774 end_list = list + list_len;
7775 if (end_find == end_list || *end_find !=
' ') {
7778 while (!isspace(*list) && *list !=
'\0') {
7782 while (isspace(*list)) {
7806 static char *
complete_queue(
const char *line,
const char *word,
int pos,
int state, ptrdiff_t word_list_offset)
7811 int wordlen = strlen(word);
7813 const char *word_list = NULL;
7817 if (word_list_offset && strlen(line) >= word_list_offset) {
7818 word_list = line + word_list_offset;
7823 if (!strncasecmp(word, q->
name, wordlen) && ++which > state
7836 if (!ret && which == state && !wordlen && !strncmp(
"queue show", line, 10)) {
7857 "Usage: queue show\n"
7858 " Provides summary information on a specified queue.\n";
7872 static const char *
const a[] = {
"queue",
"show" };
7884 struct rule_list *rl_iter;
7921 int qlongestholdtime = 0;
7924 char idText[256] =
"";
7934 snprintf(idText, 256,
"ActionID: %s\r\n",
id);
7945 qlongestholdtime = 0;
7959 for (qe = q->
head; qe; qe = qe->
next) {
7960 if ((now - qe->
start) > qlongestholdtime) {
7961 qlongestholdtime = now - qe->
start;
7972 "LongestHoldTime: %d\r\n"
7975 q->
name, qmemcount, qmemavail, qchancount, q->
holdtime, q->
talktime, qlongestholdtime, idText);
7982 "Event: QueueSummaryComplete\r\n"
7997 char idText[256] =
"";
8008 snprintf(idText,
sizeof(idText),
"ActionID: %s\r\n",
id);
8026 "ServiceLevel: %d\r\n"
8027 "ServicelevelPerf: %2.1f\r\n"
8042 "Membership: %s\r\n"
8044 "CallsTaken: %d\r\n"
8058 for (qe = q->
head; qe; qe = qe->
next) {
8064 "CallerIDNum: %s\r\n"
8065 "CallerIDName: %s\r\n"
8066 "ConnectedLineNum: %s\r\n"
8067 "ConnectedLineName: %s\r\n"
8076 (
long) (now - qe->
start), idText);
8085 "Event: QueueStatusComplete\r\n"
8094 const char *queuename, *interface, *penalty_s, *paused_s, *membername, *state_interface;
8095 int paused, penalty = 0;
8116 else if (sscanf(penalty_s,
"%30d", &penalty) != 1 || penalty < 0)
8124 switch (
add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members, state_interface)) {
8126 ast_queue_log(queuename,
"MANAGER", interface,
"ADDMEMBER",
"%s", paused ?
"PAUSED" :
"");
8145 const char *queuename, *interface;
8157 ast_queue_log(queuename,
"MANAGER", interface,
"REMOVEMEMBER",
"%s",
"");
8164 astman_send_error(s, m,
"Unable to remove interface from queue: No such queue");
8179 const char *queuename, *interface, *paused_s, *reason;
8197 astman_send_ack(s, m, paused ?
"Interface paused successfully" :
"Interface unpaused successfully");
8203 const char *queuename, *event, *
message, *interface, *uniqueid;
8216 ast_queue_log(queuename,
S_OR(uniqueid,
"NONE"), interface, event,
"%s", message);
8225 const char *queuename = NULL;
8226 int header_found = 0;
8242 if (!header_found) {
8256 const char *queuename = NULL;
8280 return state == 0 ?
ast_strdup(
"penalty") : NULL;
8285 sprintf(num,
"%d", state);
8302 const char *queuename, *interface, *penalty_s;
8315 penalty = atoi(penalty_s);
8327 const char *queuename, *interface, *membername = NULL, *state_interface = NULL;
8332 e->
command =
"queue add member";
8334 "Usage: queue add member <dial string> to <queue> [[[penalty <penalty>] as <membername>] state_interface <interface>]\n"
8335 " Add a dial string (Such as a channel,e.g. SIP/6001) to a queue with optionally: a penalty, membername and a state_interface\n";
8341 if ((a->
argc != 6) && (a->
argc != 8) && (a->
argc != 10) && (a->
argc != 12)) {
8343 }
else if (strcmp(a->
argv[4],
"to")) {
8345 }
else if ((a->
argc >= 8) && strcmp(a->
argv[6],
"penalty")) {
8347 }
else if ((a->
argc >= 10) && strcmp(a->
argv[8],
"as")) {
8349 }
else if ((a->
argc == 12) && strcmp(a->
argv[10],
"state_interface")) {
8353 queuename = a->
argv[5];
8354 interface = a->argv[3];
8356 if (sscanf(a->
argv[7],
"%30d", &penalty) == 1) {
8358 ast_cli(a->
fd,
"Penalty must be >= 0\n");
8362 ast_cli(a->
fd,
"Penalty must be an integer >= 0\n");
8369 if (a->
argc >= 10) {
8370 membername = a->
argv[9];
8373 if (a->
argc >= 12) {
8374 state_interface = a->
argv[11];
8377 switch (
add_to_queue(queuename, interface, membername, penalty, 0, queue_persistent_members, state_interface)) {
8379 ast_queue_log(queuename,
"CLI", interface,
"ADDMEMBER",
"%s",
"");
8380 ast_cli(a->
fd,
"Added interface '%s' to queue '%s'\n", interface, queuename);
8383 ast_cli(a->
fd,
"Unable to add interface '%s' to queue '%s': Already there\n", interface, queuename);
8386 ast_cli(a->
fd,
"Unable to add interface to queue '%s': No such queue\n", queuename);
8406 int wordlen = strlen(word);
8409 if (pos > 5 || pos < 3)
8412 return (state == 0 ?
ast_strdup(
"from") : NULL);
8424 if (!strncasecmp(word, m->
membername, wordlen) && ++which > state) {
8430 queue_t_unref(q,
"Done with iterator, returning interface name");
8447 const char *queuename, *interface;
8451 e->
command =
"queue remove member";
8453 "Usage: queue remove member <channel> from <queue>\n"
8454 " Remove a specific channel from a queue.\n";
8462 }
else if (strcmp(a->
argv[4],
"from")) {
8466 queuename = a->
argv[5];
8467 interface = a->argv[3];
8471 ast_queue_log(queuename,
"CLI", interface,
"REMOVEMEMBER",
"%s",
"");
8472 ast_cli(a->
fd,
"Removed interface '%s' from queue '%s'\n", interface, queuename);
8475 ast_cli(a->
fd,
"Unable to remove interface '%s' from queue '%s': Not there\n", interface, queuename);
8478 ast_cli(a->
fd,
"Unable to remove interface from queue '%s': No such queue\n", queuename);
8484 ast_cli(a->
fd,
"Unable to remove interface '%s' from queue '%s': Member is not dynamic\n", interface, queuename);
8498 return state == 0 ?
ast_strdup(
"queue") : NULL;
8502 return state == 0 ?
ast_strdup(
"reason") : NULL;
8512 const char *queuename, *interface, *reason;
8517 e->
command =
"queue {pause|unpause} member";
8519 "Usage: queue {pause|unpause} member <member> [queue <queue> [reason <reason>]]\n"
8520 " Pause or unpause a queue member. Not specifying a particular queue\n"
8521 " will pause or unpause a member across all queues to which the member\n"
8530 }
else if (a->
argc >= 5 && strcmp(a->
argv[4],
"queue")) {
8532 }
else if (a->
argc == 8 && strcmp(a->
argv[6],
"reason")) {
8537 interface = a->argv[3];
8538 queuename = a->
argc >= 6 ? a->
argv[5] : NULL;
8539 reason = a->
argc == 8 ? a->
argv[7] : NULL;
8540 paused = !strcasecmp(a->
argv[1],
"pause");
8543 ast_cli(a->
fd,
"%spaused interface '%s'", paused ?
"" :
"un", interface);
8545 ast_cli(a->
fd,
" in queue '%s'", queuename);
8547 ast_cli(a->
fd,
" for reason '%s'", reason);
8551 ast_cli(a->
fd,
"Unable to %spause interface '%s'", paused ?
"" :
"un", interface);
8553 ast_cli(a->
fd,
" in queue '%s'", queuename);
8555 ast_cli(a->
fd,
" for reason '%s'", reason);
8586 const char *queuename = NULL, *interface;
8591 e->
command =
"queue set penalty";
8593 "Usage: queue set penalty <penalty> on <interface> [in <queue>]\n"
8594 " Set a member's penalty in the queue specified. If no queue is specified\n"
8595 " then that interface's penalty is set in all queues to which that interface is a member\n";
8601 if (a->
argc != 6 && a->
argc != 8) {
8603 }
else if (strcmp(a->
argv[4],
"on") || (a->
argc > 6 && strcmp(a->
argv[6],
"in"))) {
8608 queuename = a->
argv[7];
8609 interface = a->argv[5];
8610 penalty = atoi(a->
argv[3]);
8614 ast_cli(a->
fd,
"Set penalty on interface '%s' from queue '%s'\n", interface, queuename);
8617 ast_cli(a->
fd,
"Failed to set penalty on interface '%s' from queue '%s'\n", interface, queuename);
8627 struct rule_list *rl_iter;
8628 int wordlen = strlen(word);
8636 if (!strncasecmp(word, rl_iter->
name, wordlen) && ++which > state) {
8649 struct rule_list *rl_iter;
8653 e->
command =
"queue show rules";
8655 "Usage: queue show rules [rulename]\n"
8656 " Show the list of rules associated with rulename. If no\n"
8657 " rulename is specified, list all rules defined in queuerules.conf\n";
8666 rule = a->
argc == 4 ? a->
argv[3] :
"";
8687 e->
command =
"queue reset stats";
8689 "Usage: queue reset stats [<queuenames>]\n"
8691 "Issuing this command will reset statistics for\n"
8692 "<queuenames>, or for all queues if no queue is\n"
8712 for (i = 3; i < a->
argc; ++i) {
8726 e->
command =
"queue reload {parameters|members|rules|all}";
8728 "Usage: queue reload {parameters|members|rules|all} [<queuenames>]\n"
8729 "Reload queues. If <queuenames> are specified, only reload information pertaining\n"
8730 "to <queuenames>. One of 'parameters,' 'members,' 'rules,' or 'all' must be\n"
8731 "specified in order to know what information to reload. Below is an explanation\n"
8732 "of each of these qualifiers.\n"
8734 "\t'members' - reload queue members from queues.conf\n"
8735 "\t'parameters' - reload all queue options except for queue members\n"
8736 "\t'rules' - reload the queuerules.conf file\n"
8737 "\t'all' - reload queue rules, parameters, and members\n"
8739 "Note: the 'rules' qualifier here cannot actually be applied to a specific queue.\n"
8740 "Use of the 'rules' qualifier causes queuerules.conf to be reloaded. Even if only\n"
8741 "one queue is specified when using this command, reloading queue rules may cause\n"
8742 "other queues to be affected\n";
8747 const char *command_end = a->
line + strlen(
"queue reload ");
8748 command_end = strchr(command_end,
' ');
8750 command_end = a->
line + strlen(a->
line);
8761 if (!strcasecmp(a->
argv[2],
"rules")) {
8763 }
else if (!strcasecmp(a->
argv[2],
"members")) {
8765 }
else if (!strcasecmp(a->
argv[2],
"parameters")) {
8767 }
else if (!strcasecmp(a->
argv[2],
"all")) {
8776 for (i = 3; i < a->
argc; ++i) {
8784 "Usage: queue pause member <channel> in <queue> reason <reason>\n";
8787 "Usage: queue unpause member <channel> in <queue> reason <reason>\n";
8790 "Usage: queue set member penalty <channel> from <queue> <penalty>\n";
8804 #define DATA_EXPORT_CALL_QUEUE(MEMBER) \
8805 MEMBER(call_queue, name, AST_DATA_STRING) \
8806 MEMBER(call_queue, moh, AST_DATA_STRING) \
8807 MEMBER(call_queue, announce, AST_DATA_STRING) \
8808 MEMBER(call_queue, context, AST_DATA_STRING) \
8809 MEMBER(call_queue, membermacro, AST_DATA_STRING) \
8810 MEMBER(call_queue, membergosub, AST_DATA_STRING) \
8811 MEMBER(call_queue, defaultrule, AST_DATA_STRING) \
8812 MEMBER(call_queue, sound_next, AST_DATA_STRING) \
8813 MEMBER(call_queue, sound_thereare, AST_DATA_STRING) \
8814 MEMBER(call_queue, sound_calls, AST_DATA_STRING) \
8815 MEMBER(call_queue, queue_quantity1, AST_DATA_STRING) \
8816 MEMBER(call_queue, queue_quantity2, AST_DATA_STRING) \
8817 MEMBER(call_queue, sound_holdtime, AST_DATA_STRING) \
8818 MEMBER(call_queue, sound_minutes, AST_DATA_STRING) \
8819 MEMBER(call_queue, sound_minute, AST_DATA_STRING) \
8820 MEMBER(call_queue, sound_seconds, AST_DATA_STRING) \
8821 MEMBER(call_queue, sound_thanks, AST_DATA_STRING) \
8822 MEMBER(call_queue, sound_callerannounce, AST_DATA_STRING) \
8823 MEMBER(call_queue, sound_reporthold, AST_DATA_STRING) \
8824 MEMBER(call_queue, dead, AST_DATA_BOOLEAN) \
8825 MEMBER(call_queue, eventwhencalled, AST_DATA_BOOLEAN) \
8826 MEMBER(call_queue, ringinuse, AST_DATA_BOOLEAN) \
8827 MEMBER(call_queue, announce_to_first_user, AST_DATA_BOOLEAN) \
8828 MEMBER(call_queue, setinterfacevar, AST_DATA_BOOLEAN) \
8829 MEMBER(call_queue, setqueuevar, AST_DATA_BOOLEAN) \
8830 MEMBER(call_queue, setqueueentryvar, AST_DATA_BOOLEAN) \
8831 MEMBER(call_queue, reportholdtime, AST_DATA_BOOLEAN) \
8832 MEMBER(call_queue, wrapped, AST_DATA_BOOLEAN) \
8833 MEMBER(call_queue, timeoutrestart, AST_DATA_BOOLEAN) \
8834 MEMBER(call_queue, announceholdtime, AST_DATA_INTEGER) \
8835 MEMBER(call_queue, maskmemberstatus, AST_DATA_BOOLEAN) \
8836 MEMBER(call_queue, realtime, AST_DATA_BOOLEAN) \
8837 MEMBER(call_queue, found, AST_DATA_BOOLEAN) \
8838 MEMBER(call_queue, announcepositionlimit, AST_DATA_INTEGER) \
8839 MEMBER(call_queue, announcefrequency, AST_DATA_SECONDS) \
8840 MEMBER(call_queue, minannouncefrequency, AST_DATA_SECONDS) \
8841 MEMBER(call_queue, periodicannouncefrequency, AST_DATA_SECONDS) \
8842 MEMBER(call_queue, numperiodicannounce, AST_DATA_INTEGER) \
8843 MEMBER(call_queue, randomperiodicannounce, AST_DATA_INTEGER) \
8844 MEMBER(call_queue, roundingseconds, AST_DATA_SECONDS) \
8845 MEMBER(call_queue, holdtime, AST_DATA_SECONDS) \
8846 MEMBER(call_queue, talktime, AST_DATA_SECONDS) \
8847 MEMBER(call_queue, callscompleted, AST_DATA_INTEGER) \
8848 MEMBER(call_queue, callsabandoned, AST_DATA_INTEGER) \
8849 MEMBER(call_queue, servicelevel, AST_DATA_INTEGER) \
8850 MEMBER(call_queue, callscompletedinsl, AST_DATA_INTEGER) \
8851 MEMBER(call_queue, monfmt, AST_DATA_STRING) \
8852 MEMBER(call_queue, montype, AST_DATA_INTEGER) \
8853 MEMBER(call_queue, count, AST_DATA_INTEGER) \
8854 MEMBER(call_queue, maxlen, AST_DATA_INTEGER) \
8855 MEMBER(call_queue, wrapuptime, AST_DATA_SECONDS) \
8856 MEMBER(call_queue, retry, AST_DATA_SECONDS) \
8857 MEMBER(call_queue, timeout, AST_DATA_SECONDS) \
8858 MEMBER(call_queue, weight, AST_DATA_INTEGER) \
8859 MEMBER(call_queue, autopause, AST_DATA_INTEGER) \
8860 MEMBER(call_queue, timeoutpriority, AST_DATA_INTEGER) \
8861 MEMBER(call_queue, rrpos, AST_DATA_INTEGER) \
8862 MEMBER(call_queue, memberdelay, AST_DATA_INTEGER) \
8863 MEMBER(call_queue, autofill, AST_DATA_INTEGER) \
8864 MEMBER(call_queue, members, AST_DATA_CONTAINER)
8869 #define DATA_EXPORT_MEMBER(MEMBER) \
8870 MEMBER(member, interface, AST_DATA_STRING) \
8871 MEMBER(member, state_interface, AST_DATA_STRING) \
8872 MEMBER(member, membername, AST_DATA_STRING) \
8873 MEMBER(member, penalty, AST_DATA_INTEGER) \
8874 MEMBER(member, calls, AST_DATA_INTEGER) \
8875 MEMBER(member, dynamic, AST_DATA_INTEGER) \
8876 MEMBER(member, realtime, AST_DATA_INTEGER) \
8877 MEMBER(member, status, AST_DATA_INTEGER) \
8878 MEMBER(member, paused, AST_DATA_BOOLEAN) \
8879 MEMBER(member, rt_uniqueid, AST_DATA_STRING)
8883 #define DATA_EXPORT_QUEUE_ENT(MEMBER) \
8884 MEMBER(queue_ent, moh, AST_DATA_STRING) \
8885 MEMBER(queue_ent, announce, AST_DATA_STRING) \
8886 MEMBER(queue_ent, context, AST_DATA_STRING) \
8887 MEMBER(queue_ent, digits, AST_DATA_STRING) \
8888 MEMBER(queue_ent, valid_digits, AST_DATA_INTEGER) \
8889 MEMBER(queue_ent, pos, AST_DATA_INTEGER) \
8890 MEMBER(queue_ent, prio, AST_DATA_INTEGER) \
8891 MEMBER(queue_ent, last_pos_said, AST_DATA_INTEGER) \
8892 MEMBER(queue_ent, last_periodic_announce_time, AST_DATA_INTEGER) \
8893 MEMBER(queue_ent, last_periodic_announce_sound, AST_DATA_INTEGER) \
8894 MEMBER(queue_ent, last_pos, AST_DATA_INTEGER) \
8895 MEMBER(queue_ent, opos, AST_DATA_INTEGER) \
8896 MEMBER(queue_ent, handled, AST_DATA_INTEGER) \
8897 MEMBER(queue_ent, pending, AST_DATA_INTEGER) \
8898 MEMBER(queue_ent, max_penalty, AST_DATA_INTEGER) \
8899 MEMBER(queue_ent, min_penalty, AST_DATA_INTEGER) \
8900 MEMBER(queue_ent, linpos, AST_DATA_INTEGER) \
8901 MEMBER(queue_ent, linwrapped, AST_DATA_INTEGER) \
8902 MEMBER(queue_ent, start, AST_DATA_INTEGER) \
8903 MEMBER(queue_ent, expire, AST_DATA_INTEGER) \
8904 MEMBER(queue_ent, cancel_answered_elsewhere, AST_DATA_INTEGER)
8921 struct ast_data *data_queue, *data_members = NULL, *enum_node;
8922 struct ast_data *data_member, *data_callers = NULL, *data_caller, *data_caller_channel;
8961 if (!data_members) {
8963 if (!data_members) {
8983 for (qe = queue->
head; qe; qe = qe->
next) {
8984 if (!data_callers) {
8986 if (!data_callers) {
9000 if (!data_caller_channel) {
9025 struct call_queue *queue, *queue_realtime = NULL;
9048 if (!queue_realtime) {
9111 if (device_state_sub)
9148 ast_log(
LOG_ERROR,
"Queue virtual context 'app_queue_gosub_virtual_context' does not exist and unable to create\n");
9152 if (queue_persistent_members)
9186 ast_log(
LOG_WARNING,
"devicestate taskprocessor reference failed - devicestate notifications will not occur\n");
9214 .nonoptreq =
"res_monitor",
static int get_member_penalty(char *queuename, char *interface)
struct ast_str * sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS]
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
static int queue_function_qac_dep(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Get the total number of members in a specific queue (Deprecated)
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
struct ast_channel * ast_waitfor_n(struct ast_channel **chan, int n, int *ms)
Waits for input on a group of channels Wait for input on an array of channels for a given # of millis...
union ast_frame_subclass subclass
#define ao2_t_find(arg1, arg2, arg3, arg4)
struct callattempt * q_next
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
enum sip_cc_notify_state state
Options for ast_pbx_run()
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
static char accountcode[AST_MAX_ACCOUNT_CODE]
static void do_print(struct mansession *s, int fd, const char *str)
direct ouput to manager or cli with proper terminator
static int say_position(struct queue_ent *qe, int ringing)
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Find devicestate as text message for output.
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
struct call_queue * parent
#define ast_channel_lock(chan)
int ast_cdr_isset_unanswered(void)
static char exten[AST_MAX_EXTENSION]
Main Channel structure associated with a channel.
char accountcode[AST_MAX_ACCOUNT_CODE]
static struct ast_custom_function queuewaitingcount_function
static int update_realtime_member_field(struct member *mem, const char *queue_name, const char *field, const char *value)
#define AST_CLI_DEFINE(fn, txt,...)
ast_device_state
Device States.
void ast_cdr_failed(struct ast_cdr *cdr)
Fail a call.
static int member_hash_fn(const void *obj, const int flags)
static int remove_members_and_mark_unfound(void *obj, void *arg, int flags)
char * str
Subscriber phone number (Malloced)
struct ast_party_connected_line connected
Channel Connected Line ID information.
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
#define MAX_PERIODIC_ANNOUNCEMENTS
#define AST_LIST_LOCK(head)
Locks a list.
static int store_next_rr(struct queue_ent *qe, struct callattempt *outgoing)
Search for best metric and add to Round Robbin queue.
Asterisk locking-related definitions:
ast_extension_states
Extension states.
void astman_append(struct mansession *s, const char *fmt,...)
static void queue_transfer_destroy(void *data)
Asterisk main include file. File version handling, generic pbx functions.
void ast_poll_channel_add(struct ast_channel *chan0, struct ast_channel *chan1)
#define ao2_link(arg1, arg2)
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
static int rqm_exec(struct ast_channel *chan, const char *data)
RemoveQueueMember application.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
static int queue_function_queuememberpaused(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
void(* end_bridge_callback_data_fixup)(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator)
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
static struct ast_custom_function queuememberstatus_function
char digits[AST_MAX_EXTENSION]
static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator)
The data tree to be returned by the callbacks and managed by functions local to this file...
char * str
Subscriber phone number (Malloced)
const ast_string_field sound_holdtime
void ast_channel_set_caller_event(struct ast_channel *chan, const struct ast_party_caller *caller, const struct ast_set_party_caller *update)
Set the caller id information in the Asterisk channel and generate an AMI event if the caller id name...
unsigned int eventwhencalled
struct ast_party_caller caller
Channel Caller ID information.
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
char * strsep(char **str, const char *delims)
struct ast_channel * chan
#define DATA_EXPORT_CALL_QUEUE(MEMBER)
struct ast_app * pbx_findapp(const char *app)
Look up an application.
static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, enum empty_conditions conditions, int devstate)
Check if members are available.
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
static struct ast_datastore_info queue_transfer_info
a datastore used to help correctly log attended transfers of queue callers
static int mark_member_dead(void *obj, void *arg, int flags)
const ast_string_field membergosub
#define queue_t_unref(a, b)
const ast_string_field uniqueid
struct ast_flags features_callee
String manipulation functions.
static char * handle_queue_add_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int load_module(void)
static struct ast_data_entry queue_data_providers[]
static char * handle_queue_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
struct rule_list::@58 rules
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Allocate and initialize an object.
char dstchannel[AST_MAX_EXTENSION]
void ast_cdr_reset(struct ast_cdr *cdr, struct ast_flags *flags)
Reset the detail record, optionally posting it first.
struct ast_party_id id
Connected party ID.
int last_periodic_announce_sound
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
void ast_party_connected_line_set_init(struct ast_party_connected_line *init, const struct ast_party_connected_line *guide)
Initialize the given connected line structure using the given guide for a set update operation...
#define ast_test_flag(p, flag)
Support for translation of data formats. translate.c.
static int upqm_exec(struct ast_channel *chan, const char *data)
UnPauseQueueMember application.
int ast_unload_realtime(const char *family)
Release any resources cached for a realtime family.
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
struct ast_party_name name
Subscriber name.
#define ANNOUNCEPOSITION_NO
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
int ast_extension_state_del(int id, ast_state_cb_type change_cb)
Deletes a registered state change callback by ID.
static char * complete_queue_pause_member(const char *line, const char *word, int pos, int state)
static void update_realtime_members(struct call_queue *q)
static char * handle_queue_remove_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
void ast_channel_update_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update)
Indicate that the redirecting id has changed.
#define DEFAULT_MIN_ANNOUNCE_FREQUENCY
struct call_queue::@57 rules
unsigned int maskmemberstatus
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap)
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
char context[AST_MAX_CONTEXT]
static int manager_queue_reset(struct mansession *s, const struct message *m)
int ast_channel_supports_html(struct ast_channel *channel)
Checks for HTML support on a channel.
static int mark_dead_and_unfound(void *obj, void *arg, int flags)
#define ao2_iterator_next(arg1)
#define ast_set_flag(p, flag)
descriptor for a cli entry.
int ast_cel_report_event(struct ast_channel *chan, enum ast_cel_event_type event_type, const char *userdefevname, const char *extra, struct ast_channel *peer2)
Report a channel event.
static int manager_queue_member_penalty(struct mansession *s, const struct message *m)
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
static void member_remove_from_queue(struct call_queue *queue, struct member *mem)
struct call_queue * lastqueue
void ast_db_freetree(struct ast_db_entry *entry)
Free structure created by ast_db_gettree()
int ast_add_extension2(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add an extension to an extension context, this time with an ast_context *.
#define ao2_callback(c, flags, cb_fn, arg)
void ast_channel_update_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Indicate that the connected line information has changed.
struct ast_taskprocessor * ast_taskprocessor_get(const char *name, enum ast_tps_options create)
Get a reference to a taskprocessor with the specified name and create the taskprocessor if necessary...
static int kill_dead_members(void *obj, void *arg, int flags)
char dcontext[AST_MAX_EXTENSION]
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define MAX_QUEUE_BUCKETS
This entries are for multiple registers.
static void member_call_pending_clear(struct member *mem)
unsigned int timeoutrestart
Structure for variables, used for configurations and for channel variables.
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
static struct ast_custom_function queuemembercount_dep
#define ao2_t_iterator_next(arg1, arg2)
globally accessible channel datastores
struct ast_cdr * ast_cdr_dup(struct ast_cdr *cdr)
Duplicate a record.
static struct callattempt * wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed, int ringing)
Wait for a member to answer the call.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
#define DATA_EXPORT_MEMBER(MEMBER)
static int queue_function_exists(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Check if a given queue exists.
static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
Calculate the metric of each member in the outgoing callattempts.
struct ast_party_redirecting redirecting
Redirecting/Diversion information.
void * ast_aoc_destroy_decoded(struct ast_aoc_decoded *decoded)
free an ast_aoc_decoded object
unsigned int announceholdtime
Structure for a data store type.
Configuration File Parser.
static int reload_queue_rules(int reload)
Reload the rules defined in queuerules.conf.
char * str
Subscriber name (Malloced)
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
int ast_db_get_allocated(const char *family, const char *key, char **out)
Get key value specified by family/key as a heap allocated string.
int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
Bridge a call, optionally allowing redirection.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
static int attended_transfer_occurred(struct ast_channel *chan)
mechanism to tell if a queue caller was atxferred by a queue member.
static char * __queues_show(struct mansession *s, int fd, int argc, const char *const *argv)
Show queue(s) status and statistics.
static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl, int newtalktime)
update the queue status
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
struct ast_str * ast_str_create(size_t init_len)
Create a malloc'ed dynamic length string.
#define AST_OPTION_TONE_VERIFY
static void reload_single_member(const char *memberdata, struct call_queue *q)
reload information pertaining to a single member
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
unsigned int setinterfacevar
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
static int set_member_penalty(const char *queuename, const char *interface, int penalty)
#define ast_str_alloca(init_len)
Structure for a data store object.
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
static void set_queue_result(struct ast_channel *chan, enum queue_result res)
sets the QUEUESTATUS channel variable
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int caller, int frame)
Run a connected line interception macro and update a channel's connected line information.
static struct strategy strategies[]
static int queue_function_memberpenalty_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Dialplan function QUEUE_MEMBER_PENALTY() Gets the members penalty.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
static int queue_delme_members_decrement_followers(void *obj, void *arg, int flag)
struct ast_aoc_decoded * aoc_s_rate_list
static int say_periodic_announcement(struct queue_ent *qe, int ringing)
Playback announcement to queued members if period has elapsed.
const ast_string_field sound_thanks
static void clear_queue(struct call_queue *q)
void ast_cli(int fd, const char *fmt,...)
static int can_ring_entry(struct queue_ent *qe, struct callattempt *call)
void ast_monitor_setjoinfiles(struct ast_channel *chan, int turnon)
#define AST_DATA_ENTRY(__path, __handler)
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
static char * queue_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define ast_module_user_remove(user)
enum ast_channel_adsicpe adsicpe
int ast_unregister_application(const char *app)
Unregister an application.
unsigned int announce_to_first_user
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
struct ao2_container * members
void ast_free_ptr(void *ptr)
#define ast_verb(level,...)
static void recalc_holdtime(struct queue_ent *qe, int newholdtime)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
const ast_string_field membermacro
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
int announcepositionlimit
static int insert_penaltychange(const char *list_name, const char *content, const int linenum)
Change queue penalty by adding rule.
static struct ast_custom_function queueexists_function
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
static int strat2int(const char *strategy)
static int queue_function_queuememberstatus(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
String fields in structures.
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
static int member_status_available(int status)
#define ast_manager_event(chan, category, event, contents,...)
static int manager_queue_rule_show(struct mansession *s, const struct message *m)
static struct member * interface_exists(struct call_queue *q, const char *interface)
static int wait_a_bit(struct queue_ent *qe)
static int compare_weight(struct call_queue *rq, struct member *member)
static const char qum_cmd_usage[]
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
struct ast_party_id id
Caller party ID.
static int queue_function_var(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
create interface var with all queue details.
static void device_state_cb(const struct ast_event *event, void *unused)
static int queue_function_memberpenalty_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Dialplan function QUEUE_MEMBER_PENALTY() Sets the members penalty.
char lastdata[AST_MAX_EXTENSION]
int ast_update_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Update realtime configuration.
struct ast_cdr * ast_cdr_append(struct ast_cdr *cdr, struct ast_cdr *newcdr)
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
static struct ast_taskprocessor * devicestate_tps
#define ast_asprintf(a, b, c...)
static int queue_function_qac(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Get number either busy / free / ready or total members of a specific queue.
#define ast_debug(level,...)
Log a DEBUG message.
int ast_channel_data_add_structure(struct ast_data *tree, struct ast_channel *chan, int add_bridged)
Insert into an astdata tree, the channel structure.
static void member_add_to_queue(struct call_queue *queue, struct member *mem)
static char * complete_queue_set_member_penalty(const char *line, const char *word, int pos, int state)
struct ast_db_entry * next
#define AST_DATA_HANDLER_VERSION
The Data API structures version.
Generic Advice of Charge encode and decode routines.
const ast_string_field sound_minute
struct ast_party_connected_line connected
struct ast_aoc_decoded * ast_aoc_decode(struct ast_aoc_encoded *encoded, size_t size, struct ast_channel *chan)
decodes an encoded aoc payload.
static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
Configure a queue parameter.
static struct ast_custom_function queuemembercount_function
struct ast_party_id ani
Automatic Number Identification (ANI)
int periodicannouncefrequency
static struct ao2_container * queues
static void end_bridge_callback(void *data)
static char * vars2manager(struct ast_channel *chan, char *vars, size_t len)
convert "\n" to "\nVariable: " ready for manager to use
General Asterisk PBX channel definitions.
static char dialcontext[AST_MAX_CONTEXT]
struct ast_party_dialed::@155 number
Dialed/Called number.
static struct ast_custom_function queuememberpenalty_function
static int pqm_exec(struct ast_channel *chan, const char *data)
PauseQueueMember application.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
static char * complete_queue(const char *line, const char *word, int pos, int state, ptrdiff_t word_list_offset)
Check if a given word is in a space-delimited list.
#define ast_config_load(filename, flags)
Load a config file.
#define ast_manager_register_xml(a, b, c)
Register a manager callback using XML documentation to describe the manager.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
struct ast_datastore_info dialed_interface_info
struct ast_aoc_encoded * ast_aoc_encode(struct ast_aoc_decoded *decoded, size_t *out_size, struct ast_channel *chan)
encodes a decoded aoc structure so it can be passed on the wire
unsigned int block_connected_update
static void parse_empty_options(const char *value, enum empty_conditions *empty, int joinempty)
const ast_string_field sound_thereare
Data structure associated with a custom dialplan function.
static void free_members(struct call_queue *q, int all)
Iterate through queue's member list and delete them.
enum ast_pbx_result ast_pbx_run_args(struct ast_channel *c, struct ast_pbx_args *args)
Execute the PBX in the current thread.
struct ast_data * ast_data_add_node(struct ast_data *root, const char *childname)
Add a container child.
#define AST_MAX_EXTENSION
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
const ast_string_field context
#define AST_STRING_FIELD(name)
Declare a string field.
#define ast_data_unregister(path)
void ast_party_number_init(struct ast_party_number *init)
Initialize the given number structure.
void * end_bridge_callback_data
Caller Party information.
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
#define ao2_ref(o, delta)
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
static int reload_handler(int reload, struct ast_flags *mask, const char *queuename)
The command center for all reload operations.
long int ast_random(void)
static void hangupcalls(struct callattempt *outgoing, struct ast_channel *exception, int cancel_answered_elsewhere)
Hang up a list of outgoing calls.
const ast_string_field sound_next
static struct callattempt * find_best(struct callattempt *outgoing)
find the entry with the best metric, or NULL
char dst[AST_MAX_EXTENSION]
A set of macros to manage forward-linked lists.
int ast_monitor_start(struct ast_channel *chan, const char *format_spec, const char *fname_base, int need_lock, int stream_action)
Start monitoring a channel.
static void queue_set_global_params(struct ast_config *cfg)
char channel[AST_MAX_EXTENSION]
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
struct call_queue * lastqueue
static int unload_module(void)
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
struct ast_party_id ani
Automatic Number Identification (ANI)
#define ast_data_register_multiple(data_entries, entries)
#define ANNOUNCEPOSITION_MORE_THAN
static int handle_statechange(void *datap)
set a member's status based on device state of that member's interface
#define ast_module_user_add(chan)
Core PBX routines and definitions.
static struct autopause autopausesmodes[]
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
void ast_party_number_free(struct ast_party_number *doomed)
Destroy the party number contents.
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
static int queue_member_decrement_followers(void *obj, void *arg, int flag)
struct ast_flags features_caller
#define ast_data_add_structure(structure_name, root, structure)
The list of nodes with their search requirement.
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
static int num_available_members(struct call_queue *q)
Get the number of members available to accept a call.
static char * handle_queue_rule_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
struct ast_party_dialed dialed
Dialed/Called information.
static int montype_default
queues.conf [general] option
static void leave_queue(struct queue_ent *qe)
Caller leaving queue.
static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
Part 2 of ring_one.
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
We define a custom "local user" structure because we use it not only for keeping track of what is i...
#define ast_strdupa(s)
duplicate a string in memory from the stack
static int member_cmp_fn(void *obj1, void *obj2, int flags)
static char * complete_queue_rule_show(const char *line, const char *word, int pos, int state)
static void destroy_queue(void *obj)
Free queue's member list then its string fields.
int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, struct ast_party_connected_line *connected)
Parse connected line indication frame data.
Responsible for call detail data.
static int queue_cmp_cb(void *obj, void *arg, int flags)
char lastapp[AST_MAX_EXTENSION]
static int autofill_default
queues.conf [general] option
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
static int manager_queue_log_custom(struct mansession *s, const struct message *m)
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
void ast_party_caller_set_init(struct ast_party_caller *init, const struct ast_party_caller *guide)
Initialize the given caller structure using the given guide for a set update operation.
static int manager_queue_reload(struct mansession *s, const struct message *m)
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason, int position)
#define ANNOUNCEPOSITION_YES
static int word_in_list(const char *list, const char *word)
Check if a given word is in a space-delimited list.
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree If family is specified, only those keys will be returned...
void ast_data_remove_node(struct ast_data *root, struct ast_data *child)
Remove a node that was added using ast_data_add_.
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
static struct ast_custom_function queuememberlist_function
static struct call_queue * load_realtime_queue(const char *queuename)
const ast_string_field name
static struct ast_datastore * setup_transfer_datastore(struct queue_ent *qe, struct member *member, time_t starttime, int callcompletedinsl)
create a datastore for storing relevant info to log attended transfers in the queue_log ...
const ast_string_field call_forward
void ast_party_connected_line_set(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src, const struct ast_set_party_connected_line *update)
Set the connected line information based on another connected line source.
unsigned int reportholdtime
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct ast_channel * chan
enum ast_channel_state _state
static void rt_handle_member_record(struct call_queue *q, char *interface, const char *rt_uniqueid, const char *membername, const char *penalty_str, const char *paused_str, const char *state_interface)
Find rt member record to update otherwise create one.
static int extensionstate2devicestate(int state)
Helper function which converts from extension state to device state values.
Connected Line/Party information.
const ast_string_field name
unsigned int pending_connected_update
int pbx_builtin_setvar_multiple(struct ast_channel *chan, const char *data)
Parse and set multiple channel variables, where the pairs are separated by the ',' character...
static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing)
A large function which calls members, updates statistics, and bridges the caller and a member...
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
#define ao2_alloc(data_size, destructor_fn)
static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused)
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
static int ql_exec(struct ast_channel *chan, const char *data)
QueueLog application.
Redirecting Line information. RDNIS (Redirecting Directory Number Information Service) Where a call d...
#define DATA_EXPORT_QUEUE_ENT(MEMBER)
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
static void dump_queue_members(struct call_queue *pm_queue)
Dump all members in a specific queue to the database.
static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
Log an attended transfer when a queue caller channel is masqueraded.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
static struct call_queue * queue_unref(struct call_queue *q)
int ast_channel_sendurl(struct ast_channel *channel, const char *url)
Sends a URL on a given link Send URL on link.
static struct call_queue * alloc_queue(const char *queuename)
#define ao2_find(arg1, arg2, arg3)
#define ast_channel_unlock(chan)
static void parse(struct mgcp_request *req)
static int member_call_pending_set(struct member *mem)
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child)
Inherits channel variable from parent to child channel.
int source
Information about the source of an update.
static char * complete_queue_remove_member(const char *line, const char *word, int pos, int state)
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
static int play_file(struct ast_channel *chan, const char *filename)
#define queues_t_link(c, q, tag)
#define queue_t_ref(a, b)
unsigned int call_pending
const ast_string_field moh
void * ast_aoc_destroy_encoded(struct ast_aoc_encoded *encoded)
free an ast_aoc_encoded object
static char * complete_queue_add_member(const char *line, const char *word, int pos, int state)
int ast_call(struct ast_channel *chan, char *addr, int timeout)
Make a call.
static int manager_queues_status(struct mansession *s, const struct message *m)
Queue status info via AMI.
#define DATASTORE_INHERIT_FOREVER
const ast_string_field defaultrule
An API for managing task processing threads that can be shared across modules.
const ast_string_field sound_seconds
static const char qpm_cmd_usage[]
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Structure used to handle boolean flags.
static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
The waiting areas for callers who are not actively calling members.
static struct call_queue * queue_ref(struct call_queue *q)
int ast_realtime_require_field(const char *family,...) attribute_sentinel
Inform realtime what fields that may be stored.
unsigned int announceposition
#define ast_clear_flag(p, flag)
static int manager_queues_show(struct mansession *s, const struct message *m)
static int manager_queues_summary(struct mansession *s, const struct message *m)
Summary of queue info via the AMI.
char src[AST_MAX_EXTENSION]
int randomperiodicannounce
static struct ast_custom_function queuememberpaused_function
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has an integer payload.
static int queue_function_queuememberlist(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Dialplan function QUEUE_MEMBER_LIST() Get list of members in a specific queue.
char macroexten[AST_MAX_EXTENSION]
#define ANNOUNCEHOLDTIME_ALWAYS
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
unsigned int setqueueentryvar
static const char qsmp_cmd_usage[]
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
static struct ast_cli_entry cli_queue[]
const ast_string_field announce
const ast_string_field sound_reporthold
static void callattempt_free(struct callattempt *doomed)
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
void ast_poll_channel_del(struct ast_channel *chan0, struct ast_channel *chan1)
int transit_network_select
Transit Network Select.
#define ANNOUNCEPOSITION_LIMIT
static int store_next_lin(struct queue_ent *qe, struct callattempt *outgoing)
Search for best metric and add to Linear queue.
void ast_party_redirecting_free(struct ast_party_redirecting *doomed)
Destroy the redirecting information contents.
void ast_party_connected_line_copy(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src)
Copy the source connected line information to the destination connected line.
A ast_taskprocessor structure is a singleton by name.
static void record_abandoned(struct queue_ent *qe)
Record that a caller gave up on waiting in queue.
static void send_agent_complete(const struct queue_ent *qe, const char *queuename, const struct ast_channel *peer, const struct member *member, time_t callstart, char *vars, size_t vars_len, enum agent_complete_reason rsn)
Send out AMI message with member call completion status information.
const ast_string_field sound_calls
int ast_channel_make_compatible(struct ast_channel *c0, struct ast_channel *c1)
Makes two channel formats compatible.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Standard Command Line Interface.
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.
time_t last_periodic_announce_time
static int queue_debug
queues.conf [general] extra debug option
static struct ast_custom_function queuevar_function
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
struct ast_event_sub * ast_event_subscribe(enum ast_event_type event_type, ast_event_cb_t cb, const char *description, void *userdata,...)
Subscribe to events.
static struct member * create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface)
allocate space for new queue member and set fields based on parameters passed
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
Copy the caller information to the connected line information.
#define ao2_container_alloc(arg1, arg2, arg3)
int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
Uses hint and devicestate callback to get the state of an extension.
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 int autopause2int(const char *autopause)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
ast_app: A registered application
void ast_cdr_noanswer(struct ast_cdr *cdr)
A call wasn't answered.
void ast_party_redirecting_init(struct ast_party_redirecting *init)
Initialize the given redirecting structure.
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
static int compress_char(const char c)
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
Set variables of queue.
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
static int aqm_exec(struct ast_channel *chan, const char *data)
AddQueueMember application.
static struct ast_event_sub * device_state_sub
Subscription to device state change events.
char state_context[AST_MAX_CONTEXT]
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static struct ast_data_handler queues_data_provider
const ast_string_field accountcode
int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
This functionc locks given context, search for the right extension and fires out all peer in this ext...
Data structure associated with a single frame of data.
#define AST_DATA_STRUCTURE(__struct, __name)
Internal Asterisk hangup causes.
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context (or ANY context if NULL)
enum empty_conditions leavewhenempty
static int use_weight
queues.conf per-queue weight option
static void reload_single_queue(struct ast_config *cfg, struct ast_flags *mask, const char *queuename)
Reload information pertaining to a particular queue.
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
struct queue_ent::@54 qe_rules
struct timeval whentohangup
enum ast_aoc_type ast_aoc_get_msg_type(struct ast_aoc_decoded *decoded)
get the message type, AOC-D, AOC-E, or AOC Request
unsigned int relativeperiodicannounce
static int get_queue_member_status(struct member *cur)
Return the current state of a member.
static int kill_dead_queues(void *obj, void *arg, int flags)
#define AST_APP_ARG(name)
Define an application argument.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
enum ast_frame_type frametype
struct ast_variable * next
static const char *const pm_family
Persistent Members astdb family.
static int queue_exec(struct ast_channel *chan, const char *data)
The starting point for all queue calls.
static void reload_queue_members(void)
Reload dynamic queue members persisted into the astdb.
const ast_string_field sound_minutes
static int queue_hash_cb(const void *obj, const int flags)
static void rna(int rnatime, struct queue_ent *qe, char *interface, char *membername, int pause)
RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer...
char context[AST_MAX_CONTEXT]
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
static void do_hang(struct callattempt *o)
common hangup actions
struct callattempt * call_next
unsigned char valid
TRUE if the name information is valid/present.
static int manager_add_queue_member(struct mansession *s, const struct message *m)
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
char clid[AST_MAX_EXTENSION]
const ast_string_field queue_quantity2
#define CONFIG_STATUS_FILEINVALID
static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump, const char *state_interface)
Add member to queue.
static void init_queue(struct call_queue *q)
Initialize Queue default values.
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
int cancel_answered_elsewhere
static int extension_state_cb(char *context, char *exten, enum ast_extension_states state, void *data)
#define ANNOUNCEHOLDTIME_ONCE
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
static int queue_function_queuewaitingcount(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Dialplan function QUEUE_WAITING_COUNT() Get number callers waiting in a specific queue.
int ast_extension_state_add(const char *context, const char *exten, ast_state_cb_type change_cb, void *data)
Registers a state change callback.
void(* end_bridge_callback)(void *)
static int remove_from_queue(const char *queuename, const char *interface)
Remove member from queue.
static int update_status(struct call_queue *q, struct member *m, const int status)
set a member's status based on device state of that member's state_interface.
static char * handle_queue_reset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Generic State IE Used by AST_EVENT_DEVICE_STATE_CHANGE Payload type: UINT The actual state values dep...
const char * ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has a string payload.
static void copy_rules(struct queue_ent *qe, const char *rulename)
Copy rule from global list into specified queue.
static void queue_member_follower_removal(struct call_queue *queue, struct member *mem)
static void update_qe_rule(struct queue_ent *qe)
update rules for queues
Say numbers and dates (maybe words one day too)
#define ASTERISK_GPL_KEY
The text the key() function should return.
unsigned int dial_callerid_absent
enum empty_conditions joinempty
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
static char * handle_queue_set_member_penalty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
struct ast_channel * chan
const ast_string_field queue_quantity1
struct ast_data * ast_data_add_str(struct ast_data *root, const char *childname, const char *string)
Add a string node type.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Asterisk module definitions.
static int manager_pause_queue_member(struct mansession *s, const struct message *m)
unsigned int no_hangup_chan
static int is_our_turn(struct queue_ent *qe)
Check if we should start attempting to call queue members.
#define queues_t_unlink(c, q, tag)
struct ast_channel * ast_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *status)
Requests a channel.
Device Name Used by AST_EVENT_DEVICE_STATE_CHANGE Payload type: STR.
union ast_frame::@172 data
struct ast_channel_tech * tech
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
static int valid_exit(struct queue_ent *qe, char digit)
Check for valid exit from queue via goto.
static int shared_lastcall
queues.conf [general] option
static int queues_data_provider_get(const struct ast_data_search *search, struct ast_data *data_root)
Persistant data storage (akin to *doze registry)
struct ast_data * ast_data_add_int(struct ast_data *root, const char *childname, int value)
Add an integer node type.
static char * handle_queue_pause_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
struct ast_event_sub * ast_event_unsubscribe(struct ast_event_sub *event_sub)
Un-subscribe from events.
ast_context: An extension context
void ast_cdr_setdestchan(struct ast_cdr *cdr, const char *chan)
Set the destination channel, if there was one.
const ast_string_field sound_callerannounce
unsigned char valid
TRUE if the number information is valid/present.
#define ao2_unlink(arg1, arg2)
this call was forwarded somewhere else
#define QUEUE_EVENT_VARIABLES
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *chan)
Initialize based on a channel.
int ast_data_search_match(const struct ast_data_search *search, struct ast_data *data)
Check the current generated node to know if it matches the search condition.
static int manager_remove_queue_member(struct mansession *s, const struct message *m)
#define ast_custom_function_register(acf)
Register a custom function.
const ast_string_field language
uint32_t version
Structure version.
struct ast_context * ast_context_find(const char *name)
Find a context.
static const char * int2strat(int strategy)
char exten[AST_MAX_EXTENSION]
int ast_stopstream(struct ast_channel *c)
Stops a stream.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
static int queue_persistent_members
queues.conf [general] option
static int reload_queues(int reload, struct ast_flags *mask, const char *queuename)
reload the queues.conf file
void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src)
Copy the source redirecting information to the destination redirecting.
static char * complete_queue_show(const char *line, const char *word, int pos, int state)
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
static int clear_stats(const char *queuename)
Facilitates resetting statistics for a queue.
The structure of the node handler.
static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
Place a call to a queue member.
static void queues_data_provider_get_helper(const struct ast_data_search *search, struct ast_data *data_root, struct call_queue *queue)
int ast_manager_unregister(char *action)
Unregister a registered manager command.
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
char state_exten[AST_MAX_EXTENSION]
static int update_cdr
queues.conf [general] option
static struct @53 queue_results[]
int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *redirecting_info, int is_caller, int is_frame)
Run a redirecting interception macro and update a channel's redirecting information.
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
char userfield[AST_MAX_USER_FIELD]
#define CONFIG_STATUS_FILEUNCHANGED
int pbx_builtin_serialize_variables(struct ast_channel *chan, struct ast_str **buf)
Create a human-readable string, specifying all variables and their corresponding values.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
void ast_cdr_busy(struct ast_cdr *cdr)
Busy a call.
struct ast_party_number number
Subscriber phone number.