}
}
+/*
+ * 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;
}
} 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)