mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-04 11:58:52 +00:00
res/res_pjsip_nat: Fix logic for REINVITES
The presence of Record-Route in re-invites is optional, thus it is important to make sure the dialog doesn't have a routset before rewriting the contact header. ASTERISK-28129 #close Change-Id: Ic8ceb54ccfc93f7e315e476c514a2c777f2da7dc
This commit is contained in:
committed by
Joshua Colp
parent
2c35dfc502
commit
da4879443b
@@ -45,10 +45,42 @@ static void rewrite_uri(pjsip_rx_data *rdata, pjsip_sip_uri *uri)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update the Record-Route headers in the request or response and in the dialog
|
||||||
|
* object if exists.
|
||||||
|
*
|
||||||
|
* When NAT is in use, the address of the next hop in the SIP may be incorrect.
|
||||||
|
* To address this asterisk uses two strategies in parallel:
|
||||||
|
* 1. intercept the messages at the transaction level and rewrite the
|
||||||
|
* messages before arriving at the dialog layer
|
||||||
|
* 2. after the application processing, update the dialog object with the
|
||||||
|
* correct information
|
||||||
|
*
|
||||||
|
* The first strategy has a limitation that the SIP message may not have all
|
||||||
|
* the information required to determine if the next hop is in the route set
|
||||||
|
* or in the contact. Causing risk that asterisk will update the Contact on
|
||||||
|
* receipt of an in-dialog message despite there being a route set saved in
|
||||||
|
* the dialog.
|
||||||
|
*
|
||||||
|
* The second strategy has a limitation that not all UAC layers have interfaces
|
||||||
|
* available to invoke this module after dialog creation. (pjsip_sesion does
|
||||||
|
* but pjsip_pubsub does not), thus this strategy can't update the dialog in
|
||||||
|
* all cases needed.
|
||||||
|
*
|
||||||
|
* The ideal solution would be to implement an "incomming_request" event
|
||||||
|
* in pubsub module that can then pass the dialog object to this module
|
||||||
|
* on SUBSCRIBE, this module then should add itself as a listener to the dialog
|
||||||
|
* for the subsequent requests and responses & then be able to properly update
|
||||||
|
* the dialog object for all required events.
|
||||||
|
*/
|
||||||
|
|
||||||
static int rewrite_route_set(pjsip_rx_data *rdata, pjsip_dialog *dlg)
|
static int rewrite_route_set(pjsip_rx_data *rdata, pjsip_dialog *dlg)
|
||||||
{
|
{
|
||||||
pjsip_rr_hdr *rr = NULL;
|
pjsip_rr_hdr *rr = NULL;
|
||||||
pjsip_sip_uri *uri;
|
pjsip_sip_uri *uri;
|
||||||
|
int res = -1;
|
||||||
|
int ignore_rr = 0;
|
||||||
|
int pubsub = 0;
|
||||||
|
|
||||||
if (rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG) {
|
if (rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG) {
|
||||||
pjsip_hdr *iter;
|
pjsip_hdr *iter;
|
||||||
@@ -60,21 +92,49 @@ static int rewrite_route_set(pjsip_rx_data *rdata, pjsip_dialog *dlg)
|
|||||||
}
|
}
|
||||||
} else if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_register_method)) {
|
} else if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_register_method)) {
|
||||||
rr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_RECORD_ROUTE, NULL);
|
rr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_RECORD_ROUTE, NULL);
|
||||||
|
} else {
|
||||||
|
/**
|
||||||
|
* Record-Route header has no meaning in REGISTER requests
|
||||||
|
* and should be ignored
|
||||||
|
*/
|
||||||
|
ignore_rr = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pjsip_method_cmp(&rdata->msg_info.cseq->method, &pjsip_subscribe_method) ||
|
||||||
|
!pjsip_method_cmp(&rdata->msg_info.cseq->method, &pjsip_notify_method)) {
|
||||||
|
/**
|
||||||
|
* There is currently no good way to get the dlg object for a pubsub dialog
|
||||||
|
* so we will just look at the rr & contact of the current message and
|
||||||
|
* hope for the best
|
||||||
|
*/
|
||||||
|
pubsub = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rr) {
|
if (rr) {
|
||||||
uri = pjsip_uri_get_uri(&rr->name_addr);
|
uri = pjsip_uri_get_uri(&rr->name_addr);
|
||||||
rewrite_uri(rdata, uri);
|
rewrite_uri(rdata, uri);
|
||||||
if (dlg && !pj_list_empty(&dlg->route_set) && !dlg->route_set_frozen) {
|
res = 0;
|
||||||
pjsip_routing_hdr *route = dlg->route_set.next;
|
|
||||||
uri = pjsip_uri_get_uri(&route->name_addr);
|
|
||||||
rewrite_uri(rdata, uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
if (dlg && !pj_list_empty(&dlg->route_set) && !dlg->route_set_frozen) {
|
||||||
|
pjsip_routing_hdr *route = dlg->route_set.next;
|
||||||
|
uri = pjsip_uri_get_uri(&route->name_addr);
|
||||||
|
rewrite_uri(rdata, uri);
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dlg && !rr && !ignore_rr && !pubsub && rdata->msg_info.to->tag.slen){
|
||||||
|
/**
|
||||||
|
* Even if this message doesn't have any route headers
|
||||||
|
* the dialog may, so wait until a later invocation that
|
||||||
|
* has a dialog reference to make sure there isn't a
|
||||||
|
* previously saved routset in the dialog before deciding
|
||||||
|
* the contact needs to be modified
|
||||||
|
*/
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rewrite_contact(pjsip_rx_data *rdata, pjsip_dialog *dlg)
|
static int rewrite_contact(pjsip_rx_data *rdata, pjsip_dialog *dlg)
|
||||||
|
Reference in New Issue
Block a user