Added methods making possible to handle forked INVITEs.
git-svn-id: http://yate.null.ro/svn/yate/trunk@610 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
485642968d
commit
0cd3df50ea
|
@ -237,7 +237,8 @@ SIPEngine::SIPEngine(const char* userAgent)
|
|||
m_t1(500000), m_t4(5000000), m_maxForwards(70),
|
||||
m_cseq(0), m_userAgent(userAgent), m_nonce_time(0)
|
||||
{
|
||||
DDebug(DebugInfo,"SIPEngine::SIPEngine() [%p]",this);
|
||||
debugName("sipengine");
|
||||
DDebug(this,DebugInfo,"SIPEngine::SIPEngine() [%p]",this);
|
||||
if (m_userAgent.null())
|
||||
m_userAgent << "YATE/" << YATE_VERSION;
|
||||
m_allowed = "ACK";
|
||||
|
@ -248,12 +249,12 @@ SIPEngine::SIPEngine(const char* userAgent)
|
|||
|
||||
SIPEngine::~SIPEngine()
|
||||
{
|
||||
DDebug(DebugInfo,"SIPEngine::~SIPEngine() [%p]",this);
|
||||
DDebug(this,DebugInfo,"SIPEngine::~SIPEngine() [%p]",this);
|
||||
}
|
||||
|
||||
SIPTransaction* SIPEngine::addMessage(SIPParty* ep, const char* buf, int len)
|
||||
{
|
||||
DDebug("SIPEngine",DebugInfo,"addMessage(%p,%d) [%p]",buf,len,this);
|
||||
DDebug(this,DebugInfo,"addMessage(%p,%d) [%p]",buf,len,this);
|
||||
SIPMessage* msg = SIPMessage::fromParsing(ep,buf,len);
|
||||
if (ep)
|
||||
ep->deref();
|
||||
|
@ -267,7 +268,7 @@ SIPTransaction* SIPEngine::addMessage(SIPParty* ep, const char* buf, int len)
|
|||
|
||||
SIPTransaction* SIPEngine::addMessage(SIPMessage* message)
|
||||
{
|
||||
DDebug("SIPEngine",DebugInfo,"addMessage(%p) [%p]",message,this);
|
||||
DDebug(this,DebugInfo,"addMessage(%p) [%p]",message,this);
|
||||
if (!message)
|
||||
return 0;
|
||||
// make sure outgoing messages are well formed
|
||||
|
@ -280,30 +281,51 @@ SIPTransaction* SIPEngine::addMessage(SIPMessage* message)
|
|||
if (!branch.startsWith("z9hG4bK"))
|
||||
branch.clear();
|
||||
Lock lock(m_mutex);
|
||||
SIPTransaction* forked = 0;
|
||||
ObjList* l = &TransList;
|
||||
for (; l; l = l->next()) {
|
||||
SIPTransaction* t = static_cast<SIPTransaction*>(l->get());
|
||||
if (t && t->processMessage(message,branch))
|
||||
return t;
|
||||
if (!t)
|
||||
continue;
|
||||
switch (t->processMessage(message,branch)) {
|
||||
case SIPTransaction::Matched:
|
||||
return t;
|
||||
case SIPTransaction::NoDialog:
|
||||
forked = t;
|
||||
break;
|
||||
case SIPTransaction::NoMatch:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (forked)
|
||||
return forkInvite(message,forked);
|
||||
|
||||
if (message->isAnswer()) {
|
||||
Debug("SIPEngine",DebugInfo,"Message %p was an unhandled answer [%p]",message,this);
|
||||
Debug(this,DebugInfo,"Message %p was an unhandled answer [%p]",message,this);
|
||||
return 0;
|
||||
}
|
||||
if (message->isACK()) {
|
||||
DDebug("SIPEngine",DebugAll,"Message %p was an unhandled ACK [%p]",message,this);
|
||||
DDebug(this,DebugAll,"Message %p was an unhandled ACK [%p]",message,this);
|
||||
return 0;
|
||||
}
|
||||
message->complete(this);
|
||||
return new SIPTransaction(message,this,message->isOutgoing());
|
||||
}
|
||||
|
||||
SIPTransaction* SIPEngine::forkInvite(SIPMessage* answer, const SIPTransaction* trans)
|
||||
{
|
||||
// TODO: build new transaction or CANCEL
|
||||
Debug(this,DebugInfo,"Message %p was a forked INVITE answer [%p]",answer,this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool SIPEngine::process()
|
||||
{
|
||||
SIPEvent* e = getEvent();
|
||||
if (!e)
|
||||
return false;
|
||||
DDebug("SIPEngine",DebugInfo,"process() got event %p",e);
|
||||
DDebug(this,DebugInfo,"process() got event %p",e);
|
||||
processEvent(e);
|
||||
return true;
|
||||
}
|
||||
|
@ -317,7 +339,7 @@ SIPEvent* SIPEngine::getEvent()
|
|||
if (t) {
|
||||
SIPEvent* e = t->getEvent();
|
||||
if (e) {
|
||||
DDebug("SIPEngine",DebugInfo,"Got event %p (state %s) from transaction %p [%p]",
|
||||
DDebug(this,DebugInfo,"Got event %p (state %s) from transaction %p [%p]",
|
||||
e,SIPTransaction::stateName(e->getState()),t,this);
|
||||
return e;
|
||||
}
|
||||
|
@ -336,7 +358,7 @@ void SIPEngine::processEvent(SIPEvent *event)
|
|||
type = "outgoing";
|
||||
if (event->isIncoming())
|
||||
type = "incoming";
|
||||
DDebug("SIPEngine",DebugAll,"Processing %s event %p message %p [%p]",
|
||||
DDebug(this,DebugAll,"Processing %s event %p message %p [%p]",
|
||||
type,event,event->getMessage(),this);
|
||||
if (event->getMessage()) {
|
||||
if (event->isOutgoing()) {
|
||||
|
@ -354,7 +376,7 @@ void SIPEngine::processEvent(SIPEvent *event)
|
|||
if (event->isIncoming()) {
|
||||
if ((event->getState() == SIPTransaction::Trying) &&
|
||||
!event->getMessage()->isAnswer()) {
|
||||
Debug("SIPEngine",DebugInfo,"Rejecting unhandled request '%s' in event %p [%p]",
|
||||
Debug(this,DebugInfo,"Rejecting unhandled request '%s' in event %p [%p]",
|
||||
event->getMessage()->method.c_str(),event,this);
|
||||
event->getTransaction()->setResponse(405);
|
||||
}
|
||||
|
@ -416,7 +438,7 @@ u_int64_t SIPEngine::getTimer(char which, bool reliable) const
|
|||
// K: Wait time for response retransmits
|
||||
return reliable ? 0 : m_t4;
|
||||
}
|
||||
Debug("SIPEngine",DebugMild,"Requested invalid timer '%c' [%p]",which,this);
|
||||
Debug(this,DebugMild,"Requested invalid timer '%c' [%p]",which,this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -431,7 +453,7 @@ void SIPEngine::nonceGet(String& nonce)
|
|||
MD5 md5(tmp);
|
||||
m_nonce = md5.hexDigest();
|
||||
m_nonce << "." << t;
|
||||
XDebug("SIPEngine",DebugAll,"Generated new nonce '%s' [%p]",
|
||||
XDebug(this,DebugAll,"Generated new nonce '%s' [%p]",
|
||||
m_nonce.c_str(),this);
|
||||
}
|
||||
nonce = m_nonce;
|
||||
|
@ -473,7 +495,7 @@ bool SIPEngine::checkUser(const String& username, const String& realm, const Str
|
|||
void SIPEngine::buildAuth(const String& username, const String& realm, const String& passwd,
|
||||
const String& nonce, const String& method, const String& uri, String& response)
|
||||
{
|
||||
XDebug("SIPEngine",DebugAll,"Building auth: '%s:%s:%s' '%s' '%s:%s'",
|
||||
XDebug(this,DebugAll,"Building auth: '%s:%s:%s' '%s' '%s:%s'",
|
||||
username.c_str(),realm.c_str(),passwd.c_str(),nonce.c_str(),method.c_str(),uri.c_str());
|
||||
MD5 m1,m2;
|
||||
m1 << username << ":" << realm << ":" << passwd;
|
||||
|
@ -508,7 +530,7 @@ int SIPEngine::authUser(const SIPMessage* message, String& user, bool proxy)
|
|||
delQuotes(usr);
|
||||
if (usr.null())
|
||||
continue;
|
||||
XDebug("SIPEngine",DebugAll,"authUser found user '%s'",usr.c_str());
|
||||
XDebug(this,DebugAll,"authUser found user '%s'",usr.c_str());
|
||||
// if we know the username check if it matches
|
||||
if (user && (usr != user))
|
||||
continue;
|
||||
|
@ -521,7 +543,7 @@ int SIPEngine::authUser(const SIPMessage* message, String& user, bool proxy)
|
|||
long age = nonceAge(nonce);
|
||||
if (age < 0)
|
||||
continue;
|
||||
XDebug("SIPEngine",DebugAll,"authUser nonce age is %ld",age);
|
||||
XDebug(this,DebugAll,"authUser nonce age is %ld",age);
|
||||
String res(t->getParam("response"));
|
||||
delQuotes(res);
|
||||
if (res.null())
|
||||
|
|
|
@ -375,7 +375,7 @@ SIPMessage::~SIPMessage()
|
|||
|
||||
void SIPMessage::complete(SIPEngine* engine, const char* user, const char* domain, const char* dlgTag)
|
||||
{
|
||||
DDebug("SIPMessage",DebugAll,"complete(%p,'%s','%s','%s')%s%s%s [%p]",
|
||||
DDebug(engine,DebugAll,"SIPMessage::complete(%p,'%s','%s','%s')%s%s%s [%p]",
|
||||
engine,user,domain,dlgTag,
|
||||
isACK() ? " ACK" : "",
|
||||
isOutgoing() ? " OUT" : "",
|
||||
|
@ -391,7 +391,7 @@ void SIPMessage::complete(SIPEngine* engine, const char* user, const char* domai
|
|||
if (!getParty()) {
|
||||
engine->buildParty(this);
|
||||
if (!getParty()) {
|
||||
Debug(DebugGoOn,"Could not complete party-less SIP message [%p]",this);
|
||||
Debug(engine,DebugGoOn,"Could not complete party-less SIP message [%p]",this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ SIPTransaction::SIPTransaction(SIPMessage* message, SIPEngine* engine, bool outg
|
|||
: m_outgoing(outgoing), m_invite(false), m_transmit(false), m_state(Invalid), m_response(0), m_timeout(0),
|
||||
m_firstMessage(message), m_lastMessage(0), m_pending(0), m_engine(engine), m_private(0)
|
||||
{
|
||||
DDebug(DebugAll,"SIPTransaction::SIPTransaction(%p,%p,%d) [%p]",
|
||||
DDebug(getEngine(),DebugAll,"SIPTransaction::SIPTransaction(%p,%p,%d) [%p]",
|
||||
message,engine,outgoing,this);
|
||||
if (m_firstMessage) {
|
||||
m_firstMessage->ref();
|
||||
|
@ -77,7 +77,7 @@ SIPTransaction::SIPTransaction(SIPTransaction& original, SIPMessage* answer)
|
|||
m_branch(original.m_branch), m_callid(original.m_callid), m_tag(original.m_tag),
|
||||
m_private(0)
|
||||
{
|
||||
DDebug(DebugAll,"SIPTransaction::SIPTransaction(&%p,%p) [%p]",
|
||||
DDebug(getEngine(),DebugAll,"SIPTransaction::SIPTransaction(&%p,%p) [%p]",
|
||||
&original,answer,this);
|
||||
|
||||
SIPMessage* msg = new SIPMessage(*original.m_firstMessage);
|
||||
|
@ -101,6 +101,20 @@ SIPTransaction::SIPTransaction(SIPTransaction& original, SIPMessage* answer)
|
|||
m_engine->TransList.append(this);
|
||||
}
|
||||
|
||||
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_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),
|
||||
m_private(0)
|
||||
{
|
||||
if (m_firstMessage)
|
||||
m_firstMessage->ref();
|
||||
|
||||
m_engine->TransList.append(this);
|
||||
}
|
||||
|
||||
SIPTransaction::~SIPTransaction()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
|
@ -149,10 +163,10 @@ bool SIPTransaction::changeState(int newstate)
|
|||
if ((newstate < 0) || (newstate == m_state))
|
||||
return false;
|
||||
if (m_state == Invalid) {
|
||||
Debug(DebugGoOn,"SIPTransaction is already invalid [%p]",this);
|
||||
Debug(getEngine(),DebugGoOn,"SIPTransaction is already invalid [%p]",this);
|
||||
return false;
|
||||
}
|
||||
DDebug(DebugAll,"SIPTransaction state changed from %s to %s [%p]",
|
||||
DDebug(getEngine(),DebugAll,"SIPTransaction state changed from %s to %s [%p]",
|
||||
stateName(m_state),stateName(newstate),this);
|
||||
m_state = newstate;
|
||||
return true;
|
||||
|
@ -172,7 +186,7 @@ void SIPTransaction::setLatestMessage(SIPMessage* message)
|
|||
{
|
||||
if (m_lastMessage == message)
|
||||
return;
|
||||
DDebug(DebugAll,"SIPTransaction latest message changing from %p %d to %p %d [%p]",
|
||||
DDebug(getEngine(),DebugAll,"SIPTransaction latest message changing from %p %d to %p %d [%p]",
|
||||
m_lastMessage, m_lastMessage ? m_lastMessage->code : 0,
|
||||
message, message ? message->code : 0, this);
|
||||
if (m_lastMessage)
|
||||
|
@ -209,7 +223,7 @@ void SIPTransaction::setTimeout(u_int64_t delay, unsigned int count)
|
|||
m_timeout = (count && delay) ? Time::now() + delay : 0;
|
||||
#ifdef DEBUG
|
||||
if (m_timeout)
|
||||
Debug(DebugAll,"SIPTransaction new %d timeouts initially " FMT64U " usec apart [%p]",
|
||||
Debug(getEngine(),DebugAll,"SIPTransaction new %d timeouts initially " FMT64U " usec apart [%p]",
|
||||
m_timeouts,m_delay,this);
|
||||
#endif
|
||||
}
|
||||
|
@ -234,7 +248,7 @@ SIPEvent* SIPTransaction::getEvent()
|
|||
timeout = --m_timeouts;
|
||||
m_timeout = (m_timeouts) ? Time::now() + m_delay : 0;
|
||||
m_delay *= 2; // exponential back-off
|
||||
DDebug(DebugAll,"SIPTransaction fired timer #%d [%p]",timeout,this);
|
||||
DDebug(getEngine(),DebugAll,"SIPTransaction fired timer #%d [%p]",timeout,this);
|
||||
}
|
||||
|
||||
e = isOutgoing() ? getClientEvent(m_state,timeout) : getServerEvent(m_state,timeout);
|
||||
|
@ -261,7 +275,7 @@ SIPEvent* SIPTransaction::getEvent()
|
|||
m_engine->TransList.remove(this);
|
||||
return e;
|
||||
case Invalid:
|
||||
Debug(DebugFail,"SIPTransaction::getEvent in invalid state [%p]",this);
|
||||
Debug(getEngine(),DebugFail,"SIPTransaction::getEvent in invalid state [%p]",this);
|
||||
break;
|
||||
}
|
||||
return e;
|
||||
|
@ -270,7 +284,7 @@ SIPEvent* SIPTransaction::getEvent()
|
|||
void SIPTransaction::setResponse(SIPMessage* message)
|
||||
{
|
||||
if (m_outgoing) {
|
||||
Debug(DebugWarn,"SIPTransaction::setResponse(%p) in client mode [%p]",message,this);
|
||||
Debug(getEngine(),DebugWarn,"SIPTransaction::setResponse(%p) in client mode [%p]",message,this);
|
||||
return;
|
||||
}
|
||||
Lock lock(mutex());
|
||||
|
@ -294,7 +308,7 @@ void SIPTransaction::setResponse(SIPMessage* message)
|
|||
bool SIPTransaction::setResponse(int code, const char* reason)
|
||||
{
|
||||
if (m_outgoing) {
|
||||
Debug(DebugWarn,"SIPTransaction::setResponse(%d,'%s') in client mode [%p]",code,reason,this);
|
||||
Debug(getEngine(),DebugWarn,"SIPTransaction::setResponse(%d,'%s') in client mode [%p]",code,reason,this);
|
||||
return false;
|
||||
}
|
||||
switch (m_state) {
|
||||
|
@ -302,7 +316,7 @@ bool SIPTransaction::setResponse(int code, const char* reason)
|
|||
case Retrans:
|
||||
case Finish:
|
||||
case Cleared:
|
||||
DDebug(DebugInfo,"SIPTransaction ignoring setResponse(%d) in state %s [%p]",
|
||||
DDebug(getEngine(),DebugInfo,"SIPTransaction ignoring setResponse(%d) in state %s [%p]",
|
||||
code,stateName(m_state),this);
|
||||
return false;
|
||||
}
|
||||
|
@ -317,7 +331,7 @@ bool SIPTransaction::setResponse(int code, const char* reason)
|
|||
void SIPTransaction::requestAuth(const String& realm, const String& domain, bool stale, bool proxy)
|
||||
{
|
||||
if (m_outgoing) {
|
||||
Debug(DebugWarn,"SIPTransaction::requestAuth() in client mode [%p]",this);
|
||||
Debug(getEngine(),DebugWarn,"SIPTransaction::requestAuth() in client mode [%p]",this);
|
||||
return;
|
||||
}
|
||||
switch (m_state) {
|
||||
|
@ -325,7 +339,7 @@ void SIPTransaction::requestAuth(const String& realm, const String& domain, bool
|
|||
case Retrans:
|
||||
case Finish:
|
||||
case Cleared:
|
||||
DDebug(DebugInfo,"SIPTransaction ignoring requestAuth() in state %s [%p]",
|
||||
DDebug(getEngine(),DebugInfo,"SIPTransaction ignoring requestAuth() in state %s [%p]",
|
||||
stateName(m_state),this);
|
||||
return;
|
||||
}
|
||||
|
@ -355,46 +369,46 @@ int SIPTransaction::authUser(String& user, bool proxy)
|
|||
return m_engine->authUser(m_firstMessage, user, proxy);
|
||||
}
|
||||
|
||||
bool SIPTransaction::processMessage(SIPMessage* message, const String& branch)
|
||||
SIPTransaction::Processed SIPTransaction::processMessage(SIPMessage* message, const String& branch)
|
||||
{
|
||||
if (!(message && m_firstMessage))
|
||||
return false;
|
||||
DDebug("SIPTransaction",DebugAll,"processMessage(%p,'%s') [%p]",
|
||||
return NoMatch;
|
||||
DDebug(getEngine(),DebugAll,"SIPTransaction::processMessage(%p,'%s') [%p]",
|
||||
message,branch.c_str(),this);
|
||||
if (branch) {
|
||||
if (branch != m_branch) {
|
||||
// different branch is allowed only for ACK in incoming INVITE...
|
||||
if (!(isInvite() && isIncoming() && message->isACK()))
|
||||
return false;
|
||||
return NoMatch;
|
||||
// ...and only if we sent a 200 response...
|
||||
if (!m_lastMessage || ((m_lastMessage->code / 100) != 2))
|
||||
return false;
|
||||
return NoMatch;
|
||||
// ...and if also matches the CSeq, Call-ID and To: tag
|
||||
if ((m_firstMessage->getCSeq() != message->getCSeq()) ||
|
||||
(getCallID() != message->getHeaderValue("Call-ID")) ||
|
||||
(getDialogTag() != message->getParamValue("To","tag")))
|
||||
return false;
|
||||
DDebug(DebugAll,"SIPTransaction found non-branch ACK response to our 2xx");
|
||||
return NoMatch;
|
||||
DDebug(getEngine(),DebugAll,"SIPTransaction found non-branch ACK response to our 2xx");
|
||||
}
|
||||
else if (getMethod() != message->method) {
|
||||
if (!(isIncoming() && isInvite() && message->isACK()))
|
||||
return false;
|
||||
return NoMatch;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (getMethod() != message->method) {
|
||||
if (!(isIncoming() && isInvite() && message->isACK()))
|
||||
return false;
|
||||
return NoMatch;
|
||||
}
|
||||
if ((m_firstMessage->getCSeq() != message->getCSeq()) ||
|
||||
(getCallID() != message->getHeaderValue("Call-ID")) ||
|
||||
(m_firstMessage->getHeaderValue("From") != message->getHeaderValue("From")) ||
|
||||
(m_firstMessage->getHeaderValue("To") != message->getHeaderValue("To")))
|
||||
return false;
|
||||
return NoMatch;
|
||||
// allow braindamaged UAs that send answers with no Via line
|
||||
if (m_firstMessage->getHeader("Via") && message->getHeader("Via") &&
|
||||
(m_firstMessage->getHeaderValue("Via") != message->getHeaderValue("Via")))
|
||||
return false;
|
||||
return NoMatch;
|
||||
// extra checks are to be made for ACK only
|
||||
if (message->isACK()) {
|
||||
// Hack to match URIs with lost tags. Cisco sucks. Period.
|
||||
|
@ -403,29 +417,42 @@ bool SIPTransaction::processMessage(SIPMessage* message, const String& branch)
|
|||
if (sc > 0)
|
||||
tmp.assign(tmp,sc);
|
||||
if ((getURI() != message->uri) && (tmp != message->uri))
|
||||
return false;
|
||||
return NoMatch;
|
||||
if (getDialogTag() != message->getParamValue("To","tag"))
|
||||
return false;
|
||||
return NoMatch;
|
||||
}
|
||||
}
|
||||
if (!message->getParty())
|
||||
message->setParty(m_firstMessage->getParty());
|
||||
if (isOutgoing() != message->isAnswer()) {
|
||||
DDebug(DebugAll,"SIPTransaction ignoring retransmitted %s %p '%s' in [%p]",
|
||||
DDebug(getEngine(),DebugAll,"SIPTransaction ignoring retransmitted %s %p '%s' in [%p]",
|
||||
message->isAnswer() ? "answer" : "request",
|
||||
message,message->method.c_str(),this);
|
||||
return false;
|
||||
return NoMatch;
|
||||
}
|
||||
DDebug(DebugAll,"SIPTransaction processing %s %p '%s' in [%p]",
|
||||
DDebug(getEngine(),DebugAll,"SIPTransaction processing %s %p '%s' in [%p]",
|
||||
message->isAnswer() ? "answer" : "request",
|
||||
message,message->method.c_str(),this);
|
||||
|
||||
if (m_tag.null() && message->isAnswer()) {
|
||||
if (message->isAnswer()) {
|
||||
const NamedString* ns = message->getParam("To","tag");
|
||||
if (ns) {
|
||||
m_tag = *ns;
|
||||
DDebug(DebugInfo,"SIPTransaction found dialog tag '%s' [%p]",
|
||||
m_tag.c_str(),this);
|
||||
if (m_tag.null()) {
|
||||
if (ns) {
|
||||
// establish the dialog
|
||||
m_tag = *ns;
|
||||
DDebug(getEngine(),DebugInfo,"SIPTransaction found dialog tag '%s' [%p]",
|
||||
m_tag.c_str(),this);
|
||||
}
|
||||
}
|
||||
else if (!ns) {
|
||||
// we have a dialog and the message has not - ignore it
|
||||
// as we would be unable to CANCEL it anyway
|
||||
return NoMatch;
|
||||
}
|
||||
else if (m_tag != *ns) {
|
||||
// we have a dialog established and this message is out of it
|
||||
// discriminate forked answers to INVITEs for later processing
|
||||
return isInvite() ? NoDialog : NoMatch;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -433,7 +460,7 @@ bool SIPTransaction::processMessage(SIPMessage* message, const String& branch)
|
|||
processClientMessage(message,m_state);
|
||||
else
|
||||
processServerMessage(message,m_state);
|
||||
return true;
|
||||
return Matched;
|
||||
}
|
||||
|
||||
void SIPTransaction::processClientMessage(SIPMessage* message, int state)
|
||||
|
|
|
@ -549,41 +549,44 @@ public:
|
|||
class YSIP_API SIPTransaction : public RefObject
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Current state of the transaction
|
||||
*/
|
||||
enum State {
|
||||
/**
|
||||
* Invalid state - before constructor or after destructor
|
||||
*/
|
||||
// Invalid state - before constructor or after destructor
|
||||
Invalid,
|
||||
|
||||
/**
|
||||
* Initial state - after the initial message was inserted
|
||||
*/
|
||||
// Initial state - after the initial message was inserted
|
||||
Initial,
|
||||
|
||||
/**
|
||||
* Trying state - got the message but no decision made yet
|
||||
*/
|
||||
// Trying state - got the message but no decision made yet
|
||||
Trying,
|
||||
|
||||
/**
|
||||
* Process state - while locally processing the event
|
||||
*/
|
||||
// Process state - while locally processing the event
|
||||
Process,
|
||||
|
||||
/**
|
||||
* Retrans state - waiting for cleanup, retransmits latest message
|
||||
*/
|
||||
// Retrans state - waiting for cleanup, retransmits latest message
|
||||
Retrans,
|
||||
|
||||
/**
|
||||
* Finish state - transmits the last message and goes to Retrans
|
||||
*/
|
||||
// Finish state - transmits the last message and goes to Retrans
|
||||
Finish,
|
||||
|
||||
/**
|
||||
* Cleared state - removed from engine, awaiting destruction
|
||||
*/
|
||||
Cleared,
|
||||
// Cleared state - removed from engine, awaiting destruction
|
||||
Cleared
|
||||
};
|
||||
|
||||
/**
|
||||
* Possible return values from @ref processMessage()
|
||||
*/
|
||||
enum Processed {
|
||||
// Not matched at all
|
||||
NoMatch,
|
||||
|
||||
// Belongs to another dialog - probably result of a fork
|
||||
NoDialog,
|
||||
|
||||
// Matched to transaction/dialog and processed
|
||||
Matched
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -595,6 +598,13 @@ public:
|
|||
*/
|
||||
SIPTransaction(SIPMessage* message, SIPEngine* engine, bool outgoing = true);
|
||||
|
||||
/**
|
||||
* Copy constructor to be used with forked INVITEs
|
||||
* @param original Original transaction that is to be copied
|
||||
* @param tag Dialog tag for the new transaction
|
||||
*/
|
||||
SIPTransaction(const SIPTransaction& original, const String& tag);
|
||||
|
||||
/**
|
||||
* Destructor - clears all held objects
|
||||
*/
|
||||
|
@ -739,10 +749,10 @@ public:
|
|||
* @param message A pointer to the message to check, should not be used
|
||||
* afterwards if this method returned True
|
||||
* @param branch The branch parameter extracted from first Via header
|
||||
* @return True if the message was handled by this transaction, in
|
||||
* @return Matched if the message was handled by this transaction, in
|
||||
* which case it takes ownership over the message
|
||||
*/
|
||||
virtual bool processMessage(SIPMessage* message, const String& branch);
|
||||
virtual Processed processMessage(SIPMessage* message, const String& branch);
|
||||
|
||||
/**
|
||||
* Get an event for this transaction if any is available.
|
||||
|
@ -960,7 +970,7 @@ protected:
|
|||
/**
|
||||
* This object can be one for each SIPListener.
|
||||
*/
|
||||
class YSIP_API SIPEngine
|
||||
class YSIP_API SIPEngine : public DebugEnabler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
@ -1044,6 +1054,14 @@ public:
|
|||
*/
|
||||
virtual void processEvent(SIPEvent *event);
|
||||
|
||||
/**
|
||||
* Handle answers that create new dialogs for an outgoing INVITE
|
||||
* @param answer The message that creates the INVITE fork
|
||||
* @param trans One of the transactions part of the same INVITE
|
||||
* @return Pointer to new transaction or NULL if message is ignored
|
||||
*/
|
||||
virtual SIPTransaction* forkInvite(SIPMessage* answer, const SIPTransaction* trans);
|
||||
|
||||
/**
|
||||
* Get the timeout to be used for transactions involving human interaction.
|
||||
* The default implementation returns 120000000 (2 minutes)
|
||||
|
|
Loading…
Reference in New Issue