@ -112,6 +112,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
# include "asterisk/utils.h"
# include "asterisk/stringfields.h"
# include "asterisk/smdi.h"
# include "asterisk/astobj2.h"
# include "asterisk/event.h"
# include "asterisk/taskprocessor.h"
@ -852,6 +853,56 @@ static int is_valid_dtmf(const char *key);
static void read_password_from_file ( const char * secretfn , char * password , int passwordlen ) ;
static int write_password_to_file ( const char * secretfn , const char * password ) ;
struct ao2_container * inprocess_container ;
struct inprocess {
int count ;
char * context ;
char mailbox [ 0 ] ;
} ;
static int inprocess_hash_fn ( const void * obj , const int flags )
{
const struct inprocess * i = obj ;
return atoi ( i - > mailbox ) ;
}
static int inprocess_cmp_fn ( void * obj , void * arg , int flags )
{
struct inprocess * i = obj , * j = arg ;
if ( ! strcmp ( i - > mailbox , j - > mailbox ) ) {
return 0 ;
}
return ! strcmp ( i - > context , j - > context ) ? CMP_MATCH : 0 ;
}
static int inprocess_count ( const char * context , const char * mailbox , int delta )
{
struct inprocess * i , * arg = alloca ( sizeof ( * arg ) + strlen ( context ) + strlen ( mailbox ) + 2 ) ;
arg - > context = arg - > mailbox + strlen ( mailbox ) + 1 ;
strcpy ( arg - > mailbox , mailbox ) ; /* SAFE */
strcpy ( arg - > context , context ) ; /* SAFE */
ao2_lock ( inprocess_container ) ;
if ( ( i = ao2_find ( inprocess_container , & arg , 0 ) ) ) {
int ret = ast_atomic_fetchadd_int ( & i - > count , delta ) ;
ao2_unlock ( inprocess_container ) ;
ao2_ref ( i , - 1 ) ;
return ret + delta ;
}
if ( ! ( i = ao2_alloc ( sizeof ( * i ) + strlen ( context ) + strlen ( mailbox ) + 2 , NULL ) ) ) {
ao2_unlock ( inprocess_container ) ;
return 0 ;
}
i - > context = i - > mailbox + strlen ( mailbox ) + 1 ;
strcpy ( i - > mailbox , mailbox ) ; /* SAFE */
strcpy ( i - > context , context ) ; /* SAFE */
i - > count = delta ;
ao2_link ( inprocess_container , i ) ;
ao2_unlock ( inprocess_container ) ;
ao2_ref ( i , - 1 ) ;
return delta ;
}
# if !(defined(ODBC_STORAGE) || defined(IMAP_STORAGE))
static int __has_voicemail ( const char * context , const char * mailbox , const char * folder , int shortcircuit ) ;
# endif
@ -4990,7 +5041,7 @@ static int copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int i
return ERROR_LOCK_PATH ;
recipmsgnum = last_message_index ( recip , todir ) + 1 ;
if ( recipmsgnum < recip - > maxmsg ) {
if ( recipmsgnum < recip - > maxmsg - ( imbox ? 0 : inprocess_count ( vmu - > mailbox , vmu - > context , 0 ) ) ) {
make_file ( topath , sizeof ( topath ) , todir , recipmsgnum ) ;
if ( EXISTS ( fromdir , msgnum , frompath , chan - > language ) ) {
COPY ( fromdir , msgnum , todir , recipmsgnum , recip - > mailbox , recip - > context , frompath , topath ) ;
@ -5508,19 +5559,20 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
}
/* Check if we have exceeded maxmsg */
if ( msgnum > = vmu - > 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_play_and_wait ( chan , " vm-mailboxfull " ) ;
ast_free ( tmp ) ;
return - 1 ;
}
# else
if ( count_messages ( vmu , dir ) > = vmu - > maxmsg ) {
if ( count_messages ( vmu , dir ) > = vmu - > maxmsg - inprocess_count ( vmu - > mailbox , vmu - > context , + 1 ) ) {
res = ast_streamfile ( chan , " vm-mailboxfull " , chan - > language ) ;
if ( ! res )
res = ast_waitstream ( chan , " " ) ;
ast_log ( AST_LOG_WARNING , " No more messages possible \n " ) ;
pbx_builtin_setvar_helper ( chan , " VMSTATUS " , " FAILED " ) ;
inprocess_count ( vmu - > mailbox , vmu - > context , - 1 ) ;
goto leave_vm_out ;
}
@ -5534,6 +5586,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
res = ast_waitstream ( chan , " " ) ;
ast_log ( AST_LOG_ERROR , " Unable to create message file: %s \n " , strerror ( errno ) ) ;
pbx_builtin_setvar_helper ( chan , " VMSTATUS " , " FAILED " ) ;
inprocess_count ( vmu - > mailbox , vmu - > context , - 1 ) ;
goto leave_vm_out ;
}
@ -5579,8 +5632,15 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
ast_callerid_merge ( callerid , sizeof ( callerid ) , S_OR ( chan - > cid . cid_name , NULL ) , S_OR ( chan - > cid . cid_num , NULL ) , " Unknown " ) ,
date , ( long ) time ( NULL ) ,
category ? category : " " ) ;
} else
} else {
ast_log ( AST_LOG_WARNING , " Error opening text file for output \n " ) ;
inprocess_count ( vmu - > mailbox , vmu - > context , - 1 ) ;
if ( ast_check_realtime ( " voicemail_data " ) ) {
ast_destroy_realtime ( " voicemail_data " , " filename " , tmptxtfile , SENTINEL ) ;
}
res = ast_streamfile ( chan , " vm-mailboxfull " , chan - > language ) ;
goto leave_vm_out ;
}
res = play_record_review ( chan , NULL , tmptxtfile , vmu - > maxsecs , fmt , 1 , vmu , & duration , NULL , options - > record_gain , vms , flag ) ;
if ( txt ) {
@ -5594,6 +5654,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
if ( ast_check_realtime ( " voicemail_data " ) ) {
ast_destroy_realtime ( " voicemail_data " , " filename " , tmptxtfile , SENTINEL ) ;
}
inprocess_count ( vmu - > mailbox , vmu - > context , - 1 ) ;
} else {
fprintf ( txt , " duration=%d \n " , duration ) ;
fclose ( txt ) ;
@ -5602,10 +5663,12 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
/* Delete files */
ast_filedelete ( tmptxtfile , NULL ) ;
unlink ( tmptxtfile ) ;
inprocess_count ( vmu - > mailbox , vmu - > context , - 1 ) ;
} else if ( ast_fileexists ( tmptxtfile , NULL , NULL ) < = 0 ) {
ast_debug ( 1 , " The recorded media file is gone, so we should remove the .txt file too! \n " ) ;
unlink ( tmptxtfile ) ;
ast_unlock_path ( dir ) ;
inprocess_count ( vmu - > mailbox , vmu - > context , - 1 ) ;
if ( ast_check_realtime ( " voicemail_data " ) ) {
ast_destroy_realtime ( " voicemail_data " , " filename " , tmptxtfile , SENTINEL ) ;
}
@ -5625,6 +5688,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
snprintf ( txtfile , sizeof ( txtfile ) , " %s.txt " , fn ) ;
ast_filerename ( tmptxtfile , fn , NULL ) ;
rename ( tmptxtfile , txtfile ) ;
inprocess_count ( vmu - > mailbox , vmu - > context , - 1 ) ;
/* Properly set permissions on voicemail text descriptor file.
Unfortunately mkstemp ( ) makes this file 0600 on most unix systems . */
@ -5689,6 +5753,8 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
}
}
}
} else {
inprocess_count ( vmu - > mailbox , vmu - > context , - 1 ) ;
}
if ( res = = ' 0 ' ) {
goto transfer ;
@ -11497,6 +11563,7 @@ static int unload_module(void)
res | = ast_manager_unregister ( " VoicemailUsersList " ) ;
ast_cli_unregister_multiple ( cli_voicemail , ARRAY_LEN ( cli_voicemail ) ) ;
ast_uninstall_vm_functions ( ) ;
ao2_ref ( inprocess_container , - 1 ) ;
if ( poll_thread ! = AST_PTHREADT_NULL )
stop_poll_thread ( ) ;
@ -11516,6 +11583,10 @@ static int load_module(void)
my_umask = umask ( 0 ) ;
umask ( my_umask ) ;
if ( ! ( inprocess_container = ao2_container_alloc ( 573 , inprocess_hash_fn , inprocess_cmp_fn ) ) ) {
return AST_MODULE_LOAD_DECLINE ;
}
/* compute the location of the voicemail spool directory */
snprintf ( VM_SPOOL_DIR , sizeof ( VM_SPOOL_DIR ) , " %s/voicemail/ " , ast_config_AST_SPOOL_DIR ) ;