@ -1008,7 +1008,7 @@ static struct ast_call_feature builtin_features[] =
} ;
static AST_ LIST_HEAD_STATIC( feature_list , ast_call_feature ) ;
static AST_ RW LIST_HEAD_STATIC( feature_list , ast_call_feature ) ;
/*! \brief register new feature into feature_list*/
void ast_register_feature ( struct ast_call_feature * feature )
@ -1018,12 +1018,13 @@ void ast_register_feature(struct ast_call_feature *feature)
return ;
}
AST_ LIST_LOCK( & feature_list ) ;
AST_ LIST_INSERT_HEAD( & feature_list , feature , feature_entry ) ;
AST_ LIST_UNLOCK( & feature_list ) ;
AST_ RW LIST_WR LOCK( & feature_list ) ;
AST_ RW LIST_INSERT_HEAD( & feature_list , feature , feature_entry ) ;
AST_ RW LIST_UNLOCK( & feature_list ) ;
if ( option_verbose > = 2 )
if ( option_verbose > = 2 ) {
ast_verbose ( VERBOSE_PREFIX_2 " Registered Feature '%s' \n " , feature - > sname ) ;
}
}
/*! \brief unregister feature from feature_list */
@ -1032,9 +1033,10 @@ void ast_unregister_feature(struct ast_call_feature *feature)
if ( ! feature )
return ;
AST_LIST_LOCK ( & feature_list ) ;
AST_LIST_REMOVE ( & feature_list , feature , feature_entry ) ;
AST_LIST_UNLOCK ( & feature_list ) ;
AST_RWLIST_WRLOCK ( & feature_list ) ;
AST_RWLIST_REMOVE ( & feature_list , feature , feature_entry ) ;
AST_RWLIST_UNLOCK ( & feature_list ) ;
free ( feature ) ;
}
@ -1043,10 +1045,11 @@ static void ast_unregister_features(void)
{
struct ast_call_feature * feature ;
AST_ LIST_LOCK( & feature_list ) ;
while ( ( feature = AST_LIST_REMOVE_HEAD ( & feature_list , feature_entry ) ) )
AST_ RW LIST_WR LOCK( & feature_list ) ;
while ( ( feature = AST_LIST_REMOVE_HEAD ( & feature_list , feature_entry ) ) ) {
free ( feature ) ;
AST_LIST_UNLOCK ( & feature_list ) ;
}
AST_RWLIST_UNLOCK ( & feature_list ) ;
}
/*! \brief find a feature by name */
@ -1054,9 +1057,10 @@ static struct ast_call_feature *find_dynamic_feature(const char *name)
{
struct ast_call_feature * tmp ;
AST_ LIST_TRAVERSE( & feature_list , tmp , feature_entry ) {
if ( ! strcasecmp ( tmp - > sname , name ) )
AST_ RW LIST_TRAVERSE( & feature_list , tmp , feature_entry ) {
if ( ! strcasecmp ( tmp - > sname , name ) ) {
break ;
}
}
return tmp ;
@ -1201,9 +1205,9 @@ static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *p
tmp = ast_strdupa ( dynamic_features ) ;
while ( ( tok = strsep ( & tmp , " # " ) ) ) {
AST_ LIST_LOCK( & feature_list ) ;
AST_ RW LIST_RD LOCK( & feature_list ) ;
if ( ! ( feature = find_dynamic_feature ( tok ) ) ) {
AST_ LIST_UNLOCK( & feature_list ) ;
AST_ RW LIST_UNLOCK( & feature_list ) ;
continue ;
}
@ -1213,14 +1217,14 @@ static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *p
ast_verbose ( VERBOSE_PREFIX_3 " Feature Found: %s exten: %s \n " , feature - > sname , tok ) ;
res = feature - > operation ( chan , peer , config , code , sense , feature ) ;
if ( res ! = FEATURE_RETURN_KEEPTRYING ) {
AST_ LIST_UNLOCK( & feature_list ) ;
AST_ RW LIST_UNLOCK( & feature_list ) ;
break ;
}
res = FEATURE_RETURN_PASSDIGITS ;
} else if ( ! strncmp ( feature - > exten , code , strlen ( code ) ) )
res = FEATURE_RETURN_STOREDIGITS ;
AST_ LIST_UNLOCK( & feature_list ) ;
AST_ RW LIST_UNLOCK( & feature_list ) ;
}
return res ;
@ -1255,14 +1259,14 @@ static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer,
/* while we have a feature */
while ( ( tok = strsep ( & tmp , " # " ) ) ) {
AST_ LIST_LOCK( & feature_list ) ;
AST_ RW LIST_RD LOCK( & feature_list ) ;
if ( ( feature = find_dynamic_feature ( tok ) ) & & ast_test_flag ( feature , AST_FEATURE_FLAG_NEEDSDTMF ) ) {
if ( ast_test_flag ( feature , AST_FEATURE_FLAG_BYCALLER ) )
ast_set_flag ( config , AST_BRIDGE_DTMF_CHANNEL_0 ) ;
if ( ast_test_flag ( feature , AST_FEATURE_FLAG_BYCALLEE ) )
ast_set_flag ( config , AST_BRIDGE_DTMF_CHANNEL_1 ) ;
}
AST_ LIST_UNLOCK( & feature_list ) ;
AST_ RW LIST_UNLOCK( & feature_list ) ;
}
}
}
@ -2286,13 +2290,14 @@ static int handle_showfeatures(int fd, int argc, char *argv[])
ast_cli ( fd , " \n " ) ;
ast_cli ( fd , format , " Dynamic Feature " , " Default " , " Current " ) ;
ast_cli ( fd , format , " --------------- " , " ------- " , " ------- " ) ;
if ( AST_ LIST_EMPTY( & feature_list ) )
if ( AST_ RW LIST_EMPTY( & feature_list ) ) {
ast_cli ( fd , " (none) \n " ) ;
else {
AST_LIST_LOCK ( & feature_list ) ;
AST_LIST_TRAVERSE ( & feature_list , feature , feature_entry )
ast_cli ( fd , format , feature - > sname , " no def " , feature - > exten ) ;
AST_LIST_UNLOCK ( & feature_list ) ;
} else {
AST_RWLIST_RDLOCK ( & feature_list ) ;
AST_RWLIST_TRAVERSE ( & feature_list , feature , feature_entry ) {
ast_cli ( fd , format , feature - > sname , " no def " , feature - > exten ) ;
}
AST_RWLIST_UNLOCK ( & feature_list ) ;
}
ast_cli ( fd , " \n Call parking \n " ) ;
ast_cli ( fd , " ------------ \n " ) ;
@ -2646,13 +2651,13 @@ static int load_config(void)
continue ;
}
AST_ LIST_LOCK( & feature_list ) ;
AST_ RW LIST_RD LOCK( & feature_list ) ;
if ( ( feature = find_dynamic_feature ( var - > name ) ) ) {
AST_ LIST_UNLOCK( & feature_list ) ;
AST_ RW LIST_UNLOCK( & feature_list ) ;
ast_log ( LOG_WARNING , " Dynamic Feature '%s' specified more than once! \n " , var - > name ) ;
continue ;
}
AST_ LIST_UNLOCK( & feature_list ) ;
AST_ RW LIST_UNLOCK( & feature_list ) ;
if ( ! ( feature = ast_calloc ( 1 , sizeof ( * feature ) ) ) )
continue ;