[asterisk-commits] branch oej/managerstuff r8891 - in
/team/oej/managerstuff: ./ apps/ channels/...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Tue Jan 31 14:20:39 MST 2006
Author: oej
Date: Mon Jan 30 03:19:22 2006
New Revision: 8891
URL: http://svn.digium.com/view/asterisk?rev=8891&view=rev
Log:
Merged revisions 8112,8122,8124,8134,8140,8162,8173,8194,8232,8242,8276,8281,8320,8347,8394,8412,8414,8418,8429,8433,8437,8445,8537,8562,8573,8588,8600,8608,8619,8632,8666,8677,8710,8729,8758,8785,8808 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.2
........
r8112 | kpfleming | 2006-01-17 00:51:37 +0100 (Tue, 17 Jan 2006) | 2 lines
do rlimit check _after_ reading config file, in case 'dumpcore' is specified there
........
r8122 | kpfleming | 2006-01-17 14:11:55 +0100 (Tue, 17 Jan 2006) | 2 lines
update CLI copyright notice
........
r8124 | mogorman | 2006-01-17 17:55:30 +0100 (Tue, 17 Jan 2006) | 3 lines
Fixed code ordering of logger_init and queue_log_init
bug 6263
........
r8134 | mattf | 2006-01-17 19:29:57 +0100 (Tue, 17 Jan 2006) | 2 lines
Backport of fix for #6094
........
r8140 | mogorman | 2006-01-17 21:10:29 +0100 (Tue, 17 Jan 2006) | 3 lines
Stop any generators running on a channel when
festival is called as described in 5996
........
r8162 | mogorman | 2006-01-18 01:47:04 +0100 (Wed, 18 Jan 2006) | 4 lines
Changed order of autoload so that pbx_ comes before
channels, and in doing so cause bug 6002 to not
be an issue
........
r8173 | russell | 2006-01-18 03:49:21 +0100 (Wed, 18 Jan 2006) | 2 lines
remove ChangeLog from the 1.2 branch. It will only be present in the tags.
........
r8194 | mogorman | 2006-01-18 22:02:06 +0100 (Wed, 18 Jan 2006) | 3 lines
Solves issue with the login proccess in meetme
patch from 6136
........
r8232 | russell | 2006-01-19 05:17:45 +0100 (Thu, 19 Jan 2006) | 3 lines
fix a seg fault due to assuming that space gets allocatted on the stack in the
same order that we declare the variables (issue #6290)
........
r8242 | russell | 2006-01-19 05:56:48 +0100 (Thu, 19 Jan 2006) | 3 lines
fix Message-Account header to use the ip address if the fromdomain
isn't set (issue #6278)
........
r8276 | tilghman | 2006-01-19 20:14:37 +0100 (Thu, 19 Jan 2006) | 2 lines
Bug 6072 - Memory leaks in the expression parser
........
r8281 | oej | 2006-01-19 20:40:28 +0100 (Thu, 19 Jan 2006) | 2 lines
Enable "musicclass" setting for sip peers as per the config sample.
........
r8320 | mogorman | 2006-01-20 02:00:46 +0100 (Fri, 20 Jan 2006) | 3 lines
solved problem with delayreject and iax trunking
bug 4291
........
r8347 | russell | 2006-01-20 19:34:42 +0100 (Fri, 20 Jan 2006) | 2 lines
fix invalid value of prev_q (issue #6302)
........
r8394 | tilghman | 2006-01-21 19:29:39 +0100 (Sat, 21 Jan 2006) | 2 lines
Bug 5936 - AddQueueMember fails on realtime queue, if queue not yet loaded
........
r8412 | russell | 2006-01-22 00:17:06 +0100 (Sun, 22 Jan 2006) | 2 lines
prevent the possibility of writing outside of the available workspace (issue #6271)
........
r8414 | russell | 2006-01-22 00:43:14 +0100 (Sun, 22 Jan 2006) | 2 lines
temporarily revert substring fix pending the result of the discussion in issue #6271
........
r8418 | russell | 2006-01-22 03:05:41 +0100 (Sun, 22 Jan 2006) | 3 lines
add a modified fix to prevent writing outside of the provided workspace when
calculating a substring (issue #6271)
........
r8429 | tilghman | 2006-01-22 09:52:49 +0100 (Sun, 22 Jan 2006) | 2 lines
Bug 6281 - Cannot set more than a single header with SIPAddHeader
........
r8433 | bweschke | 2006-01-22 16:13:41 +0100 (Sun, 22 Jan 2006) | 3 lines
Bug fix: Correct some scenarios where CALL_LIMIT could not be getting adjusted properly allowing chan_sip to send calls when it really shouldn't. Bug #6111
........
r8437 | russell | 2006-01-22 18:47:13 +0100 (Sun, 22 Jan 2006) | 2 lines
fix MixMonitor crash (issue #6321, probably others)
........
r8445 | russell | 2006-01-22 20:03:53 +0100 (Sun, 22 Jan 2006) | 2 lines
fix memory leak from not freeing the queue member list when freeing an old queue
........
r8537 | oej | 2006-01-24 14:15:13 +0100 (Tue, 24 Jan 2006) | 2 lines
Issue #6308 - never send response to ACK. (Reported by whiskerp)
........
r8562 | oej | 2006-01-24 20:21:15 +0100 (Tue, 24 Jan 2006) | 2 lines
Issue 6114: Don't hangup on BYE/ALSO with no channel.
........
r8573 | mattf | 2006-01-24 21:37:30 +0100 (Tue, 24 Jan 2006) | 2 lines
Backport fix for #6229, hangup on polarity reversal
........
r8588 | kpfleming | 2006-01-24 23:32:09 +0100 (Tue, 24 Jan 2006) | 2 lines
ensure that channel cannot become zombie after we check but before we try to start indications
........
r8600 | russell | 2006-01-24 23:55:32 +0100 (Tue, 24 Jan 2006) | 2 lines
completely arbitrary whitespace change for testing something with svnmerge ...
........
r8608 | kpfleming | 2006-01-25 02:50:52 +0100 (Wed, 25 Jan 2006) | 2 lines
ensure hangup cause code is handled properly when channel does not return a frame (issue #6346)
........
r8619 | russell | 2006-01-25 06:38:36 +0100 (Wed, 25 Jan 2006) | 2 lines
don't leak almost 200 bytes for each new channel (issue #6330)
........
r8632 | oej | 2006-01-25 10:46:43 +0100 (Wed, 25 Jan 2006) | 2 lines
Issue #6439 - the "timebomb" bug. Patch by Markster over GPRS
........
r8666 | russell | 2006-01-25 19:39:44 +0100 (Wed, 25 Jan 2006) | 2 lines
fix memory leak (inspired by issue #6351)
........
r8677 | russell | 2006-01-25 20:14:43 +0100 (Wed, 25 Jan 2006) | 3 lines
don't call ast_update_realtime with uninitialized variables if we get a
registration with an expirey of 0 seconds (issue #6173)
........
r8710 | oej | 2006-01-26 15:39:36 +0100 (Thu, 26 Jan 2006) | 2 lines
Issue 5898: Registrations does not get deleted if there's an active SIP dialog
........
r8729 | russell | 2006-01-26 20:42:35 +0100 (Thu, 26 Jan 2006) | 2 lines
fix problem with dtmf on e&m (issue #6364)
........
r8758 | tilghman | 2006-01-27 01:52:12 +0100 (Fri, 27 Jan 2006) | 2 lines
Bug 6072 - Revisions to the source bison and flex files don't auto-regenerate these files
........
r8785 | oej | 2006-01-27 09:02:16 +0100 (Fri, 27 Jan 2006) | 2 lines
Issue 6362 - Register without Contact: and Expires: fails (reporter: op)
........
r8808 | oej | 2006-01-28 14:52:15 +0100 (Sat, 28 Jan 2006) | 3 lines
Issue 6182 - Don't remove scheduled event until it's really done.
(reported by malverian)
........
Removed:
team/oej/managerstuff/ChangeLog
Modified:
team/oej/managerstuff/ (props changed)
team/oej/managerstuff/apps/app_dial.c
team/oej/managerstuff/apps/app_festival.c
team/oej/managerstuff/apps/app_meetme.c
team/oej/managerstuff/apps/app_milliwatt.c
team/oej/managerstuff/apps/app_queue.c
team/oej/managerstuff/ast_expr2.c
team/oej/managerstuff/ast_expr2.fl
team/oej/managerstuff/ast_expr2.h
team/oej/managerstuff/ast_expr2.y
team/oej/managerstuff/ast_expr2f.c
team/oej/managerstuff/asterisk.c
team/oej/managerstuff/channel.c
team/oej/managerstuff/channels/chan_features.c
team/oej/managerstuff/channels/chan_iax2.c
team/oej/managerstuff/channels/chan_sip.c
team/oej/managerstuff/channels/chan_zap.c
team/oej/managerstuff/loader.c
team/oej/managerstuff/logger.c
team/oej/managerstuff/pbx.c
team/oej/managerstuff/res/res_features.c
team/oej/managerstuff/utils/astman.c
Propchange: team/oej/managerstuff/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Mon Jan 30 03:19:22 2006
@@ -1,1 +1,1 @@
-/branches/1.2:1-7496,7498-8109
+/branches/1.2:1-7496,7498-8888
Modified: team/oej/managerstuff/apps/app_dial.c
URL: http://svn.digium.com/view/asterisk/team/oej/managerstuff/apps/app_dial.c?rev=8891&r1=8890&r2=8891&view=diff
==============================================================================
--- team/oej/managerstuff/apps/app_dial.c (original)
+++ team/oej/managerstuff/apps/app_dial.c Mon Jan 30 03:19:22 2006
@@ -652,6 +652,7 @@
ast_hangup(o->chan);
o->chan = NULL;
ast_clear_flag(o, DIAL_STILLGOING);
+ HANDLE_CAUSE(in->hangupcause, in);
}
}
o = o->next;
Modified: team/oej/managerstuff/apps/app_festival.c
URL: http://svn.digium.com/view/asterisk/team/oej/managerstuff/apps/app_festival.c?rev=8891&r1=8890&r2=8891&view=diff
==============================================================================
--- team/oej/managerstuff/apps/app_festival.c (original)
+++ team/oej/managerstuff/apps/app_festival.c Mon Jan 30 03:19:22 2006
@@ -177,7 +177,8 @@
if (chan->_state != AST_STATE_UP)
ast_answer(chan);
ast_stopstream(chan);
-
+ ast_indicate(chan, -1);
+
owriteformat = chan->writeformat;
res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
if (res < 0) {
Modified: team/oej/managerstuff/apps/app_meetme.c
URL: http://svn.digium.com/view/asterisk/team/oej/managerstuff/apps/app_meetme.c?rev=8891&r1=8890&r2=8891&view=diff
==============================================================================
--- team/oej/managerstuff/apps/app_meetme.c (original)
+++ team/oej/managerstuff/apps/app_meetme.c Mon Jan 30 03:19:22 2006
@@ -1739,7 +1739,8 @@
if (dynamic_pin) {
if (dynamic_pin[0] == 'q') {
/* Query the user to enter a PIN */
- ast_app_getdata(chan, "conf-getpin", dynamic_pin, AST_MAX_EXTENSION - 1, 0);
+ if (ast_app_getdata(chan, "conf-getpin", dynamic_pin, AST_MAX_EXTENSION - 1, 0) < 0)
+ return NULL;
}
cnf = build_conf(confno, dynamic_pin, "", make, dynamic);
} else {
Modified: team/oej/managerstuff/apps/app_milliwatt.c
URL: http://svn.digium.com/view/asterisk/team/oej/managerstuff/apps/app_milliwatt.c?rev=8891&r1=8890&r2=8891&view=diff
==============================================================================
--- team/oej/managerstuff/apps/app_milliwatt.c (original)
+++ team/oej/managerstuff/apps/app_milliwatt.c Mon Jan 30 03:19:22 2006
@@ -75,30 +75,29 @@
static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int samples)
{
struct ast_frame wf;
- unsigned char waste[AST_FRIENDLY_OFFSET];
- unsigned char buf[640];
+ unsigned char buf[AST_FRIENDLY_OFFSET + 640];
int i,*indexp = (int *) data;
- if (len > sizeof(buf))
+ if (len + AST_FRIENDLY_OFFSET > sizeof(buf))
{
- ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",(int)sizeof(buf),len);
- len = sizeof(buf);
+ ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",(int)(sizeof(buf) - AST_FRIENDLY_OFFSET),len);
+ len = sizeof(buf) - AST_FRIENDLY_OFFSET;
}
- waste[0] = 0; /* make compiler happy */
wf.frametype = AST_FRAME_VOICE;
wf.subclass = AST_FORMAT_ULAW;
wf.offset = AST_FRIENDLY_OFFSET;
wf.mallocd = 0;
- wf.data = buf;
+ wf.data = buf + AST_FRIENDLY_OFFSET;
wf.datalen = len;
wf.samples = wf.datalen;
wf.src = "app_milliwatt";
wf.delivery.tv_sec = 0;
wf.delivery.tv_usec = 0;
+ wf.prev = wf.next = NULL;
/* create a buffer containing the digital milliwatt pattern */
for(i = 0; i < len; i++)
{
- buf[i] = digital_milliwatt[(*indexp)++];
+ buf[AST_FRIENDLY_OFFSET + i] = digital_milliwatt[(*indexp)++];
*indexp &= 7;
}
if (ast_write(chan,&wf) < 0)
Modified: team/oej/managerstuff/apps/app_queue.c
URL: http://svn.digium.com/view/asterisk/team/oej/managerstuff/apps/app_queue.c?rev=8891&r1=8890&r2=8891&view=diff
==============================================================================
--- team/oej/managerstuff/apps/app_queue.c (original)
+++ team/oej/managerstuff/apps/app_queue.c Mon Jan 30 03:19:22 2006
@@ -114,6 +114,7 @@
#define DEFAULT_RETRY 5
#define DEFAULT_TIMEOUT 15
#define RECHECK 1 /* Recheck every second to see we we're at the top yet */
+#define MAX_PERIODIC_ANNOUNCEMENTS 10 /* The maximum periodic announcements we can have */
#define RES_OKAY 0 /* Action completed */
#define RES_EXISTS (-1) /* Entry already exists */
@@ -223,7 +224,7 @@
/*! \brief Persistent Members astdb family */
static const char *pm_family = "/Queue/PersistentMembers";
-/* The maximum lengh of each persistent member queue database entry */
+/* The maximum length of each persistent member queue database entry */
#define PM_MAX_LEN 2048
/*! \brief queues.conf [general] option */
@@ -282,7 +283,8 @@
int pos; /*!< Where we are in the queue */
int prio; /*!< Our priority */
int last_pos_said; /*!< Last position we told the user */
- time_t last_periodic_announce_time; /*!< The last time we played a periodic anouncement */
+ time_t last_periodic_announce_time; /*!< The last time we played a periodic announcement */
+ int last_periodic_announce_sound; /* The last periodic announcement we made */
time_t last_pos; /*!< Last time we told the user their position */
int opos; /*!< Where we started in the queue */
int handled; /*!< Whether our call was handled */
@@ -317,18 +319,18 @@
char moh[80]; /*!< Music On Hold class to be used */
char announce[80]; /*!< Announcement to play when call is answered */
char context[AST_MAX_CONTEXT]; /*!< Exit context */
- 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;
- unsigned int maskmemberstatus:1;
- unsigned int realtime:1;
+ 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;
+ unsigned int maskmemberstatus:1;
+ unsigned int realtime:1;
int announcefrequency; /*!< How often to announce their position */
int periodicannouncefrequency; /*!< How often to play periodic announcement */
int roundingseconds; /*!< How many seconds do we round to? */
@@ -347,7 +349,7 @@
char sound_seconds[80]; /*!< Sound file: "seconds." (def. queue-seconds) */
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) */
- char sound_periodicannounce[80];/*!< Sound file: Custom announce, no default */
+ char sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS][80];/* Sound files: Custom announce, no default */
int count; /*!< How many entries */
int maxlen; /*!< Max number of entries */
@@ -356,18 +358,21 @@
int retry; /*!< Retry calling everyone after this amount of time */
int timeout; /*!< How long to wait for an answer */
int weight; /*!< Respective weight */
-
+ int autopause; /*!< Auto pause queue members if they fail to answer */
+
/* Queue strategy things */
int rrpos; /*!< Round Robin - position */
int memberdelay; /*!< Seconds to delay connecting member to caller */
-
+ int autofill; /*!< Ignore the head call status and ring an available agent */
+
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 */
+ AST_LIST_ENTRY(ast_call_queue) list; /*!< Next call queue */
};
-static struct ast_call_queue *queues = NULL;
-AST_MUTEX_DEFINE_STATIC(qlock);
+static AST_LIST_HEAD_STATIC(queues, ast_call_queue);
+
+static int set_member_paused(char *queuename, char *interface, int paused);
static void set_queue_result(struct ast_channel *chan, enum queue_result res)
{
@@ -475,8 +480,8 @@
}
if (option_debug)
ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d' (%s)\n", technology, loc, sc->state, devstate2str(sc->state));
- ast_mutex_lock(&qlock);
- for (q = queues; q; q = q->next) {
+ AST_LIST_LOCK(&queues);
+ AST_LIST_TRAVERSE(&queues, q, list) {
ast_mutex_lock(&q->lock);
cur = q->members;
while(cur) {
@@ -502,7 +507,7 @@
}
ast_mutex_unlock(&q->lock);
}
- ast_mutex_unlock(&qlock);
+ AST_LIST_UNLOCK(&queues);
free(sc);
return NULL;
}
@@ -514,9 +519,8 @@
struct statechange *sc;
pthread_t t;
pthread_attr_t attr;
-
- sc = malloc(sizeof(struct statechange) + strlen(dev) + 1);
- if (sc) {
+
+ if ((sc = ast_calloc(1, sizeof(*sc) + strlen(dev) + 1))) {
sc->state = state;
strcpy(sc->dev, dev);
pthread_attr_init(&attr);
@@ -535,10 +539,7 @@
/* Add a new member */
- cur = malloc(sizeof(struct member));
-
- if (cur) {
- memset(cur, 0, sizeof(struct member));
+ if ((cur = ast_calloc(1, sizeof(*cur)))) {
cur->penalty = penalty;
cur->paused = paused;
ast_copy_string(cur->interface, interface, sizeof(cur->interface));
@@ -554,9 +555,7 @@
{
struct ast_call_queue *q;
- q = malloc(sizeof(*q));
- if (q) {
- memset(q, 0, sizeof(*q));
+ if ((q = ast_calloc(1, sizeof(*q)))) {
ast_mutex_init(&q->lock);
ast_copy_string(q->name, queuename, sizeof(q->name));
}
@@ -565,6 +564,7 @@
static void init_queue(struct ast_call_queue *q)
{
+ int i;
q->dead = 0;
q->retry = DEFAULT_RETRY;
q->timeout = -1;
@@ -587,7 +587,10 @@
ast_copy_string(q->sound_thanks, "queue-thankyou", sizeof(q->sound_thanks));
ast_copy_string(q->sound_lessthan, "queue-less-than", sizeof(q->sound_lessthan));
ast_copy_string(q->sound_reporthold, "queue-reporthold", sizeof(q->sound_reporthold));
- ast_copy_string(q->sound_periodicannounce, "queue-periodic-announce", sizeof(q->sound_periodicannounce));
+ ast_copy_string(q->sound_periodicannounce[0], "queue-periodic-announce", sizeof(q->sound_periodicannounce[0]));
+ for (i=1;i<MAX_PERIODIC_ANNOUNCEMENTS;i++) {
+ q->sound_periodicannounce[i][0]='\0';
+ }
}
static void clear_queue(struct ast_call_queue *q)
@@ -608,6 +611,9 @@
extra fields in the tables. */
static void queue_set_param(struct ast_call_queue *q, const char *param, const char *val, int linenum, int failunknown)
{
+ int i = 0;
+ char *c, *lastc;
+ char buff[80];
if (!strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
ast_copy_string(q->moh, val, sizeof(q->moh));
} else if (!strcasecmp(param, "announce")) {
@@ -662,8 +668,24 @@
q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
else
q->announceholdtime = 0;
- } else if (!strcasecmp(param, "periodic-announce")) {
- ast_copy_string(q->sound_periodicannounce, val, sizeof(q->sound_periodicannounce));
+ } else if (!strcasecmp(param, "periodic-announce")) {
+ if (strchr(val,'|')) {
+ lastc = (char *)val;
+ while ((c = strchr(lastc,'|'))) {
+ if (i > MAX_PERIODIC_ANNOUNCEMENTS)
+ break;
+ strncpy(buff, lastc, abs(lastc - c));
+ buff[abs(lastc - c)] = '\0';
+ ast_copy_string(q->sound_periodicannounce[i], buff, sizeof(q->sound_periodicannounce[i]));
+ lastc = (c + 1);
+ i++;
+ }
+ if (strlen(lastc)) {
+ ast_copy_string(q->sound_periodicannounce[i], lastc, sizeof(q->sound_periodicannounce[i]));
+ }
+ } else {
+ ast_copy_string(q->sound_periodicannounce[i], val, sizeof(q->sound_periodicannounce[i]));
+ }
} else if (!strcasecmp(param, "periodic-announce-frequency")) {
q->periodicannouncefrequency = atoi(val);
} else if (!strcasecmp(param, "retry")) {
@@ -672,6 +694,10 @@
q->retry = DEFAULT_RETRY;
} else if (!strcasecmp(param, "wrapuptime")) {
q->wrapuptime = atoi(val);
+ } else if (!strcasecmp(param, "autofill")) {
+ q->autofill = ast_true(val);
+ } else if (!strcasecmp(param, "autopause")) {
+ q->autopause = ast_true(val);
} else if (!strcasecmp(param, "maxlen")) {
q->maxlen = atoi(val);
if (q->maxlen < 0)
@@ -761,29 +787,48 @@
}
}
+static void free_members(struct ast_call_queue *q, int all)
+{
+ /* Free non-dynamic members */
+ struct member *curm, *next, *prev = NULL;
+
+ for (curm = q->members; curm; curm = next) {
+ next = curm->next;
+ if (all || !curm->dynamic) {
+ if (prev)
+ prev->next = next;
+ else
+ q->members = next;
+ free(curm);
+ } else
+ prev = curm;
+ }
+}
+
+static void destroy_queue(struct ast_call_queue *q)
+{
+ free_members(q, 1);
+ ast_mutex_destroy(&q->lock);
+ free(q);
+}
/*!\brief Reload a single queue via realtime.
\return Return the queue, or NULL if it doesn't exist.
- \note Should be called with the global qlock locked.
- When found, the queue is returned with q->lock locked. */
+ \note Should be called with the global qlock locked. */
static struct ast_call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
{
struct ast_variable *v;
- struct ast_call_queue *q, *prev_q;
+ struct ast_call_queue *q;
struct member *m, *prev_m, *next_m;
char *interface;
char *tmp, *tmp_name;
char tmpbuf[64]; /* Must be longer than the longest queue param name. */
/* Find the queue in the in-core list (we will create a new one if not found). */
- q = queues;
- prev_q = NULL;
- while (q) {
+ AST_LIST_TRAVERSE(&queues, q, list) {
if (!strcasecmp(q->name, queuename)) {
break;
}
- q = q->next;
- prev_q = q;
}
/* Static queues override realtime. */
@@ -794,6 +839,7 @@
ast_mutex_unlock(&q->lock);
return NULL;
} else {
+ ast_mutex_unlock(&q->lock);
return q;
}
}
@@ -814,13 +860,9 @@
/* Delete if unused (else will be deleted when last caller leaves). */
if (!q->count) {
/* Delete. */
- if (!prev_q) {
- queues = q->next;
- } else {
- prev_q->next = q->next;
- }
+ AST_LIST_REMOVE(&queues, q, list);
ast_mutex_unlock(&q->lock);
- free(q);
+ destroy_queue(q);
} else
ast_mutex_unlock(&q->lock);
}
@@ -829,14 +871,12 @@
/* Create a new queue if an in-core entry does not exist yet. */
if (!q) {
- q = alloc_queue(queuename);
- if (!q)
+ if (!(q = alloc_queue(queuename)))
return NULL;
ast_mutex_lock(&q->lock);
clear_queue(q);
q->realtime = 1;
- q->next = queues;
- queues = q;
+ AST_LIST_INSERT_HEAD(&queues, q, list);
}
init_queue(q); /* Ensure defaults for all parameters not set explicitly. */
@@ -888,13 +928,60 @@
m = next_m;
}
+ ast_mutex_unlock(&q->lock);
+
return q;
}
-static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason)
+static struct ast_call_queue *load_realtime_queue(char *queuename)
{
struct ast_variable *queue_vars = NULL;
struct ast_config *member_config = NULL;
+ struct ast_call_queue *q;
+
+ /* Find the queue in the in-core list first. */
+ AST_LIST_LOCK(&queues);
+ AST_LIST_TRAVERSE(&queues, q, list) {
+ if (!strcasecmp(q->name, queuename)) {
+ break;
+ }
+ }
+ AST_LIST_UNLOCK(&queues);
+
+ if (!q) {
+ /*! \note Load from realtime before taking the global qlock, to avoid blocking all
+ queue operations while waiting for the DB.
+
+ This will be two separate database transactions, so we might
+ see queue parameters as they were before another process
+ changed the queue and member list as it was after the change.
+ Thus we might see an empty member list when a queue is
+ deleted. In practise, this is unlikely to cause a problem. */
+
+ queue_vars = ast_load_realtime("queues", "name", queuename, NULL);
+ if (queue_vars) {
+ member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, NULL);
+ if (!member_config) {
+ ast_log(LOG_ERROR, "no queue_members defined in your config (extconfig.conf).\n");
+ return NULL;
+ }
+ }
+
+ AST_LIST_LOCK(&queues);
+
+ q = find_queue_by_name_rt(queuename, queue_vars, member_config);
+ if (member_config)
+ ast_config_destroy(member_config);
+ if (queue_vars)
+ ast_variables_destroy(queue_vars);
+
+ AST_LIST_UNLOCK(&queues);
+ }
+ return q;
+}
+
+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;
int res = -1;
@@ -902,35 +989,12 @@
int inserted = 0;
enum queue_member_status stat;
- /*! \note Load from realtime before taking the global qlock, to avoid blocking all
- queue operations while waiting for the DB.
-
- This will be two separate database transactions, so we might
- see queue parameters as they were before another process
- changed the queue and member list as it was after the change.
- Thus we might see an empty member list when a queue is
- deleted. In practise, this is unlikely to cause a problem. */
- queue_vars = ast_load_realtime("queues", "name", queuename, NULL);
- if (queue_vars) {
- member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, NULL);
- if (!member_config) {
- ast_log(LOG_ERROR, "no queue_members defined in your config (extconfig.conf).\n");
- return res;
- }
- }
-
- ast_mutex_lock(&qlock);
- q = find_queue_by_name_rt(queuename, queue_vars, member_config);
- /* Note: If found, find_queue_by_name_rt() returns with q->lock locked. */
- if(member_config)
- ast_config_destroy(member_config);
- if(queue_vars)
- ast_variables_destroy(queue_vars);
-
- if (!q) {
- ast_mutex_unlock(&qlock);
+ q = load_realtime_queue(queuename);
+ if (!q)
return res;
- }
+
+ AST_LIST_LOCK(&queues);
+ ast_mutex_lock(&q->lock);
/* This is our one */
stat = get_member_status(q, qe->max_penalty);
@@ -978,50 +1042,8 @@
#endif
}
ast_mutex_unlock(&q->lock);
- ast_mutex_unlock(&qlock);
+ AST_LIST_UNLOCK(&queues);
return res;
-}
-
-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) {
- next = curm->next;
- if (all || !curm->dynamic) {
- if (prev)
- prev->next = next;
- else
- q->members = next;
- free(curm);
- } else
- prev = curm;
- curm = next;
- }
-}
-
-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) {
- if (prev)
- prev->next = cur->next;
- else
- queues = cur->next;
- } else {
- prev = cur;
- }
- }
- ast_mutex_unlock(&qlock);
- free_members(q, 1);
- ast_mutex_destroy(&q->lock);
- free(q);
}
static int play_file(struct ast_channel *chan, char *filename)
@@ -1231,6 +1253,9 @@
ast_mutex_unlock(&q->lock);
if (q->dead && !q->count) {
/* It's dead and nobody is in it, so kill it */
+ AST_LIST_LOCK(&queues);
+ AST_LIST_REMOVE(&queues, q, list);
+ AST_LIST_UNLOCK(&queues);
destroy_queue(q);
}
}
@@ -1305,7 +1330,7 @@
/* &qlock and &rq->lock already set by try_calling()
* to solve deadlock */
- for (q = queues; q; q = q->next) {
+ AST_LIST_TRAVERSE(&queues, q, list) {
if (q == rq) /* don't check myself, could deadlock */
continue;
ast_mutex_lock(&q->lock);
@@ -1325,7 +1350,6 @@
if (found)
break;
}
- ast_mutex_unlock(&qlock);
return found;
}
@@ -1570,8 +1594,13 @@
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Playing periodic announcement\n");
+ /* Check to make sure we have a sound file. If not, reset to the first sound file */
+ if (qe->last_periodic_announce_sound >= MAX_PERIODIC_ANNOUNCEMENTS || !strlen(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound])) {
+ qe->last_periodic_announce_sound = 0;
+ }
+
/* play the announcement */
- res = background_file(qe, qe->chan, qe->parent->sound_periodicannounce);
+ res = background_file(qe, qe->chan, qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]);
/* Resume Music on Hold */
ast_moh_start(qe->chan, qe->moh);
@@ -1579,6 +1608,9 @@
/* update last_periodic_announce_time */
qe->last_periodic_announce_time = now;
+ /* Update the current periodic announcement to the next announcement */
+ qe->last_periodic_announce_sound++;
+
return res;
}
@@ -1615,6 +1647,7 @@
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;
+ char on[256] = "";
struct localuser *o;
int found;
int numlines;
@@ -1658,6 +1691,7 @@
peer = o;
}
} else if (o->chan && (o->chan == winner)) {
+ ast_copy_string(on, o->member->interface, sizeof(on));
if (!ast_strlen_zero(o->chan->call_forward)) {
char tmpchan[256]="";
char *stuff;
@@ -1707,11 +1741,7 @@
if (in->cid.cid_ani) {
if (o->chan->cid.cid_ani)
free(o->chan->cid.cid_ani);
- o->chan->cid.cid_ani = malloc(strlen(in->cid.cid_ani) + 1);
- if (o->chan->cid.cid_ani)
- strncpy(o->chan->cid.cid_ani, in->cid.cid_ani, strlen(in->cid.cid_ani) + 1);
- else
- ast_log(LOG_WARNING, "Out of memory\n");
+ o->chan->cid.cid_ani = ast_strdup(in->cid.cid_ani);
}
if (o->chan->cid.cid_rdnis)
free(o->chan->cid.cid_rdnis);
@@ -1836,8 +1866,19 @@
}
ast_frfree(f);
}
- if (!*to && (option_verbose > 2))
- ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
+ if (!*to) {
+ if (option_verbose > 2)
+ ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
+ if (qe->parent->autopause) {
+ if (!set_member_paused(qe->parent->name, on, 1)) {
+ if (option_verbose > 2)
+ ast_verbose( VERBOSE_PREFIX_3 "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n", on, qe->parent->name);
+ } else {
+ if (option_verbose > 2)
+ ast_verbose( VERBOSE_PREFIX_3 "Failed to pause Queue Member %s in queue %s!\n", on, qe->parent->name);
+ }
+ }
+ }
}
return peer;
@@ -1852,7 +1893,7 @@
/* Atomically read the parent head -- does not need a lock */
ch = qe->parent->head;
/* If we are now at the top of the head, break out */
- if (ch == qe) {
+ if ((ch == qe) || (qe->parent->autofill)) {
if (option_debug)
ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name);
res = 1;
@@ -2050,7 +2091,7 @@
/* Hold the lock while we setup the outgoing calls */
if (use_weight)
- ast_mutex_lock(&qlock);
+ AST_LIST_LOCK(&queues);
ast_mutex_lock(&qe->parent->lock);
if (option_debug)
ast_log(LOG_DEBUG, "%s is trying to call a queue member.\n",
@@ -2063,15 +2104,12 @@
announce = announceoverride;
while(cur) {
- tmp = malloc(sizeof(*tmp));
- if (!tmp) {
+ if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
ast_mutex_unlock(&qe->parent->lock);
if (use_weight)
- ast_mutex_unlock(&qlock);
- ast_log(LOG_WARNING, "Out of memory\n");
+ AST_LIST_UNLOCK(&queues);
goto out;
}
- memset(tmp, 0, sizeof(*tmp));
tmp->stillgoing = -1;
if (option_debug) {
if (url)
@@ -2116,7 +2154,7 @@
ring_one(qe, outgoing, &numbusies);
ast_mutex_unlock(&qe->parent->lock);
if (use_weight)
- ast_mutex_unlock(&qlock);
+ AST_LIST_UNLOCK(&queues);
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) {
@@ -2129,7 +2167,7 @@
peer = NULL;
if (!peer) {
if (to) {
- /* Musta gotten hung up */
+ /* Must gotten hung up */
record_abandoned(qe);
res = -1;
} else {
@@ -2296,7 +2334,7 @@
ast_hangup(peer);
update_queue(qe->parent, member);
if (bridge == 0)
- res = 1; /* JDG: bridge successfull, leave app_queue */
+ res = 1; /* JDG: bridge successfully, leave app_queue */
else
res = bridge; /* bridge error, stay in the queue */
}
@@ -2326,7 +2364,7 @@
}
-/* Dump all members in a specific queue to the databse
+/* Dump all members in a specific queue to the database
*
* <pm_family>/<queuename> = <interface>;<penalty>;<paused>[|...]
*
@@ -2371,8 +2409,8 @@
struct member *last_member, *look;
int res = RES_NOSUCHQUEUE;
- ast_mutex_lock(&qlock);
- for (q = queues ; q ; q = q->next) {
+ AST_LIST_LOCK(&queues);
+ AST_LIST_TRAVERSE(&queues, q, list) {
ast_mutex_lock(&q->lock);
if (!strcmp(q->name, queuename)) {
if ((last_member = interface_exists(q, interface))) {
@@ -2406,7 +2444,7 @@
}
ast_mutex_unlock(&q->lock);
}
- ast_mutex_unlock(&qlock);
+ AST_LIST_UNLOCK(&queues);
return res;
}
@@ -2416,45 +2454,46 @@
struct member *new_member;
int res = RES_NOSUCHQUEUE;
- ast_mutex_lock(&qlock);
- for (q = queues ; q ; q = q->next) {
+ /* \note Ensure the appropriate realtime queue is loaded. Note that this
+ * short-circuits if the queue is already in memory. */
+ q = load_realtime_queue(queuename);
+
+ AST_LIST_LOCK(&queues);
+
+ if (q) {
ast_mutex_lock(&q->lock);
- if (!strcmp(q->name, queuename)) {
- if (interface_exists(q, interface) == NULL) {
- new_member = create_queue_member(interface, penalty, paused);
-
- if (new_member != NULL) {
- new_member->dynamic = 1;
- new_member->next = q->members;
- q->members = new_member;
- manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
- "Queue: %s\r\n"
- "Location: %s\r\n"
- "Membership: %s\r\n"
- "Penalty: %d\r\n"
- "CallsTaken: %d\r\n"
- "LastCall: %d\r\n"
- "Status: %d\r\n"
- "Paused: %d\r\n",
- q->name, new_member->interface, new_member->dynamic ? "dynamic" : "static",
- new_member->penalty, new_member->calls, (int)new_member->lastcall, new_member->status, new_member->paused);
+ if (interface_exists(q, interface) == NULL) {
+ new_member = create_queue_member(interface, penalty, paused);
+
+ if (new_member != NULL) {
+ new_member->dynamic = 1;
+ new_member->next = q->members;
+ q->members = new_member;
+ manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
+ "Queue: %s\r\n"
+ "Location: %s\r\n"
+ "Membership: %s\r\n"
+ "Penalty: %d\r\n"
+ "CallsTaken: %d\r\n"
+ "LastCall: %d\r\n"
+ "Status: %d\r\n"
+ "Paused: %d\r\n",
+ q->name, new_member->interface, new_member->dynamic ? "dynamic" : "static",
+ new_member->penalty, new_member->calls, (int)new_member->lastcall, new_member->status, new_member->paused);
- if (dump)
- dump_queue_members(q);
-
- res = RES_OKAY;
- } else {
- res = RES_OUTOFMEMORY;
- }
+ if (dump)
+ dump_queue_members(q);
+
+ res = RES_OKAY;
} else {
- res = RES_EXISTS;
- }
- ast_mutex_unlock(&q->lock);
- break;
+ res = RES_OUTOFMEMORY;
+ }
+ } else {
+ res = RES_EXISTS;
}
ast_mutex_unlock(&q->lock);
}
- ast_mutex_unlock(&qlock);
+ AST_LIST_UNLOCK(&queues);
return res;
}
@@ -2469,8 +2508,8 @@
if (ast_strlen_zero(queuename))
ast_queue_log("NONE", "NONE", interface, (paused ? "PAUSEALL" : "UNPAUSEALL"), "%s", "");
- ast_mutex_lock(&qlock);
- for (q = queues ; q ; q = q->next) {
+ AST_LIST_LOCK(&queues);
+ AST_LIST_TRAVERSE(&queues, q, list) {
ast_mutex_lock(&q->lock);
if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) {
if ((mem = interface_exists(q, interface))) {
@@ -2493,7 +2532,7 @@
}
ast_mutex_unlock(&q->lock);
}
- ast_mutex_unlock(&qlock);
+ AST_LIST_UNLOCK(&queues);
if (found)
return RESULT_SUCCESS;
@@ -2517,7 +2556,7 @@
struct ast_call_queue *cur_queue;
char queue_data[PM_MAX_LEN];
- ast_mutex_lock(&qlock);
+ AST_LIST_LOCK(&queues);
/* Each key in 'pm_family' is the name of a queue */
db_tree = ast_db_gettree(pm_family, NULL);
@@ -2525,13 +2564,11 @@
queue_name = entry->key + strlen(pm_family) + 2;
- cur_queue = queues;
- while (cur_queue) {
+ AST_LIST_TRAVERSE(&queues, cur_queue, list) {
ast_mutex_lock(&cur_queue->lock);
if (!strcmp(queue_name, cur_queue->name))
break;
ast_mutex_unlock(&cur_queue->lock);
- cur_queue = cur_queue->next;
}
if (!cur_queue) {
@@ -2555,7 +2592,7 @@
paused_tok = strsep(&member, ";");
if (!penalty_tok) {
- ast_log(LOG_WARNING, "Error parsing persisent member string for '%s' (penalty)\n", queue_name);
+ ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (penalty)\n", queue_name);
break;
}
penalty = strtol(penalty_tok, NULL, 10);
@@ -2584,9 +2621,9 @@
}
}
- ast_mutex_unlock(&qlock);
+ AST_LIST_UNLOCK(&queues);
if (db_tree) {
- ast_log(LOG_NOTICE, "Queue members sucessfully reloaded from database.\n");
+ ast_log(LOG_NOTICE, "Queue members successfully reloaded from database.\n");
ast_db_freetree(db_tree);
}
}
@@ -2607,15 +2644,12 @@
return -1;
}
+ if (!(parse = ast_strdupa(data)))
+ return -1;
+
+ AST_STANDARD_APP_ARGS(args, parse);
+
LOCAL_USER_ADD(u);
-
- if (!(parse = ast_strdupa(data))) {
- ast_log(LOG_WARNING, "Memory Error!\n");
- LOCAL_USER_REMOVE(u);
- return -1;
- }
-
- AST_STANDARD_APP_ARGS(args, parse);
if (args.options) {
if (strchr(args.options, 'j'))
@@ -2663,15 +2697,12 @@
return -1;
}
+ if (!(parse = ast_strdupa(data)))
+ return -1;
+
+ AST_STANDARD_APP_ARGS(args, parse);
+
LOCAL_USER_ADD(u);
-
- if (!(parse = ast_strdupa(data))) {
- ast_log(LOG_WARNING, "Memory Error!\n");
- LOCAL_USER_REMOVE(u);
- return -1;
- }
-
- AST_STANDARD_APP_ARGS(args, parse);
if (args.options) {
if (strchr(args.options, 'j'))
@@ -2721,15 +2752,12 @@
return -1;
}
+ if (!(parse = ast_strdupa(data)))
+ return -1;
+
+ AST_STANDARD_APP_ARGS(args, parse);
+
LOCAL_USER_ADD(u);
-
- if (!(parse = ast_strdupa(data))) {
- ast_log(LOG_WARNING, "Memory Error!\n");
- LOCAL_USER_REMOVE(u);
- return -1;
- }
-
- AST_STANDARD_APP_ARGS(args, parse);
if (ast_strlen_zero(args.interface)) {
args.interface = ast_strdupa(chan->name);
@@ -2789,15 +2817,12 @@
return -1;
}
+ if (!(parse = ast_strdupa(data)))
+ return -1;
+
+ AST_STANDARD_APP_ARGS(args, parse);
+
LOCAL_USER_ADD(u);
-
- if (!(parse = ast_strdupa(data))) {
- ast_log(LOG_WARNING, "Memory Error!\n");
- LOCAL_USER_REMOVE(u);
- return -1;
- }
-
- AST_STANDARD_APP_ARGS(args, parse);
if (ast_strlen_zero(args.interface)) {
args.interface = ast_strdupa(chan->name);
@@ -2851,22 +2876,24 @@
int res=-1;
int ringing=0;
struct localuser *u;
- char *queuename;
- char info[512];
- char *info_ptr = info;
- char *options = NULL;
- char *url = NULL;
- char *announceoverride = NULL;
const char *user_priority;
const char *max_penalty_str;
int prio;
int max_penalty;
- char *queuetimeoutstr = NULL;
enum queue_result reason = QUEUE_UNKNOWN;
/* whether to exit Queue application after the timeout hits */
int go_on = 0;
+ char *parse;
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(queuename);
+ AST_APP_ARG(options);
+ AST_APP_ARG(url);
+ AST_APP_ARG(announceoverride);
+ AST_APP_ARG(queuetimeoutstr);
+ );
+
/* Our queue entry */
struct queue_ent qe;
@@ -2874,24 +2901,23 @@
ast_log(LOG_WARNING, "Queue requires an argument: queuename[|options[|URL][|announceoverride][|timeout]]\n");
return -1;
}
+
+ parse = ast_strdupa(data);
+ if (!parse) {
+ ast_log(LOG_ERROR, "Out of memory!\n");
+ return -1;
+ }
+ AST_STANDARD_APP_ARGS(args, parse);
LOCAL_USER_ADD(u);
/* Setup our queue entry */
memset(&qe, 0, sizeof(qe));
qe.start = time(NULL);
-
- /* Parse our arguments XXX Check for failure XXX */
- ast_copy_string(info, (char *) data, sizeof(info));
- queuename = strsep(&info_ptr, "|");
- options = strsep(&info_ptr, "|");
- url = strsep(&info_ptr, "|");
- announceoverride = strsep(&info_ptr, "|");
- queuetimeoutstr = info_ptr;
/* set the expire time based on the supplied timeout; */
- if (queuetimeoutstr)
- qe.expire = qe.start + atoi(queuetimeoutstr);
+ if (args.queuetimeoutstr)
+ qe.expire = qe.start + atoi(args.queuetimeoutstr);
else
qe.expire = 0;
@@ -2928,12 +2954,12 @@
max_penalty = 0;
}
- if (options && (strchr(options, 'r')))
+ if (args.options && (strchr(args.options, 'r')))
ringing = 1;
if (option_debug)
[... 8484 lines stripped ...]
More information about the asterisk-commits
mailing list