Module: sems Branch: master Commit: f50051ddf3cb9703bb9eeb5a056b66d03d26a230 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sems/?a=commit;h=f50051ddf3cb9703bb9eeb5a056b66d03d26a230
Author: Raphael Coeffic <[email protected]> Committer: Raphael Coeffic <[email protected]> Date: Fri Feb 25 15:19:17 2011 +0100 b/f: PRACK transaction matching. PRACK should be first matched using normal transaction matching to identify retransmissions. Then, it can be matched against the original INVITE transaction to disable the re-transmission timers. --- core/sip/trans_layer.cpp | 8 ++-- core/sip/trans_table.cpp | 99 ++++++++++++++++++++++++++------------------- core/sip/trans_table.h | 5 ++- 3 files changed, 65 insertions(+), 47 deletions(-) diff --git a/core/sip/trans_layer.cpp b/core/sip/trans_layer.cpp index 341230a..85fe929 100644 --- a/core/sip/trans_layer.cpp +++ b/core/sip/trans_layer.cpp @@ -1116,8 +1116,7 @@ void _trans_layer::received_msg(sip_msg* msg) DBG("trans_layer::update_uas_trans() failed!\n"); // Anyway, there is nothing we can do... } - else if((err == TS_TERMINATED) || - (err == TS_REMOVED)){ + else { // do not touch the transaction anymore: // it could have been deleted !!! @@ -1129,7 +1128,8 @@ void _trans_layer::received_msg(sip_msg* msg) // the UA. assert(ua); DBG("Passing ACK to the UA.\n"); - ua->handle_sip_request(trans_ticket(t,bucket),msg); + ua->handle_sip_request(trans_ticket(), // dummy + msg); DROP_MSG; } @@ -1161,7 +1161,7 @@ void _trans_layer::received_msg(sip_msg* msg) inv_h = hash(msg->callid->value, get_rack(msg)->cseq_str); inv_bucket = get_trans_bucket(inv_h); inv_bucket->lock(); - if((inv_t = inv_bucket->match_request(msg)) != NULL) { + if((inv_t = inv_bucket->match_1xx_prack(msg)) != NULL) { assert(msg->u.request->method != inv_t->msg->u.request->method); err = update_uas_request(inv_bucket,inv_t,msg); diff --git a/core/sip/trans_table.cpp b/core/sip/trans_table.cpp index 680685f..4ac6be4 100644 --- a/core/sip/trans_table.cpp +++ b/core/sip/trans_table.cpp @@ -98,14 +98,14 @@ sip_trans* trans_bucket::match_request(sip_msg* msg) } if(msg->u.request->method != (*it)->msg->u.request->method) { - if((*it)->msg->u.request->method == sip_request::INVITE) { - if(msg->u.request->method == sip_request::ACK) { - if ((t = match_200_ack(*it,msg))) - break; - } else if(msg->u.request->method == sip_request::PRACK) { - if ((t = match_1xx_prack(*it,msg))) - break; - } + + // ACK is the only request that should match an existing + // transaction without being a re-transmission + if( ((*it)->msg->u.request->method == sip_request::INVITE) + && (msg->u.request->method == sip_request::ACK) + && (t = match_200_ack(*it,msg)) ){ + + break; } continue; @@ -335,48 +335,63 @@ sip_trans* trans_bucket::match_200_ack(sip_trans* t, sip_msg* msg) return t; } -sip_trans* trans_bucket::match_1xx_prack(sip_trans* t, sip_msg* msg) +sip_trans* trans_bucket::match_1xx_prack(sip_msg* msg) { - /* first, check quickly if lenghts match (From tag, To tag, Call-ID) */ - - sip_from_to* from = dynamic_cast<sip_from_to*>(msg->from->p); - sip_from_to* t_from = dynamic_cast<sip_from_to*>(t->msg->from->p); - if(from->tag.len != t_from->tag.len) - return 0; - - sip_from_to* to = dynamic_cast<sip_from_to*>(msg->to->p); - if(to->tag.len != t->to_tag.len) - return 0; - - if(msg->callid->value.len != t->msg->callid->value.len) - return 0; - + DBG("Matching %.*s request\n", + msg->u.request->method_str.len, + msg->u.request->method_str.s); - sip_rack *rack = dynamic_cast<sip_rack *>(msg->rack->p); - sip_cseq* t_cseq = dynamic_cast<sip_cseq*>(t->msg->cseq->p); - if (rack->cseq != t_cseq->num) - return 0; + if(elmts.empty()) + return NULL; + + trans_list::iterator it = elmts.begin(); + for(;it!=elmts.end();++it) { + + if( (*it)->msg->type != SIP_REQUEST ){ + continue; + } + sip_trans* t = *it; - if (rack->rseq != t->last_rseq) - return 0; + /* first, check quickly if lenghts match (From tag, To tag, Call-ID) */ - if (rack->method != t->msg->u.request->method) - return 0; + sip_from_to* from = dynamic_cast<sip_from_to*>(msg->from->p); + sip_from_to* t_from = dynamic_cast<sip_from_to*>(t->msg->from->p); + if(from->tag.len != t_from->tag.len) + continue; + sip_from_to* to = dynamic_cast<sip_from_to*>(msg->to->p); + if(to->tag.len != t->to_tag.len) + continue; + + if(msg->callid->value.len != t->msg->callid->value.len) + continue; - /* numbers fit, try content */ + sip_rack *rack = dynamic_cast<sip_rack *>(msg->rack->p); + sip_cseq* t_cseq = dynamic_cast<sip_cseq*>(t->msg->cseq->p); + if (rack->cseq != t_cseq->num) + continue; + + if (rack->rseq != t->last_rseq) + continue; + + if (rack->method != t->msg->u.request->method) + continue; + + /* numbers fit, try content */ + if(memcmp(from->tag.s,t_from->tag.s,from->tag.len)) + continue; + + if(memcmp(msg->callid->value.s,t->msg->callid->value.s, + msg->callid->value.len)) + continue; + + if(memcmp(to->tag.s,t->to_tag.s,to->tag.len)) + continue; - if(memcmp(from->tag.s,t_from->tag.s,from->tag.len)) - return NULL; + return t; + } - if(memcmp(msg->callid->value.s,t->msg->callid->value.s, - msg->callid->value.len)) - return NULL; - - if(memcmp(to->tag.s,t->to_tag.s,to->tag.len)) - return NULL; - - return t; + return NULL; } sip_trans* trans_bucket::add_trans(sip_msg* msg, int ttype) diff --git a/core/sip/trans_table.h b/core/sip/trans_table.h index 08b1643..1c2e0ea 100644 --- a/core/sip/trans_table.h +++ b/core/sip/trans_table.h @@ -24,6 +24,10 @@ public: // in this bucket sip_trans* match_request(sip_msg* msg); + // Match a PRACK request against transactions + // in this bucket + sip_trans* match_1xx_prack(sip_msg* msg); + // Match a reply to UAC transactions // in this bucket sip_trans* match_reply(sip_msg* msg); @@ -32,7 +36,6 @@ public: private: sip_trans* match_200_ack(sip_trans* t,sip_msg* msg); - sip_trans* match_1xx_prack(sip_trans* t,sip_msg* msg); }; trans_bucket* get_trans_bucket(const cstring& callid, const cstring& cseq_num); _______________________________________________ Semsdev mailing list [email protected] http://lists.iptel.org/mailman/listinfo/semsdev
