Hi everyone.
I met a problem some time ago, that when callers were leaving voice messages it wasn’t saved to DB, nor anywere.
Through a brief research I found several (in fact - two) “.lock” files in //INBOX OS directories (most commonly used). And, also, found tons of “Couldn’t lock directory …/INBOX. Voicemail will be lost.” in asterisk-log output.
So, just removing “.lock” files solves the problem. But… In fact, it solves the problem for some time only and, which is worse, we lost all voicemails leaved from the time “.lock”-file appeared.
First, using search, it seems that such a problem happens even with 1.8.* Asterisk (by the way, we are using 1.4.21.1), just maybe with different circumstances.
Next I dived into sources, and learned that asterisk uses “.lock” files to lock directories for internal needs (for example, to count messages) and, when anything is going Ok, Asterisk unlocks directories by removing those files. But when some errors occures (I couldn’t create erroneous situations by myself, thit is sad, but people in Internets say, that errors is possibly take place during leaving voicemail), the directory may not become unlocked and then noone tries to check for such horrible situation to solve it and directory stays locked, maybe, forever (or I’m wrong?)
So, at the end, we can’t afford loosing voicemails, and, as temporary solution, it was decided to make a patch in app_voicemail.c to copy files from //tmp before asterisk manages to delete them.
This is my code fragment, in app_voicemail.c, in function leave_voicemail (I hope you’ll easily find that place in vanilla sources), my code is between “this is where my code starts” and “this is where my code ends” :
if (txt) {
if (duration < vmminmessage) {
fclose(txt);
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration
ast_filedelete(tmptxtfile, NULL);
unlink(tmptxtfile);
} 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);
/* this is where my code starts */
/* There we need to back up files which asterisk is supposing to delete right under */
char backupdir[PATH_MAX]; /* for creating failed_vm directory in VM_SPOOL_DIR */
mode_t backup_mode = VOICEMAIL_DIR_MODE; /* just copied from create_dirpath */
char backupfile[PATH_MAX]; /* for backing up file in case of locked INBOX dir */
char bak_fn[PATH_MAX]="\0";
snprintf(backupdir, sizeof(backupdir), "%s%s", VM_SPOOL_DIR, "failed_vm");
/* It's easier just to try to make it than to check for its existence */
mkdir(backupdir, backup_mode);
/* dir prepared (i hope =) ), if not, we'll just fail to copy later, so no difference in result */
/* now we need in some manner copy only filename from tmptxtfile */
// int path_len = strlen(tmptxtfile);
const char *last_sep = strrchr(tmptxtfile, '/');
if(last_sep != NULL)
{
last_sep++;
strcat(bak_fn, last_sep);
}
snprintf(backupfile, sizeof(backupfile), "%s/%s", backupdir, bak_fn);
/* and finaly - copying */
ast_filecopy(tmptxtfile, backupfile, NULL); /* it supposed to copy WAV file */
copy(tmptxtfile, backupfile); /* it supposed to copy only txt file */
/* below we let vanilla asterisk to think it's working as it wants */
/* this is where my code ends */
/* Delete files */
ast_filedelete(tmptxtfile, NULL);
unlink(tmptxtfile);
} else if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
It was my issue, but the aim it to ask some help.
First - is my idea quite right?
Then, I ask you to look through code to think about security of it - this is what I’m personaly concerned with.
Third, maybe it’s possible to make some improvements (I tried to use native-asterisk methods, but I’m not sure if it was done proper way).
I mean, this code works fine, but maybe not as fine as it could be =).
Thanks.