📄 transactionstate.cxx
字号:
// response with status code from 300-699 MUST cause the client
// transaction to transition to "Completed".
if (mIsReliable)
{
// Stack MUST pass the received response up to the TU, and the client
// transaction MUST generate an ACK request, even if the transport is
// reliable
SipMessage* invite = mMsgToRetransmit;
mMsgToRetransmit = Helper::makeFailureAck(*invite, *sip);
delete invite;
// want to use the same transport as was selected for Invite
assert(mTarget.getType() != UNKNOWN_TRANSPORT);
sendToWire(mMsgToRetransmit);
sendToTU(msg); // don't delete msg
terminateClientTransaction(mId);
delete this;
}
else
{
if (mState == Calling || mState == Proceeding)
{
// MUST pass the received response up to the TU, and the client
// transaction MUST generate an ACK request, even if the transport is
// reliable, if transport is Unreliable then Fire the Timer D which
// take care of re-Transmission of ACK
mState = Completed;
mController.mTimers.add(Timer::TimerD, mId, Timer::TD );
SipMessage* ack;
ack = Helper::makeFailureAck(*mMsgToRetransmit, *sip);
delete mMsgToRetransmit;
mMsgToRetransmit = ack;
sendToWire(ack);
sendToTU(msg); // don't delete msg
}
else if (mState == Completed)
{
// Any retransmissions of the final response that
// are received while in the "Completed" state MUST
// cause the ACK to be re-passed to the transport
// layer for retransmission.
assert (mMsgToRetransmit->method() == ACK);
sendToWire(mMsgToRetransmit, true);
delete msg;
}
else
{
/* This should never Happen if it happens we should have a plan
what to do here?? for now assert will work
*/
CritLog( << "State invalid");
// !ah! syslog
assert(0);
}
}
}
break;
case CANCEL:
assert(0);
break;
default:
delete msg;
break;
}
}
else if (isTimer(msg))
{
/* Handle Transaction Timers , Retransmission Timers which were set and Handle
Cancellation of Timers for Re-transmissions here */
TimerMessage* timer = dynamic_cast<TimerMessage*>(msg);
StackLog (<< "timer fired: " << *timer);
switch (timer->getType())
{
case Timer::TimerA:
if (mState == Calling)
{
unsigned long d = timer->getDuration()*2;
// TimerA is supposed to double with each retransmit RFC3261 17.1.1
mController.mTimers.add(Timer::TimerA, mId, d);
InfoLog (<< "Retransmitting INVITE: " << mMsgToRetransmit->brief());
sendToWire(mMsgToRetransmit, true);
}
delete msg;
break;
case Timer::TimerB:
if (mState == Calling)
{
sendToTU(Helper::makeResponse(*mMsgToRetransmit, 408));
terminateClientTransaction(mId);
delete this;
}
delete msg;
break;
case Timer::TimerD:
terminateClientTransaction(mId);
delete msg;
delete this;
break;
case Timer::TimerCleanUp:
// !ah! Cancelled Invite Cleanup Timer fired.
StackLog (<< "Timer::TimerCleanUp: " << *this << std::endl << *mMsgToRetransmit);
if (mState == Proceeding)
{
assert(mMsgToRetransmit && mMsgToRetransmit->method() == INVITE);
InfoLog(<<"Making 408 for canceled invite that received no response: "<< mMsgToRetransmit->brief());
sendToTU(Helper::makeResponse(*mMsgToRetransmit, 408));
terminateClientTransaction(msg->getTransactionId());
delete this;
}
delete msg;
break;
default:
delete msg;
break;
}
}
else if (isTransportError(msg))
{
processTransportFailure(msg);
delete msg;
}
else
{
//StackLog ( << "TransactionState::processClientInvite: message unhandled");
delete msg;
}
}
void
TransactionState::processServerNonInvite(TransactionMessage* msg)
{
StackLog (<< "TransactionState::processServerNonInvite: " << msg->brief());
if (isRequest(msg) && !isInvite(msg) && isFromWire(msg)) // retransmission from the wire
{
if (mState == Trying)
{
// ignore
delete msg;
}
else if (mState == Proceeding || mState == Completed)
{
sendToWire(mMsgToRetransmit, true);
delete msg;
}
else
{
CritLog (<< "Fatal error in TransactionState::processServerNonInvite "
<< msg->brief()
<< " state=" << *this);
assert(0);
return;
}
}
else if (isResponse(msg) && isFromTU(msg))
{
SipMessage* sip = dynamic_cast<SipMessage*>(msg);
int code = sip->header(h_StatusLine).responseCode();
if (code >= 100 && code < 200) // 1XX
{
if (mState == Trying || mState == Proceeding)
{
delete mMsgToRetransmit;
mMsgToRetransmit = sip;
mState = Proceeding;
sendToWire(sip); // don't delete msg
}
else
{
// ignore
delete msg;
}
}
else if (code >= 200 && code <= 699)
{
if (mIsReliable)
{
delete mMsgToRetransmit;
mMsgToRetransmit = sip;
sendToWire(sip); // don't delete msg
terminateServerTransaction(mId);
delete this;
}
else
{
if (mState == Trying || mState == Proceeding)
{
mState = Completed;
mController.mTimers.add(Timer::TimerJ, mId, 64*Timer::T1 );
delete mMsgToRetransmit;
mMsgToRetransmit = sip;
sendToWire(sip); // don't delete msg
}
else if (mState == Completed)
{
// ignore
delete msg;
}
else
{
CritLog (<< "Fatal error in TransactionState::processServerNonInvite "
<< msg->brief()
<< " state=" << *this);
assert(0);
return;
}
}
}
else
{
// ignore
delete msg;
}
}
else if (isTimer(msg))
{
TimerMessage* timer = dynamic_cast<TimerMessage*>(msg);
assert(timer);
switch (timer->getType())
{
case Timer::TimerJ:
if (mState == Completed)
{
terminateServerTransaction(mId);
delete this;
}
delete msg;
break;
case Timer::TimerTrying:
if (mState == Trying)
{
// Timer E has reached T2 - send a 100 as recommended by RFC4320 NIT-Problem-Actions
sendToWire(mMsgToRetransmit);
mState = Proceeding;
}
delete msg;
break;
default:
delete msg;
break;
}
}
else if (isTransportError(msg))
{
processTransportFailure(msg);
delete msg;
}
else
{
//StackLog (<< "TransactionState::processServerNonInvite: message unhandled");
delete msg;
}
}
void
TransactionState::processServerInvite(TransactionMessage* msg)
{
StackLog (<< "TransactionState::processServerInvite: " << msg->brief());
if (isRequest(msg) && isFromWire(msg))
{
SipMessage* sip = dynamic_cast<SipMessage*>(msg);
switch (sip->method())
{
case INVITE:
// note: handling of initial INVITE message is done in TransactionState:process
if (mState == Proceeding || mState == Completed)
{
/*
The server transaction has already been constructed so this
message is a retransmission. The server transaction must
respond with a 100 Trying _or_ the last provisional response
passed from the TU for this transaction.
*/
//StackLog (<< "Received invite from wire - forwarding to TU state=" << mState);
if (!mMsgToRetransmit)
{
mMsgToRetransmit = make100(sip);
}
delete msg;
sendToWire(mMsgToRetransmit);
}
else
{
//StackLog (<< "Received invite from wire - ignoring state=" << mState);
delete msg;
}
break;
case ACK:
/*
If an ACK is received while the server transaction is in the
"Completed" state, the server transaction MUST transition to the
"Confirmed" state.
*/
if (mState == Completed)
{
if (mIsReliable)
{
//StackLog (<< "Received ACK in Completed (reliable) - delete transaction");
terminateServerTransaction(mId);
delete this;
delete msg;
}
else
{
//StackLog (<< "Received ACK in Completed (unreliable) - confirmed, start Timer I");
mState = Confirmed;
mController.mTimers.add(Timer::TimerI, mId, Timer::T4 );
delete msg;
}
}
else
{
//StackLog (<< "Ignore ACK not in Completed state");
delete msg;
}
break;
case CANCEL:
assert(0);
break;
default:
//StackLog (<< "Received unexpected request. Ignoring message");
delete msg;
break;
}
}
else if (isResponse(msg, 100, 699) && isFromTU(msg))
{
SipMessage* sip = dynamic_cast<SipMessage*>(msg);
int code = sip->header(h_StatusLine).responseCode();
switch (sip->method())
{
case INVITE:
if (code == 100)
{
if (mState == Trying || mState == Proceeding)
{
//StackLog (<< "Received 100 in Trying or Proceeding. Send over wire");
delete mMsgToRetransmit; // may be replacing the 100
mMsgToRetransmit = sip;
mState = Proceeding;
sendToWire(msg); // don't delete msg
}
else
{
//StackLog (<< "Ignoring 100 - not in Trying or Proceeding.");
delete msg;
}
}
else if (code > 100 && code < 200)
{
if (mState == Trying || mState == Proceeding)
{
//StackLog (<< "Received 1xx in Trying or Proceeding. Send over wire");
delete mMsgToRetransmit; // may be replacing the 100
mMsgToRetransmit = sip;
mState = Proceeding;
sendToWire(msg); // don't delete msg
}
else
{
//StackLog (<< "Received 100 when not in Trying State. Ignoring");
delete msg;
}
}
else if (code >= 200 && code < 300)
{
if (mState == Trying || mState == Proceeding)
{
StackLog (<< "Received 2xx when in Trying or Proceeding State of server invite transaction");
StackLog (<< *this);
sendToWire(msg);
// Keep the StaleServer transaction around, so we can keep the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -