dect
/
asterisk
Archived
13
0
Fork 0

Merged revisions 27636 via svnmerge from

https://origsvn.digium.com/svn/asterisk/branches/1.2

........
r27636 | tilghman | 2006-05-16 21:19:50 -0500 (Tue, 16 May 2006) | 2 lines

Bug 7125 - Fix race condition between resequencing and leaving a message

........


git-svn-id: http://svn.digium.com/svn/asterisk/trunk@27637 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
tilghman 2006-05-17 02:27:17 +00:00
parent 080ef129f8
commit 4cce0ae9f2
1 changed files with 112 additions and 103 deletions

View File

@ -2413,17 +2413,17 @@ struct leave_vm_options {
static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_options *options)
{
char tmptxtfile[256], txtfile[256];
char txtfile[256], tmptxtfile[256];
char callerid[256];
FILE *txt;
int res = 0;
int res = 0, txtdes;
int msgnum;
int duration = 0;
int ausemacro = 0;
int ousemacro = 0;
int ouseexten = 0;
char date[256];
char dir[256];
char dir[256], tmpdir[260];
char fn[256];
char prefile[256]="";
char tempfile[256]="";
@ -2475,6 +2475,7 @@ 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 */
create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp");
/* Check current or macro-calling context for special extensions */
if (ast_test_flag(vmu, VM_OPERATOR)) {
@ -2579,121 +2580,129 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
if (!ast_strlen_zero(fmt)) {
msgnum = 0;
if (vm_lock_path(dir)) {
free_user(vmu);
return ERROR_LOCK_PATH;
if (count_messages(vmu, dir) >= vmu->maxmsg) {
res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
if (!res)
res = ast_waitstream(chan, "");
ast_log(LOG_WARNING, "No more messages possible\n");
pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
goto leave_vm_out;
}
/*
* This operation can be very expensive if done say over NFS or if the mailbox has 100+ messages
* in the folder. So we should get this first so we don't cut off the first few seconds of the
* message.
*/
do {
make_file(fn, sizeof(fn), dir, msgnum);
if (!EXISTS(dir,msgnum,fn,chan->language))
break;
msgnum++;
} while (msgnum < vmu->maxmsg);
snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
txtdes = mkstemp(tmptxtfile);
if (txtdes < 0) {
res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
if (!res)
res = ast_waitstream(chan, "");
ast_log(LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
goto leave_vm_out;
}
/* Now play the beep once we have the message number for our next message. */
if (res >= 0) {
/* Unless we're *really* silent, try to send the beep */
res = ast_stream_and_wait(chan, "beep", chan->language, "");
}
if (msgnum < vmu->maxmsg) {
/* assign a variable with the name of the voicemail file */
pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
/* Store information */
snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
snprintf(tmptxtfile, sizeof(tmptxtfile), "%s.txt.tmp", fn);
txt = fopen(tmptxtfile, "w+");
if (txt) {
get_date(date, sizeof(date));
fprintf(txt,
";\n"
"; Message Information file\n"
";\n"
"[message]\n"
"origmailbox=%s\n"
"context=%s\n"
"macrocontext=%s\n"
"exten=%s\n"
"priority=%d\n"
"callerchan=%s\n"
"callerid=%s\n"
"origdate=%s\n"
"origtime=%ld\n"
"category=%s\n",
ext,
chan->context,
chan->macrocontext,
chan->exten,
chan->priority,
chan->name,
ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"),
date, (long)time(NULL),
category ? category : "");
} else
ast_log(LOG_WARNING, "Error opening text file for output\n");
res = play_record_review(chan, NULL, fn, vmmaxmessage, fmt, 1, vmu, &duration, dir, options->record_gain);
if (res == '0') {
if (txt && EXISTS(dir,msgnum,fn,chan->language)) {
fclose(txt);
rename(tmptxtfile, txtfile);
} else if (txt && !EXISTS(dir,msgnum,fn,chan->language)) {
if (option_debug)
ast_log(LOG_DEBUG, "The recorded media file is gone, so we should remove the .txt file too!\n");
fclose(txt);
unlink(tmptxtfile);
}
goto transfer;
}
if (res > 0)
res = 0;
if (txt) {
fprintf(txt, "duration=%d\n", duration);
fclose(txt);
rename(tmptxtfile, txtfile);
}
/* Store information */
txt = fdopen(txtdes, "w+");
if (txt) {
get_date(date, sizeof(date));
fprintf(txt,
";\n"
"; Message Information file\n"
";\n"
"[message]\n"
"origmailbox=%s\n"
"context=%s\n"
"macrocontext=%s\n"
"exten=%s\n"
"priority=%d\n"
"callerchan=%s\n"
"callerid=%s\n"
"origdate=%s\n"
"origtime=%ld\n"
"category=%s\n",
ext,
chan->context,
chan->macrocontext,
chan->exten,
chan->priority,
chan->name,
ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"),
date, (long)time(NULL),
category ? category : "");
} else
ast_log(LOG_WARNING, "Error opening text file for output\n");
res = play_record_review(chan, NULL, tmptxtfile, vmmaxmessage, fmt, 1, vmu, &duration, NULL, options->record_gain);
if (txt) {
if (duration < vmminmessage) {
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmminmessage);
DELETE(dir,msgnum,fn);
/* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
goto leave_vm_out;
}
/* Are there to be more recipients of this message? */
while (tmpptr) {
struct ast_vm_user recipu, *recip;
char *exten, *context;
exten = strsep(&tmpptr, "&");
context = strchr(exten, '@');
if (context) {
*context = '\0';
context++;
}
if ((recip = find_user(&recipu, context, exten))) {
copy_message(chan, vmu, 0, msgnum, duration, recip, fmt);
free_user(recip);
} else {
fprintf(txt, "duration=%d\n", duration);
fclose(txt);
if (vm_lock_path(dir)) {
ast_log(LOG_ERROR, "Couldn't lock directory %s. Voicemail will be lost.\n", dir);
/* Delete files */
ast_filedelete(tmptxtfile, NULL);
unlink(tmptxtfile);
} else {
for (;;) {
make_file(fn, sizeof(fn), dir, msgnum);
if (!EXISTS(dir, msgnum, fn, NULL))
break;
msgnum++;
}
/* assign a variable with the name of the voicemail file */
pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
ast_filerename(tmptxtfile, fn, NULL);
rename(tmptxtfile, txtfile);
ast_unlock_path(dir);
/* Are there to be more recipients of this message? */
while (tmpptr) {
struct ast_vm_user recipu, *recip;
char *exten, *context;
exten = strsep(&tmpptr, "&");
context = strchr(exten, '@');
if (context) {
*context = '\0';
context++;
}
if ((recip = find_user(&recipu, context, exten))) {
copy_message(chan, vmu, 0, msgnum, duration, recip, fmt);
free_user(recip);
}
}
if (ast_fileexists(fn, NULL, NULL)) {
STORE(dir, vmu->mailbox, vmu->context, msgnum);
notify_new_message(chan, vmu, msgnum, duration, fmt, chan->cid.cid_num, chan->cid.cid_name);
DISPOSE(dir, msgnum);
}
}
}
if (ast_fileexists(fn, NULL, NULL)) {
STORE(dir, vmu->mailbox, vmu->context, msgnum);
notify_new_message(chan, vmu, msgnum, duration, fmt, chan->cid.cid_num, chan->cid.cid_name);
DISPOSE(dir, msgnum);
}
pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
} else {
ast_unlock_path(dir);
res = ast_stream_and_wait(chan, "vm-mailboxfull", chan->language, "");
ast_log(LOG_WARNING, "No more messages possible\n");
pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
}
if (res == '0') {
goto transfer;
} else if (res > 0)
res = 0;
if (duration < vmminmessage)
/* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
else
pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
} else
ast_log(LOG_WARNING, "No format for saving voicemail?\n");
leave_vm_out: