Merge "build-system: Allow building with static pjproject"
authorzuul <zuul@gerrit.asterisk.org>
Thu, 3 Mar 2016 17:30:41 +0000 (11:30 -0600)
committerGerrit Code Review <gerrit2@gerrit.digium.api>
Thu, 3 Mar 2016 17:30:42 +0000 (11:30 -0600)
CHANGES
channels/chan_sip.c
funcs/func_callerid.c
main/callerid.c
main/message.c
res/res_pjsip_diversion.c
res/res_pjsip_messaging.c
res/res_pjsip_send_to_voicemail.c

diff --git a/CHANGES b/CHANGES
index aaaf3f5..7c04285 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -250,6 +250,36 @@ app_confbridge
    conference state and made the locked column a yes/no value instead of a
    locked/unlocked value.
 
+REDIRECTING(reason)
+------------------
+ * The REDIRECTING(reason) value is now treated consistently between
+   chan_sip and chan_pjsip.
+
+   Both channel drivers match incoming reason values with values documented
+   by REDIRECTING(reason) and values documented by RFC5806 regardless of
+   whether they are quoted or not.  RFC5806 values are mapped to the
+   equivalent REDIRECTING(reason) documented value and is set in
+   REDIRECTING(reason).  e.g., an incoming RFC5806 'unconditional' value or a
+   quoted string version ('"unconditional"') is converted to
+   REDIRECTING(reason)'s 'cfu' value.  The user's dialplan only needs to deal
+   with 'cfu' instead of any of the aliases.
+
+   The incoming 480 response reason text supported by chan_sip checks for
+   known reason values and if not matched then puts quotes around the reason
+   string and assigns that to REDIRECTING(reason).
+
+   Both channel drivers send outgoing known REDIRECTING(reason) values as the
+   unquoted RFC5806 equivalent.  User custom values are either sent as is or
+   with added quotes if SIP doesn't allow a character within the value as
+   part of a RFC3261 Section 25.1 token.  Note that there are still
+   limitations on what characters can be put in a custom user value.  e.g.,
+   embedding quotes in the middle of the reason string is just going to cause
+   you grief.
+
+ * Setting a REDIRECTING(reason) value now recognizes RFC5806 aliases.
+   e.g., Setting REDIRECTING(reason) to 'unconditional' is converted to the
+   'cfu' value.
+
 res_pjproject
 ------------------
  * This module is the successor of res_pjsip_log_forwarder.  As well as
index 0b0d114..2d5843d 100644 (file)
@@ -710,7 +710,7 @@ static const struct  cfsip_methods {
  */
 static const struct sip_reasons {
        enum AST_REDIRECTING_REASON code;
-       char * const text;
+       const char *text;
 } sip_reason_table[] = {
        { AST_REDIRECTING_REASON_UNKNOWN, "unknown" },
        { AST_REDIRECTING_REASON_USER_BUSY, "user-busy" },
@@ -723,8 +723,8 @@ static const struct sip_reasons {
        { AST_REDIRECTING_REASON_FOLLOW_ME, "follow-me" },
        { AST_REDIRECTING_REASON_OUT_OF_ORDER, "out-of-service" },
        { AST_REDIRECTING_REASON_AWAY, "away" },
-       { AST_REDIRECTING_REASON_CALL_FWD_DTE, "unknown"},
-       { AST_REDIRECTING_REASON_SEND_TO_VM, "send_to_vm"},
+       { AST_REDIRECTING_REASON_CALL_FWD_DTE, "cf_dte" },              /* Non-standard */
+       { AST_REDIRECTING_REASON_SEND_TO_VM, "send_to_vm" },    /* Non-standard */
 };
 
 
@@ -2375,52 +2375,54 @@ static int map_s_x(const struct _map_x_s *table, const char *s, int errorvalue)
        return errorvalue;
 }
 
-static enum AST_REDIRECTING_REASON sip_reason_str_to_code(const char *text)
+/*!
+ * \internal
+ * \brief Determine if the given string is a SIP token.
+ * \since 13.8.0
+ *
+ * \param str String to determine if is a SIP token.
+ *
+ * \note A token is defined by RFC3261 Section 25.1
+ *
+ * \return Non-zero if the string is a SIP token.
+ */
+static int sip_is_token(const char *str)
 {
-       enum AST_REDIRECTING_REASON ast = AST_REDIRECTING_REASON_UNKNOWN;
-       int i;
+       int is_token;
+
+       if (ast_strlen_zero(str)) {
+               /* An empty string is not a token. */
+               return 0;
+       }
 
-       for (i = 0; i < ARRAY_LEN(sip_reason_table); ++i) {
-               if (!strcasecmp(text, sip_reason_table[i].text)) {
-                       ast = sip_reason_table[i].code;
+       is_token = 1;
+       do {
+               if (!isalnum(*str)
+                       && !strchr("-.!%*_+`'~", *str)) {
+                       /* The character is not allowed in a token. */
+                       is_token = 0;
                        break;
                }
-       }
+       } while (*++str);
 
-       return ast;
+       return is_token;
 }
 
-static const char *sip_reason_code_to_str(struct ast_party_redirecting_reason *reason, int *table_lookup)
+static const char *sip_reason_code_to_str(struct ast_party_redirecting_reason *reason)
 {
-       int code = reason->code;
+       int idx;
+       int code;
 
-       /* If there's a specific string set, then we just
-        * use it.
-        */
+       /* use specific string if given */
        if (!ast_strlen_zero(reason->str)) {
-               /* If we care about whether this can be found in
-                * the table, then we need to check about that.
-                */
-               if (table_lookup) {
-                       /* If the string is literally "unknown" then don't bother with the lookup
-                        * because it can lead to a false negative.
-                        */
-                       if (!strcasecmp(reason->str, "unknown") ||
-                                       sip_reason_str_to_code(reason->str) != AST_REDIRECTING_REASON_UNKNOWN) {
-                               *table_lookup = TRUE;
-                       } else {
-                               *table_lookup = FALSE;
-                       }
-               }
                return reason->str;
        }
 
-       if (table_lookup) {
-               *table_lookup = TRUE;
-       }
-
-       if (code >= 0 && code < ARRAY_LEN(sip_reason_table)) {
-               return sip_reason_table[code].text;
+       code = reason->code;
+       for (idx = 0; idx < ARRAY_LEN(sip_reason_table); ++idx) {
+               if (code == sip_reason_table[idx].code) {
+                       return sip_reason_table[idx].text;
+               }
        }
 
        return "unknown";
@@ -14219,7 +14221,7 @@ static void add_diversion(struct sip_request *req, struct sip_pvt *pvt)
 {
        struct ast_party_id diverting_from;
        const char *reason;
-       int found_in_table;
+       const char *quote_str;
        char header_text[256];
        char encoded_number[SIPBUFSIZE/2];
 
@@ -14244,17 +14246,18 @@ static void add_diversion(struct sip_request *req, struct sip_pvt *pvt)
                ast_copy_string(encoded_number, diverting_from.number.str, sizeof(encoded_number));
        }
 
-       reason = sip_reason_code_to_str(&ast_channel_redirecting(pvt->owner)->reason, &found_in_table);
+       reason = sip_reason_code_to_str(&ast_channel_redirecting(pvt->owner)->reason);
+
+       /* Reason is either already quoted or it is a token to not need quotes added. */
+       quote_str = *reason == '\"' || sip_is_token(reason) ? "" : "\"";
 
        /* We at least have a number to place in the Diversion header, which is enough */
        if (!diverting_from.name.valid
                || ast_strlen_zero(diverting_from.name.str)) {
                snprintf(header_text, sizeof(header_text), "<sip:%s@%s>;reason=%s%s%s",
-                               encoded_number,
-                               ast_sockaddr_stringify_host_remote(&pvt->ourip),
-                               found_in_table ? "" : "\"",
-                               reason,
-                               found_in_table ? "" : "\"");
+                       encoded_number,
+                       ast_sockaddr_stringify_host_remote(&pvt->ourip),
+                       quote_str, reason, quote_str);
        } else {
                char escaped_name[SIPBUFSIZE/2];
                if (sip_cfg.pedanticsipchecking) {
@@ -14263,12 +14266,10 @@ static void add_diversion(struct sip_request *req, struct sip_pvt *pvt)
                        ast_copy_string(escaped_name, diverting_from.name.str, sizeof(escaped_name));
                }
                snprintf(header_text, sizeof(header_text), "\"%s\" <sip:%s@%s>;reason=%s%s%s",
-                               escaped_name,
-                               encoded_number,
-                               ast_sockaddr_stringify_host_remote(&pvt->ourip),
-                               found_in_table ? "" : "\"",
-                               reason,
-                               found_in_table ? "" : "\"");
+                       escaped_name,
+                       encoded_number,
+                       ast_sockaddr_stringify_host_remote(&pvt->ourip),
+                       quote_str, reason, quote_str);
        }
 
        add_header(req, "Diversion", header_text);
@@ -17740,6 +17741,9 @@ static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, c
        char *params, *reason_param = NULL;
        struct sip_request *req;
 
+       ast_assert(reason_code != NULL);
+       ast_assert(reason_str != NULL);
+
        req = oreq ? oreq : &p->initreq;
 
        ast_copy_string(tmp, sip_get_header(req, "Diversion"), sizeof(tmp));
@@ -17773,16 +17777,6 @@ static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, c
                        if ((end = strchr(reason_param, ';'))) {
                                *end = '\0';
                        }
-                       /* Remove enclosing double-quotes */
-                       if (*reason_param == '"')
-                               reason_param = ast_strip_quoted(reason_param, "\"", "\"");
-                       if (!ast_strlen_zero(reason_param)) {
-                               sip_set_redirstr(p, reason_param);
-                               if (p->owner) {
-                                       pbx_builtin_setvar_helper(p->owner, "__PRIREDIRECTREASON", p->redircause);
-                                       pbx_builtin_setvar_helper(p->owner, "__SIPREDIRECTREASON", reason_param);
-                               }
-                       }
                }
        }
 
@@ -17814,12 +17808,27 @@ static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, c
        }
 
        if (!ast_strlen_zero(reason_param)) {
-               if (reason_code) {
-                       *reason_code = sip_reason_str_to_code(reason_param);
+               *reason_str = ast_strdup(reason_param);
+
+               /* Remove any enclosing double-quotes */
+               if (*reason_param == '"') {
+                       reason_param = ast_strip_quoted(reason_param, "\"", "\"");
                }
 
-               if (reason_str) {
-                       *reason_str = ast_strdup(reason_param);
+               *reason_code = ast_redirecting_reason_parse(reason_param);
+               if (*reason_code < 0) {
+                       *reason_code = AST_REDIRECTING_REASON_UNKNOWN;
+               } else {
+                       ast_free(*reason_str);
+                       *reason_str = ast_strdup("");
+               }
+
+               if (!ast_strlen_zero(reason_param)) {
+                       sip_set_redirstr(p, reason_param);
+                       if (p->owner) {
+                               pbx_builtin_setvar_helper(p->owner, "__PRIREDIRECTREASON", p->redircause);
+                               pbx_builtin_setvar_helper(p->owner, "__SIPREDIRECTREASON", reason_param);
+                       }
                }
        }
 
@@ -22698,10 +22707,11 @@ static void change_redirecting_information(struct sip_pvt *p, struct sip_request
                redirecting->to.name.str = redirecting_to_name;
        }
        redirecting->reason.code = reason;
+       ast_free(redirecting->reason.str);
+       redirecting->reason.str = reason_str;
        if (reason_str) {
-               ast_debug(3, "Got redirecting reason %s\n", reason_str);
-               ast_free(redirecting->reason.str);
-               redirecting->reason.str = reason_str;
+               ast_debug(3, "Got redirecting reason %s\n", ast_strlen_zero(reason_str)
+                       ? sip_reason_code_to_str(&redirecting->reason) : reason_str);
        }
 }
 
@@ -23502,14 +23512,22 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
                if (p->owner && !req->ignore) {
                        struct ast_party_redirecting redirecting;
                        struct ast_set_party_redirecting update_redirecting;
+                       char *quoted_rest = ast_alloca(strlen(rest) + 3);
+
                        ast_party_redirecting_set_init(&redirecting, ast_channel_redirecting(p->owner));
                        memset(&update_redirecting, 0, sizeof(update_redirecting));
 
-                       redirecting.reason.code = sip_reason_str_to_code(rest);
-                       redirecting.reason.str = ast_strdup(rest);
+                       redirecting.reason.code = ast_redirecting_reason_parse(rest);
+                       if (redirecting.reason.code < 0) {
+                               sprintf(quoted_rest, "\"%s\"", rest);/* Safe */
+
+                               redirecting.reason.code = AST_REDIRECTING_REASON_UNKNOWN;
+                               redirecting.reason.str = quoted_rest;
+                       } else {
+                               redirecting.reason.str = "";
+                       }
 
                        ast_channel_queue_redirecting_update(p->owner, &redirecting, &update_redirecting);
-                       ast_party_redirecting_free(&redirecting);
 
                        ast_queue_control(p->owner, AST_CONTROL_BUSY);
                }
index dee1977..133e259 100644 (file)
@@ -373,22 +373,27 @@ ASTERISK_REGISTER_FILE()
                        fields get/set a combined value for the corresponding
                        <replaceable>...-name-pres</replaceable> and <replaceable>...-num-pres</replaceable>
                        fields.</para>
-                       <para>The allowable values for the <replaceable>reason</replaceable>
+                       <para>The recognized values for the <replaceable>reason</replaceable>
                        and <replaceable>orig-reason</replaceable> fields are the following:</para>
                        <enumlist>
-                               <enum name = "unknown"><para>Unknown</para></enum>
+                               <enum name = "away"><para>Callee is Away</para></enum>
+                               <enum name = "cf_dte"><para>Call Forwarding By The Called DTE</para></enum>
                                <enum name = "cfb"><para>Call Forwarding Busy</para></enum>
                                <enum name = "cfnr"><para>Call Forwarding No Reply</para></enum>
-                               <enum name = "unavailable"><para>Callee is Unavailable</para></enum>
-                               <enum name = "time_of_day"><para>Time of Day</para></enum>
-                               <enum name = "dnd"><para>Do Not Disturb</para></enum>
+                               <enum name = "cfu"><para>Call Forwarding Unconditional</para></enum>
                                <enum name = "deflection"><para>Call Deflection</para></enum>
+                               <enum name = "dnd"><para>Do Not Disturb</para></enum>
                                <enum name = "follow_me"><para>Follow Me</para></enum>
                                <enum name = "out_of_order"><para>Called DTE Out-Of-Order</para></enum>
-                               <enum name = "away"><para>Callee is Away</para></enum>
-                               <enum name = "cf_dte"><para>Call Forwarding By The Called DTE</para></enum>
-                               <enum name = "cfu"><para>Call Forwarding Unconditional</para></enum>
+                               <enum name = "send_to_vm"><para>Send the call to voicemail</para></enum>
+                               <enum name = "time_of_day"><para>Time of Day</para></enum>
+                               <enum name = "unavailable"><para>Callee is Unavailable</para></enum>
+                               <enum name = "unknown"><para>Unknown</para></enum>
                        </enumlist>
+                       <note><para>You can set a user defined reason string that SIP can
+                       send/receive instead.  The user defined reason string my need to be
+                       quoted depending upon SIP or the peer's requirements.  These strings
+                       are treated as unknown by the non-SIP channel drivers.</para></note>
                        <para>The allowable values for the <replaceable>xxx-name-charset</replaceable>
                        field are the following:</para>
                        <enumlist>
index 69fe6ff..d2b3218 100644 (file)
@@ -1209,7 +1209,16 @@ static const struct ast_value_translation redirecting_reason_types[] = {
        { AST_REDIRECTING_REASON_OUT_OF_ORDER,   "out_of_order", "Called DTE Out-Of-Order" },
        { AST_REDIRECTING_REASON_AWAY,           "away",         "Callee is Away" },
        { AST_REDIRECTING_REASON_CALL_FWD_DTE,   "cf_dte",       "Call Forwarding By The Called DTE" },
-       { AST_REDIRECTING_REASON_SEND_TO_VM,     "send_to_vm",   "Call is being redirected to user's voicemail"},
+       { AST_REDIRECTING_REASON_SEND_TO_VM,     "send_to_vm",   "Call is being redirected to user's voicemail" },
+
+       /* Convenience SIP aliases.  Alias descriptions are not used. */
+       { AST_REDIRECTING_REASON_USER_BUSY,      "user-busy" },
+       { AST_REDIRECTING_REASON_NO_ANSWER,      "no-answer" },
+       { AST_REDIRECTING_REASON_UNCONDITIONAL,  "unconditional" },
+       { AST_REDIRECTING_REASON_TIME_OF_DAY,    "time-of-day" },
+       { AST_REDIRECTING_REASON_DO_NOT_DISTURB, "do-not-disturb" },
+       { AST_REDIRECTING_REASON_FOLLOW_ME,      "follow-me" },
+       { AST_REDIRECTING_REASON_OUT_OF_ORDER,   "out-of-service" },
 /* *INDENT-ON* */
 };
 
@@ -1232,7 +1241,7 @@ const char *ast_redirecting_reason_describe(int data)
 
        for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
                if (redirecting_reason_types[index].value == data) {
-                       return redirecting_reason_types[index].description;
+                       return redirecting_reason_types[index].description ?: "Redirecting reason alias-bug";
                }
        }
 
index 7098f69..54c604c 100644 (file)
@@ -398,7 +398,7 @@ static void msg_destructor(void *obj)
        struct ast_msg *msg = obj;
 
        ast_string_field_free_memory(msg);
-       ao2_ref(msg->vars, -1);
+       ao2_cleanup(msg->vars);
 }
 
 struct ast_msg *ast_msg_alloc(void)
index ea2c7cd..f1a6ddf 100644 (file)
 
 static const pj_str_t diversion_name = { "Diversion", 9 };
 
+/*!
+ * \internal
+ * \brief Determine if the given string is a SIP token.
+ * \since 13.8.0
+ *
+ * \param str String to determine if is a SIP token.
+ *
+ * \note A token is defined by RFC3261 Section 25.1
+ *
+ * \return Non-zero if the string is a SIP token.
+ */
+static int sip_is_token(const char *str)
+{
+       int is_token;
+
+       if (ast_strlen_zero(str)) {
+               /* An empty string is not a token. */
+               return 0;
+       }
+
+       is_token = 1;
+       do {
+               if (!isalnum(*str)
+                       && !strchr("-.!%*_+`'~", *str)) {
+                       /* The character is not allowed in a token. */
+                       is_token = 0;
+                       break;
+               }
+       } while (*++str);
+
+       return is_token;
+}
+
 /*! \brief Diversion header reasons
  *
  * The core defines a bunch of constants used to define
@@ -46,7 +79,7 @@ static const pj_str_t diversion_name = { "Diversion", 9 };
  */
 static const struct reasons {
        enum AST_REDIRECTING_REASON code;
-       char *const text;
+       const char *text;
 } reason_table[] = {
        { AST_REDIRECTING_REASON_UNKNOWN, "unknown" },
        { AST_REDIRECTING_REASON_USER_BUSY, "user-busy" },
@@ -59,39 +92,28 @@ static const struct reasons {
        { AST_REDIRECTING_REASON_FOLLOW_ME, "follow-me" },
        { AST_REDIRECTING_REASON_OUT_OF_ORDER, "out-of-service" },
        { AST_REDIRECTING_REASON_AWAY, "away" },
-       { AST_REDIRECTING_REASON_CALL_FWD_DTE, "unknown"},
-       { AST_REDIRECTING_REASON_SEND_TO_VM, "send_to_vm"},
+       { AST_REDIRECTING_REASON_CALL_FWD_DTE, "cf_dte" },              /* Non-standard */
+       { AST_REDIRECTING_REASON_SEND_TO_VM, "send_to_vm" },    /* Non-standard */
 };
 
 static const char *reason_code_to_str(const struct ast_party_redirecting_reason *reason)
 {
-       int code = reason->code;
+       int idx;
+       int code;
 
        /* use specific string if given */
        if (!ast_strlen_zero(reason->str)) {
                return reason->str;
        }
 
-       if (code >= 0 && code < ARRAY_LEN(reason_table)) {
-               return reason_table[code].text;
-       }
-
-       return "unknown";
-}
-
-static enum AST_REDIRECTING_REASON reason_str_to_code(const char *text)
-{
-       enum AST_REDIRECTING_REASON code = AST_REDIRECTING_REASON_UNKNOWN;
-       int i;
-
-       for (i = 0; i < ARRAY_LEN(reason_table); ++i) {
-               if (!strcasecmp(text, reason_table[i].text)) {
-                       code = reason_table[i].code;
-                       break;
+       code = reason->code;
+       for (idx = 0; idx < ARRAY_LEN(reason_table); ++idx) {
+               if (code == reason_table[idx].code) {
+                       return reason_table[idx].text;
                }
        }
 
-       return code;
+       return "unknown";
 }
 
 static pjsip_fromto_hdr *get_diversion_header(pjsip_rx_data *rdata)
@@ -159,13 +181,31 @@ static void set_redirecting_reason(pjsip_fromto_hdr *hdr,
 {
        static const pj_str_t reason_name = { "reason", 6 };
        pjsip_param *reason = pjsip_param_find(&hdr->other_param, &reason_name);
+       char *reason_str;
 
        if (!reason) {
                return;
        }
 
        set_redirecting_value(&data->str, &reason->value);
-       data->code = reason_str_to_code(data->str);
+       if (!data->str) {
+               /* Oops, allocation failure */
+               return;
+       }
+       reason_str = ast_strdupa(data->str);
+
+       /* Remove any enclosing double-quotes */
+       if (*reason_str == '"') {
+               reason_str = ast_strip_quoted(reason_str, "\"", "\"");
+       }
+
+       data->code = ast_redirecting_reason_parse(reason_str);
+       if (data->code < 0) {
+               data->code = AST_REDIRECTING_REASON_UNKNOWN;
+       } else {
+               ast_free(data->str);
+               data->str = ast_strdup("");
+       }
 }
 
 static void set_redirecting(struct ast_sip_session *session,
@@ -251,6 +291,9 @@ static void add_diversion_header(pjsip_tx_data *tdata, struct ast_party_redirect
        pjsip_sip_uri *uri;
        pjsip_param *param;
        pjsip_fromto_hdr *old_hdr;
+       const char *reason_str;
+       const char *quote_str;
+       char *reason_buf;
 
        struct ast_party_id *id = &data->from;
        pjsip_uri *base = PJSIP_MSG_FROM_HDR(tdata->msg)->uri;
@@ -272,7 +315,17 @@ static void add_diversion_header(pjsip_tx_data *tdata, struct ast_party_redirect
 
        param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
        param->name = pj_str("reason");
-       param->value = pj_str((char*)reason_code_to_str(&data->reason));
+
+       reason_str = reason_code_to_str(&data->reason);
+
+       /* Reason is either already quoted or it is a token to not need quotes added. */
+       quote_str = *reason_str == '\"' || sip_is_token(reason_str) ? "" : "\"";
+
+       reason_buf = pj_pool_alloc(tdata->pool, strlen(reason_str) + 3);
+       sprintf(reason_buf, "%s%s%s", quote_str, reason_str, quote_str);/* Safe */
+
+       param->value = pj_str(reason_buf);
+
        pj_list_insert_before(&hdr->other_param, param);
 
        hdr->uri = (pjsip_uri *) name_addr;
index 7532e39..f72f3f0 100644 (file)
@@ -530,6 +530,10 @@ static struct msg_data* msg_data_create(const struct ast_msg *msg, const char *t
        /* Make sure we start with sip: */
        mdata->to = ast_begins_with(to, "sip:") ? ast_strdup(++to) : ast_strdup(to - 3);
        mdata->from = ast_strdup(from);
+       if (!mdata->to || !mdata->from) {
+               ao2_ref(mdata, -1);
+               return NULL;
+       }
 
        /* sometimes from can still contain the tag at this point, so remove it */
        if ((tag = strchr(mdata->from, ';'))) {
@@ -597,7 +601,7 @@ static int sip_msg_send(const struct ast_msg *msg, const char *to, const char *f
 
        if (!(mdata = msg_data_create(msg, to, from)) ||
            ast_sip_push_task(message_serializer, msg_send, mdata)) {
-               ao2_ref(mdata, -1);
+               ao2_cleanup(mdata);
                return -1;
        }
        return 0;
index 9d2b5b1..bd70bcf 100644 (file)
@@ -47,7 +47,8 @@
 #define SEND_TO_VM_HEADER_VALUE "feature_send_to_vm"
 
 #define SEND_TO_VM_REDIRECT "REDIRECTING(reason)"
-#define SEND_TO_VM_REDIRECT_VALUE "\"send_to_vm\""
+#define SEND_TO_VM_REDIRECT_VALUE "send_to_vm"
+#define SEND_TO_VM_REDIRECT_QUOTED_VALUE "\"" SEND_TO_VM_REDIRECT_VALUE "\""
 
 static void send_response(struct ast_sip_session *session, int code, struct pjsip_rx_data *rdata)
 {
@@ -102,9 +103,13 @@ static int has_diversion_reason(pjsip_rx_data *rdata)
        pjsip_param *reason;
        pjsip_fromto_hdr *hdr = get_diversion_header(rdata);
 
-       return hdr &&
-               (reason = get_diversion_reason(hdr)) &&
-               !pj_stricmp2(&reason->value, SEND_TO_VM_REDIRECT_VALUE);
+       if (!hdr) {
+               return 0;
+       }
+       reason = get_diversion_reason(hdr);
+       return reason
+               && (!pj_stricmp2(&reason->value, SEND_TO_VM_REDIRECT_QUOTED_VALUE)
+                       || !pj_stricmp2(&reason->value, SEND_TO_VM_REDIRECT_VALUE));
 }
 
 static int has_call_feature(pjsip_rx_data *rdata)
@@ -160,12 +165,10 @@ static int handle_incoming_request(struct ast_sip_session *session, struct pjsip
        sip_session_datastore->data = other_party;
 
        if (ast_sip_session_add_datastore(session, sip_session_datastore)) {
-               ast_channel_unref(other_party);
                ao2_ref(sip_session_datastore, -1);
                send_response(session, 500, rdata);
                return -1;
        }
-       ao2_ref(sip_session_datastore, -1);
 
        if (has_feature) {
                pbx_builtin_setvar_helper(other_party, SEND_TO_VM_HEADER,
@@ -177,6 +180,7 @@ static int handle_incoming_request(struct ast_sip_session *session, struct pjsip
                                          SEND_TO_VM_REDIRECT_VALUE);
        }
 
+       ao2_ref(sip_session_datastore, -1);
        return 0;
 }