📄 transactionstate.cxx
字号:
SipMessage* sip = dynamic_cast<SipMessage*>(msg); switch (sip->method()) { // Received INVITE request from TU="Transaction User", Start Timer B which controls // transaction timeouts. case INVITE: delete mMsgToRetransmit; saveOriginalContactAndVia(*sip); mMsgToRetransmit = sip; mController.mTimers.add(Timer::TimerB, mId, Timer::TB); sendToWire(msg); // don't delete msg break; case CANCEL: assert(0); break; default: delete msg; break; } } else if (isResponse(msg) && isFromWire(msg)) { SipMessage* sip = dynamic_cast<SipMessage*>(msg); int code = sip->header(h_StatusLine).responseCode(); switch (sip->method()) { case INVITE: /* If the client transaction receives a provisional response while in the "Calling" state, it transitions to the "Proceeding" state. In the "Proceeding" state, the client transaction SHOULD NOT retransmit the request any longer (this will be Handled in "else if (isTimer(msg))") The Retransmissions will be stopped, Not by Cancelling Timers but by Ignoring the fired Timers depending upon the State which stack is in. */ if (code >= 100 && code < 200) // 1XX { if (mState == Calling || mState == Proceeding) { mState = Proceeding; sendToTU(sip); // don't delete msg } else { delete msg; } } /* When in either the "Calling" or "Proceeding" states, reception of a 2xx response MUST cause the client transaction to enter the "Terminated" state, and the response MUST be passed up to the TU State Machine is changed to Stale since, we wanted to ensure that all 2xx gets to TU */ else if (code >= 200 && code < 300) { sendToTU(sip); // don't delete msg //terminateClientTransaction(mId); mMachine = ClientStale; StackLog (<< "Received 2xx on client invite transaction"); StackLog (<< *this); mController.mTimers.add(Timer::TimerStaleClient, mId, Timer::TS ); } else if (code >= 300) { // When in either the "Calling" or "Proceeding" states, reception of a // 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; }}voidTransactionState::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; }}voidTransactionState::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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -