From d0554783e24ab47e9040d089922eeb568e94d90a Mon Sep 17 00:00:00 2001 From: Torrey Searle <torrey@voxbone.com> Date: Wed, 24 Oct 2018 14:38:37 +0200 Subject: [PATCH] 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 --- res/res_pjsip_nat.c | 74 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 7 deletions(-) diff --git a/res/res_pjsip_nat.c b/res/res_pjsip_nat.c index 1d42805d84..bbf33597c2 100644 --- a/res/res_pjsip_nat.c +++ b/res/res_pjsip_nat.c @@ -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) { pjsip_rr_hdr *rr = NULL; pjsip_sip_uri *uri; + int res = -1; + int ignore_rr = 0; + int pubsub = 0; if (rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG) { 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)) { 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) { uri = pjsip_uri_get_uri(&rr->name_addr); rewrite_uri(rdata, uri); - 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; + } - return 0; + 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; } - return -1; + 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) -- GitLab