summaryrefslogtreecommitdiff
path: root/pjsip
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2007-11-05 23:14:18 +0000
committerBenny Prijono <bennylp@teluu.com>2007-11-05 23:14:18 +0000
commit64d35f1ec59ac48d81207b04b15020691f075845 (patch)
tree7383f51e1eb9854f394ea4d81203f509b9caf438 /pjsip
parent25e349017057a341703e5689039474403707455f (diff)
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: http://svn.pjsip.org/repos/pjproject/trunk@1550 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip')
-rw-r--r--pjsip/src/pjsip/sip_dialog.c58
1 files changed, 52 insertions, 6 deletions
diff --git a/pjsip/src/pjsip/sip_dialog.c b/pjsip/src/pjsip/sip_dialog.c
index b4317753..595574aa 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;
+
+ msg = rdata->msg_info.msg;
+ msg_cseq = rdata->msg_info.cseq->cseq;
- /* Ignore if route set has been set */
+ /* 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);
}