@ -12,7 +12,7 @@
* channels for your use .
* channels for your use .
*
*
* This program is free software , distributed under the terms of
* This program is free software , distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree .
* at the top of the source tree .
*/
*/
@ -921,15 +921,18 @@ struct ast_state_cb {
int id ;
int id ;
void * data ;
void * data ;
ast_state_cb_type callback ;
ast_state_cb_type callback ;
/*! \note Only used by ast_merge_contexts_and_delete */
AST_LIST_ENTRY ( ast_state_cb ) entry ;
AST_LIST_ENTRY ( ast_state_cb ) entry ;
} ;
} ;
/*! \brief Structure for dial plan hints
/*!
* \ brief Structure for dial plan hints
\ note Hints are pointers from an extension in the dialplan to one or
*
more devices ( tech / name )
* \ note Hints are pointers from an extension in the dialplan to
- See \ ref AstExtState
* one or more devices ( tech / name )
*/
*
* See \ ref AstExtState
*/
struct ast_hint {
struct ast_hint {
struct ast_exten * exten ; /*!< Extension */
struct ast_exten * exten ; /*!< Extension */
int laststate ; /*!< Last known state */
int laststate ; /*!< Last known state */
@ -1114,12 +1117,12 @@ static void __ast_internal_context_destroy( struct ast_context *con);
static int ast_add_extension_nolock ( const char * context , int replace , const char * extension ,
static int ast_add_extension_nolock ( const char * context , int replace , const char * extension ,
int priority , const char * label , const char * callerid ,
int priority , const char * label , const char * callerid ,
const char * application , void * data , void ( * datad ) ( void * ) , const char * registrar ) ;
const char * application , void * data , void ( * datad ) ( void * ) , const char * registrar ) ;
static int add_pri_lockopt ( struct ast_context * con , struct ast_exten * tmp ,
struct ast_exten * el , struct ast_exten * e , int replace , int lockhints ) ;
static int ast_add_extension2_lockopt ( struct ast_context * con ,
static int ast_add_extension2_lockopt ( struct ast_context * con ,
int replace , const char * extension , int priority , const char * label , const char * callerid ,
int replace , const char * extension , int priority , const char * label , const char * callerid ,
const char * application , void * data , void ( * datad ) ( void * ) ,
const char * application , void * data , void ( * datad ) ( void * ) ,
const char * registrar , int lockconts , int lockhints ) ;
const char * registrar , int lock_context ) ;
static struct ast_context * find_context_locked ( const char * context ) ;
static struct ast_context * find_context ( const char * context ) ;
/* a func for qsort to use to sort a char array */
/* a func for qsort to use to sort a char array */
static int compare_char ( const void * a , const void * b )
static int compare_char ( const void * a , const void * b )
@ -1263,7 +1266,9 @@ static struct pbx_builtin {
static struct ast_context * contexts ;
static struct ast_context * contexts ;
static struct ast_hashtab * contexts_table = NULL ;
static struct ast_hashtab * contexts_table = NULL ;
/*!\brief Lock for the ast_context list
/*!
* \ brief Lock for the ast_context list
* \ note
* This lock MUST be recursive , or a deadlock on reload may result . See
* This lock MUST be recursive , or a deadlock on reload may result . See
* https : //issues.asterisk.org/view.php?id=17643
* https : //issues.asterisk.org/view.php?id=17643
*/
*/
@ -1275,10 +1280,12 @@ static AST_RWLIST_HEAD_STATIC(switches, ast_switch);
static int stateid = 1 ;
static int stateid = 1 ;
/*!
/*!
* \ brief When holding this container ' s lock , do _not_ do anything that will cause conlock
* \ note When holding this container ' s lock , do _not_ do
* to be taken , unless you _already_ hold it . The ast_merge_contexts_and_delete
* anything that will cause conlock to be taken , unless you
* function will take the locks in conlock / hints order , so any other
* _already_ hold it . The ast_merge_contexts_and_delete function
* paths that require both locks must also take them in that order .
* will take the locks in conlock / hints order , so any other
* paths that require both locks must also take them in that
* order .
*/
*/
static struct ao2_container * hints ;
static struct ao2_container * hints ;
@ -1306,8 +1313,6 @@ void check_contexts_trouble(void)
x = 2 ;
x = 2 ;
}
}
static struct ast_context * find_context_locked ( const char * context ) ;
static struct ast_context * find_context ( const char * context ) ;
int check_contexts ( char * , int ) ;
int check_contexts ( char * , int ) ;
int check_contexts ( char * file , int line )
int check_contexts ( char * file , int line )
@ -1353,9 +1358,7 @@ int check_contexts(char *file, int line )
hashtab structure */
hashtab structure */
for ( c2 = contexts ; c2 ; c2 = c2 - > next ) {
for ( c2 = contexts ; c2 ; c2 = c2 - > next ) {
c1 = find_context_locked ( c2 - > name ) ;
c1 = find_context_locked ( c2 - > name ) ;
if ( c1 )
if ( c1 ) {
{
ast_unlock_contexts ( ) ;
ast_unlock_contexts ( ) ;
/* is every entry in the root list also in the root_table? */
/* is every entry in the root list also in the root_table? */
@ -2602,17 +2605,20 @@ struct fake_context /* this struct is purely for matching in the hashtab */
struct ast_context * ast_context_find ( const char * name )
struct ast_context * ast_context_find ( const char * name )
{
{
struct ast_context * tmp = NULL ;
struct ast_context * tmp ;
struct fake_context item ;
struct fake_context item ;
ast_copy_string ( item . name , name , sizeof ( item . name ) ) ;
if ( ! name ) {
return NULL ;
}
ast_rdlock_contexts ( ) ;
ast_rdlock_contexts ( ) ;
if ( contexts_table ) {
if ( contexts_table ) {
tmp = ast_hashtab_lookup ( contexts_table , & item ) ;
ast_copy_string ( item . name , name , sizeof ( item . name ) ) ;
tmp = ast_hashtab_lookup ( contexts_table , & item ) ;
} else {
} else {
while ( ( tmp = ast_walk_contexts ( tmp ) ) ) {
tmp = NULL ;
if ( ! name | | ! strcasecmp ( name , tmp - > name ) ) {
while ( ( tmp = ast_walk_contexts ( tmp ) ) ) {
if ( ! strcasecmp ( name , tmp - > name ) ) {
break ;
break ;
}
}
}
}
@ -2679,11 +2685,7 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
if ( bypass ) { /* bypass means we only look there */
if ( bypass ) { /* bypass means we only look there */
tmp = bypass ;
tmp = bypass ;
} else { /* look in contexts */
} else { /* look in contexts */
struct fake_context item ;
tmp = find_context ( context ) ;
ast_copy_string ( item . name , context , sizeof ( item . name ) ) ;
tmp = ast_hashtab_lookup ( contexts_table , & item ) ;
if ( ! tmp ) {
if ( ! tmp ) {
return NULL ;
return NULL ;
}
}
@ -4387,9 +4389,9 @@ static int handle_statechange(void *datap)
continue ;
continue ;
}
}
hint = device - > hint ;
hint = device - > hint ;
/* Get device state for this hint */
/* Get device state for this hint */
state = ast_extension_state2 ( hint - > exten ) ;
state = ast_extension_state2 ( hint - > exten ) ;
if ( ( state = = - 1 ) | | ( state = = hint - > laststate ) ) {
if ( ( state = = - 1 ) | | ( state = = hint - > laststate ) ) {
ao2_t_ref ( device , - 1 , " no statechange for device " ) ;
ao2_t_ref ( device , - 1 , " no statechange for device " ) ;
continue ;
continue ;
@ -5276,36 +5278,33 @@ void pbx_set_overrideswitch(const char *newval)
/*!
/*!
* \ brief lookup for a context with a given name ,
* \ brief lookup for a context with a given name ,
* \ retval found context or NULL if not found .
* \ retval found context or NULL if not found .
*/
*/
static struct ast_context * find_context ( const char * context )
static struct ast_context * find_context ( const char * context )
{
{
struct ast_context * c = NULL ;
struct fake_context item ;
struct fake_context item ;
ast_copy_string ( item . name , context , sizeof ( item . name ) ) ;
ast_copy_string ( item . name , context , sizeof ( item . name ) ) ;
c = ast_hashtab_lookup ( contexts_table , & item ) ;
return ast_hashtab_lookup ( contexts_table , & item ) ;
return c ;
}
}
/*!
/*!
* \ brief lookup for a context with a given name ,
* \ brief lookup for a context with a given name ,
* \ retval with conlock held if found .
* \ retval with conlock held if found .
* \ retval NULL if not found .
* \ retval NULL if not found .
*/
*/
static struct ast_context * find_context_locked ( const char * context )
static struct ast_context * find_context_locked ( const char * context )
{
{
struct ast_context * c = NULL ;
struct ast_context * c ;
struct fake_context item ;
struct fake_context item ;
ast_copy_string ( item . name , context , sizeof ( item . name ) ) ;
ast_copy_string ( item . name , context , sizeof ( item . name ) ) ;
ast_rdlock_contexts ( ) ;
ast_rdlock_contexts ( ) ;
c = ast_hashtab_lookup ( contexts_table , & item ) ;
c = ast_hashtab_lookup ( contexts_table , & item ) ;
if ( ! c ) {
if ( ! c )
ast_unlock_contexts ( ) ;
ast_unlock_contexts ( ) ;
}
return c ;
return c ;
}
}
@ -5315,12 +5314,13 @@ static struct ast_context *find_context_locked(const char *context)
* This function locks contexts list by & conlist , search for the right context
* This function locks contexts list by & conlist , search for the right context
* structure , leave context list locked and call ast_context_remove_include2
* structure , leave context list locked and call ast_context_remove_include2
* which removes include , unlock contexts list and return . . .
* which removes include , unlock contexts list and return . . .
*/
*/
int ast_context_remove_include ( const char * context , const char * include , const char * registrar )
int ast_context_remove_include ( const char * context , const char * include , const char * registrar )
{
{
int ret = - 1 ;
int ret = - 1 ;
struct ast_context * c = find_context_locked ( context ) ;
struct ast_context * c ;
c = find_context_locked ( context ) ;
if ( c ) {
if ( c ) {
/* found, remove include from this context ... */
/* found, remove include from this context ... */
ret = ast_context_remove_include2 ( c , include , registrar ) ;
ret = ast_context_remove_include2 ( c , include , registrar ) ;
@ -5376,8 +5376,9 @@ int ast_context_remove_include2(struct ast_context *con, const char *include, co
int ast_context_remove_switch ( const char * context , const char * sw , const char * data , const char * registrar )
int ast_context_remove_switch ( const char * context , const char * sw , const char * data , const char * registrar )
{
{
int ret = - 1 ; /* default error return */
int ret = - 1 ; /* default error return */
struct ast_context * c = find_context_locked ( context ) ;
struct ast_context * c ;
c = find_context_locked ( context ) ;
if ( c ) {
if ( c ) {
/* remove switch from this context ... */
/* remove switch from this context ... */
ret = ast_context_remove_switch2 ( c , sw , data , registrar ) ;
ret = ast_context_remove_switch2 ( c , sw , data , registrar ) ;
@ -5420,11 +5421,7 @@ int ast_context_remove_switch2(struct ast_context *con, const char *sw, const ch
return ret ;
return ret ;
}
}
/*
/*! \note This function will lock conlock. */
* \ note This functions lock contexts list , search for the right context ,
* call ast_context_remove_extension2 , unlock contexts list and return .
* In this function we are using
*/
int ast_context_remove_extension ( const char * context , const char * extension , int priority , const char * registrar )
int ast_context_remove_extension ( const char * context , const char * extension , int priority , const char * registrar )
{
{
return ast_context_remove_extension_callerid ( context , extension , priority , NULL , 0 , registrar ) ;
return ast_context_remove_extension_callerid ( context , extension , priority , NULL , 0 , registrar ) ;
@ -5433,12 +5430,15 @@ int ast_context_remove_extension(const char *context, const char *extension, int
int ast_context_remove_extension_callerid ( const char * context , const char * extension , int priority , const char * callerid , int matchcallerid , const char * registrar )
int ast_context_remove_extension_callerid ( const char * context , const char * extension , int priority , const char * callerid , int matchcallerid , const char * registrar )
{
{
int ret = - 1 ; /* default error return */
int ret = - 1 ; /* default error return */
struct ast_context * c = find_context_locked ( context ) ;
struct ast_context * c ;
c = find_context_locked ( context ) ;
if ( c ) { /* ... remove extension ... */
if ( c ) { /* ... remove extension ... */
ret = ast_context_remove_extension_callerid2 ( c , extension , priority , callerid , matchcallerid , registrar , 1 ) ;
ret = ast_context_remove_extension_callerid2 ( c , extension , priority , callerid ,
matchcallerid , registrar , 0 ) ;
ast_unlock_contexts ( ) ;
ast_unlock_contexts ( ) ;
}
}
return ret ;
return ret ;
}
}
@ -5619,21 +5619,14 @@ int ast_context_remove_extension_callerid2(struct ast_context *con, const char *
*/
*/
int ast_context_lockmacro ( const char * context )
int ast_context_lockmacro ( const char * context )
{
{
struct ast_context * c = NULL ;
struct ast_context * c ;
int ret = - 1 ;
int ret = - 1 ;
struct fake_context item ;
ast_rdlock_contexts ( ) ;
ast_copy_string ( item . name , context , sizeof ( item . name ) ) ;
c = ast_hashtab_lookup ( contexts_table , & item ) ;
c = find_context_locked ( context ) ;
if ( c )
if ( c ) {
ret = 0 ;
ast_unlock_contexts ( ) ;
ast_unlock_contexts ( ) ;
/* if we found context, lock macrolock */
/* if we found context, lock macrolock */
if ( ret = = 0 ) {
ret = ast_mutex_lock ( & c - > macrolock ) ;
ret = ast_mutex_lock ( & c - > macrolock ) ;
}
}
@ -5647,21 +5640,14 @@ int ast_context_lockmacro(const char *context)
*/
*/
int ast_context_unlockmacro ( const char * context )
int ast_context_unlockmacro ( const char * context )
{
{
struct ast_context * c = NULL ;
struct ast_context * c ;
int ret = - 1 ;
int ret = - 1 ;
struct fake_context item ;
ast_rdlock_contexts ( ) ;
ast_copy_string ( item . name , context , sizeof ( item . name ) ) ;
c = ast_hashtab_lookup ( contexts_table , & item ) ;
c = find_context_locked ( context ) ;
if ( c )
if ( c ) {
ret = 0 ;
ast_unlock_contexts ( ) ;
ast_unlock_contexts ( ) ;
/* if we found context, unlock macrolock */
/* if we found context, unlock macrolock */
if ( ret = = 0 ) {
ret = ast_mutex_unlock ( & c - > macrolock ) ;
ret = ast_mutex_unlock ( & c - > macrolock ) ;
}
}
@ -5955,8 +5941,8 @@ static char *handle_show_hints(struct ast_cli_entry *e, int cmd, struct ast_cli_
ast_extension_state2str ( hint - > laststate ) , watchers ) ;
ast_extension_state2str ( hint - > laststate ) , watchers ) ;
num + + ;
num + + ;
}
}
ao2_iterator_destroy ( & i ) ;
ao2_iterator_destroy ( & i ) ;
ast_cli ( a - > fd , " ---------------- \n " ) ;
ast_cli ( a - > fd , " ---------------- \n " ) ;
ast_cli ( a - > fd , " - %d hints registered \n " , num ) ;
ast_cli ( a - > fd , " - %d hints registered \n " , num ) ;
return CLI_SUCCESS ;
return CLI_SUCCESS ;
@ -7214,7 +7200,8 @@ static void context_merge(struct ast_context **extcontexts, struct ast_hashtab *
void ast_merge_contexts_and_delete ( struct ast_context * * extcontexts , struct ast_hashtab * exttable , const char * registrar )
void ast_merge_contexts_and_delete ( struct ast_context * * extcontexts , struct ast_hashtab * exttable , const char * registrar )
{
{
double ft ;
double ft ;
struct ast_context * tmp , * oldcontextslist ;
struct ast_context * tmp ;
struct ast_context * oldcontextslist ;
struct ast_hashtab * oldtable ;
struct ast_hashtab * oldtable ;
struct store_hints store = AST_LIST_HEAD_INIT_VALUE ;
struct store_hints store = AST_LIST_HEAD_INIT_VALUE ;
struct store_hint * this ;
struct store_hint * this ;
@ -7224,18 +7211,23 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_
struct ast_state_cb * thiscb ;
struct ast_state_cb * thiscb ;
struct ast_hashtab_iter * iter ;
struct ast_hashtab_iter * iter ;
struct ao2_iterator i ;
struct ao2_iterator i ;
struct timeval begintime ;
struct timeval writelocktime ;
struct timeval endlocktime ;
struct timeval enddeltime ;
/* it is very important that this function hold the hint list lock _and_ the conlock
/*
during its operation ; not only do we need to ensure that the list of contexts
* It is very important that this function hold the hints
and extensions does not change , but also that no hint callbacks ( watchers ) are
* container lock _and_ the conlock during its operation ; not
added or removed during the merge / delete process
* only do we need to ensure that the list of contexts and
* extensions does not change , but also that no hint callbacks
in addition , the locks _must_ be taken in this order , because there are already
* ( watchers ) are added or removed during the merge / delete
other code paths that use this order
* process
*
* In addition , the locks _must_ be taken in this order , because
* there are already other code paths that use this order
*/
*/
struct timeval begintime , writelocktime , endlocktime , enddeltime ;
begintime = ast_tvnow ( ) ;
begintime = ast_tvnow ( ) ;
ast_rdlock_contexts ( ) ;
ast_rdlock_contexts ( ) ;
iter = ast_hashtab_start_traversal ( contexts_table ) ;
iter = ast_hashtab_start_traversal ( contexts_table ) ;
@ -7330,13 +7322,17 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_
ast_unlock_contexts ( ) ;
ast_unlock_contexts ( ) ;
endlocktime = ast_tvnow ( ) ;
endlocktime = ast_tvnow ( ) ;
/* the old list and hashtab no longer are relevant, delete them while the rest of asterisk
/*
is now freely using the new stuff instead */
* The old list and hashtab no longer are relevant , delete them
* while the rest of asterisk is now freely using the new stuff
* instead .
*/
ast_hashtab_destroy ( oldtable , NULL ) ;
ast_hashtab_destroy ( oldtable , NULL ) ;
for ( tmp = oldcontextslist ; tmp ; ) {
for ( tmp = oldcontextslist ; tmp ; ) {
struct ast_context * next ; /* next starting point */
struct ast_context * next ; /* next starting point */
next = tmp - > next ;
next = tmp - > next ;
__ast_internal_context_destroy ( tmp ) ;
__ast_internal_context_destroy ( tmp ) ;
tmp = next ;
tmp = next ;
@ -7358,7 +7354,6 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_
ft = ast_tvdiff_us ( enddeltime , begintime ) ;
ft = ast_tvdiff_us ( enddeltime , begintime ) ;
ft / = 1000000.0 ;
ft / = 1000000.0 ;
ast_verb ( 3 , " Total time merge_contexts_delete: %8.6f sec \n " , ft ) ;
ast_verb ( 3 , " Total time merge_contexts_delete: %8.6f sec \n " , ft ) ;
return ;
}
}
/*
/*
@ -7369,8 +7364,9 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_
int ast_context_add_include ( const char * context , const char * include , const char * registrar )
int ast_context_add_include ( const char * context , const char * include , const char * registrar )
{
{
int ret = - 1 ;
int ret = - 1 ;
struct ast_context * c = find_context_locked ( context ) ;
struct ast_context * c ;
c = find_context_locked ( context ) ;
if ( c ) {
if ( c ) {
ret = ast_context_add_include2 ( c , include , registrar ) ;
ret = ast_context_add_include2 ( c , include , registrar ) ;
ast_unlock_contexts ( ) ;
ast_unlock_contexts ( ) ;
@ -7700,8 +7696,9 @@ int ast_context_add_include2(struct ast_context *con, const char *value,
int ast_context_add_switch ( const char * context , const char * sw , const char * data , int eval , const char * registrar )
int ast_context_add_switch ( const char * context , const char * sw , const char * data , int eval , const char * registrar )
{
{
int ret = - 1 ;
int ret = - 1 ;
struct ast_context * c = find_context_locked ( context ) ;
struct ast_context * c ;
c = find_context_locked ( context ) ;
if ( c ) { /* found, add switch to this context */
if ( c ) { /* found, add switch to this context */
ret = ast_context_add_switch2 ( c , sw , data , eval , registrar ) ;
ret = ast_context_add_switch2 ( c , sw , data , eval , registrar ) ;
ast_unlock_contexts ( ) ;
ast_unlock_contexts ( ) ;
@ -7779,8 +7776,9 @@ int ast_context_add_switch2(struct ast_context *con, const char *value,
int ast_context_remove_ignorepat ( const char * context , const char * ignorepat , const char * registrar )
int ast_context_remove_ignorepat ( const char * context , const char * ignorepat , const char * registrar )
{
{
int ret = - 1 ;
int ret = - 1 ;
struct ast_context * c = find_context_locked ( context ) ;
struct ast_context * c ;
c = find_context_locked ( context ) ;
if ( c ) {
if ( c ) {
ret = ast_context_remove_ignorepat2 ( c , ignorepat , registrar ) ;
ret = ast_context_remove_ignorepat2 ( c , ignorepat , registrar ) ;
ast_unlock_contexts ( ) ;
ast_unlock_contexts ( ) ;
@ -7822,8 +7820,9 @@ int ast_context_remove_ignorepat2(struct ast_context *con, const char *ignorepat
int ast_context_add_ignorepat ( const char * context , const char * value , const char * registrar )
int ast_context_add_ignorepat ( const char * context , const char * value , const char * registrar )
{
{
int ret = - 1 ;
int ret = - 1 ;
struct ast_context * c = find_context_locked ( context ) ;
struct ast_context * c ;
c = find_context_locked ( context ) ;
if ( c ) {
if ( c ) {
ret = ast_context_add_ignorepat2 ( c , value , registrar ) ;
ret = ast_context_add_ignorepat2 ( c , value , registrar ) ;
ast_unlock_contexts ( ) ;
ast_unlock_contexts ( ) ;
@ -7872,8 +7871,10 @@ int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const
int ast_ignore_pattern ( const char * context , const char * pattern )
int ast_ignore_pattern ( const char * context , const char * pattern )
{
{
struct ast_context * con = ast_context_find ( context ) ;
struct ast_context * con = ast_context_find ( context ) ;
if ( con ) {
if ( con ) {
struct ast_ignorepat * pat ;
struct ast_ignorepat * pat ;
for ( pat = con - > ignorepats ; pat ; pat = pat - > next ) {
for ( pat = con - > ignorepats ; pat ; pat = pat - > next ) {
if ( ast_extension_match ( pat - > pattern , pattern ) )
if ( ast_extension_match ( pat - > pattern , pattern ) )
return 1 ;
return 1 ;
@ -7893,11 +7894,12 @@ static int ast_add_extension_nolock(const char *context, int replace, const char
const char * application , void * data , void ( * datad ) ( void * ) , const char * registrar )
const char * application , void * data , void ( * datad ) ( void * ) , const char * registrar )
{
{
int ret = - 1 ;
int ret = - 1 ;
struct ast_context * c = find_context ( context ) ;
struct ast_context * c ;
c = find_context ( context ) ;
if ( c ) {
if ( c ) {
ret = ast_add_extension2_lockopt ( c , replace , extension , priority , label , callerid ,
ret = ast_add_extension2_lockopt ( c , replace , extension , priority , label , callerid ,
application , data , datad , registrar , 0, 0 ) ;
application , data , datad , registrar , 1 ) ;
}
}
return ret ;
return ret ;
@ -7912,8 +7914,9 @@ int ast_add_extension(const char *context, int replace, const char *extension,
const char * application , void * data , void ( * datad ) ( void * ) , const char * registrar )
const char * application , void * data , void ( * datad ) ( void * ) , const char * registrar )
{
{
int ret = - 1 ;
int ret = - 1 ;
struct ast_context * c = find_context_locked ( context ) ;
struct ast_context * c ;
c = find_context_locked ( context ) ;
if ( c ) {
if ( c ) {
ret = ast_add_extension2 ( c , replace , extension , priority , label , callerid ,
ret = ast_add_extension2 ( c , replace , extension , priority , label , callerid ,
application , data , datad , registrar ) ;
application , data , datad , registrar ) ;
@ -8071,19 +8074,8 @@ static int ext_strncpy(char *dst, const char *src, int len)
* \ retval 0 on success .
* \ retval 0 on success .
* \ retval - 1 on failure .
* \ retval - 1 on failure .
*/
*/
static int add_pri ( struct ast_context * con , struct ast_exten * tmp ,
static int add_pri ority ( struct ast_context * con , struct ast_exten * tmp ,
struct ast_exten * el , struct ast_exten * e , int replace )
struct ast_exten * el , struct ast_exten * e , int replace )
{
return add_pri_lockopt ( con , tmp , el , e , replace , 1 ) ;
}
/*!
* \ brief add the extension in the priority chain .
* \ retval 0 on success .
* \ retval - 1 on failure .
*/
static int add_pri_lockopt ( struct ast_context * con , struct ast_exten * tmp ,
struct ast_exten * el , struct ast_exten * e , int replace , int lockhints )
{
{
struct ast_exten * ep ;
struct ast_exten * ep ;
struct ast_exten * eh = e ;
struct ast_exten * eh = e ;
@ -8220,11 +8212,7 @@ static int add_pri_lockopt(struct ast_context *con, struct ast_exten *tmp,
}
}
/* And immediately return success. */
/* And immediately return success. */
if ( tmp - > priority = = PRIORITY_HINT ) {
if ( tmp - > priority = = PRIORITY_HINT ) {
if ( lockhints ) {
ast_add_hint ( tmp ) ;
ast_add_hint ( tmp ) ;
} else {
ast_add_hint ( tmp ) ;
}
}
}
}
}
return 0 ;
return 0 ;
@ -8260,18 +8248,21 @@ int ast_add_extension2(struct ast_context *con,
const char * application , void * data , void ( * datad ) ( void * ) ,
const char * application , void * data , void ( * datad ) ( void * ) ,
const char * registrar )
const char * registrar )
{
{
return ast_add_extension2_lockopt ( con , replace , extension , priority , label , callerid , application , data , datad , registrar , 1 , 1 ) ;
return ast_add_extension2_lockopt ( con , replace , extension , priority , label , callerid ,
application , data , datad , registrar , 1 ) ;
}
}
/*! \brief
/*!
* Does all the work of ast_add_extension2 , but adds two args , to determine if
* \ brief Same as ast_add_extension2 ( ) but controls the context locking .
* context and hint locking should be done . In merge_and_delete , we need to do
*
* this without locking , as the locks are already held .
* \ details
* Does all the work of ast_add_extension2 , but adds an arg to
* determine if context locking should be done .
*/
*/
static int ast_add_extension2_lockopt ( struct ast_context * con ,
static int ast_add_extension2_lockopt ( struct ast_context * con ,
int replace , const char * extension , int priority , const char * label , const char * callerid ,
int replace , const char * extension , int priority , const char * label , const char * callerid ,
const char * application , void * data , void ( * datad ) ( void * ) ,
const char * application , void * data , void ( * datad ) ( void * ) ,
const char * registrar , int lock conts, int lockhints )
const char * registrar , int lock _context )
{
{
/*
/*
* Sort extensions ( or patterns ) according to the rules indicated above .
* Sort extensions ( or patterns ) according to the rules indicated above .
@ -8348,7 +8339,7 @@ static int ast_add_extension2_lockopt(struct ast_context *con,
tmp - > datad = datad ;
tmp - > datad = datad ;
tmp - > registrar = registrar ;
tmp - > registrar = registrar ;
if ( lock conts ) {
if ( lock _context ) {
ast_wrlock_context ( con ) ;
ast_wrlock_context ( con ) ;
}
}
@ -8381,9 +8372,9 @@ static int ast_add_extension2_lockopt(struct ast_context *con,
if ( res > = 0 )
if ( res > = 0 )
break ;
break ;
}
}
if ( e & & res = = 0 ) { /* exact match, insert in the pri chain */
if ( e & & res = = 0 ) { /* exact match, insert in the pri ority chain */
res = add_pri ( con , tmp , el , e , replace ) ;
res = add_pri ority ( con , tmp , el , e , replace ) ;
if ( lock conts ) {
if ( lock _context ) {
ast_unlock_context ( con ) ;
ast_unlock_context ( con ) ;
}
}
if ( res < 0 ) {
if ( res < 0 ) {
@ -8442,15 +8433,11 @@ static int ast_add_extension2_lockopt(struct ast_context *con,
}
}
ast_hashtab_insert_safe ( con - > root_table , tmp ) ;
ast_hashtab_insert_safe ( con - > root_table , tmp ) ;
if ( lock conts ) {
if ( lock _context ) {
ast_unlock_context ( con ) ;
ast_unlock_context ( con ) ;
}
}
if ( tmp - > priority = = PRIORITY_HINT ) {
if ( tmp - > priority = = PRIORITY_HINT ) {
if ( lockhints ) {
ast_add_hint ( tmp ) ;
ast_add_hint ( tmp ) ;
} else {
ast_add_hint ( tmp ) ;
}
}
}
}
}
if ( option_debug ) {
if ( option_debug ) {
@ -10102,17 +10089,17 @@ int load_pbx(void)
/*
/*
* Lock context list functions . . .
* Lock context list functions . . .
*/
*/
int ast_wrlock_contexts ( )
int ast_wrlock_contexts ( void )
{
{
return ast_mutex_lock ( & conlock ) ;
return ast_mutex_lock ( & conlock ) ;
}
}
int ast_rdlock_contexts ( )
int ast_rdlock_contexts ( void )
{
{
return ast_mutex_lock ( & conlock ) ;
return ast_mutex_lock ( & conlock ) ;
}
}
int ast_unlock_contexts ( )
int ast_unlock_contexts ( void )
{
{
return ast_mutex_unlock ( & conlock ) ;
return ast_mutex_unlock ( & conlock ) ;
}
}