From 42307c7b7935fbb8412c5b1660d31b94d1b05265 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Mon, 5 Nov 2007 23:14:18 +0000 Subject: [PATCH] Update ticket #408: although route set must not be updated on subsequent requests, dialog MUST recompute the route set upon receiving 2xx response if the route set was previously computed from 1xx response git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@1550 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip/src/pjsip/sip_dialog.c | 58 ++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/pjsip/src/pjsip/sip_dialog.c b/pjsip/src/pjsip/sip_dialog.c index b43177532..595574aa9 100644 --- a/pjsip/src/pjsip/sip_dialog.c +++ b/pjsip/src/pjsip/sip_dialog.c @@ -642,7 +642,7 @@ PJ_DEF(pj_status_t) pjsip_dlg_fork( const pjsip_dialog *first_dlg, r = r->next; } - dlg->route_set_frozen = PJ_TRUE; + //dlg->route_set_frozen = PJ_TRUE; /* Clone client authentication session. */ status = pjsip_auth_clt_clone(dlg->pool, &dlg->auth_sess, @@ -1538,16 +1538,49 @@ on_return: } /* Update route-set from incoming message */ -static void dlg_update_routeset(pjsip_dialog *dlg, const pjsip_msg *msg) +static void dlg_update_routeset(pjsip_dialog *dlg, const pjsip_rx_data *rdata) { const pjsip_hdr *hdr, *end_hdr; + pj_int32_t msg_cseq; + const pjsip_msg *msg; - /* Ignore if route set has been set */ + msg = rdata->msg_info.msg; + msg_cseq = rdata->msg_info.cseq->cseq; + + /* Ignore if route set has been frozen */ if (dlg->route_set_frozen) return; + /* Only update route set if this message belongs to the same + * transaction as the initial transaction that establishes dialog. + */ + if (dlg->role == PJSIP_ROLE_UAC) { + + /* Ignore subsequent request from remote */ + if (msg->type != PJSIP_RESPONSE_MSG) + return; + + /* Ignore subsequent responses with higher CSeq than initial CSeq */ + if (msg_cseq != dlg->local.first_cseq) + return; + + } else { + + /* For callee dialog, route set should have been set by initial + * request and it will have been rejected by dlg->route_set_frozen + * check above. + */ + pj_assert(!"Should not happen"); + + } + + /* Based on the checks above, we should only get response message here */ + pj_assert(msg->type == PJSIP_RESPONSE_MSG); + + /* Reset route set */ pj_list_init(&dlg->route_set); + /* Update route set */ end_hdr = &msg->hdr; for (hdr=msg->hdr.prev; hdr!=end_hdr; hdr=hdr->prev) { if (hdr->type == PJSIP_H_RECORD_ROUTE) { @@ -1557,9 +1590,22 @@ static void dlg_update_routeset(pjsip_dialog *dlg, const pjsip_msg *msg) pj_list_push_back(&dlg->route_set, r); } } - dlg->route_set_frozen = PJ_TRUE; + + /* Freeze the route set only when the route set comes in 2xx response. + * If it is in 1xx response, prepare to recompute the route set when + * the 2xx response comes in. + * + * There is a debate whether route set should be frozen when the dialog + * is established with reliable provisional response, but I think + * it is safer to not freeze the route set (thus recompute the route set + * upon receiving 2xx response). Also RFC 3261 says so in 13.2.2.4. + */ + if (PJSIP_IS_STATUS_IN_CLASS(msg->line.status.code, 200)) { + dlg->route_set_frozen = PJ_TRUE; + } } + /* This function is called by user agent upon receiving incoming response * message. */ @@ -1618,7 +1664,7 @@ void pjsip_dlg_on_rx_response( pjsip_dialog *dlg, pjsip_rx_data *rdata ) * empty set. This route set, even if empty, overrides any pre-existing * route set for future requests in this dialog. */ - dlg_update_routeset(dlg, rdata->msg_info.msg); + dlg_update_routeset(dlg, rdata); /* The remote target MUST be set to the URI from the Contact header * field of the response. @@ -1678,7 +1724,7 @@ void pjsip_dlg_on_rx_response( pjsip_dialog *dlg, pjsip_rx_data *rdata ) dlg->target = dlg->remote.contact->uri; } - dlg_update_routeset(dlg, rdata->msg_info.msg); + dlg_update_routeset(dlg, rdata); }