aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2005-03-28 20:48:24 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2005-03-28 20:48:24 +0000
commitd55d17a49496aec0974405dcd25707de499c7d81 (patch)
tree510ad77207125249e64eb1829ba60b42a60242b0
parentad3c5e1c18fbbaf40cea47038fefe4a5f7b414fc (diff)
Fix a bunch of const stuff, merge queue changes, add experimental "hybrid" DTMF mode
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@5293 f38db490-d61c-443f-a65b-d21fe96a405b
-rwxr-xr-xMakefile1
-rwxr-xr-xUPGRADE.txt7
-rwxr-xr-xapps/app_queue.c497
-rwxr-xr-xchannel.c4
-rwxr-xr-xchannels/chan_agent.c4
-rwxr-xr-xchannels/chan_iax2.c38
-rwxr-xr-xchannels/chan_local.c6
-rwxr-xr-xchannels/chan_mgcp.c13
-rwxr-xr-xchannels/chan_phone.c6
-rwxr-xr-xchannels/chan_sip.c25
-rwxr-xr-xchannels/chan_zap.c6
-rwxr-xr-xconfigs/mgcp.conf.sample2
-rwxr-xr-xconfigs/queues.conf.sample11
-rwxr-xr-xdoc/README.variables2
-rwxr-xr-xinclude/asterisk/channel.h10
-rwxr-xr-xinclude/asterisk/tdd.h2
-rwxr-xr-xtdd.c2
17 files changed, 369 insertions, 267 deletions
diff --git a/Makefile b/Makefile
index 86e4a4464..8894d28fe 100755
--- a/Makefile
+++ b/Makefile
@@ -476,6 +476,7 @@ bininstall: all
rm -f $(DESTDIR)$(ASTVARLIBDIR)/sounds/voicemail
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds
mkdir -p $(DESTDIR)$(ASTLOGDIR)/cdr-csv
+ mkdir -p $(DESTDIR)$(ASTLOGDIR)/cdr-custom
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/keys
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/firmware
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/firmware/iax
diff --git a/UPGRADE.txt b/UPGRADE.txt
index 89f2ed2a5..64836acf5 100755
--- a/UPGRADE.txt
+++ b/UPGRADE.txt
@@ -26,3 +26,10 @@ Applications:
* The CallerPres application has been removed. Use SetCallerPres
instead. It accepts both numeric and symbolic names.
+
+Queues:
+
+* A queue is now considered empty not only if there are no members but if
+ none of the members are available (e.g. agents not logged on). To
+ restore the original behavior, use "leavewhenempty=strict" or
+ "joinwhenempty=strict" instead of "=yes" for those options.
diff --git a/apps/app_queue.c b/apps/app_queue.c
index 9e6ac2d64..78783563d 100755
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -3,7 +3,7 @@
*
* True call queues with optional send URL on answer
*
- * Copyright (C) 1999-2004, Digium, Inc.
+ * Copyright (C) 1999-2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
@@ -14,8 +14,8 @@
* Each dynamic agent in each queue is now stored in the astdb.
* When asterisk is restarted, each agent will be automatically
* readded into their recorded queues. This feature can be
- * configured with the 'peristent_members=<1|0>' KVP under the
- * '[general]' group in queues.conf. The default is on.
+ * configured with the 'persistent_members=<1|0>' setting in the
+ * '[general]' category in queues.conf. The default is on.
*
* 2004-06-04: Priorities in queues added by inAccess Networks (work funded by Hellas On Line (HOL) www.hol.gr).
*
@@ -123,9 +123,11 @@ static char *descrip =
" The optional URL will be sent to the called party if the channel supports\n"
"it.\n"
" The timeout will cause the queue to fail out after a specified number of\n"
-"seconds, checked between each queues.conf 'timeout' and 'retry' cycle.\n";
+"seconds, checked between each queues.conf 'timeout' and 'retry' cycle.\n"
+" This application sets the following channel variable upon completion:\n"
+" QUEUESTATUS The status of the call as a text string, one of\n"
+" TIMEOUT | FULL | JOINEMPTY | LEAVEEMPTY | JOINUNAVAIL | LEAVEUNAVAIL\n";
-/* PHM 06/26/03 */
static char *app_aqm = "AddQueueMember" ;
static char *app_aqm_synopsis = "Dynamically adds queue members" ;
static char *app_aqm_descrip =
@@ -176,27 +178,35 @@ static char *app_upqm_descrip =
static const char *pm_family = "/Queue/PersistentMembers";
/* The maximum lengh of each persistent member queue database entry */
#define PM_MAX_LEN 2048
+
/* queues.conf [general] option */
static int queue_persistent_members = 0;
+
/* queues.conf per-queue weight option */
static int use_weight = 0;
+enum queue_result {
+ QUEUE_UNKNOWN = 0,
+ QUEUE_TIMEOUT = 1,
+ QUEUE_JOINEMPTY = 2,
+ QUEUE_LEAVEEMPTY = 3,
+ QUEUE_JOINUNAVAIL = 4,
+ QUEUE_LEAVEUNAVAIL = 5,
+ QUEUE_FULL = 6,
+};
-#define QUEUE_FLAG_RINGBACKONLY (1 << 0)
-#define QUEUE_FLAG_MUSICONHOLD (1 << 1)
-#define QUEUE_FLAG_DATAQUALITY (1 << 2)
-#define QUEUE_FLAG_REDIR_IN (1 << 3)
-#define QUEUE_FLAG_REDIR_OUT (1 << 4)
-#define QUEUE_FLAG_DISCON_IN (1 << 5)
-#define QUEUE_FLAG_DISCON_OUT (1 << 6)
-#define QUEUE_FLAG_MONJOIN (1 << 7) /* Should we join the two files when we are done with the call */
-#define QUEUE_FLAG_DEAD (1 << 8) /* Whether the queue is dead or not */
-#define QUEUE_FLAG_JOINEMPTY (1 << 9) /* Do we care if the queue has no members? */
-#define QUEUE_FLAG_EVENTWHENCALLED (1 << 10) /* Generate an event when the agent is called (before pickup) */
-#define QUEUE_FLAG_LEAVEWHENEMPTY (1 << 11) /* If all agents leave the queue, remove callers from the queue */
-#define QUEUE_FLAG_REPORTHOLDTIME (1 << 12) /* Should we report caller hold time to answering member? */
-#define QUEUE_FLAG_WRAPPED (1 << 13) /* Round Robin - wrapped around? */
-#define QUEUE_FLAG_TIMEOUTRESTART (1 << 14) /* Restart timer when member call */
+const struct {
+ enum queue_result id;
+ char *text;
+} queue_results[] = {
+ { QUEUE_UNKNOWN, "UNKNOWN" },
+ { QUEUE_TIMEOUT, "TIMEOUT" },
+ { QUEUE_JOINEMPTY,"JOINEMPTY" },
+ { QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
+ { QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
+ { QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
+ { QUEUE_FULL, "FULL" },
+};
/* We define a custom "local user" structure because we
use it not only for keeping track of what is in use but
@@ -208,7 +218,6 @@ struct localuser {
int stillgoing;
int metric;
int oldstatus;
- unsigned int flags; /* flag bits */
time_t lastcall;
struct member *member;
struct localuser *next;
@@ -244,22 +253,37 @@ struct member {
struct member *next; /* Next member */
};
+/* values used in multi-bit flags in ast_call_queue */
+#define QUEUE_EMPTY_NORMAL 1
+#define QUEUE_EMPTY_STRICT 2
+#define ANNOUNCEHOLDTIME_ALWAYS 1
+#define ANNOUNCEHOLDTIME_ONCE 2
+
struct ast_call_queue {
- ast_mutex_t lock;
- char name[80]; /* Name of the queue */
- char moh[80]; /* Name of musiconhold to be used */
+ ast_mutex_t lock;
+ char name[80]; /* Name */
+ char moh[80]; /* Music On Hold class to be used */
char announce[80]; /* Announcement to play when call is answered */
- char context[80]; /* Context for this queue */
- unsigned int flags; /* flag bits */
- int strategy; /* Queueing strategy */
+ char context[80]; /* Exit context */
+ struct {
+ unsigned int monjoin:1;
+ unsigned int dead:1;
+ unsigned int joinempty:2;
+ unsigned int eventwhencalled:1;
+ unsigned int leavewhenempty:2;
+ unsigned int reportholdtime:1;
+ unsigned int wrapped:1;
+ unsigned int timeoutrestart:1;
+ unsigned int announceholdtime:2;
+ unsigned int strategy:3;
+ };
int announcefrequency; /* How often to announce their position */
int roundingseconds; /* How many seconds do we round to? */
- int announceholdtime; /* When to announce holdtime: 0 = never, -1 = every announcement, 1 = only once */
- int holdtime; /* Current avg holdtime for this queue, based on recursive boxcar filter */
+ int holdtime; /* Current avg holdtime, based on recursive boxcar filter */
int callscompleted; /* Number of queue calls completed */
int callsabandoned; /* Number of queue calls abandoned */
int servicelevel; /* seconds setting for servicelevel*/
- int callscompletedinsl; /* Number of queue calls answered with servicelevel*/
+ int callscompletedinsl; /* Number of calls answered with servicelevel*/
char monfmt[8]; /* Format to use when recording calls */
char sound_next[80]; /* Sound file: "Your call is now first in line" (def. queue-youarenext) */
char sound_thereare[80]; /* Sound file: "There are currently" (def. queue-thereare) */
@@ -271,26 +295,37 @@ struct ast_call_queue {
char sound_thanks[80]; /* Sound file: "Thank you for your patience." (def. queue-thankyou) */
char sound_reporthold[80]; /* Sound file: "Hold time" (def. queue-reporthold) */
- int count; /* How many entries are in the queue */
- int maxlen; /* Max number of entries in queue */
+ int count; /* How many entries */
+ int maxlen; /* Max number of entries */
int wrapuptime; /* Wrapup Time */
int retry; /* Retry calling everyone after this amount of time */
int timeout; /* How long to wait for an answer */
- int weight; /* This queue's respective weight */
+ int weight; /* Respective weight */
/* Queue strategy things */
int rrpos; /* Round Robin - position */
int memberdelay; /* Seconds to delay connecting member to caller */
- struct member *members; /* Member channels to be tried */
- struct queue_ent *head; /* Start of the actual queue */
+ struct member *members; /* Head of the list of members */
+ struct queue_ent *head; /* Head of the list of callers */
struct ast_call_queue *next; /* Next call queue */
};
static struct ast_call_queue *queues = NULL;
AST_MUTEX_DEFINE_STATIC(qlock);
+static void set_queue_result(struct ast_channel *chan, enum queue_result res)
+{
+ int i;
+
+ for (i = 0; i < sizeof(queue_results) / sizeof(queue_results[0]); i++) {
+ if (queue_results[i].id == res) {
+ pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
+ return;
+ }
+ }
+}
static char *int2strat(int strategy)
{
@@ -313,8 +348,7 @@ static int strat2int(char *strategy)
}
/* Insert the 'new' entry after the 'prev' entry of queue 'q' */
-static inline void insert_entry(struct ast_call_queue *q,
- struct queue_ent *prev, struct queue_ent *new, int *pos)
+static inline void insert_entry(struct ast_call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
{
struct queue_ent *cur;
@@ -333,24 +367,31 @@ static inline void insert_entry(struct ast_call_queue *q,
new->opos = *pos;
}
-static int has_no_members(struct ast_call_queue *q)
+enum queue_member_status {
+ QUEUE_NO_MEMBERS,
+ QUEUE_NO_REACHABLE_MEMBERS,
+ QUEUE_NORMAL
+};
+
+static enum queue_member_status get_member_status(const struct ast_call_queue *q)
{
struct member *member;
- int empty = 1;
- member = q->members;
- while(empty && member) {
- switch(member->status) {
- case AST_DEVICE_UNAVAILABLE:
+ enum queue_member_status result = QUEUE_NO_MEMBERS;
+
+ for (member = q->members; member; member = member->next) {
+ switch (member->status) {
case AST_DEVICE_INVALID:
- /* Not logged on, etc */
+ /* nothing to do */
+ break;
+ case AST_DEVICE_UNAVAILABLE:
+ result = QUEUE_NO_REACHABLE_MEMBERS;
break;
default:
- /* Not empty */
- empty = 0;
+ return QUEUE_NORMAL;
}
- member = member->next;
}
- return empty;
+
+ return result;
}
struct statechange {
@@ -372,7 +413,6 @@ static void *changethread(void *data)
*loc = '\0';
loc++;
} else {
- ast_log(LOG_WARNING, "Can't change device '%s' with no technology!\n", sc->dev);
free(sc);
return NULL;
}
@@ -432,7 +472,7 @@ static int statechange_queue(const char *dev, int state, void *ign)
return 0;
}
-static int join_queue(char *queuename, struct queue_ent *qe)
+static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason)
{
struct ast_call_queue *q;
struct queue_ent *cur, *prev = NULL;
@@ -443,9 +483,17 @@ static int join_queue(char *queuename, struct queue_ent *qe)
ast_mutex_lock(&qlock);
for (q = queues; q; q = q->next) {
if (!strcasecmp(q->name, queuename)) {
+ enum queue_member_status stat;
/* This is our one */
ast_mutex_lock(&q->lock);
- if ((!has_no_members(q) || ast_test_flag(q, QUEUE_FLAG_JOINEMPTY)) && (!q->maxlen || (q->count < q->maxlen))) {
+ stat = get_member_status(q);
+ if (!q->joinempty && (stat == QUEUE_NO_MEMBERS))
+ *reason = QUEUE_JOINEMPTY;
+ else if ((q->joinempty == QUEUE_EMPTY_NORMAL) && (stat == QUEUE_NO_REACHABLE_MEMBERS))
+ *reason = QUEUE_JOINUNAVAIL;
+ else if (q->maxlen && (q->count >= q->maxlen))
+ *reason = QUEUE_FULL;
+ else {
/* There's space for us, put us at the right position inside
* the queue.
* Take into account the priority of the calling user */
@@ -494,6 +542,7 @@ static void free_members(struct ast_call_queue *q, int all)
{
/* Free non-dynamic members */
struct member *curm, *next, *prev;
+
curm = q->members;
prev = NULL;
while(curm) {
@@ -513,6 +562,7 @@ static void free_members(struct ast_call_queue *q, int all)
static void destroy_queue(struct ast_call_queue *q)
{
struct ast_call_queue *cur, *prev = NULL;
+
ast_mutex_lock(&qlock);
for (cur = queues; cur; cur = cur->next) {
if (cur == q) {
@@ -591,7 +641,8 @@ static int say_position(struct queue_ent *qe)
/* If the hold time is >1 min, if it's enabled, and if it's not
supposed to be only once and we have already said it, say it */
- if ((avgholdmins+avgholdsecs) > 0 && (qe->parent->announceholdtime) && (!(qe->parent->announceholdtime==1 && qe->last_pos)) ) {
+ if ((avgholdmins+avgholdsecs) > 0 && (qe->parent->announceholdtime) &&
+ (!(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE) && qe->last_pos)) {
res += play_file(qe->chan, qe->parent->sound_holdtime);
if(avgholdmins>0) {
if (avgholdmins < 2) {
@@ -652,6 +703,7 @@ static void leave_queue(struct queue_ent *qe)
struct ast_call_queue *q;
struct queue_ent *cur, *prev = NULL;
int pos = 0;
+
q = qe->parent;
if (!q)
return;
@@ -683,16 +735,17 @@ ast_log(LOG_NOTICE, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name
cur = cur->next;
}
ast_mutex_unlock(&q->lock);
- if (ast_test_flag(q, QUEUE_FLAG_DEAD) && !q->count) {
+ if (q->dead && !q->count) {
/* It's dead and nobody is in it, so kill it */
destroy_queue(q);
}
}
-static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
+/* Hang up a list of outgoing calls */
+static void hangupcalls(struct localuser *outgoing, struct ast_channel *exception)
{
- /* Hang up a tree of stuff */
struct localuser *oo;
+
while(outgoing) {
/* Hangup any existing lines we have open */
if (outgoing->chan && (outgoing->chan != exception))
@@ -706,6 +759,7 @@ static void hanguptree(struct localuser *outgoing, struct ast_channel *exception
static int update_status(struct ast_call_queue *q, struct member *member, int status)
{
struct member *cur;
+
/* Since a reload could have taken place, we have to traverse the list to
be sure it's still valid */
ast_mutex_lock(&q->lock);
@@ -746,10 +800,10 @@ static int update_dial_status(struct ast_call_queue *q, struct member *member, i
return update_status(q, member, status);
}
-static int compare_weight(struct ast_call_queue *rq, struct member *member)
-{
/* traverse all defined queues which have calls waiting and contain this member
return 0 if no other queue has precedence (higher weight) or 1 if found */
+static int compare_weight(struct ast_call_queue *rq, struct member *member)
+{
struct ast_call_queue *q;
struct member *mem;
int found = 0;
@@ -780,8 +834,6 @@ static int compare_weight(struct ast_call_queue *rq, struct member *member)
return found;
}
-
-
static int ring_entry(struct queue_ent *qe, struct localuser *tmp, int *busies)
{
int res;
@@ -876,7 +928,7 @@ static int ring_entry(struct queue_ent *qe, struct localuser *tmp, int *busies)
(*busies)++;
return 0;
} else {
- if (ast_test_flag(qe->parent, QUEUE_FLAG_EVENTWHENCALLED)) {
+ if (qe->parent->eventwhencalled) {
manager_event(EVENT_FLAG_AGENT, "AgentCalled",
"AgentCalled: %s\r\n"
"ChannelCalling: %s\r\n"
@@ -901,6 +953,7 @@ static int ring_one(struct queue_ent *qe, struct localuser *outgoing, int *busie
struct localuser *cur;
struct localuser *best;
int bestmetric=0;
+
do {
best = NULL;
cur = outgoing;
@@ -946,6 +999,7 @@ static int store_next(struct queue_ent *qe, struct localuser *outgoing)
struct localuser *cur;
struct localuser *best;
int bestmetric=0;
+
best = NULL;
cur = outgoing;
while(cur) {
@@ -964,7 +1018,7 @@ static int store_next(struct queue_ent *qe, struct localuser *outgoing)
qe->parent->rrpos = best->metric % 1000;
} else {
/* Just increment rrpos */
- if (!ast_test_flag(qe->parent, QUEUE_FLAG_WRAPPED)) {
+ if (qe->parent->wrapped) {
/* No more channels, start over */
qe->parent->rrpos = 0;
} else {
@@ -972,13 +1026,14 @@ static int store_next(struct queue_ent *qe, struct localuser *outgoing)
qe->parent->rrpos++;
}
}
- ast_clear_flag(qe->parent, QUEUE_FLAG_WRAPPED);
+ qe->parent->wrapped = 0;
return 0;
}
static int valid_exit(struct queue_ent *qe, char digit)
{
char tmp[2];
+
if (ast_strlen_zero(qe->context))
return 0;
tmp[0] = digit;
@@ -994,7 +1049,7 @@ static int valid_exit(struct queue_ent *qe, char digit)
#define AST_MAX_WATCHERS 256
-#define BUILD_STATS do { \
+#define BUILD_WATCHERS do { \
o = outgoing; \
found = -1; \
pos = 1; \
@@ -1014,7 +1069,7 @@ static int valid_exit(struct queue_ent *qe, char digit)
} \
} while(0)
-static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser *outgoing, int *to, struct ast_flags *flags, char *digit, int prebusies)
+static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser *outgoing, int *to, char *digit, int prebusies, int caller_disconnect)
{
char *queue = qe->parent->name;
struct localuser *o;
@@ -1034,12 +1089,12 @@ static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser
struct ast_channel *in = qe->chan;
while(*to && !peer) {
- BUILD_STATS;
+ BUILD_WATCHERS;
if ((found < 0) && stillgoing && !qe->parent->strategy) {
/* On "ringall" strategy we only move to the next penalty level
when *all* ringing phones are done in the current penalty level */
ring_one(qe, outgoing, &numbusies);
- BUILD_STATS;
+ BUILD_WATCHERS;
}
if (found < 0) {
if (numlines == (numbusies + numnochan)) {
@@ -1058,7 +1113,6 @@ static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
peer = o;
- ast_copy_flags(flags, o, QUEUE_FLAG_REDIR_IN | QUEUE_FLAG_REDIR_OUT | QUEUE_FLAG_DISCON_IN | QUEUE_FLAG_DISCON_OUT);
}
} else if (o->chan && (o->chan == winner)) {
if (!ast_strlen_zero(o->chan->call_forward)) {
@@ -1141,11 +1195,9 @@ static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser
case AST_CONTROL_ANSWER:
/* This is our guy if someone answered. */
if (!peer) {
- ast_copy_flags(flags, o, QUEUE_FLAG_REDIR_IN | QUEUE_FLAG_REDIR_OUT | QUEUE_FLAG_DISCON_IN | QUEUE_FLAG_DISCON_OUT);
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
peer = o;
- ast_copy_flags(flags, o, QUEUE_FLAG_REDIR_IN & QUEUE_FLAG_REDIR_OUT & QUEUE_FLAG_DISCON_IN & QUEUE_FLAG_DISCON_OUT);
}
break;
case AST_CONTROL_BUSY:
@@ -1157,7 +1209,7 @@ static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser
ast_hangup(o->chan);
o->chan = NULL;
if (qe->parent->strategy) {
- if (ast_test_flag(qe->parent, QUEUE_FLAG_TIMEOUTRESTART))
+ if (qe->parent->timeoutrestart)
*to = orig;
ring_one(qe, outgoing, &numbusies);
}
@@ -1172,7 +1224,7 @@ static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser
ast_hangup(o->chan);
o->chan = NULL;
if (qe->parent->strategy) {
- if (ast_test_flag(qe->parent, QUEUE_FLAG_TIMEOUTRESTART))
+ if (qe->parent->timeoutrestart)
*to = orig;
ring_one(qe, outgoing, &numbusies);
}
@@ -1201,7 +1253,7 @@ static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser
ast_hangup(o->chan);
o->chan = NULL;
if (qe->parent->strategy) {
- if (ast_test_flag(qe->parent, QUEUE_FLAG_TIMEOUTRESTART))
+ if (qe->parent->timeoutrestart)
*to = orig;
ring_one(qe, outgoing, &numbusies);
}
@@ -1222,7 +1274,7 @@ static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser
*to=-1;
return NULL;
}
- if (f && (f->frametype == AST_FRAME_DTMF) && ast_test_flag(flags, QUEUE_FLAG_DISCON_OUT) && (f->subclass == '*')) {
+ if (f && (f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass == '*')) {
if (option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
*to=0;
@@ -1264,21 +1316,35 @@ static int is_our_turn(struct queue_ent *qe)
return res;
}
-static int wait_our_turn(struct queue_ent *qe, int ringing)
+static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
{
int res = 0;
/* This is the holding pen for callers 2 through maxlen */
for (;;) {
+ enum queue_member_status stat;
+
if (is_our_turn(qe))
break;
/* If we have timed out, break out */
- if (qe->expire && (time(NULL) > qe->expire))
+ if (qe->expire && (time(NULL) > qe->expire)) {
+ *reason = QUEUE_TIMEOUT;
break;
+ }
+
+ stat = get_member_status(qe->parent);
/* leave the queue if no agents, if enabled */
- if (ast_test_flag(qe->parent, QUEUE_FLAG_LEAVEWHENEMPTY) && has_no_members(qe->parent)) {
+ if (qe->parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
+ *reason = QUEUE_LEAVEEMPTY;
+ leave_queue(qe);
+ break;
+ }
+
+ /* leave the queue if no reachable agents, if enabled */
+ if ((qe->parent->leavewhenempty == QUEUE_EMPTY_NORMAL) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
+ *reason = QUEUE_LEAVEUNAVAIL;
leave_queue(qe);
break;
}
@@ -1298,6 +1364,7 @@ static int wait_our_turn(struct queue_ent *qe, int ringing)
static int update_queue(struct ast_call_queue *q, struct member *member)
{
struct member *cur;
+
/* Since a reload could have taken place, we have to traverse the list to
be sure it's still valid */
ast_mutex_lock(&q->lock);
@@ -1324,24 +1391,23 @@ static int calc_metric(struct ast_call_queue *q, struct member *mem, int pos, st
break;
case QUEUE_STRATEGY_ROUNDROBIN:
if (!pos) {
- if (!ast_test_flag(q, QUEUE_FLAG_WRAPPED)) {
+ if (!q->wrapped) {
/* No more channels, start over */
q->rrpos = 0;
} else {
/* Prioritize next entry */
q->rrpos++;
}
- ast_clear_flag(q, QUEUE_FLAG_WRAPPED);
+ q->wrapped = 0;
}
/* Fall through */
case QUEUE_STRATEGY_RRMEMORY:
if (pos < q->rrpos) {
tmp->metric = 1000 + pos;
} else {
- if (pos > q->rrpos) {
+ if (pos > q->rrpos)
/* Indicate there is another priority */
- ast_set_flag(q, QUEUE_FLAG_WRAPPED);
- }
+ q->wrapped = 1;
tmp->metric = pos;
}
tmp->metric += mem->penalty * 1000000;
@@ -1368,32 +1434,56 @@ static int calc_metric(struct ast_call_queue *q, struct member *mem, int pos, st
return 0;
}
-static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverride, char *url, int *go_on)
+static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *go_on)
{
struct member *cur;
struct localuser *outgoing=NULL, *tmp = NULL;
int to;
- struct ast_flags flags;
char restofit[AST_MAX_EXTENSION];
char oldexten[AST_MAX_EXTENSION]="";
char oldcontext[AST_MAX_EXTENSION]="";
char queuename[256]="";
char *newnum;
- char *options;
char *monitorfilename;
struct ast_channel *peer;
struct ast_channel *which;
struct localuser *lpeer;
struct member *member;
int res = 0, bridge = 0;
- int zapx = 2;
int numbusies = 0;
int x=0;
char *announce = NULL;
char digit = 0;
time_t callstart;
time_t now;
- struct ast_bridge_config config;
+ struct ast_bridge_config bridge_config;
+ char nondataquality = 1;
+
+ memset(&bridge_config, 0, sizeof(bridge_config));
+
+ for (; options && *options; options++)
+ switch (*options) {
+ case 't':
+ ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
+ break;
+ case 'T':
+ ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
+ break;
+ case 'd':
+ nondataquality = 0;
+ break;
+ case 'h':
+ ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
+ break;
+ case 'H':
+ ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
+ break;
+ case 'n':
+ if ((now - qe->start >= qe->parent->timeout))
+ *go_on = 1;
+ break;
+ }
+
/* Hold the lock while we setup the outgoing calls */
if (use_weight)
ast_mutex_lock(&qlock);
@@ -1408,9 +1498,9 @@ static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverr
announce = qe->announce;
if (announceoverride && !ast_strlen_zero(announceoverride))
announce = announceoverride;
+
while(cur) {
- /* Get a technology/[device:]number pair */
- tmp = malloc(sizeof(struct localuser));
+ tmp = malloc(sizeof(*tmp));
if (!tmp) {
ast_mutex_unlock(&qe->parent->lock);
if (use_weight)
@@ -1418,37 +1508,8 @@ static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverr
ast_log(LOG_WARNING, "Out of memory\n");
goto out;
}
- memset(tmp, 0, sizeof(struct localuser));
+ memset(tmp, 0, sizeof(*tmp));
tmp->stillgoing = -1;
- options = ooptions;
- for (; options && *options; options++)
- switch (*options) {
- case 't':
- ast_set_flag(tmp, QUEUE_FLAG_REDIR_IN);
- break;
- case 'T':
- ast_set_flag(tmp, QUEUE_FLAG_REDIR_OUT);
- break;
- case 'r':
- ast_set_flag(tmp, QUEUE_FLAG_RINGBACKONLY);
- break;
- case 'm':
- ast_set_flag(tmp, QUEUE_FLAG_MUSICONHOLD);
- break;
- case 'd':
- ast_set_flag(tmp, QUEUE_FLAG_DATAQUALITY);
- break;
- case 'h':
- ast_set_flag(tmp, QUEUE_FLAG_DISCON_IN);
- break;
- case 'H':
- ast_set_flag(tmp, QUEUE_FLAG_DISCON_OUT);
- break;
- case 'n':
- if ((now - qe->start >= qe->parent->timeout))
- *go_on = 1;
- break;
- }
if (option_debug) {
if (url)
ast_log(LOG_DEBUG, "Queue with URL=%s_\n", url);
@@ -1490,7 +1551,7 @@ static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverr
ast_mutex_unlock(&qe->parent->lock);
if (use_weight)
ast_mutex_unlock(&qlock);
- lpeer = wait_for_answer(qe, outgoing, &to, &flags, &digit, numbusies);
+ lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT));
ast_mutex_lock(&qe->parent->lock);
if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) {
store_next(qe, outgoing);
@@ -1521,20 +1582,16 @@ static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverr
we will always return with -1 so that it is hung up properly after the
conversation. */
qe->handled++;
- if (!strcmp(qe->chan->type,"Zap")) {
- zapx = !ast_test_flag(tmp, QUEUE_FLAG_DATAQUALITY);
- ast_channel_setoption(qe->chan,AST_OPTION_TONE_VERIFY,&zapx,sizeof(char),0);
- }
- if (!strcmp(peer->type,"Zap")) {
- zapx = !ast_test_flag(tmp, QUEUE_FLAG_DATAQUALITY);
- ast_channel_setoption(peer,AST_OPTION_TONE_VERIFY,&zapx,sizeof(char),0);
- }
+ if (!strcmp(qe->chan->type,"Zap"))
+ ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
+ if (!strcmp(peer->type,"Zap"))
+ ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
/* Update parameters for the queue */
recalc_holdtime(qe);
member = lpeer->member;
- hanguptree(outgoing, peer);
+ hangupcalls(outgoing, peer);
outgoing = NULL;
- if (announce || ast_test_flag(qe->parent, QUEUE_FLAG_REPORTHOLDTIME) || qe->parent->memberdelay) {
+ if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
int res2;
res2 = ast_autoservice_start(qe->chan);
if (!res2) {
@@ -1546,7 +1603,7 @@ static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverr
if (play_file(peer, announce))
ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", announce);
}
- if (!res2 && ast_test_flag(qe->parent, QUEUE_FLAG_REPORTHOLDTIME)) {
+ if (!res2 && qe->parent->reportholdtime) {
if (!play_file(peer, qe->parent->sound_reporthold)) {
int holdtime;
time_t now;
@@ -1567,13 +1624,13 @@ static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverr
/* Agent must have hung up */
ast_log(LOG_WARNING, "Agent on %s hungup on the customer. They're going to be pissed.\n", peer->name);
ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "AGENTDUMP", "%s", "");
- if (ast_test_flag(qe->parent, QUEUE_FLAG_EVENTWHENCALLED)) {
+ if (qe->parent->eventwhencalled) {
manager_event(EVENT_FLAG_AGENT, "AgentDump",
- "Queue: %s\r\n"
- "Uniqueid: %s\r\n"
- "Channel: %s\r\n"
- "Member: %s\r\n",
- queuename, qe->chan->uniqueid, peer->name, member->interface);
+ "Queue: %s\r\n"
+ "Uniqueid: %s\r\n"
+ "Channel: %s\r\n"
+ "Member: %s\r\n",
+ queuename, qe->chan->uniqueid, peer->name, member->interface);
}
ast_hangup(peer);
goto out;
@@ -1602,80 +1659,68 @@ static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverr
/* Begin Monitoring */
if (qe->parent->monfmt && *qe->parent->monfmt) {
monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
- if(pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC") || pbx_builtin_getvar_helper( qe->chan, "MONITOR_EXEC_ARGS"))
+ if (pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC") || pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC_ARGS"))
which = qe->chan;
else
which = peer;
- if(monitorfilename) {
+ if (monitorfilename)
ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1 );
- } else {
+ else
ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1 );
- }
- if(ast_test_flag(qe->parent, QUEUE_FLAG_MONJOIN)) {
+ if (qe->parent->monjoin)
ast_monitor_setjoinfiles(which, 1);
- }
}
/* Drop out of the queue at this point, to prepare for next caller */
leave_queue(qe);
- if( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
+ if (url && !ast_strlen_zero(url) && ast_channel_supports_html(peer)) {
if (option_debug)
ast_log(LOG_DEBUG, "app_queue: sendurl=%s.\n", url);
- ast_channel_sendurl( peer, url );
+ ast_channel_sendurl(peer, url);
}
ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "CONNECT", "%ld", (long)time(NULL) - qe->start);
- if (ast_test_flag(qe->parent, QUEUE_FLAG_EVENTWHENCALLED)) {
+ if (qe->parent->eventwhencalled)
manager_event(EVENT_FLAG_AGENT, "AgentConnect",
- "Queue: %s\r\n"
- "Uniqueid: %s\r\n"
- "Channel: %s\r\n"
- "Member: %s\r\n"
- "Holdtime: %ld\r\n",
- queuename, qe->chan->uniqueid, peer->name, member->interface, (long)time(NULL) - qe->start);
- }
+ "Queue: %s\r\n"
+ "Uniqueid: %s\r\n"
+ "Channel: %s\r\n"
+ "Member: %s\r\n"
+ "Holdtime: %ld\r\n",
+ queuename, qe->chan->uniqueid, peer->name, member->interface,
+ (long)time(NULL) - qe->start);
strncpy(oldcontext, qe->chan->context, sizeof(oldcontext) - 1);
strncpy(oldexten, qe->chan->exten, sizeof(oldexten) - 1);
time(&callstart);
- memset(&config,0,sizeof(struct ast_bridge_config));
-
- if (ast_test_flag(&flags, QUEUE_FLAG_REDIR_IN))
- ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
- if (ast_test_flag(&flags, QUEUE_FLAG_REDIR_OUT))
- ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
- if (ast_test_flag(&flags, QUEUE_FLAG_DISCON_IN))
- ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
- if (ast_test_flag(&flags, QUEUE_FLAG_DISCON_OUT))
- ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
- bridge = ast_bridge_call(qe->chan,peer,&config);
+ bridge = ast_bridge_call(qe->chan,peer, &bridge_config);
if (strcasecmp(oldcontext, qe->chan->context) || strcasecmp(oldexten, qe->chan->exten)) {
ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "TRANSFER", "%s|%s", qe->chan->exten, qe->chan->context);
} else if (qe->chan->_softhangup) {
- ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETECALLER", "%ld|%ld", (long)(callstart - qe->start), (long)(time(NULL) - callstart));
- if (ast_test_flag(qe->parent, QUEUE_FLAG_EVENTWHENCALLED)) {
+ ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETECALLER", "%ld|%ld",
+ (long)(callstart - qe->start), (long)(time(NULL) - callstart));
+ if (qe->parent->eventwhencalled)
manager_event(EVENT_FLAG_AGENT, "AgentComplete",
- "Queue: %s\r\n"
- "Uniqueid: %s\r\n"
- "Channel: %s\r\n"
- "Member: %s\r\n"
- "HoldTime: %ld\r\n"
- "TalkTime: %ld\r\n"
- "Reason: caller\r\n",
- queuename, qe->chan->uniqueid, peer->name, member->interface, (long)(callstart - qe->start), (long)(time(NULL) - callstart));
- }
+ "Queue: %s\r\n"
+ "Uniqueid: %s\r\n"
+ "Channel: %s\r\n"
+ "Member: %s\r\n"
+ "HoldTime: %ld\r\n"
+ "TalkTime: %ld\r\n"
+ "Reason: caller\r\n",
+ queuename, qe->chan->uniqueid, peer->name, member->interface,
+ (long)(callstart - qe->start), (long)(time(NULL) - callstart));
} else {
ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETEAGENT", "%ld|%ld", (long)(callstart - qe->start), (long)(time(NULL) - callstart));
- if (ast_test_flag(qe->parent, QUEUE_FLAG_EVENTWHENCALLED)) {
+ if (qe->parent->eventwhencalled)
manager_event(EVENT_FLAG_AGENT, "AgentComplete",
- "Queue: %s\r\n"
- "Uniqueid: %s\r\n"
- "Channel: %s\r\n"
- "HoldTime: %ld\r\n"
- "TalkTime: %ld\r\n"
- "Reason: agent\r\n",
- queuename, qe->chan->uniqueid, peer->name, (long)(callstart - qe->start), (long)(time(NULL) - callstart));
- }
-
+ "Queue: %s\r\n"
+ "Uniqueid: %s\r\n"
+ "Channel: %s\r\n"
+ "HoldTime: %ld\r\n"
+ "TalkTime: %ld\r\n"
+ "Reason: agent\r\n",
+ queuename, qe->chan->uniqueid, peer->name, (long)(callstart - qe->start),
+ (long)(time(NULL) - callstart));
}
if(bridge != AST_PBX_NO_HANGUP_PEER)
@@ -1687,7 +1732,7 @@ static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverr
res = bridge; /* bridge error, stay in the queue */
}
out:
- hanguptree(outgoing, NULL);
+ hangupcalls(outgoing, NULL);
return res;
}
@@ -1695,11 +1740,10 @@ static int wait_a_bit(struct queue_ent *qe)
{
/* Don't need to hold the lock while we setup the outgoing calls */
int retrywait = qe->parent->retry * 1000;
+
return ast_waitfordigit(qe->chan, retrywait);
}
-/* [PHM 06/26/03] */
-
static struct member * interface_exists(struct ast_call_queue *q, char *interface)
{
struct member *mem;
@@ -2236,6 +2280,7 @@ static int queue_exec(struct ast_channel *chan, void *data)
char *user_priority;
int prio;
char *queuetimeoutstr = NULL;
+ enum queue_result reason = QUEUE_UNKNOWN;
/* whether to exit Queue application after the timeout hits */
int go_on = 0;
@@ -2274,10 +2319,10 @@ static int queue_exec(struct ast_channel *chan, void *data)
if (sscanf(user_priority, "%d", &prio) == 1) {
if (option_debug)
ast_log(LOG_DEBUG, "%s: Got priority %d from ${QUEUE_PRIO}.\n",
- chan->name, prio);
+ chan->name, prio);
} else {
ast_log(LOG_WARNING, "${QUEUE_PRIO}: Invalid value (%s), channel %s.\n",
- user_priority, chan->name);
+ user_priority, chan->name);
prio = 0;
}
} else {
@@ -2286,23 +2331,20 @@ static int queue_exec(struct ast_channel *chan, void *data)
prio = 0;
}
- if (options) {
- if (strchr(options, 'r')) {
- ringing = 1;
- }
- }
+ if (options && (strchr(options, 'r')))
+ ringing = 1;
if (option_debug)
ast_log(LOG_DEBUG, "queue: %s, options: %s, url: %s, announce: %s, expires: %ld, priority: %d\n",
- queuename, options, url, announceoverride, (long)qe.expire, (int)prio);
+ queuename, options, url, announceoverride, (long)qe.expire, (int)prio);
qe.chan = chan;
qe.prio = (int)prio;
qe.last_pos_said = 0;
qe.last_pos = 0;
- if (!join_queue(queuename, &qe)) {
- ast_queue_log(queuename, chan->uniqueid, "NONE", "ENTERQUEUE", "%s|%s", url ? url : "", chan->cid.cid_num ? chan->cid.cid_num : "");
- /* Start music on hold */
+ if (!join_queue(queuename, &qe, &reason)) {
+ ast_queue_log(queuename, chan->uniqueid, "NONE", "ENTERQUEUE", "%s|%s", url ? url : "",
+ chan->cid.cid_num ? chan->cid.cid_num : "");
check_turns:
if (ringing) {
ast_indicate(chan, AST_CONTROL_RINGING);
@@ -2312,7 +2354,7 @@ check_turns:
for (;;) {
/* This is the wait loop for callers 2 through maxlen */
- res = wait_our_turn(&qe, ringing);
+ res = wait_our_turn(&qe, ringing, &reason);
/* If they hungup, return immediately */
if (res < 0) {
/* Record this abandoned call */
@@ -2339,8 +2381,11 @@ check_turns:
/* they may dial a digit from the queue context; */
/* or, they may timeout. */
+ enum queue_member_status stat;
+
/* Leave if we have exceeded our queuetimeout */
if (qe.expire && (time(NULL) > qe.expire)) {
+ reason = QUEUE_TIMEOUT;
res = 0;
break;
}
@@ -2363,14 +2408,25 @@ check_turns:
break;
}
+ stat = get_member_status(qe.parent);
+
/* leave the queue if no agents, if enabled */
- if (ast_test_flag(qe.parent, QUEUE_FLAG_LEAVEWHENEMPTY) && has_no_members(qe.parent)) {
+ if (qe.parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
+ reason = QUEUE_LEAVEEMPTY;
+ res = 0;
+ break;
+ }
+
+ /* leave the queue if no reachable agents, if enabled */
+ if ((qe.parent->leavewhenempty == QUEUE_EMPTY_NORMAL) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
+ reason = QUEUE_LEAVEUNAVAIL;
res = 0;
break;
}
/* Leave if we have exceeded our queuetimeout */
if (qe.expire && (time(NULL) > qe.expire)) {
+ reason = QUEUE_TIMEOUT;
res = 0;
break;
}
@@ -2396,6 +2452,7 @@ check_turns:
res = -1;
}
ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHTIMEOUT", "%d", qe.pos);
+ reason = QUEUE_TIMEOUT;
res = 0;
break;
}
@@ -2422,9 +2479,12 @@ check_turns:
ast_stopstream(chan);
}
leave_queue(&qe);
+ if (reason != QUEUE_UNKNOWN)
+ set_queue_result(chan, reason);
} else {
ast_log(LOG_WARNING, "Unable to join queue '%s'\n", queuename);
- res = 0;
+ set_queue_result(chan, reason);
+ res = 0;
}
LOCAL_USER_REMOVE(u);
return res;
@@ -2450,7 +2510,7 @@ static void reload_queues(void)
/* Mark all queues as dead for the moment */
q = queues;
while(q) {
- ast_set_flag(q, QUEUE_FLAG_DEAD);
+ q->dead = 1;
q = q->next;
}
/* Chug through config file */
@@ -2480,7 +2540,7 @@ static void reload_queues(void)
if (!new)
ast_mutex_lock(&q->lock);
/* Re-initialize the queue */
- ast_clear_flag(q, QUEUE_FLAG_DEAD);
+ q->dead = 0;
q->retry = DEFAULT_RETRY;
q->timeout = -1;
q->maxlen = 0;
@@ -2545,7 +2605,7 @@ static void reload_queues(void)
} else if (!strcasecmp(var->name, "timeout")) {
q->timeout = atoi(var->value);
} else if (!strcasecmp(var->name, "monitor-join")) {
- ast_set2_flag(q, ast_true(var->value), QUEUE_FLAG_MONJOIN);
+ q->monjoin = ast_true(var->value);
} else if (!strcasecmp(var->name, "monitor-format")) {
strncpy(q->monfmt, var->value, sizeof(q->monfmt) - 1);
} else if (!strcasecmp(var->name, "queue-youarenext")) {
@@ -2575,7 +2635,12 @@ static void reload_queues(void)
q->roundingseconds=0;
}
} else if (!strcasecmp(var->name, "announce-holdtime")) {
- q->announceholdtime = (!strcasecmp(var->value,"once")) ? 1 : ast_true(var->value);
+ if (!strcasecmp(var->value, "once"))
+ q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
+ else if (ast_true(var->value))
+ q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
+ else
+ q->announceholdtime = 0;
} else if (!strcasecmp(var->name, "retry")) {
q->retry = atoi(var->value);
} else if (!strcasecmp(var->name, "wrapuptime")) {
@@ -2591,13 +2656,23 @@ static void reload_queues(void)
q->strategy = 0;
}
} else if (!strcasecmp(var->name, "joinempty")) {
- ast_set2_flag(q, ast_true(var->value), QUEUE_FLAG_JOINEMPTY);
+ if (!strcasecmp(var->value, "strict"))
+ q->joinempty = QUEUE_EMPTY_STRICT;
+ else if (ast_true(var->value))
+ q->joinempty = QUEUE_EMPTY_NORMAL;
+ else
+ q->joinempty = 0;
} else if (!strcasecmp(var->name, "leavewhenempty")) {
- ast_set2_flag(q, ast_true(var->value), QUEUE_FLAG_LEAVEWHENEMPTY);
+ if (!strcasecmp(var->value, "strict"))
+ q->leavewhenempty = QUEUE_EMPTY_STRICT;
+ else if (ast_true(var->value))
+ q->leavewhenempty = QUEUE_EMPTY_NORMAL;
+ else
+ q->leavewhenempty = 0;
} else if (!strcasecmp(var->name, "eventwhencalled")) {
- ast_set2_flag(q, ast_true(var->value), QUEUE_FLAG_EVENTWHENCALLED);
+ q->eventwhencalled = ast_true(var->value);
} else if (!strcasecmp(var->name, "reportholdtime")) {
- ast_set2_flag(q, ast_true(var->value), QUEUE_FLAG_REPORTHOLDTIME);
+ q->reportholdtime = ast_true(var->value);
} else if (!strcasecmp(var->name, "memberdelay")) {
q->memberdelay = atoi(var->value);
} else if (!strcasecmp(var->name, "weight")) {
@@ -2605,7 +2680,7 @@ static void reload_queues(void)
if (q->weight)
use_weight++;
} else if (!strcasecmp(var->name, "timeoutrestart")) {
- ast_set2_flag(q, ast_true(var->value), QUEUE_FLAG_TIMEOUTRESTART);
+ q->timeoutrestart = ast_true(var->value);
} else {
ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queue.conf\n", cat, var->name, var->lineno);
}
@@ -2637,7 +2712,7 @@ static void reload_queues(void)
ql = NULL;
while(q) {
qn = q->next;
- if (ast_test_flag(q, QUEUE_FLAG_DEAD)) {
+ if (q->dead) {
if (ql)
ql->next = q->next;
else
diff --git a/channel.c b/channel.c
index d2ac71a24..ba42f9ad2 100755
--- a/channel.c
+++ b/channel.c
@@ -2219,14 +2219,14 @@ int ast_channel_supports_html(struct ast_channel *chan)
return 0;
}
-int ast_channel_sendhtml(struct ast_channel *chan, int subclass, char *data, int datalen)
+int ast_channel_sendhtml(struct ast_channel *chan, int subclass, const char *data, int datalen)
{
if (chan->tech->send_html)
return chan->tech->send_html(chan, subclass, data, datalen);
return -1;
}
-int ast_channel_sendurl(struct ast_channel *chan, char *url)
+int ast_channel_sendurl(struct ast_channel *chan, const char *url)
{
if (chan->tech->send_html)
return chan->tech->send_html(chan, AST_HTML_URL, url, strlen(url) + 1);
diff --git a/channels/chan_agent.c b/channels/chan_agent.c
index 1d592827b..9043eaf8c 100755
--- a/channels/chan_agent.c
+++ b/channels/chan_agent.c
@@ -201,7 +201,7 @@ static int agent_hangup(struct ast_channel *ast);
static int agent_answer(struct ast_channel *ast);
static struct ast_frame *agent_read(struct ast_channel *ast);
static int agent_write(struct ast_channel *ast, struct ast_frame *f);
-static int agent_sendhtml(struct ast_channel *ast, int subclass, char *data, int datalen);
+static int agent_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
static int agent_indicate(struct ast_channel *ast, int condition);
static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge);
@@ -450,7 +450,7 @@ static struct ast_frame *agent_read(struct ast_channel *ast)
return f;
}
-static int agent_sendhtml(struct ast_channel *ast, int subclass, char *data, int datalen)
+static int agent_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
{
struct agent_pvt *p = ast->tech_pvt;
int res = -1;
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 6c852cf01..c44dc97f1 100755
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -653,11 +653,11 @@ static ast_mutex_t iaxsl[IAX_MAX_CALLS];
static struct timeval lastused[IAX_MAX_CALLS];
-static int send_command(struct chan_iax2_pvt *, char, int, unsigned int, char *, int, int);
-static int send_command_locked(unsigned short callno, char, int, unsigned int, char *, int, int);
-static int send_command_immediate(struct chan_iax2_pvt *, char, int, unsigned int, char *, int, int);
-static int send_command_final(struct chan_iax2_pvt *, char, int, unsigned int, char *, int, int);
-static int send_command_transfer(struct chan_iax2_pvt *, char, int, unsigned int, char *, int);
+static int send_command(struct chan_iax2_pvt *, char, int, unsigned int, const char *, int, int);
+static int send_command_locked(unsigned short callno, char, int, unsigned int, const char *, int, int);
+static int send_command_immediate(struct chan_iax2_pvt *, char, int, unsigned int, const char *, int, int);
+static int send_command_final(struct chan_iax2_pvt *, char, int, unsigned int, const char *, int, int);
+static int send_command_transfer(struct chan_iax2_pvt *, char, int, unsigned int, const char *, int);
static struct iax2_user *build_user(const char *name, struct ast_variable *v, int temponly);
static void destroy_user(struct iax2_user *user);
static int expire_registry(void *data);
@@ -670,9 +670,9 @@ static int iax2_provision(struct sockaddr_in *end, char *dest, const char *templ
static struct ast_channel *iax2_request(const char *type, int format, void *data, int *cause);
static int iax2_devicestate(void *data);
static int iax2_digit(struct ast_channel *c, char digit);
-static int iax2_sendtext(struct ast_channel *c, char *text);
+static int iax2_sendtext(struct ast_channel *c, const char *text);
static int iax2_sendimage(struct ast_channel *c, struct ast_frame *img);
-static int iax2_sendhtml(struct ast_channel *c, int subclass, char *data, int datalen);
+static int iax2_sendhtml(struct ast_channel *c, int subclass, const char *data, int datalen);
static int iax2_call(struct ast_channel *c, char *dest, int timeout);
static int iax2_hangup(struct ast_channel *c);
static int iax2_answer(struct ast_channel *c);
@@ -681,7 +681,7 @@ static int iax2_write(struct ast_channel *c, struct ast_frame *f);
static int iax2_indicate(struct ast_channel *c, int condition);
static int iax2_setoption(struct ast_channel *c, int option, void *data, int datalen);
static int iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
-static int iax2_transfer(struct ast_channel *c, char *dest);
+static int iax2_transfer(struct ast_channel *c, const char *dest);
static int iax2_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan);
static const struct ast_channel_tech iax2_tech = {
@@ -2487,7 +2487,7 @@ static int iax2_digit(struct ast_channel *c, char digit)
return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF, digit, 0, NULL, 0, -1);
}
-static int iax2_sendtext(struct ast_channel *c, char *text)
+static int iax2_sendtext(struct ast_channel *c, const char *text)
{
return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT,
@@ -2499,7 +2499,7 @@ static int iax2_sendimage(struct ast_channel *c, struct ast_frame *img)
return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1);
}
-static int iax2_sendhtml(struct ast_channel *c, int subclass, char *data, int datalen)
+static int iax2_sendhtml(struct ast_channel *c, int subclass, const char *data, int datalen)
{
return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, data, datalen, -1);
}
@@ -3214,7 +3214,7 @@ static int iax2_indicate(struct ast_channel *c, int condition)
return send_command_locked(callno, AST_FRAME_CONTROL, condition, 0, NULL, 0, -1);
}
-static int iax2_transfer(struct ast_channel *c, char *dest)
+static int iax2_transfer(struct ast_channel *c, const char *dest)
{
unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
struct iax_ie_data ied;
@@ -4484,7 +4484,7 @@ static int iax2_write(struct ast_channel *c, struct ast_frame *f)
return res;
}
-static int __send_command(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno,
+static int __send_command(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const char *data, int datalen, int seqno,
int now, int transfer, int final)
{
struct ast_frame f;
@@ -4495,16 +4495,16 @@ static int __send_command(struct chan_iax2_pvt *i, char type, int command, unsig
f.mallocd = 0;
f.offset = 0;
f.src = (char *)__FUNCTION__;
- f.data = data;
+ f.data = (char *)data;
return iax2_send(i, &f, ts, seqno, now, transfer, final);
}
-static int send_command(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno)
+static int send_command(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const char *data, int datalen, int seqno)
{
return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0);
}
-static int send_command_locked(unsigned short callno, char type, int command, unsigned int ts, char *data, int datalen, int seqno)
+static int send_command_locked(unsigned short callno, char type, int command, unsigned int ts, const char *data, int datalen, int seqno)
{
int res;
ast_mutex_lock(&iaxsl[callno]);
@@ -4514,25 +4514,25 @@ static int send_command_locked(unsigned short callno, char type, int command, un
}
#ifdef BRIDGE_OPTIMIZATION
-static int forward_command(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno)
+static int forward_command(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const char *data, int datalen, int seqno)
{
return __send_command(iaxs[i->bridgecallno], type, command, ts, data, datalen, seqno, 0, 0, 0);
}
#endif
-static int send_command_final(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno)
+static int send_command_final(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const char *data, int datalen, int seqno)
{
/* It is assumed that the callno has already been locked */
iax2_predestroy_nolock(i->callno);
return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1);
}
-static int send_command_immediate(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno)
+static int send_command_immediate(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const char *data, int datalen, int seqno)
{
return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0);
}
-static int send_command_transfer(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, char *data, int datalen)
+static int send_command_transfer(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const char *data, int datalen)
{
return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0);
}
diff --git a/channels/chan_local.c b/channels/chan_local.c
index 95b1cdad9..05a20992e 100755
--- a/channels/chan_local.c
+++ b/channels/chan_local.c
@@ -61,7 +61,7 @@ static struct ast_frame *local_read(struct ast_channel *ast);
static int local_write(struct ast_channel *ast, struct ast_frame *f);
static int local_indicate(struct ast_channel *ast, int condition);
static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
-static int local_sendhtml(struct ast_channel *ast, int subclass, char *data, int datalen);
+static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
static const struct ast_channel_tech local_tech = {
.type = type,
@@ -264,7 +264,7 @@ static int local_digit(struct ast_channel *ast, char digit)
return res;
}
-static int local_sendhtml(struct ast_channel *ast, int subclass, char *data, int datalen)
+static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
{
struct local_pvt *p = ast->tech_pvt;
int res = -1;
@@ -273,7 +273,7 @@ static int local_sendhtml(struct ast_channel *ast, int subclass, char *data, int
ast_mutex_lock(&p->lock);
isoutbound = IS_OUTBOUND(ast, p);
f.subclass = subclass;
- f.data = data;
+ f.data = (char *)data;
f.datalen = datalen;
res = local_queue_frame(p, isoutbound, &f, ast);
ast_mutex_unlock(&p->lock);
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index 75e6c6696..04f7d675e 100755
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -120,6 +120,7 @@ static const char config[] = "mgcp.conf";
#define MGCP_DTMF_RFC2833 (1 << 0)
#define MGCP_DTMF_INBAND (1 << 1)
+#define MGCP_DTMF_HYBRID (1 << 2)
#define DEFAULT_MGCP_GW_PORT 2427 /* From RFC 2705 */
#define DEFAULT_MGCP_CA_PORT 2727 /* From RFC 2705 */
@@ -988,6 +989,8 @@ static int mgcp_hangup(struct ast_channel *ast)
if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) {
/* SC: check whether other channel is active. */
if (!sub->next->owner) {
+ if (p->dtmfmode & MGCP_DTMF_HYBRID)
+ p->dtmfmode &= ~MGCP_DTMF_INBAND;
if (mgcpdebug) {
ast_verbose(VERBOSE_PREFIX_2 "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
}
@@ -1377,7 +1380,7 @@ static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state)
if (sub->rtp)
tmp->fds[0] = ast_rtp_fd(sub->rtp);
tmp->type = type;
- if (i->dtmfmode & MGCP_DTMF_INBAND) {
+ if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
i->dsp = ast_dsp_new();
ast_dsp_set_features(i->dsp,DSP_FEATURE_DTMF_DETECT);
/* SC: this is to prevent clipping of dtmf tones during dsp processing */
@@ -2617,6 +2620,10 @@ static void *mgcp_ss(void *data)
}
ast_setstate(chan, AST_STATE_RING);
/*zt_enable_ec(p);*/
+ if (p->dtmfmode & MGCP_DTMF_HYBRID) {
+ p->dtmfmode |= MGCP_DTMF_INBAND;
+ ast_indicate(chan, -1);
+ }
res = ast_pbx_run(chan);
if (res) {
ast_log(LOG_WARNING, "PBX exited non-zero\n");
@@ -3608,6 +3615,8 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
dtmfmode = MGCP_DTMF_INBAND;
else if (!strcasecmp(v->value, "rfc2833"))
dtmfmode = MGCP_DTMF_RFC2833;
+ else if (!strcasecmp(v->value, "hybrid"))
+ dtmfmode = MGCP_DTMF_HYBRID;
else if (!strcasecmp(v->value, "none"))
dtmfmode = 0;
else
@@ -3702,6 +3711,8 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
e->capability = capability;
e->parent = gw;
e->dtmfmode = dtmfmode;
+ if (!ep_reload && e->sub->rtp)
+ e->dtmfmode |= MGCP_DTMF_INBAND;
e->adsi = adsi;
e->type = TYPE_LINE;
e->immediate = immediate;
diff --git a/channels/chan_phone.c b/channels/chan_phone.c
index 81958e078..62778ed76 100755
--- a/channels/chan_phone.c
+++ b/channels/chan_phone.c
@@ -139,7 +139,7 @@ static int phone_answer(struct ast_channel *ast);
static struct ast_frame *phone_read(struct ast_channel *ast);
static int phone_write(struct ast_channel *ast, struct ast_frame *frame);
static struct ast_frame *phone_exception(struct ast_channel *ast);
-static int phone_send_text(struct ast_channel *ast, char *text);
+static int phone_send_text(struct ast_channel *ast, const char *text);
static const struct ast_channel_tech phone_tech = {
.type = type,
@@ -536,7 +536,7 @@ static struct ast_frame *phone_read(struct ast_channel *ast)
return &p->fr;
}
-static int phone_write_buf(struct phone_pvt *p, char *buf, int len, int frlen)
+static int phone_write_buf(struct phone_pvt *p, const char *buf, int len, int frlen)
{
int res;
/* Store as much of the buffer as we can, then write fixed frames */
@@ -567,7 +567,7 @@ static int phone_write_buf(struct phone_pvt *p, char *buf, int len, int frlen)
return len;
}
-static int phone_send_text(struct ast_channel *ast, char *text)
+static int phone_send_text(struct ast_channel *ast, const char *text)
{
int length = strlen(text);
return phone_write_buf(ast->tech_pvt, text, length, length) ==
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 023ecd4a0..4ae182c22 100755
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -653,9 +653,9 @@ static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int inc,
static int transmit_invite(struct sip_pvt *p, int sipmethod, int sendsdp, char *auth, char *authheader, char *vxml_url, char *distinctive_ring, char *osptoken, int addsipheaders, int init);
static int transmit_reinvite_with_sdp(struct sip_pvt *p);
static int transmit_info_with_digit(struct sip_pvt *p, char digit);
-static int transmit_message_with_text(struct sip_pvt *p, char *text);
-static int transmit_refer(struct sip_pvt *p, char *dest);
-static int sip_sipredirect(struct sip_pvt *p, char *dest);
+static int transmit_message_with_text(struct sip_pvt *p, const char *text);
+static int transmit_refer(struct sip_pvt *p, const char *dest);
+static int sip_sipredirect(struct sip_pvt *p, const char *dest);
static struct sip_peer *temp_peer(char *name);
static int do_proxy_auth(struct sip_pvt *p, struct sip_request *req, char *header, char *respheader, int sipmethod, int init);
static void free_old_route(struct sip_route *route);
@@ -670,17 +670,16 @@ static int callevents = 0;
static struct ast_channel *sip_request(const char *type, int format, void *data, int *cause);
static int sip_devicestate(void *data);
-static int sip_sendtext(struct ast_channel *ast, char *text);
+static int sip_sendtext(struct ast_channel *ast, const char *text);
static int sip_call(struct ast_channel *ast, char *dest, int timeout);
static int sip_hangup(struct ast_channel *ast);
static int sip_answer(struct ast_channel *ast);
static struct ast_frame *sip_read(struct ast_channel *ast);
static int sip_write(struct ast_channel *ast, struct ast_frame *frame);
static int sip_indicate(struct ast_channel *ast, int condition);
-static int sip_transfer(struct ast_channel *ast, char *dest);
+static int sip_transfer(struct ast_channel *ast, const char *dest);
static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
static int sip_senddigit(struct ast_channel *ast, char digit);
-static int sip_sendtext(struct ast_channel *ast, char *text);
static int clear_realm_authentication(struct sip_auth *authlist); /* Clear realm authentication list (at reload) */
static struct sip_auth *add_realm_authentication(struct sip_auth *authlist, char *configuration, int lineno); /* Add realm authentication in list */
static struct sip_auth *find_realm_authentication(struct sip_auth *authlist, char *realm); /* Find authentication for a specific realm */
@@ -1178,7 +1177,7 @@ static char *ditch_braces(char *tmp)
/*--- sip_sendtext: Send SIP MESSAGE text within a call ---*/
/* Called from PBX core text message functions */
-static int sip_sendtext(struct ast_channel *ast, char *text)
+static int sip_sendtext(struct ast_channel *ast, const char *text)
{
struct sip_pvt *p = ast->tech_pvt;
int debug=sip_debug_test_pvt(p);
@@ -2098,7 +2097,7 @@ static int sip_senddigit(struct ast_channel *ast, char digit)
/*--- sip_transfer: Transfer SIP call */
-static int sip_transfer(struct ast_channel *ast, char *dest)
+static int sip_transfer(struct ast_channel *ast, const char *dest)
{
struct sip_pvt *p = ast->tech_pvt;
int res;
@@ -3122,7 +3121,7 @@ static int add_blank_header(struct sip_request *req)
}
/*--- add_line: Add content (not header) to SIP message */
-static int add_line(struct sip_request *req, char *line)
+static int add_line(struct sip_request *req, const char *line)
{
if (req->len >= sizeof(req->data) - 4) {
ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
@@ -3573,7 +3572,7 @@ static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_
}
/*--- add_text: Add text body to SIP message ---*/
-static int add_text(struct sip_request *req, char *text)
+static int add_text(struct sip_request *req, const char *text)
{
/* XXX Convert \n's to \r\n's XXX */
int len = strlen(text);
@@ -4603,7 +4602,7 @@ static int transmit_register(struct sip_registry *r, int sipmethod, char *auth,
}
/*--- transmit_message_with_text: Transmit text with SIP MESSAGE method ---*/
-static int transmit_message_with_text(struct sip_pvt *p, char *text)
+static int transmit_message_with_text(struct sip_pvt *p, const char *text)
{
struct sip_request req;
reqprep(&req, p, SIP_MESSAGE, 0, 1);
@@ -4612,7 +4611,7 @@ static int transmit_message_with_text(struct sip_pvt *p, char *text)
}
/*--- transmit_refer: Transmit SIP REFER message ---*/
-static int transmit_refer(struct sip_pvt *p, char *dest)
+static int transmit_refer(struct sip_pvt *p, const char *dest)
{
struct sip_request req;
char from[256];
@@ -10633,7 +10632,7 @@ static int sip_getheader(struct ast_channel *chan, void *data)
/* Called by the transfer() dialplan application through the sip_transfer() */
/* pbx interface function if the call is in ringing state */
/* coded by Martin Pycko (m78pl@yahoo.com) */
-static int sip_sipredirect(struct sip_pvt *p, char *dest)
+static int sip_sipredirect(struct sip_pvt *p, const char *dest)
{
char *cdest;
char *extension, *host, *port;
diff --git a/channels/chan_zap.c b/channels/chan_zap.c
index d10886531..c68f0ff48 100755
--- a/channels/chan_zap.c
+++ b/channels/chan_zap.c
@@ -299,7 +299,7 @@ static int restart_monitor(void);
static int zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
-static int zt_sendtext(struct ast_channel *c, char *text);
+static int zt_sendtext(struct ast_channel *c, const char *text);
static inline int zt_get_event(int fd)
{
@@ -615,7 +615,7 @@ static struct zt_pvt {
static struct ast_channel *zt_request(const char *type, int format, void *data, int *cause);
static int zt_digit(struct ast_channel *ast, char digit);
-static int zt_sendtext(struct ast_channel *c, char *text);
+static int zt_sendtext(struct ast_channel *c, const char *text);
static int zt_call(struct ast_channel *ast, char *rdest, int timeout);
static int zt_hangup(struct ast_channel *ast);
static int zt_answer(struct ast_channel *ast);
@@ -10189,7 +10189,7 @@ int load_module(void)
return res;
}
-static int zt_sendtext(struct ast_channel *c, char *text)
+static int zt_sendtext(struct ast_channel *c, const char *text)
{
#define END_SILENCE_LEN 400
#define HEADER_MS 50
diff --git a/configs/mgcp.conf.sample b/configs/mgcp.conf.sample
index 2af96c9b3..63e725557 100755
--- a/configs/mgcp.conf.sample
+++ b/configs/mgcp.conf.sample
@@ -45,7 +45,7 @@
;
;context=local
;host=dynamic
-;dtmfmode=none ; DTMF Mode can be 'none', 'rfc2833', or 'inband'. Default is none.
+;dtmfmode=none ; DTMF Mode can be 'none', 'rfc2833', or 'inband' or 'hybrid' which starts in none and moves to inband. Default is none.
;slowsequence=yes ; The DPH100M does not follow MGCP standards for sequencing
;line => aaln/1
diff --git a/configs/queues.conf.sample b/configs/queues.conf.sample
index 0c3447ffa..983b89dcd 100755
--- a/configs/queues.conf.sample
+++ b/configs/queues.conf.sample
@@ -122,14 +122,21 @@ persistentmembers = yes
;
; monitor-join = yes
;
-; If you wish to allow queues that have no members currently to be joined, set this to yes
+; This setting controls whether callers can join a queue with no members. There are three
+; choices:
+;
+; yes - callers can join a queue with no members or only unavailable members
+; no - callers cannot join a queue with no members or only unavailable members
+; strict - callers cannot join a queue with no members
;
; joinempty = yes
;
-; If you wish to remove callers from the queue if there are no agents present, set this to yes
+; If you wish to remove callers from the queue when new callers cannot join, set this setting
+; to one of the same choices for 'joinwhenempty'
;
; leavewhenempty = yes
;
+;
; Asterisk can generate AgentCalled events when an agent is rung, if this is turned on
; (may generate a LOT of extra manager events)
;
diff --git a/doc/README.variables b/doc/README.variables
index f65ef29d1..83d3011dd 100755
--- a/doc/README.variables
+++ b/doc/README.variables
@@ -340,6 +340,8 @@ ${MONITOR_EXEC} Application to execute after monitoring a call
${MONITOR_EXEC_ARGS} Arguments to application
${MONITOR_FILENAME} File for monitoring (recording) calls in queue
${QUEUE_PRIO} Queue priority
+${QUEUESTATUS} Status of the call, one of:
+ (TIMEOUT | FULL | JOINEMPTY | LEAVEEMPTY | JOINUNAVAIL | LEAVEUNAVAIL)
${RECORDED_FILE} * Recorded file in record()
${TALK_DETECED} * Result from talkdetect()
${TOUCH_MONITOR} The filename base to use with Touch Monitor (auto record)
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index a28135c12..92c500031 100755
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -115,13 +115,13 @@ struct ast_channel_tech {
int (* const write)(struct ast_channel *chan, struct ast_frame *frame);
/*! Display or transmit text */
- int (* const send_text)(struct ast_channel *chan, char *text);
+ int (* const send_text)(struct ast_channel *chan, const char *text);
/*! Display or send an image */
int (* const send_image)(struct ast_channel *chan, struct ast_frame *frame);
/*! Send HTML data */
- int (* const send_html)(struct ast_channel *chan, int subclass, char *data, int len);
+ int (* const send_html)(struct ast_channel *chan, int subclass, const char *data, int len);
/*! Handle an exception, reading a frame */
struct ast_frame * (* const exception)(struct ast_channel *chan);
@@ -143,7 +143,7 @@ struct ast_channel_tech {
int (* const queryoption)(struct ast_channel *chan, int option, void *data, int *datalen);
/*! Blind transfer other side */
- int (* const transfer)(struct ast_channel *chan, char *newdest);
+ int (* const transfer)(struct ast_channel *chan, const char *newdest);
/*! Write a frame, in standard format */
int (* const write_video)(struct ast_channel *chan, struct ast_frame *frame);
@@ -841,11 +841,11 @@ int ast_channel_supports_html(struct ast_channel *channel);
/*! Sends HTML on given channel */
/*! Send HTML or URL on link. Returns 0 on success or -1 on failure */
-int ast_channel_sendhtml(struct ast_channel *channel, int subclass, char *data, int datalen);
+int ast_channel_sendhtml(struct ast_channel *channel, int subclass, const char *data, int datalen);
/*! Sends a URL on a given link */
/*! Send URL on link. Returns 0 on success or -1 on failure */
-int ast_channel_sendurl(struct ast_channel *channel, char *url);
+int ast_channel_sendurl(struct ast_channel *channel, const char *url);
/*! Defers DTMF */
/*! Defer DTMF so that you only read things like hangups and audio. Returns
diff --git a/include/asterisk/tdd.h b/include/asterisk/tdd.h
index 9c5313b8c..669b68ce9 100755
--- a/include/asterisk/tdd.h
+++ b/include/asterisk/tdd.h
@@ -35,7 +35,7 @@ extern void tdd_init(void);
* This function creates a stream of TDD data in ulaw format. It returns the size
* (in bytes) of the data (if it returns a size of 0, there is probably an error)
*/
-extern int tdd_generate(struct tdd_state *tdd, unsigned char *buf, char *string);
+extern int tdd_generate(struct tdd_state *tdd, unsigned char *buf, const char *string);
/*! Create a TDD state machine */
/*!
diff --git a/tdd.c b/tdd.c
index e2a6cc839..a3664e82e 100755
--- a/tdd.c
+++ b/tdd.c
@@ -233,7 +233,7 @@ static inline float tdd_getcarrier(float *cr, float *ci, int bit)
PUT_TDD_STOP; /* Stop bit */ \
} while(0);
-int tdd_generate(struct tdd_state *tdd, unsigned char *buf, char *str)
+int tdd_generate(struct tdd_state *tdd, unsigned char *buf, const char *str)
{
int bytes=0;
int i,x;