Merge "threadpool, res_pjsip: Add serializer group shutdown API calls."
authorMatt Jordan <mjordan@digium.com>
Fri, 26 Jun 2015 18:36:17 +0000 (13:36 -0500)
committerGerrit Code Review <gerrit2@gerrit.digium.api>
Fri, 26 Jun 2015 18:36:17 +0000 (13:36 -0500)
CHANGES
doc/appdocsxml.xslt
main/manager_channels.c
res/res_pjsip.c
res/res_pjsip_nat.c
res/res_pjsip_refer.c

diff --git a/CHANGES b/CHANGES
index d2fa84c..cf37e69 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -186,6 +186,9 @@ AMI
  * A new ContactStatus event has been added that reflects res_pjsip contact
    lifecycle changes:  Created, Removed, Reachable, Unreachable, Unknown.
 
+ * Added the Linkedid header to the common channel headers listed for each
+   channel in AMI events.
+
 res_pjsip
 ------------------
 * A new 'g726_non_standard' endpoint option has been added that, when set to
index 8cbeaa3..6e4c5ac 100644 (file)
                 <xsl:value-of select="concat(@prefix,'Uniqueid')"/>
             </xsl:attribute>
         </xsl:element>
+        <xsl:element name="parameter">
+            <xsl:attribute name="name">
+                <xsl:value-of select="concat(@prefix,'Linkedid')"/>
+            </xsl:attribute>
+            <para>Uniqueid of the oldest channel associated with this channel.</para>
+        </xsl:element>
     </xsl:template>
 
     <xsl:template match="bridge_snapshot">
index da7eeba..da9bf47 100644 (file)
@@ -435,7 +435,8 @@ struct ast_str *ast_manager_build_channel_state_string_prefix(
                "%sContext: %s\r\n"
                "%sExten: %s\r\n"
                "%sPriority: %d\r\n"
-               "%sUniqueid: %s\r\n",
+               "%sUniqueid: %s\r\n"
+               "%sLinkedid: %s\r\n",
                prefix, snapshot->name,
                prefix, snapshot->state,
                prefix, ast_state2str(snapshot->state),
@@ -448,7 +449,8 @@ struct ast_str *ast_manager_build_channel_state_string_prefix(
                prefix, snapshot->context,
                prefix, snapshot->exten,
                prefix, snapshot->priority,
-               prefix, snapshot->uniqueid);
+               prefix, snapshot->uniqueid,
+               prefix, snapshot->linkedid);
 
        if (!res) {
                ast_free(out);
index 23cf2f0..bb5bc03 100644 (file)
                                <configOption name="rewrite_contact">
                                        <synopsis>Allow Contact header to be rewritten with the source IP address-port</synopsis>
                                        <description><para>
-                                               On inbound SIP messages from this endpoint, the Contact header will be changed to have the
-                                               source IP address and port. This option does not affect outbound messages send to this
-                                               endpoint.
+                                               On inbound SIP messages from this endpoint, the Contact header or an appropriate Record-Route
+                                               header will be changed to have the source IP address and port. This option does not affect
+                                               outbound messages sent to this endpoint.
                                        </para></description>
                                </configOption>
                                <configOption name="rtp_ipv6" default="no">
index c717ba2..fadefd8 100644 (file)
 #include "asterisk/module.h"
 #include "asterisk/acl.h"
 
-static pj_bool_t handle_rx_message(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
+static void rewrite_uri(pjsip_rx_data *rdata, pjsip_sip_uri *uri)
 {
-       pjsip_contact_hdr *contact;
+       pj_cstr(&uri->host, rdata->pkt_info.src_name);
+       if (strcasecmp("udp", rdata->tp_info.transport->type_name)) {
+               uri->transport_param = pj_str(rdata->tp_info.transport->type_name);
+       } else {
+               uri->transport_param.slen = 0;
+       }
+       uri->port = rdata->pkt_info.src_port;
+}
 
-       if (!endpoint) {
-               return PJ_FALSE;
+static int rewrite_route_set(pjsip_rx_data *rdata, pjsip_dialog *dlg)
+{
+       pjsip_rr_hdr *rr = NULL;
+       pjsip_sip_uri *uri;
+
+       if (rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG) {
+               pjsip_hdr *iter;
+               for (iter = rdata->msg_info.msg->hdr.prev; iter != &rdata->msg_info.msg->hdr; iter = iter->prev) {
+                       if (iter->type == PJSIP_H_RECORD_ROUTE) {
+                               rr = (pjsip_rr_hdr *)iter;
+                               break;
+                       }
+               }
+       } else {
+               rr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_RECORD_ROUTE, NULL);
+       }
+
+       if (rr) {
+               uri = pjsip_uri_get_uri(&rr->name_addr);
+               rewrite_uri(rdata, uri);
+               if (dlg && dlg->route_set.next && !dlg->route_set_frozen) {
+                       pjsip_routing_hdr *route = dlg->route_set.next;
+                       uri = pjsip_uri_get_uri(&route->name_addr);
+                       rewrite_uri(rdata, uri);
+               }
+
+               return 0;
        }
 
-       if (endpoint->nat.rewrite_contact && (contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL)) &&
-               !contact->star && (PJSIP_URI_SCHEME_IS_SIP(contact->uri) || PJSIP_URI_SCHEME_IS_SIPS(contact->uri))) {
+       return -1;
+}
+
+static int rewrite_contact(pjsip_rx_data *rdata, pjsip_dialog *dlg)
+{
+       pjsip_contact_hdr *contact;
+
+       contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
+       if (contact && !contact->star && (PJSIP_URI_SCHEME_IS_SIP(contact->uri) || PJSIP_URI_SCHEME_IS_SIPS(contact->uri))) {
                pjsip_sip_uri *uri = pjsip_uri_get_uri(contact->uri);
-               pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
 
-               pj_cstr(&uri->host, rdata->pkt_info.src_name);
-               if (strcasecmp("udp", rdata->tp_info.transport->type_name)) {
-                       uri->transport_param = pj_str(rdata->tp_info.transport->type_name);
-               } else {
-                       uri->transport_param.slen = 0;
-               }
-               uri->port = rdata->pkt_info.src_port;
-               ast_debug(4, "Re-wrote Contact URI host/port to %.*s:%d\n",
-                       (int)pj_strlen(&uri->host), pj_strbuf(&uri->host), uri->port);
+               rewrite_uri(rdata, uri);
 
-               /* rewrite the session target since it may have already been pulled from the contact header */
-               if (dlg && (!dlg->remote.contact
+               if (dlg && !dlg->route_set_frozen && (!dlg->remote.contact
                        || pjsip_uri_cmp(PJSIP_URI_IN_REQ_URI, dlg->remote.contact->uri, contact->uri))) {
                        dlg->remote.contact = (pjsip_contact_hdr*)pjsip_hdr_clone(dlg->pool, contact);
                        dlg->target = dlg->remote.contact->uri;
                }
+               return 0;
+       }
+
+       return -1;
+}
+
+static pj_bool_t handle_rx_message(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
+{
+       pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
+
+       if (!endpoint) {
+               return PJ_FALSE;
+       }
+
+       if (endpoint->nat.rewrite_contact) {
+               /* rewrite_contact is intended to ensure we send requests/responses to
+                * a routeable address when NAT is involved. The URI that dictates where
+                * we send requests/responses can be determined either by Record-Route
+                * headers or by the Contact header if no Record-Route headers are present.
+                * We therefore will attempt to rewrite a Record-Route header first, and if
+                * none are present, we fall back to rewriting the Contact header instead.
+                */
+               if (rewrite_route_set(rdata, dlg)) {
+                       rewrite_contact(rdata, dlg);
+               }
        }
 
        if (endpoint->nat.force_rport) {
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);
 }