summaryrefslogtreecommitdiff
path: root/channels
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2012-02-17 19:22:22 +0000
committerMark Michelson <mmichelson@digium.com>2012-02-17 19:22:22 +0000
commit8a20faa8d7c5b7feea2d8580172196d197c20835 (patch)
treeb3d2952d775cfcc8aa80d8b5e38f0baf2548af4f /channels
parent73b5346e7935980ebb31201ba53485051a5fd4d0 (diff)
Fix regressions with regards to route-set creation on early dialogs.
This fixes two main issues: 1. Asterisk would send a CANCEL to the route created by the provisional response instead of using the same destination it did in the initial INVITE. 2. If a new route set arrives in a 200 OK than was in the 1XX response (perfectly possible if our outbound INVITE gets forked), then the route set in the 200 OK needs to overwrite the route set in the 1XX response. (closes issue ASTERISK-19358) Reported by: Karsten Wemheuer Tested by: Karsten Wemheuer patches: ASTERISK-19358.patch uploaded by Mark Michelson (license 5049) ASTERISK-19358.patch uploaded by Stefan Schmidt (license 6034) Review: https://reviewboard.asterisk.org/r/1749 ........ Merged revisions 355732 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 355733 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@355745 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_sip.c34
1 files changed, 21 insertions, 13 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 1d8d4dbf6..d846737b2 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -1296,7 +1296,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);
@@ -8184,7 +8184,7 @@ static void forked_invite_init(struct sip_request *req, const char *new_theirtag
ast_string_field_set(p, our_contact, original->our_contact);
ast_string_field_set(p, fullcontact, original->fullcontact);
parse_ok_contact(p, req);
- build_route(p, req, 1);
+ build_route(p, req, 1, 0);
transmit_request(p, SIP_ACK, p->ocseq, XMIT_UNRELIABLE, TRUE);
transmit_request(p, SIP_BYE, 0, XMIT_RELIABLE, TRUE);
@@ -10663,7 +10663,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);
}
@@ -14632,8 +14636,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;
@@ -14651,8 +14656,11 @@ 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
@@ -20775,7 +20783,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)) {
@@ -20826,7 +20834,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;
@@ -20853,7 +20861,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)) {
@@ -20955,7 +20963,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)) {
@@ -23530,7 +23538,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);
@@ -25567,7 +25575,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");