< Previous by Date Date Index Next by Date >
< Previous in Thread Thread Index Next in Thread >

[reSIProcate] A suggestion about shifting responsibility of retransmissions of 2xx responses


Since the ServerStale machine state has been introduced into the Server Invite 
Transaction(in transactionstate.cxx), and that type of Transaction will stayed 
for Timer::TS millisecond (equals T2), I think the responsibility of 
retransmitting 2xx could shift to the library, as a result, the TU can  utilize 
the timing mechanism in the library. 

To achive this goal,at first, the 2xx response should retained in 
mMsgToRetransmit:

//      In Transactionstate::processServerInvite():
            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
                  // source Tuple that the request was received on. 
                  terminateServerTransaction(mId); 
                  mMachine = ServerStale;
                  mController.mTimers.add(Timer::TimerStaleServer, mId, 
Timer::TS );
         delete msg;

//Should change to:

            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);
                  if (mMsgToRetransmit) delete mMsgToRetransmit; //added by 
yuhuicai
                  mMsgToRetransmit = sip; //added by yuhuicai
                  sendToWire(msg);
                  
                  // Keep the StaleServer transaction around, so we can keep the
                  // source Tuple that the request was received on. 
                  terminateServerTransaction(mId); 
                  mMachine = ServerStale;
                  mController.mTimers.add(Timer::TimerStaleServer, mId, 
Timer::TS );
//       delete msg; // Modified by yuhuicai


Second, when the reinvite msg come, the saved 2xx could be send:

//In TransactionState::processServerStale():
   else if (sip && isRequest(sip) && sip->header(h_RequestLine).getMethod() == 
INVITE)
   {
      // this can happen when an upstream UAC never received the 200 and
      // retransmits the INVITE when using unreliable transport
      // Drop the INVITE since the 200 will get retransmitted by the downstream 
UAS
      StackLog (<< "Dropping retransmitted INVITE in stale server transaction" 
<< sip->brief());
      delete msg;
   }


//Should change to:

   else if (sip && isRequest(sip) && sip->header(h_RequestLine).getMethod() == 
INVITE)
   {
      // this can happen when an upstream UAC never received the 200 and
      // retransmits the INVITE when using unreliable transport
      // Drop the INVITE since the 200 will get retransmitted by the downstream 
UAS
      StackLog (<< "Dropping retransmitted INVITE in stale server transaction" 
<< sip->brief());
      sendToWire(mMsgToRetransmit); //added by yuhuicai
      delete msg;
   }


Maybe an interface should be added to let user choose rertansmit 2xx by TU or 
by library, and the default behavior is rertansmit  by TU.

I have tested these codes and it works well. But  it do not according to 
RFC3261(17.2.1):
     "If, while in the "Proceeding" state, the TU passes a 2xx response to the 
server transaction, the server transaction MUST pass this response to the 
transport layer for transmission. It is not retransmitted by the server 
transaction; retransmissions of 2xx responses are handled by the TU. The server 
transaction MUST then transition to the "Terminated" state."

So, if you think it's unreasonable, just disregard it. :-)