Allow controlling the number of (re)transmission per SIP transaction.

git-svn-id: http://yate.null.ro/svn/yate/trunk@5844 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2014-06-12 09:50:50 +00:00
parent 45931bec7f
commit 41241ca8fc
3 changed files with 54 additions and 14 deletions

View File

@ -28,7 +28,8 @@ using namespace TelEngine;
// Constructor from new message
SIPTransaction::SIPTransaction(SIPMessage* message, SIPEngine* engine, bool outgoing)
: m_outgoing(outgoing), m_invite(false), m_transmit(false), m_state(Invalid), m_response(0), m_timeout(0),
: m_outgoing(outgoing), m_invite(false), m_transmit(false), m_state(Invalid),
m_response(0), m_timeouts(0), m_timeout(0),
m_firstMessage(message), m_lastMessage(0), m_pending(0), m_engine(engine), m_private(0)
{
DDebug(getEngine(),DebugAll,"SIPTransaction::SIPTransaction(%p,%p,%d) [%p]",
@ -64,13 +65,15 @@ SIPTransaction::SIPTransaction(SIPMessage* message, SIPEngine* engine, bool outg
}
m_invite = (getMethod() == YSTRING("INVITE"));
m_state = Initial;
m_transCount = outgoing ? m_engine->getReqTransCount() : m_engine->getRspTransCount();
m_engine->append(this);
}
// Constructor from original and authentication requesting answer
SIPTransaction::SIPTransaction(SIPTransaction& original, SIPMessage* answer)
: m_outgoing(true), m_invite(original.m_invite), m_transmit(false),
m_state(Process), m_response(original.m_response), m_timeout(0),
: m_outgoing(true), m_invite(original.m_invite), m_transmit(false), m_state(Process),
m_response(original.m_response), m_transCount(original.m_transCount),
m_timeouts(0), m_timeout(0),
m_firstMessage(original.m_firstMessage), m_lastMessage(original.m_lastMessage),
m_pending(0), m_engine(original.m_engine),
m_branch(original.m_branch), m_callid(original.m_callid), m_tag(original.m_tag),
@ -113,8 +116,9 @@ SIPTransaction::SIPTransaction(SIPTransaction& original, SIPMessage* answer)
// Constructor from original and forked dialog tag
SIPTransaction::SIPTransaction(const SIPTransaction& original, const String& tag)
: m_outgoing(true), m_invite(original.m_invite), m_transmit(false),
m_state(Process), m_response(original.m_response), m_timeout(0),
: m_outgoing(true), m_invite(original.m_invite), m_transmit(false), m_state(Process),
m_response(original.m_response), m_transCount(original.m_transCount),
m_timeouts(0), m_timeout(0),
m_firstMessage(original.m_firstMessage), m_lastMessage(0),
m_pending(0), m_engine(original.m_engine),
m_branch(original.m_branch), m_callid(original.m_callid), m_tag(tag),
@ -230,6 +234,18 @@ void SIPTransaction::setPendingEvent(SIPEvent* event, bool replace)
m_pending = event;
}
void SIPTransaction::setTransCount(int count)
{
if (count < 0)
return;
else if (count < 2)
m_transCount = 2;
else if (count > 10)
m_transCount = 10;
else
m_transCount = count;
}
void SIPTransaction::setTimeout(u_int64_t delay, unsigned int count)
{
m_timeouts = count;
@ -319,7 +335,7 @@ void SIPTransaction::setResponse(SIPMessage* message)
bool reliable = message->getParty() && message->getParty()->isReliable();
bool retrans = !reliable || message->code < 300;
setTimeout(m_engine->getTimer(retrans ? 'G' : 'H',reliable),
retrans ? m_engine->getRspTransCount() : 1);
retrans ? getTransCount() : 1);
}
}
else {
@ -593,7 +609,7 @@ SIPEvent* SIPTransaction::getClientEvent(int state, int timeout)
if (changeState(Trying)) {
bool reliable = e->getParty() && e->getParty()->isReliable();
if (!reliable)
setTimeout(m_engine->getTimer(isInvite() ? 'A' : 'E'),m_engine->getReqTransCount());
setTimeout(m_engine->getTimer(isInvite() ? 'A' : 'E'),getTransCount());
else
setTimeout(m_engine->getTimer(isInvite() ? 'B' : 'F',true),1);
}
@ -706,9 +722,9 @@ void SIPTransaction::msgTransmitFailed(SIPMessage* msg)
if (msg != m_firstMessage)
return;
// Reliable transport: terminate now
// Non reliable: terminate if this is the first attempt
// Non reliable: terminate if this is the last attempt
if ((msg->getParty() && msg->getParty()->isReliable()) ||
m_engine->getReqTransCount() == m_timeouts) {
m_timeouts >= getTransCount()) {
Debug(getEngine(),DebugInfo,
"SIPTransaction send failed state=%s: clearing [%p]",
stateName(m_state),this);

View File

@ -837,6 +837,19 @@ public:
inline void setCleared()
{ changeState(Cleared); }
/**
* Get the transmission attempts count for non-reliable transports
* @return Current number of transmission attempts
*/
inline unsigned int getTransCount() const
{ return m_transCount; }
/**
* Set the number of transmission attempts for non-reliable transports
* @param count Transmission attempts, clamped between 2 and 10, negative values ignored
*/
void setTransCount(int count);
/**
* Send back an authentication required response
* @param realm Authentication realm to send in the answer
@ -1021,6 +1034,7 @@ protected:
bool m_transmit;
int m_state;
int m_response;
unsigned int m_transCount;
unsigned int m_timeouts;
u_int64_t m_delay;
u_int64_t m_timeout;

View File

@ -726,6 +726,7 @@ private:
int m_interval;
int m_alive;
int m_flags;
int m_trans;
SIPTransaction* m_tr;
bool m_marked;
bool m_valid;
@ -1057,7 +1058,7 @@ class YateSIPGenerate : public GenObject
{
YCLASS(YateSIPGenerate,GenObject)
public:
YateSIPGenerate(SIPMessage* m);
YateSIPGenerate(SIPMessage* m, int tries);
virtual ~YateSIPGenerate();
bool process(SIPEvent* ev);
inline bool busy() const
@ -5333,8 +5334,10 @@ void YateSIPEndPoint::regRun(const SIPMessage* message, SIPTransaction* t)
}
copySipHeaders(msg,*message,true,static_cast<const YateSIPEngine*>(t->getEngine())->foreignAuth());
SIPMessage* r = 0;
bool ok = Engine::dispatch(msg);
t->setTransCount(msg.getIntValue(YSTRING("xsip_trans_count"),-1));
// Always OK deregistration attempts
if (Engine::dispatch(msg) || dereg) {
if (ok || dereg) {
if (dereg) {
r = new SIPMessage(t->initialMessage(),200);
Debug(&plugin,DebugNote,"Unregistered user '%s'",user.c_str());
@ -5508,6 +5511,7 @@ bool YateSIPEndPoint::generic(const SIPMessage* message, SIPTransaction* t, cons
int code = 0;
bool ok = Engine::dispatch(m);
t->setTransCount(m.getIntValue(YSTRING("xsip_trans_count"),-1));
while (isMsg && ok) {
ok = m.retValue() && m.retValue() != YSTRING("-") &&
m.retValue() != YSTRING("error");
@ -6063,10 +6067,12 @@ YateSIPConnection::YateSIPConnection(Message& msg, const String& uri, const char
if (!sdp)
sdp = createRtpSDP(m_host,msg);
m->setBody(buildSIPBody(msg,sdp));
int tries = msg.getIntValue(YSTRING("xsip_trans_count"),-1);
m_tr = plugin.ep()->engine()->addMessage(m);
if (m_tr) {
m_tr->ref();
m_tr->setUserData(this);
m_tr->setTransCount(tries);
}
m->deref();
setMaxcall(msg);
@ -7574,6 +7580,7 @@ bool YateSIPConnection::callRouted(Message& msg)
if (m_hungup || !m_tr)
return false;
if (m_tr->getState() == SIPTransaction::Process) {
m_tr->setTransCount(msg.getIntValue(YSTRING("isip_trans_count"),-1));
String s(msg.retValue());
if (s.startSkip("sip/",false) && s && msg.getBoolValue(YSTRING("redirect"))) {
Debug(this,DebugAll,"YateSIPConnection redirecting to '%s' [%p]",s.c_str(),this);
@ -7969,7 +7976,7 @@ bool YateSIPConnection::sendTone(Message& msg, const char* tone, int meth, bool&
YateSIPLine::YateSIPLine(const String& name)
: String(name), Mutex(true,"YateSIPLine"),
m_resend(0), m_keepalive(0), m_interval(0), m_alive(0),
m_flags(-1), m_tr(0), m_marked(false), m_valid(false),
m_flags(-1), m_trans(-1), m_tr(0), m_marked(false), m_valid(false),
m_localPort(0), m_partyPort(0), m_localDetect(false),
m_keepTcpOffline(s_lineKeepTcpOffline),
m_matchPort(true), m_matchUser(true)
@ -8126,6 +8133,7 @@ void YateSIPLine::login()
if (m_tr) {
m_tr->ref();
m_tr->setUserData(this);
m_tr->setTransCount(m_trans);
if (m_callid.null())
m_callid = m_tr->getCallID();
}
@ -8327,6 +8335,7 @@ bool YateSIPLine::update(const Message& msg)
chg = change(m_password,msg.getValue(YSTRING("password"))) || chg;
chg = change(m_domain,msg.getValue(YSTRING("domain"))) || chg;
chg = change(m_flags,msg.getIntValue(YSTRING("xsip_flags"),-1)) || chg;
m_trans = msg.getIntValue(YSTRING("xsip_trans_count"),-1);
m_display = msg.getValue(YSTRING("description"));
m_interval = msg.getIntValue(YSTRING("interval"),600);
m_matchPort = msg.getBoolValue(YSTRING("match_port"),true);
@ -8407,13 +8416,14 @@ void YateSIPLine::transportChangedStatus(int stat, const String& reason)
}
}
YateSIPGenerate::YateSIPGenerate(SIPMessage* m)
YateSIPGenerate::YateSIPGenerate(SIPMessage* m, int tries)
: m_tr(0), m_code(0)
{
m_tr = plugin.ep()->engine()->addMessage(m);
if (m_tr) {
m_tr->ref();
m_tr->setUserData(this);
m_tr->setTransCount(tries);
}
m->deref();
}
@ -9055,7 +9065,7 @@ bool SIPDriver::sendMethod(Message& msg, const char* method, bool msgExec,
sip->deref();
return true;
}
YateSIPGenerate gen(sip);
YateSIPGenerate gen(sip,msg.getIntValue(YSTRING("xsip_trans_count"),-1));
while (gen.busy())
Thread::idle();
if (gen.code()) {