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:
parent
45931bec7f
commit
41241ca8fc
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()) {
|
||||
|
|
Loading…
Reference in New Issue