📄 transactionstate.cxx
字号:
{
// can't be retransmission
sendToWire(mMsgToRetransmit, false);
}
}
void
TransactionState::processReliability(TransportType type)
{
switch (type)
{
case UDP:
case DCCP:
if (mIsReliable)
{
mIsReliable = false;
StackLog (<< "Unreliable transport: " << *this);
switch (mMachine)
{
case ClientNonInvite:
mController.mTimers.add(Timer::TimerE1, mId, Timer::T1 );
break;
case ClientInvite:
mController.mTimers.add(Timer::TimerA, mId, Timer::T1 );
break;
default:
break;
}
}
break;
default:
if (!mIsReliable)
{
mIsReliable = true;
}
break;
}
}
// !ah! only used one place, so leaving it here instead of making a helper.
// !ah! broken out for clarity -- only used for forceTargets.
// Expects that host portion is IP address notation.
static const Tuple
simpleTupleForUri(const Uri& uri)
{
const Data& host = uri.host();
int port = uri.port();
resip::TransportType transport = UNKNOWN_TRANSPORT;
if (uri.exists(p_transport))
{
transport = Tuple::toTransport(uri.param(p_transport));
}
if (transport == UNKNOWN_TRANSPORT)
{
transport = UDP;
}
if (port == 0)
{
switch(transport)
{
case TLS:
port = Symbols::DefaultSipsPort;
break;
case UDP:
case TCP:
default:
port = Symbols::DefaultSipPort;
break;
// !ah! SCTP?
}
}
return Tuple(host,port,transport);
}
void
TransactionState::sendToWire(TransactionMessage* msg, bool resend)
{
SipMessage* sip = dynamic_cast<SipMessage*>(msg);
if (!sip)
{
CritLog(<<"sendToWire: message not a sip message at address " << (void*)msg);
assert(sip);
return;
}
if(mController.mStack.statisticsManagerEnabled())
{
mController.mStatsManager.sent(sip, resend);
}
// !jf! for responses, go back to source always (not RFC exactly)
if (mMachine == ServerNonInvite || mMachine == ServerInvite || mMachine == ServerStale)
{
assert(mDnsResult == 0);
assert(sip->exists(h_Vias));
assert(!sip->header(h_Vias).empty());
Tuple target(mResponseTarget);
if (sip->hasForceTarget())
{
target = simpleTupleForUri(sip->getForceTarget());
target.transport = mResponseTarget.transport;
StackLog(<<"!ah! response with force target going to : "<<target);
}
else if (sip->header(h_Vias).front().exists(p_rport) && sip->header(h_Vias).front().param(p_rport).hasValue())
{
target.setPort(sip->header(h_Vias).front().param(p_rport).port());
StackLog(<< "rport present in response, sending to " << target);
}
else
{
StackLog(<< "tid=" << sip->getTransactionId() << " sending to : " << target);
}
if (resend)
{
mController.mTransportSelector.retransmit(sip, target);
}
else
{
mController.mTransportSelector.transmit(sip, target);
}
}
else if (sip->getDestination().connectionId || sip->getDestination().transport)
{
DebugLog(<< "Sending to tuple: " << sip->getDestination());
mTarget = sip->getDestination();
processReliability(mTarget.getType());
mController.mTransportSelector.transmit(sip, mTarget); // dns not used
}
else if (mDnsResult == 0 && !mIsCancel) // no dns query yet
{
StackLog (<< "sendToWire with no dns result: " << *this);
assert(sip->isRequest());
assert(!mIsCancel);
mDnsResult = mController.mTransportSelector.createDnsResult(this);
mController.mTransportSelector.dnsResolve(mDnsResult, sip);
}
else // reuse the last dns tuple
{
assert(sip->isRequest());
assert(mTarget.getType() != UNKNOWN_TRANSPORT);
if (resend)
{
if (mTarget.transport)
{
mController.mTransportSelector.retransmit(sip, mTarget);
}
else
{
DebugLog (<< "No transport found(network could be down) for " << sip->brief());
}
}
else
{
mController.mTransportSelector.transmit(sip, mTarget);
}
}
}
void
TransactionState::sendToTU(TransactionMessage* msg) const
{
SipMessage* sipMsg = dynamic_cast<SipMessage*>(msg);
if (sipMsg && sipMsg->isResponse() && mDnsResult)
{
// whitelisting rules.
switch (sipMsg->header(h_StatusLine).statusCode())
{
case 503:
// blacklist last target.
// !slg! TODO: Need to blacklist only for Retry-After interval
if (mDnsResult != 0 && mDnsResult->available() == DnsResult::Available)
{
mDnsResult->next();
}
break;
case 408:
if(sipMsg->getReceivedTransport() == 0 && mState == Trying) // only blacklist if internally generated and we haven't received any responses yet
{
// blacklist last target.
if (mDnsResult->available() == DnsResult::Available)
{
mDnsResult->next();
}
}
else
{
mDnsResult->success();
}
break;
case 500:
case 504:
case 600:
// !bwc! Only blacklist if Retry-After is present.
// (Although, this is somewhat silly right now, since the value
// of Retry-After is completely ignored.)
if(sipMsg->exists(h_RetryAfter) &&
mDnsResult->available() == DnsResult::Available)
{
mDnsResult->next();
}
else
{
mDnsResult->success();
}
break;
default:
mDnsResult->success();
break;
}
}
TransactionState::sendToTU(mTransactionUser, mController, msg);
}
void
TransactionState::sendToTU(TransactionUser* tu, TransactionController& controller, TransactionMessage* msg)
{
if (!tu)
{
DebugLog(<< "Send to default TU: " << std::endl << std::endl << *msg);
}
else
{
DebugLog (<< "Send to TU: " << *tu << " " << std::endl << std::endl << *msg);
}
msg->setTransactionUser(tu);
controller.mTuSelector.add(msg, TimeLimitFifo<Message>::InternalElement);
}
SipMessage*
TransactionState::make100(SipMessage* request) const
{
return (Helper::makeResponse(*request, 100));
}
void
TransactionState::add(const Data& tid)
{
if (mMachine == ClientNonInvite || mMachine == ClientInvite || mMachine == ClientStale || mMachine == Stateless )
{
mController.mClientTransactionMap.add(tid, this);
}
else
{
mController.mServerTransactionMap.add(tid, this);
}
}
void
TransactionState::erase(const Data& tid)
{
if (mMachine == ClientNonInvite || mMachine == ClientInvite || mMachine == ClientStale || mMachine == Stateless)
{
mController.mClientTransactionMap.erase(tid);
}
else
{
mController.mServerTransactionMap.erase(tid);
}
}
bool
TransactionState::isRequest(TransactionMessage* msg) const
{
SipMessage* sip = dynamic_cast<SipMessage*>(msg);
return sip && sip->isRequest();
}
bool
TransactionState::isInvite(TransactionMessage* msg) const
{
if (isRequest(msg))
{
SipMessage* sip = dynamic_cast<SipMessage*>(msg);
return (sip->method()) == INVITE;
}
return false;
}
bool
TransactionState::isResponse(TransactionMessage* msg, int lower, int upper) const
{
SipMessage* sip = dynamic_cast<SipMessage*>(msg);
if (sip && sip->isResponse())
{
int c = sip->header(h_StatusLine).responseCode();
return (c >= lower && c <= upper);
}
return false;
}
bool
TransactionState::isTimer(TransactionMessage* msg) const
{
return dynamic_cast<TimerMessage*>(msg) != 0;
}
bool
TransactionState::isFromTU(TransactionMessage* msg) const
{
SipMessage* sip = dynamic_cast<SipMessage*>(msg);
return sip && !sip->isExternal();
}
bool
TransactionState::isFromWire(TransactionMessage* msg) const
{
SipMessage* sip = dynamic_cast<SipMessage*>(msg);
return sip && sip->isExternal();
}
bool
TransactionState::isTransportError(TransactionMessage* msg) const
{
return dynamic_cast<TransportFailure*>(msg) != 0;
}
const Data&
TransactionState::tid(SipMessage* sip) const
{
assert(0);
assert (mMachine != Stateless || (mMachine == Stateless && !mId.empty()));
assert (mMachine == Stateless || (mMachine != Stateless && sip));
return (mId.empty() && sip) ? sip->getTransactionId() : mId;
}
void
TransactionState::terminateClientTransaction(const Data& tid)
{
mState = Terminated;
if (mController.mTuSelector.isTransactionUserStillRegistered(mTransactionUser) &&
mTransactionUser->isRegisteredForTransactionTermination())
{
//StackLog (<< "Terminate client transaction " << tid);
sendToTU(new TransactionTerminated(tid, true, mTransactionUser));
}
}
void
TransactionState::terminateServerTransaction(const Data& tid)
{
mState = Terminated;
if (mController.mTuSelector.isTransactionUserStillRegistered(mTransactionUser) &&
mTransactionUser->isRegisteredForTransactionTermination())
{
//StackLog (<< "Terminate server transaction " << tid);
sendToTU(new TransactionTerminated(tid, false, mTransactionUser));
}
}
std::ostream&
resip::operator<<(std::ostream& strm, const resip::TransactionState& state)
{
strm << "tid=" << state.mId << " [ ";
switch (state.mMachine)
{
case TransactionState::ClientNonInvite:
strm << "ClientNonInvite";
break;
case TransactionState::ClientInvite:
strm << "ClientInvite";
break;
case TransactionState::ServerNonInvite:
strm << "ServerNonInvite";
break;
case TransactionState::ServerInvite:
strm << "ServerInvite";
break;
case TransactionState::Stateless:
strm << "Stateless";
break;
case TransactionState::ClientStale:
strm << "ClientStale";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -