@ -255,17 +255,6 @@ struct ast_exten {
char stuff [ 0 ] ;
} ;
/*! \brief ast_include: include= support in extensions.conf */
struct ast_include {
const char * name ;
const char * rname ; /*!< Context to include */
const char * registrar ; /*!< Registrar */
int hastime ; /*!< If time construct exists */
struct ast_timing timing ; /*!< time construct */
struct ast_include * next ; /*!< Link them together */
char stuff [ 0 ] ;
} ;
/*! \brief ast_sw: Switch statement in extensions.conf */
struct ast_sw {
char * name ;
@ -313,7 +302,7 @@ struct ast_context {
struct ast_hashtab * root_table ; /*!< For exact matches on the extensions in the pattern tree, and for traversals of the pattern_tree */
struct match_char * pattern_tree ; /*!< A tree to speed up extension pattern matching */
struct ast_context * next ; /*!< Link them together */
struct ast_include * includes ; /*!< Include other contexts */
struct ast_include s includes ; /*!< Include other contexts */
struct ast_ignorepat * ignorepats ; /*!< Patterns for which to continue playing dialtone */
char * registrar ; /*!< Registrar -- make sure you malloc this, as the registrar may have to survive module unloads */
int refcount ; /*!< each module that would have created this context should inc/dec this as appropriate */
@ -1001,14 +990,6 @@ int check_contexts(char *file, int line )
}
# endif
static inline int include_valid ( struct ast_include * i )
{
if ( ! i - > hastime )
return 1 ;
return ast_check_timing ( & ( i - > timing ) ) ;
}
static void pbx_destroy ( struct ast_pbx * p )
{
ast_free ( p ) ;
@ -2399,7 +2380,7 @@ struct fake_context /* this struct is purely for matching in the hashtab */
struct ast_hashtab * root_table ;
struct match_char * pattern_tree ;
struct ast_context * next ;
struct ast_include * includes ;
struct ast_include s includes ;
struct ast_ignorepat * ignorepats ;
const char * registrar ;
int refcount ;
@ -2459,11 +2440,11 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
int x , res ;
struct ast_context * tmp = NULL ;
struct ast_exten * e = NULL , * eroot = NULL ;
struct ast_include * i = NULL ;
struct ast_sw * sw = NULL ;
struct ast_exten pattern = { NULL , } ;
struct scoreboard score = { 0 , } ;
struct ast_str * tmpdata = NULL ;
int idx ;
pattern . label = label ;
pattern . priority = priority ;
@ -2729,9 +2710,11 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
}
q - > incstack [ q - > stacklen + + ] = tmp - > name ; /* Setup the stack */
/* Now try any includes we have in this context */
for ( i = tmp - > includes ; i ; i = i - > next ) {
for ( idx = 0 ; idx < ast_context_includes_count ( tmp ) ; idx + + ) {
const struct ast_include * i = ast_context_includes_get ( tmp , idx ) ;
if ( include_valid ( i ) ) {
if ( ( e = pbx_find_extension ( chan , bypass , q , i - > rname , exten , priority , label , callerid , action ) ) ) {
if ( ( e = pbx_find_extension ( chan , bypass , q , include_rname ( i ) , exten , priority , label , callerid , action ) ) ) {
# ifdef NEED_DEBUG_HERE
ast_log ( LOG_NOTICE , " Returning recursive match of %s \n " , e - > exten ) ;
# endif
@ -4755,13 +4738,6 @@ static struct ast_context *find_context_locked(const char *context)
return c ;
}
/*! \brief Free an ast_include and associated data. */
static void include_free ( struct ast_include * include )
{
ast_destroy_timing ( & ( include - > timing ) ) ;
ast_free ( include ) ;
}
/*!
* \ brief Remove included contexts .
* This function locks contexts list by & conlist , search for the right context
@ -4793,21 +4769,22 @@ int ast_context_remove_include(const char *context, const char *include, const c
*/
int ast_context_remove_include2 ( struct ast_context * con , const char * include , const char * registrar )
{
struct ast_include * i , * pi = NULL ;
int ret = - 1 ;
int idx ;
ast_wrlock_context ( con ) ;
/* find our include */
for ( i = con - > includes ; i ; pi = i , i = i - > next ) {
if ( ! strcmp ( i - > name , include ) & &
( ! registrar | | ! strcmp ( i - > registrar , registrar ) ) ) {
for ( idx = 0 ; idx < ast_context_includes_count ( con ) ; idx + + ) {
struct ast_include * i = AST_VECTOR_GET ( & con - > includes , idx ) ;
if ( ! strcmp ( ast_get_include_name ( i ) , include ) & &
( ! registrar | | ! strcmp ( ast_get_include_registrar ( i ) , registrar ) ) ) {
/* remove from list */
ast_verb ( 3 , " Removing inclusion of context '%s' in context '%s; registrar=%s' \n " , include , ast_get_context_name ( con ) , registrar ) ;
if ( pi )
pi - > next = i - > next ;
else
con - > includes = i - > next ;
AST_VECTOR_REMOVE_ORDERED ( & con - > includes , idx ) ;
/* free include and return */
include_free ( i ) ;
ret = 0 ;
@ -5406,7 +5383,7 @@ static void print_ext(struct ast_exten *e, char * buf, int buflen)
}
/* XXX not verified */
static int show_dialplan_helper ( int fd , const char * context , const char * exten , struct dialplan_counters * dpc , struct ast_include * rinclude , int includecount , const char * includes [ ] )
static int show_dialplan_helper ( int fd , const char * context , const char * exten , struct dialplan_counters * dpc , const struct ast_include * rinclude , int includecount , const char * includes [ ] )
{
struct ast_context * c = NULL ;
int res = 0 , old_total_exten = dpc - > total_exten ;
@ -5415,8 +5392,8 @@ static int show_dialplan_helper(int fd, const char *context, const char *exten,
/* walk all contexts ... */
while ( ( c = ast_walk_contexts ( c ) ) ) {
int idx ;
struct ast_exten * e ;
struct ast_include * i ;
struct ast_ignorepat * ip ;
# ifndef LOW_MEMORY
char buf [ 1024 ] , buf2 [ 1024 ] ;
@ -5504,8 +5481,9 @@ static int show_dialplan_helper(int fd, const char *context, const char *exten,
}
/* walk included and write info ... */
i = NULL ;
while ( ( i = ast_walk_context_includes ( c , i ) ) ) {
for ( idx = 0 ; idx < ast_context_includes_count ( c ) ; idx + + ) {
const struct ast_include * i = ast_context_includes_get ( c , idx ) ;
snprintf ( buf , sizeof ( buf ) , " '%s' " , ast_get_include_name ( i ) ) ;
if ( exten ) {
/* Check all includes for the requested extension */
@ -5757,7 +5735,7 @@ static void manager_dpsendack(struct mansession *s, const struct message *m)
static int manager_show_dialplan_helper ( struct mansession * s , const struct message * m ,
const char * actionidtext , const char * context ,
const char * exten , struct dialplan_counters * dpc ,
struct ast_include * rinclude )
const struct ast_include * rinclude )
{
struct ast_context * c ;
int res = 0 , old_total_exten = dpc - > total_exten ;
@ -5778,8 +5756,8 @@ static int manager_show_dialplan_helper(struct mansession *s, const struct messa
c = NULL ; /* walk all contexts ... */
while ( ( c = ast_walk_contexts ( c ) ) ) {
int idx ;
struct ast_exten * e ;
struct ast_include * i ;
struct ast_ignorepat * ip ;
if ( context & & strcmp ( ast_get_context_name ( c ) , context ) ! = 0 )
@ -5835,8 +5813,9 @@ static int manager_show_dialplan_helper(struct mansession *s, const struct messa
}
}
i = NULL ; /* walk included and write info ... */
while ( ( i = ast_walk_context_includes ( c , i ) ) ) {
for ( idx = 0 ; idx < ast_context_includes_count ( c ) ; idx + + ) {
const struct ast_include * i = ast_context_includes_get ( c , idx ) ;
if ( exten ) {
/* Check all includes for the requested extension */
manager_show_dialplan_helper ( s , m , actionidtext , ast_get_include_name ( i ) , exten , dpc , i ) ;
@ -6114,7 +6093,7 @@ struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts,
tmp - > root = NULL ;
tmp - > root_table = NULL ;
tmp - > registrar = ast_strdup ( registrar ) ;
tmp - > includes = NULL ;
AST_VECTOR_INIT ( & tmp - > includes , 0 ) ;
tmp - > ignorepats = NULL ;
tmp - > refcount = 1 ;
} else {
@ -6166,16 +6145,19 @@ AST_LIST_HEAD_NOLOCK(store_hints, store_hint);
static void context_merge_incls_swits_igps_other_registrars ( struct ast_context * new , struct ast_context * old , const char * registrar )
{
struct ast_include * i ;
int idx ;
struct ast_ignorepat * ip ;
struct ast_sw * sw ;
ast_verb ( 3 , " merging incls/swits/igpats from old(%s) to new(%s) context, registrar = %s \n " , ast_get_context_name ( old ) , ast_get_context_name ( new ) , registrar ) ;
/* copy in the includes, switches, and ignorepats */
/* walk through includes */
for ( i = NULL ; ( i = ast_walk_context_includes ( old , i ) ) ; ) {
if ( strcmp ( ast_get_include_registrar ( i ) , registrar ) = = 0 )
for ( idx = 0 ; idx < ast_context_includes_count ( old ) ; idx + + ) {
const struct ast_include * i = ast_context_includes_get ( old , idx ) ;
if ( ! strcmp ( ast_get_include_registrar ( i ) , registrar ) ) {
continue ; /* not mine */
}
ast_context_add_include2 ( new , ast_get_include_name ( i ) , ast_get_include_registrar ( i ) ) ;
}
@ -6586,53 +6568,32 @@ int ast_context_add_include2(struct ast_context *con, const char *value,
const char * registrar )
{
struct ast_include * new_include ;
char * c ;
struct ast_include * i , * il = NULL ; /* include, include_last */
int length ;
char * p ;
length = sizeof ( struct ast_include ) ;
length + = 2 * ( strlen ( value ) + 1 ) ;
int idx ;
/* allocate new include structure ... */
if ( ! ( new_include = ast_calloc ( 1 , length ) ) )
new_include = include_alloc ( value , registrar ) ;
if ( ! new_include ) {
return - 1 ;
/* Fill in this structure. Use 'p' for assignments, as the fields
* in the structure are ' const char * '
*/
p = new_include - > stuff ;
new_include - > name = p ;
strcpy ( p , value ) ;
p + = strlen ( value ) + 1 ;
new_include - > rname = p ;
strcpy ( p , value ) ;
/* Strip off timing info, and process if it is there */
if ( ( c = strchr ( p , ' , ' ) ) ) {
* c + + = ' \0 ' ;
new_include - > hastime = ast_build_timing ( & ( new_include - > timing ) , c ) ;
}
new_include - > next = NULL ;
new_include - > registrar = registrar ;
ast_wrlock_context ( con ) ;
/* ... go to last include and check if context is already included too... */
for ( i = con - > includes ; i ; i = i - > next ) {
if ( ! strcasecmp ( i - > name , new_include - > name ) ) {
for ( idx = 0 ; idx < ast_context_includes_count ( con ) ; idx + + ) {
const struct ast_include * i = ast_context_includes_get ( con , idx ) ;
if ( ! strcasecmp ( ast_get_include_name ( i ) , ast_get_include_name ( new_include ) ) ) {
include_free ( new_include ) ;
ast_unlock_context ( con ) ;
errno = EEXIST ;
return - 1 ;
}
il = i ;
}
/* ... include new context into context list, unlock, return */
if ( il )
il - > next = new_include ;
else
con - > includes = new_include ;
ast_verb ( 3 , " Including context '%s' in context '%s' \n " , new_include - > name , ast_get_context_name ( con ) ) ;
AST_VECTOR_APPEND ( & con - > includes , new_include ) ;
ast_verb ( 3 , " Including context '%s' in context '%s' \n " ,
ast_get_include_name ( new_include ) , ast_get_context_name ( con ) ) ;
ast_unlock_context ( con ) ;
@ -7834,17 +7795,15 @@ int ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, const cha
static void __ast_internal_context_destroy ( struct ast_context * con )
{
struct ast_include * tmpi ;
struct ast_sw * sw ;
struct ast_exten * e , * el , * en ;
struct ast_ignorepat * ipi ;
struct ast_context * tmp = con ;
for ( tmpi = tmp - > includes ; tmpi ; ) { /* Free includes */
struct ast_include * tmpil = tmpi ;
tmpi = tmpi - > next ;
include_free ( tmpil ) ;
}
/* Free includes */
AST_VECTOR_CALLBACK_VOID ( & tmp - > includes , include_free ) ;
AST_VECTOR_FREE ( & tmp - > includes ) ;
for ( ipi = tmp - > ignorepats ; ipi ; ) { /* Free ignorepats */
struct ast_ignorepat * ipl = ipi ;
ipi = ipi - > next ;
@ -7910,8 +7869,8 @@ void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *context
struct ast_hashtab_iter * exten_iter ;
struct ast_hashtab_iter * prio_iter ;
struct ast_ignorepat * ip , * ipl = NULL , * ipn = NULL ;
struct ast_include * i , * pi = NULL , * ni = NULL ;
struct ast_sw * sw = NULL ;
int idx ;
/* remove any ignorepats whose registrar matches */
for ( ip = tmp - > ignorepats ; ip ; ip = ipn ) {
@ -7930,23 +7889,13 @@ void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *context
ipl = ip ;
}
/* remove any includes whose registrar matches */
for ( i = tmp - > includes ; i ; i = ni ) {
ni = i - > next ;
if ( strcmp ( i - > registrar , registrar ) = = 0 ) {
/* remove from list */
if ( pi ) {
pi - > next = i - > next ;
/* free include */
include_free ( i ) ;
continue ; /* don't change pi */
} else {
tmp - > includes = i - > next ;
/* free include */
include_free ( i ) ;
continue ; /* don't change pi */
}
for ( idx = ast_context_includes_count ( tmp ) - 1 ; idx > = 0 ; idx - - ) {
struct ast_include * i = AST_VECTOR_GET ( & tmp - > includes , idx ) ;
if ( ! strcmp ( ast_get_include_registrar ( i ) , registrar ) ) {
AST_VECTOR_REMOVE_ORDERED ( & tmp - > includes , idx ) ;
include_free ( i ) ;
}
pi = i ;
}
/* remove any switches whose registrar matches */
AST_LIST_TRAVERSE_SAFE_BEGIN ( & tmp - > alts , sw , list ) {
@ -8006,7 +7955,7 @@ void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *context
/* delete the context if it's registrar matches, is empty, has refcount of 1, */
/* it's not empty, if it has includes, ignorepats, or switches that are registered from
another registrar . It ' s not empty if there are any extensions */
if ( strcmp ( tmp - > registrar , registrar ) = = 0 & & tmp - > refcount < 2 & & ! tmp - > root & & ! tmp - > ignorepats & & ! tmp - > includes & & AST_LIST_EMPTY ( & tmp - > alts ) ) {
if ( strcmp ( tmp - > registrar , registrar ) = = 0 & & tmp - > refcount < 2 & & ! tmp - > root & & ! tmp - > ignorepats & & ! ast_context_includes_count ( tmp ) & & AST_LIST_EMPTY ( & tmp - > alts ) ) {
ast_debug ( 1 , " delete ctx %s %s \n " , tmp - > name , tmp - > registrar ) ;
ast_hashtab_remove_this_object ( contexttab , tmp ) ;
@ -8407,11 +8356,6 @@ const char *ast_get_extension_label(struct ast_exten *exten)
return exten ? exten - > label : NULL ;
}
const char * ast_get_include_name ( struct ast_include * inc )
{
return inc ? inc - > name : NULL ;
}
const char * ast_get_ignorepat_name ( struct ast_ignorepat * ip )
{
return ip ? ip - > pattern : NULL ;
@ -8435,11 +8379,6 @@ const char *ast_get_extension_registrar(struct ast_exten *e)
return e ? e - > registrar : NULL ;
}
const char * ast_get_include_registrar ( struct ast_include * i )
{
return i ? i - > registrar : NULL ;
}
const char * ast_get_ignorepat_registrar ( struct ast_ignorepat * ip )
{
return ip ? ip - > registrar : NULL ;
@ -8517,13 +8456,43 @@ struct ast_exten *ast_walk_extension_priorities(struct ast_exten *exten,
return priority ? priority - > peer : exten ;
}
struct ast_include * ast_walk_context_includes ( struct ast_context * con ,
struct ast_include * inc )
const struct ast_include * ast_walk_context_includes ( const struct ast_context * con ,
const struct ast_include * inc )
{
if ( ! inc )
return con ? con - > includes : NULL ;
else
return inc - > next ;
if ( inc ) {
int idx ;
int next = 0 ;
for ( idx = 0 ; idx < ast_context_includes_count ( con ) ; idx + + ) {
const struct ast_include * include = AST_VECTOR_GET ( & con - > includes , idx ) ;
if ( next ) {
return include ;
}
if ( inc = = include ) {
next = 1 ;
}
}
return NULL ;
}
if ( ! ast_context_includes_count ( con ) ) {
return NULL ;
}
return ast_context_includes_get ( con , 0 ) ;
}
int ast_context_includes_count ( const struct ast_context * con )
{
return AST_VECTOR_SIZE ( & con - > includes ) ;
}
const struct ast_include * ast_context_includes_get ( const struct ast_context * con , int idx )
{
return AST_VECTOR_GET ( & con - > includes , idx ) ;
}
struct ast_ignorepat * ast_walk_context_ignorepats ( struct ast_context * con ,
@ -8537,16 +8506,19 @@ struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con,
int ast_context_verify_includes ( struct ast_context * con )
{
struct ast_include * inc = NULL ;
int idx ;
int res = 0 ;
while ( ( inc = ast_walk_context_includes ( con , inc ) ) ) {
if ( ast_context_find ( inc - > rname ) )
for ( idx = 0 ; idx < ast_context_includes_count ( con ) ; idx + + ) {
const struct ast_include * inc = ast_context_includes_get ( con , idx ) ;
if ( ast_context_find ( include_rname ( inc ) ) ) {
continue ;
}
res = - 1 ;
ast_log ( LOG_WARNING , " Context '%s' tries to include nonexistent context '%s' \n " ,
ast_get_context_name ( con ) , inc - > rname ) ;
ast_get_context_name ( con ) , include_rname ( inc ) ) ;
break ;
}