res_pjsip_refer: Prevent sending duplicate headers.
authorMark Michelson <mmichelson@digium.com>
Fri, 26 Jun 2015 15:41:05 +0000 (10:41 -0500)
committerMark Michelson <mmichelson@digium.com>
Fri, 26 Jun 2015 15:41:05 +0000 (10:41 -0500)
res_pjsip_refer will attempt to add Referred-By or Replaces headers to
outbound INVITEs at times. If the INVITE gets challenged for
authentication, then we will resend the INVITE. Prior to this patch, the
Referred-By or Replaces header would be re-added to the outbound INVITE,
resulting in duplicated headers.

ASTERISK-25204 #close
Reported by Mark Michelson

Change-Id: I59fb5c08b4d253c0dba9ee3d3950b5025358222d

res/res_pjsip_refer.c

index 7420e7e..657406b 100644 (file)
@@ -1087,10 +1087,41 @@ static int refer_incoming_request(struct ast_sip_session *session, pjsip_rx_data
        }
 }
 
-static void refer_outgoing_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
+/*!
+ * \brief Use the value of a channel variable as the value of a SIP header
+ *
+ * This looks up a variable name on a channel, then takes that value and adds
+ * it to an outgoing SIP request. If the header already exists on the message,
+ * then no action is taken.
+ *
+ * \pre chan is locked.
+ *
+ * \param chan The channel on which to find the variable.
+ * \param var_name The name of the channel variable to use.
+ * \param header_name The name of the SIP header to add to the outgoing message.
+ * \param tdata The outgoing SIP message on which to add the header
+ */
+static void add_header_from_channel_var(struct ast_channel *chan, const char *var_name, const char *header_name, pjsip_tx_data *tdata)
 {
-       const char *hdr;
+       const char *var_value;
+       pj_str_t pj_header_name;
+       pjsip_hdr *header;
+
+       var_value = pbx_builtin_getvar_helper(chan, var_name);
+       if (ast_strlen_zero(var_value)) {
+               return;
+       }
 
+       pj_cstr(&pj_header_name, header_name);
+       header = pjsip_msg_find_hdr_by_name(tdata->msg, &pj_header_name, NULL);
+       if (header) {
+               return;
+       }
+       ast_sip_add_header(tdata, header_name, var_value);
+}
+
+static void refer_outgoing_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
+{
        if (pjsip_method_cmp(&tdata->msg->line.req.method, &pjsip_invite_method)
                || !session->channel
                || session->inv_session->state != PJSIP_INV_STATE_NULL) {
@@ -1098,15 +1129,8 @@ static void refer_outgoing_request(struct ast_sip_session *session, struct pjsip
        }
 
        ast_channel_lock(session->channel);
-       hdr = pbx_builtin_getvar_helper(session->channel, "SIPREPLACESHDR");
-       if (!ast_strlen_zero(hdr)) {
-               ast_sip_add_header(tdata, "Replaces", hdr);
-       }
-
-       hdr = pbx_builtin_getvar_helper(session->channel, "SIPREFERREDBYHDR");
-       if (!ast_strlen_zero(hdr)) {
-               ast_sip_add_header(tdata, "Referred-By", hdr);
-       }
+       add_header_from_channel_var(session->channel, "SIPREPLACESHDR", "Replaces", tdata);
+       add_header_from_channel_var(session->channel, "SIPREFERREDBYHDR", "Referred-By", tdata);
        ast_channel_unlock(session->channel);
 }