Merge "res_pjsip_nat: Rewrite route set when required."

This commit is contained in:
Matt Jordan
2015-06-26 10:59:35 -05:00
committed by Gerrit Code Review
2 changed files with 78 additions and 24 deletions

View File

@@ -302,9 +302,9 @@
<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">

View File

@@ -32,34 +32,88 @@
#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)
{
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;
}
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;
}
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);
rewrite_uri(rdata, uri);
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 && (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))) {
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 the session target since it may have already been pulled from the contact header */
if (dlg && (!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;
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);
}
}