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.
sayer/1.4-spce2.6
Raphael Coeffic 16 years ago
parent a78d6347d5
commit f50051ddf3

@ -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);

@ -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)

@ -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);

Loading…
Cancel
Save