diff options
author | file <file@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-05-18 14:07:46 +0000 |
---|---|---|
committer | file <file@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-05-18 14:07:46 +0000 |
commit | f261c09f7d1e9de13761e1bc0d4f6939faba808b (patch) | |
tree | 70c26ede8db35e673ce37eaf4a0537de370e226d | |
parent | 950794c189d79caaa9a07fe5eb62cb1a7cfde628 (diff) |
Allow contexts in regexten so that extensions can be added to multiple contexts when peer registers (issue #6869 reported by and created by Marquis)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@28168 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r-- | channels/chan_sip.c | 60 | ||||
-rw-r--r-- | configs/sip.conf.sample | 9 |
2 files changed, 61 insertions, 8 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 730de659f..db4bedae8 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -1942,17 +1942,30 @@ static void realtime_update_peer(const char *peername, struct sockaddr_in *sin, static void register_peer_exten(struct sip_peer *peer, int onoff) { char multi[256]; - char *stringp, *ext; + char *stringp, *ext, *context; if (!ast_strlen_zero(global_regcontext)) { ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi)); stringp = multi; while((ext = strsep(&stringp, "&"))) { + if((context = strchr(ext, '@'))) { + context++; + if (!ast_context_find(context)) { + ast_log(LOG_WARNING, "Context %s must exist in regcontext!\n", context); + continue; + } + ext = strsep(&ext, "@"); + if (onoff) + ast_add_extension(context, 1, ext, 1, NULL, NULL, "Noop", ast_strdup(peer->name), free, "SIP"); + else + ast_context_remove_extension(context, ext, 1, NULL); + } else { if (onoff) ast_add_extension(global_regcontext, 1, ext, 1, NULL, NULL, "Noop", ast_strdup(peer->name), free, "SIP"); else ast_context_remove_extension(global_regcontext, ext, 1, NULL); + } } } } @@ -8105,6 +8118,32 @@ static const char *insecure2str(int port, int invite) return "no"; } +/*! \brief cleanup_stale_contexts: Destroy disused contexts between reloads + Only used in reload_config so the code for regcontext doesn't get ugly +*/ +static void cleanup_stale_contexts(char *new, char *old) +{ + char *oldcontext, *newcontext, *stalecontext, *stringp, newlist[AST_MAX_CONTEXT]; + + while ((oldcontext = strsep(&old, "&"))) { + stalecontext = '\0'; + ast_copy_string(newlist, new, sizeof(newlist)); + stringp = newlist; + while ((newcontext = strsep(&stringp, "&"))) { + if (strcmp(newcontext, oldcontext) == 0) { + /* This is not the context you're looking for */ + stalecontext = '\0'; + break; + } else if (strcmp(newcontext, oldcontext)) { + stalecontext = oldcontext; + } + + } + if (stalecontext) + ast_context_destroy(ast_context_find(stalecontext), "SIP"); + } +} + /*! \brief sip_prune_realtime: Remove temporary realtime objects from memory (CLI) */ static int sip_prune_realtime(int fd, int argc, char *argv[]) { @@ -13197,7 +13236,8 @@ static int reload_config(enum channelreloadreason reason) struct sip_peer *peer; struct sip_user *user; struct ast_hostent ahp; - char *cat; + char *cat, *stringp, *context, *oldregcontext; + char newcontexts[AST_MAX_CONTEXT], oldcontexts[AST_MAX_CONTEXT]; struct hostent *hp; int format; char iabuf[INET_ADDRSTRLEN]; @@ -13216,6 +13256,10 @@ static int reload_config(enum channelreloadreason reason) return -1; } + /* Initialize copy of current global_regcontext for later use in removing stale contexts */ + ast_copy_string(oldcontexts, global_regcontext, sizeof(oldcontexts)); + oldregcontext = oldcontexts; + /* Clear all flags before setting default values */ /* Preserve debugging settings for console */ ast_copy_flags(&debugflag, &global_flags[1], SIP_PAGE2_DEBUG_CONSOLE); @@ -13361,10 +13405,16 @@ static int reload_config(enum channelreloadreason reason) } else if (!strcasecmp(v->name, "language")) { ast_copy_string(default_language, v->value, sizeof(default_language)); } else if (!strcasecmp(v->name, "regcontext")) { + ast_copy_string(newcontexts, v->value, sizeof(newcontexts)); + stringp = newcontexts; + /* Let's remove any contexts that are no longer defined in regcontext */ + cleanup_stale_contexts(stringp, oldregcontext); + /* Create contexts if they don't exist already */ + while ((context = strsep(&stringp, "&"))) { + if (!ast_context_find(context)) + ast_context_create(NULL, context,"SIP"); + } ast_copy_string(global_regcontext, v->value, sizeof(global_regcontext)); - /* Create context if it doesn't exist already */ - if (!ast_context_find(global_regcontext)) - ast_context_create(NULL, global_regcontext, "SIP"); } else if (!strcasecmp(v->name, "callerid")) { ast_copy_string(default_callerid, v->value, sizeof(default_callerid)); } else if (!strcasecmp(v->name, "fromdomain")) { diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample index c4cbf0e66..178e29b00 100644 --- a/configs/sip.conf.sample +++ b/configs/sip.conf.sample @@ -139,9 +139,12 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; ; If regcontext is specified, Asterisk will dynamically create and destroy a ; NoOp priority 1 extension for a given peer who registers or unregisters with -; us. The actual extension is the 'regexten' parameter of the registering -; peer or its name if 'regexten' is not provided. More than one regexten may -; be supplied if they are separated by '&'. Patterns may be used in regexten. +; us. Multiple contexts may be specified by separating them with '&'. The +; actual extension is the 'regexten' parameter of the registering peer or its +; name if 'regexten' is not provided. If more than one context is provided, +; the context must be specified within regexten by appending the desired +; context after '@'. More than one regexten may be supplied if they are +; separated by '&'. Patterns may be used in regexten. ; ;regcontext=sipregistrations ; |