diff --git a/channels/chan_sip.c b/channels/chan_sip.c index c86b0bded1..f43fd73ab6 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -3809,6 +3809,7 @@ static int reqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod, in char newto[256]; char *c, *n; char *ot, *of; + int is_strict = 0; /* Strict routing flag */ memset(req, 0, sizeof(struct sip_request)); @@ -3823,17 +3824,23 @@ static int reqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod, in p->branch ^= rand(); build_via(p, p->via, sizeof(p->via)); } + + + /* Check for strict or loose router */ + if (p->route && !ast_strlen_zero(p->route->hop) && strstr(p->route->hop,";lr") == NULL) + is_strict = 1; + if (sipmethod == SIP_CANCEL) { c = p->initreq.rlPart2; /* Use original URI */ } else if (sipmethod == SIP_ACK) { /* Use URI from Contact: in 200 OK (if INVITE) (we only have the contacturi on INVITEs) */ if (!ast_strlen_zero(p->okcontacturi)) - c = p->okcontacturi; - else - c = p->initreq.rlPart2; + c = is_strict ? p->route->hop : p->okcontacturi; + else + c = p->initreq.rlPart2; } else if (!ast_strlen_zero(p->okcontacturi)) { - c = p->okcontacturi; /* Use for BYE, REFER or REINVITE */ + c = is_strict ? p->route->hop : p->okcontacturi; /* Use for BYE or REINVITE */ } else if (!ast_strlen_zero(p->uri)) { c = p->uri; } else { @@ -3852,7 +3859,10 @@ static int reqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod, in add_header(req, "Via", p->via); if (p->route) { set_destination(p, p->route->hop); - add_route(req, p->route->next); + if (is_strict) + add_route(req, p->route->next); + else + add_route(req, p->route); } ot = get_header(orig, "To"); @@ -5486,33 +5496,38 @@ static void build_route(struct sip_pvt *p, struct sip_request *req, int backward rr += len; } } - /* 2nd append the Contact: if there is one */ - /* Can be multiple Contact headers, comma separated values - we just take the first */ - contact = get_header(req, "Contact"); - if (!ast_strlen_zero(contact)) { - ast_log(LOG_DEBUG, "build_route: Contact hop: %s\n", contact); - /* Look for <: delimited address */ - c = strchr(contact, '<'); - if (c) { - /* Take to > */ - ++c; - len = strcspn(c, ">") + 1; - } else { - /* No <> - just take the lot */ - c = contact; - len = strlen(contact) + 1; - } - thishop = malloc(sizeof(*thishop) + len); - if (thishop) { - ast_copy_string(thishop->hop, c, len); - thishop->next = NULL; - /* Goes at the end */ - if (tail) - tail->next = thishop; - else - head = thishop; + + /* Only append the contact if we are dealing with a strict router */ + if (!head || (!ast_strlen_zero(head->hop) && strstr(head->hop,";lr") == NULL) ) { + /* 2nd append the Contact: if there is one */ + /* Can be multiple Contact headers, comma separated values - we just take the first */ + contact = get_header(req, "Contact"); + if (!ast_strlen_zero(contact)) { + ast_log(LOG_DEBUG, "build_route: Contact hop: %s\n", contact); + /* Look for <: delimited address */ + c = strchr(contact, '<'); + if (c) { + /* Take to > */ + ++c; + len = strcspn(c, ">") + 1; + } else { + /* No <> - just take the lot */ + c = contact; + len = strlen(contact) + 1; + } + thishop = malloc(sizeof(*thishop) + len); + if (thishop) { + strcpy(thishop->hop, c); + thishop->next = NULL; + /* Goes at the end */ + if (tail) + tail->next = thishop; + else + head = thishop; + } } } + /* Store as new route */ p->route = head;