diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 2a49d53370..c901d05474 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -1280,7 +1280,7 @@ static int auto_congest(const void *arg); static struct sip_pvt *find_call(struct sip_request *req, struct ast_sockaddr *addr, const int intended_method); static void free_old_route(struct sip_route *route); static void list_route(struct sip_route *route); -static void build_route(struct sip_pvt *p, struct sip_request *req, int backwards); +static void build_route(struct sip_pvt *p, struct sip_request *req, int backwards, int resp); static enum check_auth_result register_verify(struct sip_pvt *p, struct ast_sockaddr *addr, struct sip_request *req, const char *uri); static struct sip_pvt *get_sip_pvt_byid_locked(const char *callid, const char *totag, const char *fromtag); @@ -10353,7 +10353,11 @@ static int reqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod, ui snprintf(tmp, sizeof(tmp), "%u %s", seqno, sip_methods[sipmethod].text); add_header(req, "Via", p->via); - if (p->route) { + /* + * Use the learned route set unless this is a CANCEL. For a CANCEL + * we have to send to the same destination as the original INVITE. + */ + if (p->route && sipmethod != SIP_CANCEL) { set_destination(p, p->route->hop); add_route(req, is_strict ? p->route->next : p->route); } @@ -14151,8 +14155,9 @@ static void list_route(struct sip_route *route) } } -/*! \brief Build route list from Record-Route header */ -static void build_route(struct sip_pvt *p, struct sip_request *req, int backwards) +/*! \brief Build route list from Record-Route header + \param resp the SIP response code or 0 for a request */ +static void build_route(struct sip_pvt *p, struct sip_request *req, int backwards, int resp) { struct sip_route *thishop, *head, *tail; int start = 0; @@ -14170,9 +14175,12 @@ static void build_route(struct sip_pvt *p, struct sip_request *req, int backward p->route = NULL; } - /* We only want to create the route set the first time this is called */ - p->route_persistent = 1; - + /* We only want to create the route set the first time this is called except + it is called from a provisional response.*/ + if ((resp < 100) || (resp > 199)) { + p->route_persistent = 1; + } + /* Build a tailq, then assign it to p->route when done. * If backwards, we add entries from the head so they end up * in reverse order. However, we do need to maintain a correct @@ -19969,7 +19977,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest * */ parse_ok_contact(p, req); if (!reinvite) { - build_route(p, req, 1); + build_route(p, req, 1, resp); } if (!req->ignore && p->owner) { if (get_rpid(p, req)) { @@ -20019,7 +20027,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest * */ parse_ok_contact(p, req); if (!reinvite) { - build_route(p, req, 1); + build_route(p, req, 1, resp); } if (!req->ignore && p->owner) { struct ast_party_redirecting redirecting; @@ -20045,7 +20053,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest * */ parse_ok_contact(p, req); if (!reinvite) { - build_route(p, req, 1); + build_route(p, req, 1, resp); } if (!req->ignore && p->owner) { if (get_rpid(p, req)) { @@ -20145,7 +20153,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest parse_ok_contact(p, req); /* Save Record-Route for any later requests we make on this dialogue */ if (!reinvite) - build_route(p, req, 1); + build_route(p, req, 1, resp); if(set_address_from_contact(p)) { /* Bad contact - we don't know how to reach this device */ @@ -22649,7 +22657,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int *recount = 1; /* Save Record-Route for any later requests we make on this dialogue */ - build_route(p, req, 0); + build_route(p, req, 0, 0); if (c) { ast_party_redirecting_init(&redirecting); @@ -24531,7 +24539,7 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, if (sipdebug) ast_debug(4, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); check_via(p, req); - build_route(p, req, 0); + build_route(p, req, 0, 0); } else if (req->debug && req->ignore) ast_verbose("Ignoring this SUBSCRIBE request\n");