[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);
if (mMsgToRetransmit) delete mMsgToRetransmit; //cyh2
mMsgToRetransmit = sip;//cyh2
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. :-)