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: https://origsvn.digium.com/svn/asterisk/trunk@27637 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Tilghman Lesher
2006-05-17 02:27:17 +00:00
parent d2da48b156
commit ffe4dedf29

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