@ -1009,42 +1009,24 @@ static ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER;
static pthread_t poll_thread = AST_PTHREADT_NULL ;
static unsigned char poll_thread_run ;
/*! Subscription to MWI event subscription changes */
static struct stasis_subscription * mwi_sub_sub ;
/*!
* \ brief A n MWI subscription
* \ brief A mailbox to be polled
*
* This is so we can keep track of which mailboxes are subscribed to .
* This way , we know which mailboxes to poll when the pollmailboxes
* option is being used .
*/
struct mwi_sub {
AST_RWLIST_ENTRY ( mwi_sub ) entry ;
struct poll_state {
int marked_used ;
int old_urgent ;
int old_new ;
int old_old ;
char * uniqueid ;
char mailbox [ 0 ] ;
} ;
struct mwi_sub_task {
const char * mailbox ;
const char * context ;
const char * uniqueid ;
} ;
static void mwi_sub_task_dtor ( struct mwi_sub_task * mwist )
{
ast_free ( ( void * ) mwist - > mailbox ) ;
ast_free ( ( void * ) mwist - > context ) ;
ast_free ( ( void * ) mwist - > uniqueid ) ;
ast_free ( mwist ) ;
}
static struct ast_taskprocessor * mwi_subscription_tps ;
static AST_RWLIST_HEAD_STATIC ( mwi_subs , mwi_sub ) ;
# define POLL_LIST_BUCKETS 511
static struct ao2_container * poll_list ;
AO2_STRING_FIELD_HASH_FN ( poll_state , mailbox ) ;
AO2_STRING_FIELD_CMP_FN ( poll_state , mailbox ) ;
/* custom audio control prompts for voicemail playback */
static char listen_control_forward_key [ 12 ] ;
@ -1122,7 +1104,7 @@ static const char *substitute_escapes(const char *value);
static int message_range_and_existence_check ( struct vm_state * vms , const char * msg_ids [ ] , size_t num_msgs , int * msg_nums , struct ast_vm_user * vmu ) ;
static void notify_new_state ( struct ast_vm_user * vmu ) ;
static int append_vmu_info_astman ( struct mansession * s , struct ast_vm_user * vmu , const char * event_name , const char * actionid ) ;
static int poll_mailbox ( void * obj , void * arg , int flags ) ;
/*!
* Place a message in the indicated folder
@ -12310,6 +12292,59 @@ static int add_message_id(struct ast_config *msg_cfg, char *dir, int msg, char *
return 0 ;
}
static void poll_state_dtor ( void * obj )
{
struct poll_state * poll_state = obj ;
ast_debug ( 3 , " DTOR: Mailbox: %s New: %d Old: %d Urgent: %d Marked Used: %d \n " , poll_state - > mailbox ,
poll_state - > old_new , poll_state - > old_old , poll_state - > old_urgent ,
poll_state - > marked_used ) ;
}
static int mark_or_create_poll_state ( struct ast_vm_user * vmu )
{
size_t len ;
struct poll_state * poll_state ;
char * mailbox ;
if ( ast_strlen_zero ( vmu - > mailbox ) ) {
ast_log ( LOG_ERROR , " Mailbox can't be empty \n " ) ;
return - 1 ;
}
len = sizeof ( vmu - > mailbox ) + sizeof ( vmu - > context ) + sizeof ( ' @ ' ) + 1 ;
mailbox = ast_alloca ( len ) ;
len = snprintf ( mailbox , len , " %s%s%s " ,
vmu - > mailbox ,
ast_strlen_zero ( vmu - > context ) ? " " : " @ " ,
vmu - > context ) ;
len + + ; /* For NULL terminator */
poll_state = ao2_find ( poll_list , mailbox , OBJ_SEARCH_KEY ) ;
if ( poll_state ) {
poll_state - > marked_used = 1 ;
ao2_ref ( poll_state , - 1 ) ;
return 0 ;
}
poll_state = ao2_alloc_options ( len + sizeof ( * poll_state ) , poll_state_dtor ,
AO2_ALLOC_OPT_LOCK_NOLOCK ) ;
if ( ! poll_state ) {
return - 1 ;
}
strcpy ( poll_state - > mailbox , mailbox ) ; /* Safe */
poll_state - > marked_used = 1 ;
ao2_link_flags ( poll_list , poll_state , OBJ_NOLOCK ) ;
poll_mailbox ( poll_state , NULL , 0 ) ;
ao2_ref ( poll_state , - 1 ) ;
return 0 ;
}
static struct ast_vm_user * find_or_create ( const char * context , const char * box )
{
struct ast_vm_user * vmu ;
@ -12339,12 +12374,18 @@ static struct ast_vm_user *find_or_create(const char *context, const char *box)
}
}
if ( ! ( vmu = ast_calloc ( 1 , sizeof ( * vmu ) ) ) )
if ( ! ( vmu = ast_calloc ( 1 , sizeof ( * vmu ) ) ) ) {
return NULL ;
}
ast_copy_string ( vmu - > context , context , sizeof ( vmu - > context ) ) ;
ast_copy_string ( vmu - > mailbox , box , sizeof ( vmu - > mailbox ) ) ;
if ( mark_or_create_poll_state ( vmu ) ) {
ast_free ( vmu ) ;
return NULL ;
}
AST_LIST_INSERT_TAIL ( & users , vmu , list ) ;
return vmu ;
@ -12600,6 +12641,7 @@ AST_TEST_DEFINE(test_voicemail_vmuser)
# endif
free_user ( vmu ) ;
return res ? AST_TEST_FAIL : AST_TEST_PASS ;
}
# endif
@ -13010,38 +13052,33 @@ static struct ast_cli_entry cli_voicemail[] = {
AST_CLI_DEFINE ( handle_voicemail_reload , " Reload voicemail configuration " ) ,
} ;
static void poll_subscribed_mailbox ( struct mwi_sub * mwi_sub )
static int poll_mailbox ( void * obj , void * arg , int flags )
{
struct poll_state * poll_state = obj ;
int new = 0 , old = 0 , urgent = 0 ;
inboxcount2 ( mwi_sub - > mailbox , & urgent , & new , & old ) ;
inboxcount2 ( poll_state - > mailbox , & urgent , & new , & old ) ;
ast_debug ( 4 , " Polled mailbox '%s' urgent: %d new: %d old: %d \n " ,
poll_state - > mailbox , urgent , new , old ) ;
# ifdef IMAP_STORAGE
if ( imap_poll_logout ) {
imap_logout ( mwi_sub - > mailbox ) ;
imap_logout ( poll_state - > mailbox ) ;
}
# endif
if ( urgent ! = mwi_sub - > old_urgent | | new ! = mwi_sub - > old_new | | old ! = mwi_sub - > old_old ) {
mwi_sub - > old_urgent = urgent ;
mwi_sub - > old_new = new ;
mwi_sub - > old_old = old ;
queue_mwi_event ( NULL , mwi_sub - > mailbox , urgent , new , old ) ;
run_externnotify ( NULL , mwi_sub - > mailbox , NULL ) ;
if ( urgent ! = poll_state - > old_urgent | | new ! = poll_state - > old_new | | old ! = poll_state - > old_old ) {
ast_debug ( 4 , " Notifying subscribers of mailbox '%s' urgent: %d new: %d old: %d \n " ,
poll_state - > mailbox , urgent , new , old ) ;
poll_state - > old_urgent = urgent ;
poll_state - > old_new = new ;
poll_state - > old_old = old ;
queue_mwi_event ( NULL , poll_state - > mailbox , urgent , new , old ) ;
run_externnotify ( NULL , poll_state - > mailbox , NULL ) ;
}
}
static void poll_subscribed_mailboxes ( void )
{
struct mwi_sub * mwi_sub ;
AST_RWLIST_RDLOCK ( & mwi_subs ) ;
AST_RWLIST_TRAVERSE ( & mwi_subs , mwi_sub , entry ) {
if ( ! ast_strlen_zero ( mwi_sub - > mailbox ) ) {
poll_subscribed_mailbox ( mwi_sub ) ;
}
}
AST_RWLIST_UNLOCK ( & mwi_subs ) ;
return 0 ;
}
static void * mb_poll_thread ( void * data )
@ -13061,18 +13098,13 @@ static void *mb_poll_thread(void *data)
if ( ! poll_thread_run )
break ;
poll_subscribed_mailboxes ( ) ;
ast_debug ( 3 , " Polling mailboxes \n " ) ;
ao2_callback ( poll_list , OBJ_NODATA | OBJ_MULTIPLE , poll_mailbox , NULL ) ;
}
return NULL ;
}
static void mwi_sub_destroy ( struct mwi_sub * mwi_sub )
{
ast_free ( mwi_sub - > uniqueid ) ;
ast_free ( mwi_sub ) ;
}
# ifdef IMAP_STORAGE
static void imap_logout ( const char * mailbox_id )
{
@ -13108,155 +13140,22 @@ static void imap_logout(const char *mailbox_id)
vmstate_delete ( vms ) ;
}
static void imap_close_subscribed_mailboxes ( void )
{
struct mwi_sub * mwi_sub ;
AST_RWLIST_RDLOCK ( & mwi_subs ) ;
AST_RWLIST_TRAVERSE ( & mwi_subs , mwi_sub , entry ) {
if ( ! ast_strlen_zero ( mwi_sub - > mailbox ) ) {
imap_logout ( mwi_sub - > mailbox ) ;
}
}
AST_RWLIST_UNLOCK ( & mwi_subs ) ;
}
# endif
static int handle_unsubscribe ( void * datap )
static int imap_close_subscribed_mailboxes_cb ( void * obj , void * arg , int flags )
{
struct mwi_sub * mwi_sub ;
char * uniqueid = datap ;
AST_RWLIST_WRLOCK ( & mwi_subs ) ;
AST_RWLIST_TRAVERSE_SAFE_BEGIN ( & mwi_subs , mwi_sub , entry ) {
if ( ! strcmp ( mwi_sub - > uniqueid , uniqueid ) ) {
AST_LIST_REMOVE_CURRENT ( entry ) ;
/* Don't break here since a duplicate uniqueid
* may have been added as a result of a cache dump . */
# ifdef IMAP_STORAGE
imap_logout ( mwi_sub - > mailbox ) ;
# endif
mwi_sub_destroy ( mwi_sub ) ;
}
}
AST_RWLIST_TRAVERSE_SAFE_END
AST_RWLIST_UNLOCK ( & mwi_subs ) ;
struct poll_state * poll_state = obj ;
imap_logout ( poll_state - > mailbox ) ;
ast_free ( uniqueid ) ;
return 0 ;
}
static int handle_subscribe ( void * datap )
{
unsigned int len ;
struct mwi_sub * mwi_sub ;
struct mwi_sub_task * p = datap ;
len = sizeof ( * mwi_sub ) + 1 ;
if ( ! ast_strlen_zero ( p - > mailbox ) )
len + = strlen ( p - > mailbox ) ;
if ( ! ast_strlen_zero ( p - > context ) )
len + = strlen ( p - > context ) + 1 ; /* Allow for seperator */
if ( ! ( mwi_sub = ast_calloc ( 1 , len ) ) )
return - 1 ;
mwi_sub - > uniqueid = ast_strdup ( p - > uniqueid ) ;
if ( ! ast_strlen_zero ( p - > mailbox ) )
strcpy ( mwi_sub - > mailbox , p - > mailbox ) ;
if ( ! ast_strlen_zero ( p - > context ) ) {
strcat ( mwi_sub - > mailbox , " @ " ) ;
strcat ( mwi_sub - > mailbox , p - > context ) ;
}
AST_RWLIST_WRLOCK ( & mwi_subs ) ;
AST_RWLIST_INSERT_TAIL ( & mwi_subs , mwi_sub , entry ) ;
AST_RWLIST_UNLOCK ( & mwi_subs ) ;
mwi_sub_task_dtor ( p ) ;
poll_subscribed_mailbox ( mwi_sub ) ;
return 0 ;
}
static void mwi_unsub_event_cb ( struct stasis_subscription_change * change )
{
char * uniqueid = ast_strdup ( change - > uniqueid ) ;
if ( ! uniqueid ) {
ast_log ( LOG_ERROR , " Unable to allocate memory for uniqueid \n " ) ;
return ;
}
if ( ast_taskprocessor_push ( mwi_subscription_tps , handle_unsubscribe , uniqueid ) < 0 ) {
ast_free ( uniqueid ) ;
}
}
static void mwi_sub_event_cb ( struct stasis_subscription_change * change )
{
struct mwi_sub_task * mwist ;
char * context ;
char * mailbox ;
mwist = ast_calloc ( 1 , ( sizeof ( * mwist ) ) ) ;
if ( ! mwist ) {
return ;
}
if ( separate_mailbox ( ast_strdupa ( stasis_topic_name ( change - > topic ) ) , & mailbox , & context ) ) {
ast_free ( mwist ) ;
return ;
}
mwist - > mailbox = ast_strdup ( mailbox ) ;
mwist - > context = ast_strdup ( context ) ;
mwist - > uniqueid = ast_strdup ( change - > uniqueid ) ;
if ( ast_taskprocessor_push ( mwi_subscription_tps , handle_subscribe , mwist ) < 0 ) {
mwi_sub_task_dtor ( mwist ) ;
}
}
static void mwi_event_cb ( void * userdata , struct stasis_subscription * sub , struct stasis_message * msg )
{
struct stasis_subscription_change * change ;
/* Only looking for subscription change notices here */
if ( stasis_message_type ( msg ) ! = stasis_subscription_change_type ( ) ) {
return ;
}
change = stasis_message_data ( msg ) ;
if ( change - > topic = = ast_mwi_topic_all ( ) ) {
return ;
}
if ( ! strcmp ( change - > description , " Subscribe " ) ) {
mwi_sub_event_cb ( change ) ;
} else if ( ! strcmp ( change - > description , " Unsubscribe " ) ) {
mwi_unsub_event_cb ( change ) ;
}
}
static int dump_cache ( void * obj , void * arg , int flags )
static void imap_close_subscribed_mailboxes ( void )
{
struct stasis_message * msg = obj ;
mwi_event_cb ( NULL , NULL , msg ) ;
return 0 ;
ao2_callback ( poll_list , OBJ_NODATA | OBJ_MULTIPLE , imap_close_subscribed_mailboxes_cb , NULL ) ;
}
# endif
static void start_poll_thread ( void )
{
int errcode ;
mwi_sub_sub = stasis_subscribe ( ast_mwi_topic_all ( ) , mwi_event_cb , NULL ) ;
if ( mwi_sub_sub ) {
struct ao2_container * cached = stasis_cache_dump ( ast_mwi_state_cache ( ) , stasis_subscription_change_type ( ) ) ;
if ( cached ) {
ao2_callback ( cached , OBJ_MULTIPLE | OBJ_NODATA , dump_cache , NULL ) ;
}
ao2_cleanup ( cached ) ;
}
poll_thread_run = 1 ;
@ -13269,8 +13168,6 @@ static void stop_poll_thread(void)
{
poll_thread_run = 0 ;
mwi_sub_sub = stasis_unsubscribe_and_join ( mwi_sub_sub ) ;
ast_mutex_lock ( & poll_lock ) ;
ast_cond_signal ( & poll_cond ) ;
ast_mutex_unlock ( & poll_lock ) ;
@ -13401,38 +13298,50 @@ static int append_vmu_info_astman(
}
static int manager_voicemail_refresh ( struct mansession * s , const struct message * m )
struct refresh_data {
const char * context ;
const char * mailbox ;
} ;
static int refresh_match ( void * obj , void * arg , int gflags )
{
const char * context = astman_get_header ( m , " Context " ) ;
const char * mailbox = astman_get_header ( m , " Mailbox " ) ;
struct mwi_sub * mwi_sub ;
struct poll_state * poll_state = obj ;
struct refresh_data * data = arg ;
const char * at ;
AST_RWLIST_RDLOCK ( & mwi_subs ) ;
AST_RWLIST_TRAVERSE ( & mwi_subs , mwi_sub , entry ) {
if ( ! ast_strlen_zero ( mwi_sub - > mailbox ) ) {
if (
/* First case: everything matches */
( ast_strlen_zero ( context ) & & ast_strlen_zero ( mailbox ) ) | |
/* Second case: match the mailbox only */
( ast_strlen_zero ( context ) & & ! ast_strlen_zero ( mailbox ) & &
( at = strchr ( mwi_sub - > mailbox , ' @ ' ) ) & &
strncmp ( mailbox , mwi_sub - > mailbox , at - mwi_sub - > mailbox ) = = 0 ) | |
/* Third case: match the context only */
( ! ast_strlen_zero ( context ) & & ast_strlen_zero ( mailbox ) & &
( at = strchr ( mwi_sub - > mailbox , ' @ ' ) ) & &
strcmp ( context , at + 1 ) = = 0 ) | |
/* Final case: match an exact specified mailbox */
( ! ast_strlen_zero ( context ) & & ! ast_strlen_zero ( mailbox ) & &
( at = strchr ( mwi_sub - > mailbox , ' @ ' ) ) & &
strncmp ( mailbox , mwi_sub - > mailbox , at - mwi_sub - > mailbox ) = = 0 & &
strcmp ( context , at + 1 ) = = 0 )
) {
poll_subscribed_mailbox ( mwi_sub ) ;
}
if ( ! ast_strlen_zero ( poll_state - > mailbox ) ) {
if (
/* First case: everything matches */
( ast_strlen_zero ( data - > context ) & & ast_strlen_zero ( data - > mailbox ) ) | |
/* Second case: match the mailbox only */
( ast_strlen_zero ( data - > context ) & & ! ast_strlen_zero ( data - > mailbox ) & &
( at = strchr ( poll_state - > mailbox , ' @ ' ) ) & &
strncmp ( data - > mailbox , poll_state - > mailbox , at - poll_state - > mailbox ) = = 0 ) | |
/* Third case: match the context only */
( ! ast_strlen_zero ( data - > context ) & & ast_strlen_zero ( data - > mailbox ) & &
( at = strchr ( poll_state - > mailbox , ' @ ' ) ) & &
strcmp ( data - > context , at + 1 ) = = 0 ) | |
/* Final case: match an exact specified mailbox */
( ! ast_strlen_zero ( data - > context ) & & ! ast_strlen_zero ( data - > mailbox ) & &
( at = strchr ( poll_state - > mailbox , ' @ ' ) ) & &
strncmp ( data - > mailbox , poll_state - > mailbox , at - poll_state - > mailbox ) = = 0 & &
strcmp ( data - > context , at + 1 ) = = 0 )
) {
poll_mailbox ( poll_state , NULL , 0 ) ;
}
}
AST_RWLIST_UNLOCK ( & mwi_subs ) ;
return 0 ;
}
static int manager_voicemail_refresh ( struct mansession * s , const struct message * m )
{
struct refresh_data data = {
. context = astman_get_header ( m , " Context " ) ,
. mailbox = astman_get_header ( m , " Mailbox " ) ,
} ;
ao2_callback ( poll_list , OBJ_NODATA | OBJ_MULTIPLE , refresh_match , ( void * ) & data ) ;
astman_send_ack ( s , m , " Refresh sent " ) ;
return RESULT_SUCCESS ;
}
@ -13643,6 +13552,26 @@ static int load_config_from_memory(int reload, struct ast_config *cfg, struct as
}
# endif
static int unmark_poll_state ( void * obj , void * arg , int flags )
{
struct poll_state * poll_state = obj ;
poll_state - > marked_used = 0 ;
return 0 ;
}
static int unmarked_poll_state ( void * obj , void * arg , int flags )
{
struct poll_state * poll_state = obj ;
if ( ! poll_state - > marked_used ) {
return CMP_MATCH ;
}
return 0 ;
}
static int actual_load_config ( int reload , struct ast_config * cfg , struct ast_config * ucfg )
{
struct ast_vm_user * current ;
@ -13653,8 +13582,6 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con
int x ;
unsigned int tmpadsi [ 4 ] ;
char secretfn [ PATH_MAX ] = " " ;
long tps_queue_low ;
long tps_queue_high ;
# ifdef IMAP_STORAGE
ast_copy_string ( imapparentfolder , " \0 " , sizeof ( imapparentfolder ) ) ;
@ -13670,6 +13597,17 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con
imap_close_subscribed_mailboxes ( ) ;
# endif
if ( poll_thread ! = AST_PTHREADT_NULL ) {
stop_poll_thread ( ) ;
}
/*
* Unmark all current poll states . As mailboxes are ( re ) loaded ,
* the state will be marked as used . Any not marked after the
* ( re ) load , will be removed .
*/
ao2_callback ( poll_list , OBJ_NODATA | OBJ_MULTIPLE , unmark_poll_state , NULL ) ;
/* Free all the users structure */
free_vm_users ( ) ;
@ -14243,23 +14181,11 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con
pagerbody = ast_strdup ( substitute_escapes ( val ) ) ;
}
tps_queue_high = AST_TASKPROCESSOR_HIGH_WATER_LEVEL ;
if ( ( val = ast_variable_retrieve ( cfg , " general " , " tps_queue_high " ) ) ) {
if ( sscanf ( val , " %30ld " , & tps_queue_high ) ! = 1 | | tps_queue_high < = 0 ) {
ast_log ( AST_LOG_WARNING , " Invalid the taskprocessor high water alert trigger level '%s' \n " , val ) ;
tps_queue_high = AST_TASKPROCESSOR_HIGH_WATER_LEVEL ;
}
ast_log ( LOG_NOTICE , " Parameter tps_queue_high is obsolete and will be ignored \n " ) ;
}
tps_queue_low = - 1 ;
if ( ( val = ast_variable_retrieve ( cfg , " general " , " tps_queue_low " ) ) ) {
if ( sscanf ( val , " %30ld " , & tps_queue_low ) ! = 1 | |
tps_queue_low < - 1 | | tps_queue_high < tps_queue_low ) {
ast_log ( AST_LOG_WARNING , " Invalid the taskprocessor low water clear alert level '%s' \n " , val ) ;
tps_queue_low = - 1 ;
}
}
if ( ast_taskprocessor_alert_set_levels ( mwi_subscription_tps , tps_queue_low , tps_queue_high ) ) {
ast_log ( AST_LOG_WARNING , " Failed to set alert levels for voicemail taskprocessor. \n " ) ;
ast_log ( LOG_NOTICE , " Parameter tps_queue_low is obsolete and will be ignored \n " ) ;
}
/* load mailboxes from users.conf */
@ -14329,15 +14255,16 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con
}
AST_LIST_UNLOCK ( & users ) ;
/* Remove any left over unmarked poll states */
ao2_callback ( poll_list , OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE , unmarked_poll_state , NULL ) ;
if ( poll_mailboxes & & poll_thread = = AST_PTHREADT_NULL )
start_poll_thread ( ) ;
if ( ! poll_mailboxes & & poll_thread ! = AST_PTHREADT_NULL )
stop_poll_thread ( ) ; ;
return 0 ;
} else {
AST_LIST_UNLOCK ( & users ) ;
ao2_callback ( poll_list , OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE , unmarked_poll_state , NULL ) ;
ast_log ( AST_LOG_WARNING , " Failed to load configuration file. \n " ) ;
return 0 ;
}
@ -14558,7 +14485,6 @@ AST_TEST_DEFINE(test_voicemail_msgcount)
{
int i , j , res = AST_TEST_PASS , syserr ;
struct ast_vm_user * vmu ;
struct ast_vm_user svm ;
struct vm_state vms ;
# ifdef IMAP_STORAGE
struct ast_channel * chan = NULL ;
@ -14611,9 +14537,11 @@ AST_TEST_DEFINE(test_voicemail_msgcount)
}
# endif
memset ( & svm , 0 , sizeof ( svm ) ) ;
if ( ! ( vmu = find_user ( & svm , testcontext , testmailbox ) ) & &
! ( vmu = find_or_create ( testcontext , testmailbox ) ) ) {
AST_LIST_LOCK ( & users ) ;
vmu = find_or_create ( testcontext , testmailbox ) ;
AST_LIST_UNLOCK ( & users ) ;
if ( ! vmu ) {
ast_test_status_update ( test , " Cannot create vmu structure \n " ) ;
ast_unreplace_sigchld ( ) ;
# ifdef IMAP_STORAGE
@ -14641,8 +14569,8 @@ AST_TEST_DEFINE(test_voicemail_msgcount)
# ifdef IMAP_STORAGE
chan = ast_channel_unref ( chan ) ;
# endif
free_user ( vmu ) ;
return AST_TEST_FAIL ;
res = AST_TEST_FAIL ;
break ;
}
}
@ -14666,27 +14594,34 @@ AST_TEST_DEFINE(test_voicemail_msgcount)
res = AST_TEST_FAIL ;
}
}
if ( res ) {
break ;
}
new = old = urgent = 0 ;
if ( ast_app_inboxcount ( testspec , & new , & old ) ) {
ast_test_status_update ( test , " inboxcount returned failure \n " ) ;
res = AST_TEST_FAIL ;
break ;
} else if ( old ! = expected_results [ i ] [ 3 + 0 ] | | new ! = expected_results [ i ] [ 3 + 2 ] ) {
ast_test_status_update ( test , " inboxcount(%s) returned old=%d (expected %d) and new=%d (expected %d) \n " ,
testspec , old , expected_results [ i ] [ 3 + 0 ] , new , expected_results [ i ] [ 3 + 2 ] ) ;
res = AST_TEST_FAIL ;
break ;
}
new = old = urgent = 0 ;
if ( ast_app_inboxcount2 ( testspec , & urgent , & new , & old ) ) {
ast_test_status_update ( test , " inboxcount2 returned failure \n " ) ;
res = AST_TEST_FAIL ;
break ;
} else if ( old ! = expected_results [ i ] [ 6 + 0 ] | |
urgent ! = expected_results [ i ] [ 6 + 1 ] | |
new ! = expected_results [ i ] [ 6 + 2 ] ) {
ast_test_status_update ( test , " inboxcount2(%s) returned old=%d (expected %d), urgent=%d (expected %d), and new=%d (expected %d) \n " ,
testspec , old , expected_results [ i ] [ 6 + 0 ] , urgent , expected_results [ i ] [ 6 + 1 ] , new , expected_results [ i ] [ 6 + 2 ] ) ;
res = AST_TEST_FAIL ;
break ;
}
new = old = urgent = 0 ;
@ -14697,6 +14632,9 @@ AST_TEST_DEFINE(test_voicemail_msgcount)
res = AST_TEST_FAIL ;
}
}
if ( res ) {
break ;
}
}
for ( i = 0 ; i < 3 ; i + + ) {
@ -14725,7 +14663,9 @@ AST_TEST_DEFINE(test_voicemail_msgcount)
syserr > 0 ? strerror ( syserr ) : " unable to fork() " ) ;
}
free_user ( vmu ) ;
/* restore config */
load_config ( 0 ) ; /* this might say "Failed to load configuration file." */
return res ;
}
@ -14776,15 +14716,13 @@ AST_TEST_DEFINE(test_voicemail_notify_endl)
snprintf ( attach , sizeof ( attach ) , " %s/sounds/en/tt-weasels " , ast_config_AST_DATA_DIR ) ;
snprintf ( attach2 , sizeof ( attach2 ) , " %s/sounds/en/tt-somethingwrong " , ast_config_AST_DATA_DIR ) ;
if ( ! ( vmu = find_user ( & vmus , testcontext , testmailbox ) ) & &
! ( vmu = find_or_create ( testcontext , testmailbox ) ) ) {
ast_test_status_update ( test , " Cannot create vmu structure \n " ) ;
return AST_TEST_NOT_RUN ;
}
AST_LIST_LOCK ( & users ) ;
vmu = find_or_create ( testcontext , testmailbox ) ;
AST_LIST_UNLOCK ( & users ) ;
if ( vmu ! = & vmu s & & ! ( vmu = find_user ( & vmus , testcontext , testmailbox ) ) ) {
ast_test_status_update ( test , " Cannot find vmu structure?!! \n " ) ;
return AST_TEST_ NOT_RUN ;
if ( ! vmu ) {
ast_test_status_update ( test , " Cannot create vmu structure \n " ) ;
return AST_TEST_ FAIL ;
}
populate_defaults ( vmu ) ;
@ -14835,7 +14773,10 @@ AST_TEST_DEFINE(test_voicemail_notify_endl)
}
}
fclose ( file ) ;
free_user ( vmu ) ;
/* restore config */
load_config ( 0 ) ; /* this might say "Failed to load configuration file." */
return res ;
}
@ -14909,7 +14850,7 @@ AST_TEST_DEFINE(test_voicemail_load_config)
# undef CHECK
/* restore config */
load_config ( 1 ) ; /* this might say "Failed to load configuration file." */
load_config ( 0 ) ; /* this might say "Failed to load configuration file." */
cleanup :
unlink ( config_filename ) ;
@ -14965,8 +14906,11 @@ AST_TEST_DEFINE(test_voicemail_vm_info)
return AST_TEST_FAIL ;
}
if ( ! ( vmu = find_user ( NULL , testcontext , testmailbox ) ) & &
! ( vmu = find_or_create ( testcontext , testmailbox ) ) ) {
AST_LIST_LOCK ( & users ) ;
vmu = find_or_create ( testcontext , testmailbox ) ;
AST_LIST_UNLOCK ( & users ) ;
if ( ! vmu ) {
ast_test_status_update ( test , " Cannot create vmu structure \n " ) ;
chan = ast_channel_unref ( chan ) ;
return AST_TEST_FAIL ;
@ -14996,7 +14940,10 @@ AST_TEST_DEFINE(test_voicemail_vm_info)
}
chan = ast_channel_unref ( chan ) ;
free_user ( vmu ) ;
/* restore config */
load_config ( 0 ) ; /* this might say "Failed to load configuration file." */
return res ;
}
# endif /* defined(TEST_FRAMEWORK) */
@ -15062,10 +15009,13 @@ static int unload_module(void)
# endif
ao2_ref ( inprocess_container , - 1 ) ;
if ( poll_thread ! = AST_PTHREADT_NULL )
if ( poll_thread ! = AST_PTHREADT_NULL ) {
stop_poll_thread ( ) ;
}
ao2_container_unregister ( " voicemail_poll_list " ) ;
ao2_cleanup ( poll_list ) ;
mwi_subscription_tps = ast_taskprocessor_unreference ( mwi_subscription_tps ) ;
ast_unload_realtime ( " voicemail " ) ;
ast_unload_realtime ( " voicemail_data " ) ;
@ -15077,6 +15027,18 @@ static int unload_module(void)
return res ;
}
static void print_poll_state ( void * v_obj , void * where , ao2_prnt_fn * prnt )
{
struct poll_state * poll_state = v_obj ;
if ( ! poll_state ) {
return ;
}
prnt ( where , " Mailbox: %s New: %d Old: %d Urgent: %d Marked Used: %d " , poll_state - > mailbox ,
poll_state - > old_new , poll_state - > old_old , poll_state - > old_urgent ,
poll_state - > marked_used ) ;
}
/*!
* \ brief Load the module
*
@ -15101,13 +15063,23 @@ static int load_module(void)
return AST_MODULE_LOAD_DECLINE ;
}
poll_list = ao2_container_alloc ( POLL_LIST_BUCKETS , poll_state_hash_fn , poll_state_cmp_fn ) ;
if ( ! poll_list ) {
ast_log ( LOG_ERROR , " Unable to create poll_list container \n " ) ;
ao2_cleanup ( inprocess_container ) ;
return AST_MODULE_LOAD_DECLINE ;
}
res = ao2_container_register ( " voicemail_poll_list " , poll_list , print_poll_state ) ;
if ( res ) {
ast_log ( LOG_ERROR , " Unable to register poll_list container \n " ) ;
ao2_cleanup ( inprocess_container ) ;
ao2_cleanup ( poll_list ) ;
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 ) ;
if ( ! ( mwi_subscription_tps = ast_taskprocessor_get ( " app_voicemail " , 0 ) ) ) {
ast_log ( AST_LOG_WARNING , " failed to reference mwi subscription taskprocessor. MWI will not work \n " ) ;
}
if ( ( res = load_config ( 0 ) ) ) {
unload_module ( ) ;
return AST_MODULE_LOAD_DECLINE ;