diff --git a/main/pbx.c b/main/pbx.c index 62994c7f8b5e0198918c0bd18c5f7f39962465b7..a61d9079230703277487dd721014c0e13ea1f110 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -324,6 +324,7 @@ struct match_char *already_in_tree(struct match_char *current, char *pat); struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly); struct match_char *add_pattern_node(struct ast_context *con, struct match_char *current, char *pattern, int is_pattern, int already, int specificity); void create_match_char_tree(struct ast_context *con); +void log_match_char_tree(struct match_char *node, char *prefix); struct ast_exten *get_canmatch_exten(struct match_char *node); void destroy_pattern_tree(struct match_char *pattern_tree); static int hashtab_compare_contexts(const void *ah_a, const void *ah_b); @@ -851,28 +852,40 @@ static void update_scoreboard(struct scoreboard *board, int length, int spec, st } } -#ifdef NEED_DEBUG -static void log_match_char_tree(struct match_char *node, char *prefix) +void log_match_char_tree(struct match_char *node, char *prefix) { char my_prefix[1024]; + char extenstr[40]; + + extenstr[0] = 0; + if (node && node->exten && node->exten) + sprintf(extenstr,"(%x)",(unsigned int)node->exten); - ast_log(LOG_DEBUG,"%s%s:%c:%d:%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->specificity, node->exten? "EXTEN":""); + if (strlen(node->x) > 1 ) + ast_log(LOG_DEBUG,"%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"", node->exten ? node->exten->exten : "", extenstr); + else + ast_log(LOG_DEBUG,"%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"", node->exten ? node->exten->exten : "", extenstr); strcpy(my_prefix,prefix); strcat(my_prefix,"+ "); if (node->next_char) - print_match_char_tree(node->next_char, my_prefix); + log_match_char_tree(node->next_char, my_prefix); if (node->alt_char) - print_match_char_tree(node->alt_char, prefix); + log_match_char_tree(node->alt_char, prefix); } -#endif static void cli_match_char_tree(struct match_char *node, char *prefix, int fd) { char my_prefix[1024]; - if (strlen(node->x) > 1 ) - ast_cli(fd, "%s[%s]:%c:%d:%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->specificity, node->exten? "EXTEN:":"", node->exten ? node->exten->exten : ""); + char extenstr[40]; + + extenstr[0] = 0; + if (node && node->exten && node->exten) + sprintf(extenstr,"(%x)",(unsigned int)node->exten); + + if (strlen(node->x) > 1) + ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:":"", node->exten ? node->exten->exten : "", extenstr); else - ast_cli(fd, "%s%s:%c:%d:%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->specificity, node->exten? "EXTEN:":"", node->exten ? node->exten->exten : ""); + ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:":"", node->exten ? node->exten->exten : "", extenstr); strcpy(my_prefix,prefix); strcat(my_prefix,"+ "); if (node->next_char) @@ -1153,9 +1166,11 @@ struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast } m2 = 0; if (already && (m2=already_in_tree(m1,buf)) && m2->next_char) { - if (!(*(s1+1))) /* if this is the end of the pattern, but not the end of the tree, then mark this node with the exten... + if (!(*(s1+1))) { /* if this is the end of the pattern, but not the end of the tree, then mark this node with the exten... a shorter pattern might win if the longer one doesn't match */ m2->exten = e1; + m2->deleted = 0; + } m1 = m2->next_char; /* m1 points to the node to compare against */ } else { if (m2) { @@ -1168,8 +1183,11 @@ struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast m1 = add_pattern_node(con, m1, buf, pattern, already,specif); /* m1 is the node just added */ } - if (!(*(s1+1))) + if (!(*(s1+1))) { + m1->deleted = 0; m1->exten = e1; + } + already = 0; } s1++; /* advance to next char */ @@ -1565,7 +1583,9 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan, pattern.label = label; pattern.priority = priority; - +#ifdef NEED_DEBUG + ast_log(LOG_NOTICE,"Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int)action); +#endif /* Initialize status if appropriate */ if (q->stacklen == 0) { q->status = STATUS_NO_CONTEXT; @@ -1615,10 +1635,13 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan, create_match_char_tree(tmp); #ifdef NEED_DEBUG ast_log(LOG_DEBUG,"Tree Created in context %s:\n", context); - print_match_char_tree(tmp->pattern_tree," "); + log_match_char_tree(tmp->pattern_tree," "); #endif } - +#ifdef NEED_DEBUG + ast_log(LOG_NOTICE,"The Trie we are searching in:\n"); + log_match_char_tree(tmp->pattern_tree, ":: "); +#endif new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid); eroot = score.exten; @@ -3647,9 +3670,13 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension /* Handle this is in the new world */ if (con->pattern_tree) { - /* find this particular extension */ - struct ast_exten ex, *exten2; + struct ast_exten ex, *exten2, *exten3; char dummy_name[1024]; + +#ifdef NEED_DEBUG + ast_log(LOG_NOTICE,"Removing %s/%s/%d from trees, registrar=%s\n", con->name, extension, priority, registrar); +#endif + /* find this particular extension */ ex.exten = dummy_name; ex.matchcid = 0; ast_copy_string(dummy_name,extension, sizeof(dummy_name)); @@ -3662,7 +3689,7 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension if (x->exten) { /* this test for safety purposes */ x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ x->exten = 0; /* get rid of what will become a bad pointer */ - ast_hashtab_remove_this_object(con->root_tree, exten); + exten2 = ast_hashtab_remove_this_object(con->root_tree, exten); } else { ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); } @@ -3670,9 +3697,16 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension ex.priority = priority; exten2 = ast_hashtab_lookup(exten->peer_tree, &ex); if (exten2) { - if (exten2->label) /* if this exten has a label, remove that, too */ - ast_hashtab_remove_this_object(exten->peer_label_tree,exten2); - ast_hashtab_remove_this_object(exten->peer_tree, exten2); + + if (exten2->label) { /* if this exten has a label, remove that, too */ + exten3 = ast_hashtab_remove_this_object(exten->peer_label_tree,exten2); + if (!exten3) + ast_log(LOG_ERROR,"Did not remove this priority label (%d/%s) from the peer_label_tree of context %s, extension %s!\n", priority, exten2->label, con->name, exten2->exten); + } + + exten3 = ast_hashtab_remove_this_object(exten->peer_tree, exten2); + if (!exten3) + ast_log(LOG_ERROR,"Did not remove this priority (%d) from the peer_tree of context %s, extension %s!\n", priority, con->name, exten2->exten); if (ast_hashtab_size(exten->peer_tree) == 0) { /* well, if the last priority of an exten is to be removed, then, the extension is removed, too! */ @@ -3680,7 +3714,9 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension if (x->exten) { /* this test for safety purposes */ x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ x->exten = 0; /* get rid of what will become a bad pointer */ - ast_hashtab_remove_this_object(con->root_tree, exten); + exten3 = ast_hashtab_remove_this_object(con->root_tree, exten); + if (!exten3) + ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_tree (%s) (priority %d)\n", exten->exten, con->name, priority); } } } else { @@ -3693,6 +3729,10 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension ast_log(LOG_WARNING,"Cannot find extension %s in pattern tree in context %s\n", extension, con->name); } +#ifdef NEED_DEBUG + ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); + log_match_char_tree(con->pattern_tree, " "); +#endif } @@ -5666,6 +5706,7 @@ static int add_pri(struct ast_context *con, struct ast_exten *tmp, ast_hashtab_insert_safe(eh->peer_label_tree,tmp); ep->peer = tmp; } else if (el) { /* We're the first extension. Take over e's functions */ + struct match_char *x = add_exten_to_pattern_tree(con, e, 1); tmp->peer_tree = e->peer_tree; tmp->peer_label_tree = e->peer_label_tree; ast_hashtab_remove_object_via_lookup(tmp->peer_tree,e); @@ -5677,7 +5718,16 @@ static int add_pri(struct ast_context *con, struct ast_exten *tmp, ast_hashtab_remove_object_via_lookup(con->root_tree, e); ast_hashtab_insert_safe(con->root_tree, tmp); el->next = tmp; + /* The pattern trie points to this exten; replace the pointer, + and all will be well */ + + if (x->exten) { /* this test for safety purposes */ + x->exten = tmp; /* replace what would become a bad pointer */ + } else { + ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); + } } else { /* We're the very first extension. */ + struct match_char *x = add_exten_to_pattern_tree(con, e, 1); ast_hashtab_remove_object_via_lookup(con->root_tree,e); ast_hashtab_insert_safe(con->root_tree,tmp); tmp->peer_tree = e->peer_tree; @@ -5691,6 +5741,13 @@ static int add_pri(struct ast_context *con, struct ast_exten *tmp, ast_hashtab_remove_object_via_lookup(con->root_tree, e); ast_hashtab_insert_safe(con->root_tree, tmp); con->root = tmp; + /* The pattern trie points to this exten; replace the pointer, + and all will be well */ + if (x->exten) { /* this test for safety purposes */ + x->exten = tmp; /* replace what would become a bad pointer */ + } else { + ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); + } } if (tmp->priority == PRIORITY_HINT) ast_change_hint(e,tmp);