From 0b0d72579e658b8fadf322cad429a4ce8afa4be2 Mon Sep 17 00:00:00 2001 From: Olle Johansson Date: Tue, 17 Oct 2006 19:57:35 +0000 Subject: Issue #5484 (branch sipdiversion) - Support for Diversion header in redirects of calls with 302 redirection. (tinning) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@45365 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_sip.c | 85 +++++++++++++++++++++++++++++++++++++++++------- doc/channelvariables.txt | 4 ++- 2 files changed, 76 insertions(+), 13 deletions(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 22d752c88..62fcf9afc 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -886,6 +886,7 @@ static struct sip_pvt { AST_STRING_FIELD(mohinterpret); /*!< MOH class to use when put on hold */ AST_STRING_FIELD(mohsuggest); /*!< MOH class to suggest when putting a peer on hold */ AST_STRING_FIELD(rdnis); /*!< Referring DNIS */ + AST_STRING_FIELD(redircause); /*!< Referring cause */ AST_STRING_FIELD(theirtag); /*!< Their tag */ AST_STRING_FIELD(username); /*!< [user] name */ AST_STRING_FIELD(peername); /*!< [peer] name, not set if [user] */ @@ -8139,29 +8140,87 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr return res; } +/*! \brief Translate referring cause */ +static void sip_set_redirstr(struct sip_pvt *p, char *reason) { + + if (strcmp(reason, "unknown")==0) { + ast_string_field_set(p, redircause, "UNKNOWN"); + } else if (strcmp(reason, "user-busy")==0) { + ast_string_field_set(p, redircause, "BUSY"); + } else if (strcmp(reason, "no-answer")==0) { + ast_string_field_set(p, redircause, "NOANSWER"); + } else if (strcmp(reason, "unavailable")==0) { + ast_string_field_set(p, redircause, "UNREACHABLE"); + } else if (strcmp(reason, "unconditional")==0) { + ast_string_field_set(p, redircause, "UNCONDITIONAL"); + } else if (strcmp(reason, "time-of-day")==0) { + ast_string_field_set(p, redircause, "UNKNOWN"); + } else if (strcmp(reason, "do-not-disturb")==0) { + ast_string_field_set(p, redircause, "UNKNOWN"); + } else if (strcmp(reason, "deflection")==0) { + ast_string_field_set(p, redircause, "UNKNOWN"); + } else if (strcmp(reason, "follow-me")==0) { + ast_string_field_set(p, redircause, "UNKNOWN"); + } else if (strcmp(reason, "out-of-service")==0) { + ast_string_field_set(p, redircause, "UNREACHABLE"); + } else if (strcmp(reason, "away")==0) { + ast_string_field_set(p, redircause, "UNREACHABLE"); + } else { + ast_string_field_set(p, redircause, "UNKNOWN"); + } +} + /*! \brief Get referring dnis */ static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq) { - char tmp[256], *c, *a; + char tmp[256], *exten, *rexten, *rdomain; + char *params, *reason = NULL; struct sip_request *req; - req = oreq; - if (!req) - req = &p->initreq; + req = oreq ? oreq : &p->initreq; + ast_copy_string(tmp, get_header(req, "Diversion"), sizeof(tmp)); if (ast_strlen_zero(tmp)) return 0; - c = get_in_brackets(tmp); - if (strncmp(c, "sip:", 4)) { - ast_log(LOG_WARNING, "Huh? Not an RDNIS SIP header (%s)?\n", c); + + exten = get_in_brackets(tmp); + if (strncmp(exten, "sip:", 4)) { + ast_log(LOG_WARNING, "Huh? Not an RDNIS SIP header (%s)?\n", exten); return -1; } - c += 4; - a = c; - strsep(&a, "@;"); /* trim anything after @ or ; */ + exten += 4; + + /* Get diversion-reason param if present */ + if ((params = strchr(tmp, ';'))) { + *params = '\0'; /* Cut off parameters */ + params++; + while (*params == ';' || *params == ' ') + params++; + /* Check if we have a reason parameter */ + if ((reason = strcasestr(params, "reason="))) { + reason+=7; + /* Remove enclosing double-quotes */ + if (*reason == '"') + ast_strip_quoted(reason, "\"", "\""); + if (!ast_strlen_zero(reason)) { + sip_set_redirstr(p, reason); + if (p->owner) { + pbx_builtin_setvar_helper(p->owner, "__PRIREDIRECTREASON", p->redircause); + pbx_builtin_setvar_helper(p->owner, "__SIPREDIRECTREASON", reason); + } + } + } + } + + rdomain = exten; + rexten = strsep(&rdomain, "@"); /* trim anything after @ */ + if (p->owner) + pbx_builtin_setvar_helper(p->owner, "__SIPRDNISDOMAIN", rdomain); + if (sip_debug_test_pvt(p)) - ast_verbose("RDNIS is %s\n", c); - ast_string_field_set(p, rdnis, c); + ast_verbose("RDNIS for this call is is %s (reason %s)\n", exten, reason ? reason : ""); + + ast_string_field_set(p, rdnis, rexten); return 0; } @@ -16502,6 +16561,7 @@ static int sip_sipredirect(struct sip_pvt *p, const char *dest) /* we'll issue the redirect message here */ if (!host) { char *localtmp; + ast_copy_string(tmp, get_header(&p->initreq, "To"), sizeof(tmp)); if (ast_strlen_zero(tmp)) { ast_log(LOG_ERROR, "Cannot retrieve the 'To' header from the original SIP request!\n"); @@ -16509,6 +16569,7 @@ static int sip_sipredirect(struct sip_pvt *p, const char *dest) } if ((localtmp = strstr(tmp, "sip:")) && (localtmp = strchr(localtmp, '@'))) { char lhost[80], lport[80]; + memset(lhost, 0, sizeof(lhost)); memset(lport, 0, sizeof(lport)); localtmp++; diff --git a/doc/channelvariables.txt b/doc/channelvariables.txt index 123f9a77e..0a859ef90 100644 --- a/doc/channelvariables.txt +++ b/doc/channelvariables.txt @@ -594,8 +594,10 @@ ${LEN(VAR)} * String length of VAR (integer) ${MEMBERINTERFACE} * The interface name of the queuemember that was chosen ${MEMBERNAME} * The member name of the queuemember that was chosen ${PRIORITY} * Current priority in the dialplan -${PRIREDIRECTREASON} Reason for redirect on PRI, if a call was directed +${PRIREDIRECTREASON} Reason for redirect on PRI, if a call was directed (also set in SIP) +${SIPREDIRECTREASON} Reason for redirect on SIP (text string) ${RDNIS} * Redirected Dial Number ID Service (Deprecated; use ${CALLERID(rdnis)}) +${SIPRDNISDOMAIN} RDNIS domain from a redirect in SIP. ${TIMESTAMP} * Current date time in the format: YYYYMMDD-HHMMSS (Deprecated; use ${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)}) ${TRANSFER_CONTEXT} Context for transferred calls ${FORWARD_CONTEXT} Context for forwarded calls -- cgit v1.2.3