/* Calculate new target for the request */ static pj_status_t proxy_calculate_target(pjsip_rx_data *rdata, pjsip_tx_data *tdata) { pjsip_sip_uri *target; /* RFC 3261 Section 16.5 Determining Request Targets */ target = (pjsip_sip_uri*) tdata->msg->line.req.uri; /* If the Request-URI of the request contains an maddr parameter, the * Request-URI MUST be placed into the target set as the only target * URI, and the proxy MUST proceed to Section 16.6. */ if (target->maddr_param.slen) { proxy_postprocess(tdata); return PJ_SUCCESS; } /* If the domain of the Request-URI indicates a domain this element is * not responsible for, the Request-URI MUST be placed into the target * set as the only target, and the element MUST proceed to the task of * Request Forwarding (Section 16.6). */ if (!is_uri_local(target)) { proxy_postprocess(tdata); return PJ_SUCCESS; } /* If the target set for the request has not been predetermined as * described above, this implies that the element is responsible for the * domain in the Request-URI, and the element MAY use whatever mechanism * it desires to determine where to send the request. */ /* We're not interested to receive request destined to us, so * respond with 404/Not Found (only if request is not ACK!). */ if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) { pjsip_endpt_respond_stateless(global.endpt, rdata, PJSIP_SC_NOT_FOUND, NULL, NULL, NULL); } /* Delete the request since we're not forwarding it */ pjsip_tx_data_dec_ref(tdata); return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_FOUND); }
// Return true if there are no route headers, or there is exactly one, // which is local bool PJUtils::check_route_headers(pjsip_rx_data* rdata) { // Get all the route headers int count = 0; bool local = true; pjsip_route_hdr* route_hdr = (pjsip_route_hdr*)pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_ROUTE, NULL); while (route_hdr != NULL) { count++; local = (is_uri_local(route_hdr->name_addr.uri)) || (is_home_domain(route_hdr->name_addr.uri)); route_hdr = (pjsip_route_hdr*)pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_ROUTE, route_hdr->next); } return (count < 2 && local); }
/// Checks whether the next Route header in the message refers to this node, /// and optionally returns the header. If there are no Route headers it /// returns false. pj_bool_t PJUtils::is_next_route_local(const pjsip_msg* msg, pjsip_route_hdr* start, pjsip_route_hdr** hdr) { bool rc = false; pjsip_route_hdr* route_hdr = (pjsip_route_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_ROUTE, (start != NULL) ? start->next : NULL); if (route_hdr != NULL) { // Found the next Route header, so check whether the URI corresponds to // this node or one of its aliases. pjsip_uri* uri = route_hdr->name_addr.uri; LOG_DEBUG("Found Route header, URI = %s", uri_to_string(PJSIP_URI_IN_ROUTING_HDR, uri).c_str()); if ((is_home_domain(uri)) || (is_uri_local(uri))) { rc = true; if (hdr != NULL) { *hdr = route_hdr; } } } return rc; }
/* Process route information in the reqeust */ static pj_status_t proxy_process_routing(pjsip_tx_data *tdata) { pjsip_sip_uri *target; pjsip_route_hdr *hroute; /* RFC 3261 Section 16.4 Route Information Preprocessing */ target = (pjsip_sip_uri*) tdata->msg->line.req.uri; /* The proxy MUST inspect the Request-URI of the request. If the * Request-URI of the request contains a value this proxy previously * placed into a Record-Route header field (see Section 16.6 item 4), * the proxy MUST replace the Request-URI in the request with the last * value from the Route header field, and remove that value from the * Route header field. The proxy MUST then proceed as if it received * this modified request. */ if (is_uri_local(target)) { pjsip_route_hdr *r; pjsip_sip_uri *uri; /* Find the first Route header */ r = hroute = (pjsip_route_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL); if (r == NULL) { /* No Route header. This request is destined for this proxy. */ return PJ_SUCCESS; } /* Find the last Route header */ while ( (r=(pjsip_route_hdr*)pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, r->next)) != NULL ) { hroute = r; } /* If the last Route header doesn't have ";lr" parameter, then * this is a strict-routed request indeed, and we follow the steps * in processing strict-route requests above. * * But if it does contain ";lr" parameter, skip the strict-route * processing. */ uri = (pjsip_sip_uri*) pjsip_uri_get_uri(&hroute->name_addr); if (uri->lr_param == 0) { /* Yes this is strict route, so: * - replace req URI with the URI in Route header, * - remove the Route header, * - proceed as if it received this modified request. */ tdata->msg->line.req.uri = hroute->name_addr.uri; target = (pjsip_sip_uri*) tdata->msg->line.req.uri; pj_list_erase(hroute); } } /* If the Request-URI contains a maddr parameter, the proxy MUST check * to see if its value is in the set of addresses or domains the proxy * is configured to be responsible for. If the Request-URI has a maddr * parameter with a value the proxy is responsible for, and the request * was received using the port and transport indicated (explicitly or by * default) in the Request-URI, the proxy MUST strip the maddr and any * non-default port or transport parameter and continue processing as if * those values had not been present in the request. */ if (target->maddr_param.slen != 0) { pjsip_sip_uri maddr_uri; maddr_uri.host = target->maddr_param; maddr_uri.port = global.port; if (is_uri_local(&maddr_uri)) { target->maddr_param.slen = 0; target->port = 0; target->transport_param.slen = 0; } } /* If the first value in the Route header field indicates this proxy, * the proxy MUST remove that value from the request. */ hroute = (pjsip_route_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL); if (hroute && is_uri_local((pjsip_sip_uri*)hroute->name_addr.uri)) { pj_list_erase(hroute); } return PJ_SUCCESS; }