aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorjpeeler <jpeeler@f38db490-d61c-443f-a65b-d21fe96a405b>2010-10-26 18:33:24 +0000
committerjpeeler <jpeeler@f38db490-d61c-443f-a65b-d21fe96a405b>2010-10-26 18:33:24 +0000
commit0bd0607dae28abcec1b5f7d229334a8f6c6b8d6d (patch)
tree7f92e2be2e9aa508f957106ed06bac5264a8bff2 /apps
parentdedac60633f986cbe16edd2b0251f7f5bb9122d9 (diff)
Merged revisions 293004 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r293004 | jpeeler | 2010-10-25 17:55:28 -0500 (Mon, 25 Oct 2010) | 29 lines Fix inprocess_container in voicemail to correctly restrict max messages. The comparison function logic was off, so the number of sessions for a given mailbox were not being incremented properly. This problem caused the maximum number of messages per folder to not be respected when simultaneously leaving multiple voicemails just below the threshold. These problems should be fixed by the above, but just in case: Fixed resequence_mailbox to rely on the actual number of detected number of files in a directory rather than just assuming only 10 messages more than the maximum had been left. Also if more messages than the maximum are deleted they are actually removed now. The second purpose of this commit should have been separated out probably, but is related to the above. Again, if the number of messages in a given voicemail folder exceeds the maximum set limit make sure to allocate enough space for the deleted and heard index tracking array. A few random fixes: There was a forgotten decrement of the inprocess count in imap_store_file. When using IMAP storage, do not look in the directory where file based storage messages may still reside and influence the message count. Ensure to use only the first format in sendmail. ABE-2516 ........ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.2@293118 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps')
-rw-r--r--apps/app_voicemail.c112
1 files changed, 91 insertions, 21 deletions
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 097ccfcc1..8082b8c90 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -627,6 +627,7 @@ struct vm_state {
char intro[PATH_MAX];
int *deleted;
int *heard;
+ int dh_arraysize; /* used for deleted / heard allocation */
int curmsg;
int lastmsg;
int newmessages;
@@ -851,7 +852,7 @@ static int inprocess_hash_fn(const void *obj, const int flags)
static int inprocess_cmp_fn(void *obj, void *arg, int flags)
{
struct inprocess *i = obj, *j = arg;
- if (!strcmp(i->mailbox, j->mailbox)) {
+ if (strcmp(i->mailbox, j->mailbox)) {
return 0;
}
return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
@@ -870,6 +871,9 @@ static int inprocess_count(const char *context, const char *mailbox, int delta)
ao2_ref(i, -1);
return ret;
}
+ if (delta < 0) {
+ ast_log(LOG_WARNING, "BUG: ref count decrement on non-existing object???\n");
+ }
if (!(i = ao2_alloc(sizeof(*i) + strlen(context) + strlen(mailbox) + 2, NULL))) {
ao2_unlock(inprocess_container);
return 0;
@@ -1546,6 +1550,33 @@ static void free_user(struct ast_vm_user *vmu)
}
}
+static int vm_allocate_dh(struct vm_state *vms, struct ast_vm_user *vmu, int count_msg) {
+
+ int arraysize = (vmu->maxmsg > count_msg ? vmu->maxmsg : count_msg);
+ if (!vms->dh_arraysize) {
+ /* initial allocation */
+ if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
+ return -1;
+ }
+ if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
+ return -1;
+ }
+ vms->dh_arraysize = arraysize;
+ } else if (vms->dh_arraysize < arraysize) {
+ if (!(vms->deleted = ast_realloc(vms->deleted, arraysize * sizeof(int)))) {
+ return -1;
+ }
+ if (!(vms->heard = ast_realloc(vms->heard, arraysize * sizeof(int)))) {
+ return -1;
+ }
+ memset(vms->deleted, 0, arraysize * sizeof(int));
+ memset(vms->heard, 0, arraysize * sizeof(int));
+ vms->dh_arraysize = arraysize;
+ }
+
+ return 0;
+}
+
/* All IMAP-specific functions should go in this block. This
* keeps them from being spread out all over the code */
#ifdef IMAP_STORAGE
@@ -1947,9 +1978,11 @@ static int imap_check_limits(struct ast_channel *chan, struct vm_state *vms, str
}
/* Check if we have exceeded maxmsg */
- if (msgnum >= vmu->maxmsg - inprocess_count(vmu->mailbox, vmu->context, 0)) {
- ast_log(AST_LOG_WARNING, "Unable to leave message since we will exceed the maximum number of messages allowed (%u > %u)\n", msgnum, vmu->maxmsg);
+ ast_debug(3, "Checking message number quota: mailbox has %d messages, maximum is set to %d, current messages %d\n", msgnum, vmu->maxmsg, inprocess_count(vmu->mailbox, vmu->context, 0));
+ if (msgnum >= vmu->maxmsg - inprocess_count(vmu->mailbox, vmu->context, +1)) {
+ ast_log(LOG_WARNING, "Unable to leave message since we will exceed the maximum number of messages allowed (%u >= %u)\n", msgnum, vmu->maxmsg);
ast_play_and_wait(chan, "vm-mailboxfull");
+ pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
return -1;
}
@@ -2095,7 +2128,7 @@ static int imap_store_file(const char *dir, const char *mailboxuser, const char
if (tempcopy)
*(vmu->email) = '\0';
-
+ inprocess_count(vmu->mailbox, vmu->context, -1);
return 0;
}
@@ -2422,6 +2455,16 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
mail_search_full (vms->mailstream, NULL, pgm, NIL);
vms->lastmsg = vms->vmArrayIndex - 1;
mail_free_searchpgm(&pgm);
+ /* Since IMAP storage actually stores both old and new messages in the same IMAP folder,
+ * ensure to allocate enough space to account for all of them. Warn if old messages
+ * have not been checked first as that is required.
+ */
+ if (box == 0 && !vms->dh_arraysize) {
+ ast_log(LOG_WARNING, "The code expects the old messages to be checked first, fix the code.\n");
+ }
+ if (vm_allocate_dh(vms, vmu, box == 0 ? vms->vmArrayIndex + vms->oldmessages : vms->lastmsg)) {
+ return -1;
+ }
ast_mutex_unlock(&vms->lock);
return 0;
@@ -4533,11 +4576,18 @@ static int sendmail(char *srcemail, struct ast_vm_user *vmu, int msgnum, char *c
FILE *p=NULL;
char tmp[80] = "/tmp/astmail-XXXXXX";
char tmp2[256];
+ char *stringp;
if (vmu && ast_strlen_zero(vmu->email)) {
ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s]. E-mail will not be sent.\n", vmu->mailbox);
return(0);
}
+
+ /* Mail only the first format */
+ format = ast_strdupa(format);
+ stringp = format;
+ strsep(&stringp, "|");
+
if (!strcmp(format, "wav49"))
format = "WAV";
ast_debug(3, "Attaching file '%s', format '%s', uservm is '%d', global is %d\n", attach, format, attach_user_voicemail, ast_test_flag((&globalflags), VM_ATTACH));
@@ -5286,7 +5336,14 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
DISPOSE(tempfile, -1);
/* It's easier just to try to make it than to check for its existence */
+#ifndef IMAP_STORAGE
create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
+#else
+ snprintf(dir, sizeof(dir), "%simap", VM_SPOOL_DIR);
+ if (mkdir(dir, VOICEMAIL_DIR_MODE) && errno != EEXIST) {
+ ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
+ }
+#endif
/* Check current or macro-calling context for special extensions */
if (ast_test_flag(vmu, VM_OPERATOR)) {
@@ -5449,7 +5506,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
/* here is a big difference! We add one to it later */
msgnum = newmsgs + oldmsgs;
ast_debug(3, "Messagecount set to %d\n",msgnum);
- snprintf(fn, sizeof(fn), "%s/imap/msg%s%04d", VM_SPOOL_DIR, vmu->mailbox, msgnum);
+ snprintf(fn, sizeof(fn), "%simap/msg%s%04d", VM_SPOOL_DIR, vmu->mailbox, msgnum);
/* set variable for compatibility */
pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
@@ -6527,7 +6584,11 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu,
}
ast_channel_unlock(chan);
+#ifndef IMAP_STORAGE
make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
+#else
+ snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
+#endif
make_file(fn, sizeof(fn), todir, msgnum);
snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
@@ -7326,6 +7387,7 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
/* Faster to make the directory than to check if it exists. */
create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
+ /* traverses directory using readdir (or select query for ODBC) */
count_msg = count_messages(vmu, vms->curdir);
if (count_msg < 0) {
return count_msg;
@@ -7333,6 +7395,10 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
vms->lastmsg = count_msg - 1;
}
+ if (vm_allocate_dh(vms, vmu, count_msg)) {
+ return -1;
+ }
+
/*
The following test is needed in case sequencing gets messed up.
There appears to be more than one way to mess up sequence, so
@@ -7345,11 +7411,14 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
return -1;
}
+ /* for local storage, checks directory for messages up to maxmsg limit */
last_msg = last_message_index(vmu, vms->curdir);
ast_unlock_path(vms->curdir);
if (last_msg < 0) {
return last_msg;
+ } else if (vms->lastmsg != last_msg) {
+ ast_log(LOG_NOTICE, "Mailbox: %s, expected %d but found %d message(s) in box with max threshold of %d.\n", vms->curdir, last_msg + 1, vms->lastmsg + 1, vmu->maxmsg);
}
return 0;
@@ -7375,7 +7444,8 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
return ERROR_LOCK_PATH;
}
- for (x = 0; x < vmu->maxmsg; x++) {
+ /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
+ for (x = 0; x < vms->lastmsg + 1; x++) {
if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
/* Save this message. It's not in INBOX or hasn't been heard */
make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
@@ -7429,7 +7499,7 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
if (vms->deleted) {
/* Since we now expunge after each delete, deleting in reverse order
* ensures that no reordering occurs between each step. */
- for (x = vmu->maxmsg - 1; x >= 0; x--) {
+ for (x = vms->dh_arraysize - 1; x >= 0; x--) {
if (vms->deleted[x]) {
ast_debug(3, "IMAP delete of %d\n", x);
DELETE(vms->curdir, x, vms->fn, vmu);
@@ -7440,10 +7510,10 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
done:
if (vms->deleted) {
- memset(vms->deleted, 0, vmu->maxmsg * sizeof(int));
+ memset(vms->deleted, 0, vms->dh_arraysize * sizeof(int));
}
if (vms->heard) {
- memset(vms->heard, 0, vmu->maxmsg * sizeof(int));
+ memset(vms->heard, 0, vms->dh_arraysize * sizeof(int));
}
return 0;
@@ -9327,20 +9397,20 @@ static int vm_execmain(struct ast_channel *chan, void *data)
/* Retrieve urgent, old and new message counts */
ast_debug(1, "Before open_mailbox\n");
res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
vms.oldmessages = vms.lastmsg + 1;
ast_debug(1, "Number of old messages: %d\n",vms.oldmessages);
/* check INBOX */
res = open_mailbox(&vms, vmu, NEW_FOLDER);
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
vms.newmessages = vms.lastmsg + 1;
ast_debug(1, "Number of new messages: %d\n",vms.newmessages);
/* Start in Urgent */
in_urgent = 1;
res = open_mailbox(&vms, vmu, 11); /*11 is the Urgent folder */
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
vms.urgentmessages = vms.lastmsg + 1;
ast_debug(1, "Number of urgent messages: %d\n",vms.urgentmessages);
@@ -9354,7 +9424,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
in_urgent = 0;
res = open_mailbox(&vms, vmu, play_folder);
}
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
/* If there are no new messages, inform the user and hangup */
@@ -9370,13 +9440,13 @@ static int vm_execmain(struct ast_channel *chan, void *data)
res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
in_urgent = 0;
play_folder = 1;
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
} else if (!vms.urgentmessages && vms.newmessages) {
/* If we have new messages but none are urgent */
in_urgent = 0;
res = open_mailbox(&vms, vmu, NEW_FOLDER);
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
}
}
@@ -9444,7 +9514,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
/* If folder is not urgent, set in_urgent to zero! */
if (cmd != 11) in_urgent = 0;
res = open_mailbox(&vms, vmu, cmd);
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
play_folder = cmd;
cmd = 0;
@@ -9575,7 +9645,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
if (res == ERROR_LOCK_PATH)
goto out;
res = open_mailbox(&vms, vmu, 11); /* Open Urgent folder */
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
ast_debug(1, "No more new messages, opened INBOX and got %d Urgent messages\n",vms.lastmsg + 1);
vms.curmsg = vms.lastmsg;
@@ -9604,7 +9674,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
if (res == ERROR_LOCK_PATH)
goto out;
res = open_mailbox(&vms, vmu, NEW_FOLDER);
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n",vms.lastmsg + 1);
vms.curmsg = -1;
@@ -9666,7 +9736,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
if (res == ERROR_LOCK_PATH)
goto out;
res = open_mailbox(&vms, vmu, NEW_FOLDER);
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n",vms.lastmsg + 1);
vms.curmsg = -1;
@@ -9703,7 +9773,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
if (res == ERROR_LOCK_PATH)
goto out;
res = open_mailbox(&vms, vmu, NEW_FOLDER);
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n",vms.lastmsg + 1);
vms.curmsg = -1;
@@ -9776,7 +9846,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
if (res == ERROR_LOCK_PATH)
goto out;
res = open_mailbox(&vms, vmu, NEW_FOLDER);
- if (res == ERROR_LOCK_PATH)
+ if (res < 0)
goto out;
ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n",vms.lastmsg + 1);
vms.curmsg = -1;