--- a/networkprotocols/tcpipv4v6prt/src/tcp_sap.cpp Mon May 03 13:58:16 2010 +0300
+++ b/networkprotocols/tcpipv4v6prt/src/tcp_sap.cpp Tue Jun 29 19:20:22 2010 +0530
@@ -260,6 +260,13 @@
iRetransTimer->InitL();
iLingerTimer->InitL();
iSockInBufSize = Protocol()->RecvBuf();
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+ if(iSockInBufSize == Protocol()->RecvBufFromIniFile())
+ iSocketStartupCase = ETrue;
+ else
+ iSocketStartupCase = EFalse;
+#endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+
iSockOutBufSize = Protocol()->SendBuf();
iSsthresh = KMaxTInt32;
iRTO = Protocol()->InitialRTO();
@@ -619,48 +626,137 @@
iSockInBufSize = KTcpMinimumWindow;
else
{
-
- //If new TCP window is larger then the previous window, increase the
- //iSockInBufSize right now. TCP recv function takes care of
- //advertising a new effective TCP window.
- if (intValue >= iSockInBufSize)
- {
- //Make it Zero so TCP could avoid the
- //TCP window shrinking processing in Recv.
- iNewTcpWindow = 0;
- //FreeWindow has to be increased at the same time.
- iFreeWindow += intValue - iSockInBufSize;
- // Make the new TCP receive buffer change effective now.
- iSockInBufSize = intValue;
- }
- else
- {
- //This sets iNewTcpWindow to a non-zero value, which indicates
- //to the TCP that window is shrunk and process TCP segments
- //which are in air before setting a new TCP receive buffer.
- //TCP Receive window starts moving only when TCP hidden window
- //size exceeds the size of the shrunk window.
-
- iNewTcpWindow = intValue;
- //Even in case of window shrink we can set the receive buffer size
- //immediately. This will be helpful, for processing SYN-ACK and other
- //receiver side processing.
- //For already connected sockets iNewTcpWindow will be taking care
- //of shrinking the window size for that TCP session.
- iSockInBufSize = iNewTcpWindow;
- if( iAdvertisedWindow > iNewTcpWindow )
- {
- iShrinkedWindowSize = iAdvertisedWindow - iNewTcpWindow;
- }
- else
- {
- // No Need to process TCP receive window processing.
- iNewTcpWindow = 0;
- }
- }
-
- }
-
+ //If its the startup case, then there should be no algorithm used to shrink
+ //or expand the window size from the default value provided in the ini file
+ //the new value should be set directly
+ if(iSocketStartupCase)
+ {
+ //Add the extra window to free window pool
+ //if the window being set is greater than what is specified in ini file (startup case), then just overwrite the new window.
+ //Add difference to free window
+ //else set free window to zero
+ if(intValue > iSockInBufSize)
+ iFreeWindow += intValue - iSockInBufSize;
+ else
+ iFreeWindow = 0;
+ //set the buffer
+ iSockInBufSize = intValue;
+ //disable startup flag.
+ iSocketStartupCase = EFalse;
+ }
+ else
+ {
+ // Check for minimum value
+ if (intValue < STATIC_CAST(TInt, KTcpMinimumWindow))
+ {
+ intValue = STATIC_CAST(TInt, KTcpMinimumWindow);
+ }
+ // Handle the situation where the connection has been established and
+ // window scaling is not in use
+ if ( InState( ETcpSynReceived | ETcpEstablished ) && !iRcvWscale )
+ {
+ // Do not allow window sizes larger than 0xFFFF
+ intValue = Min ( intValue, 0xFFFF );
+ }
+
+ // Check whether we are increasing or decreasing window size
+ if ( intValue >= iSockInBufSize )
+ {
+ // New window is larger than current one, check if a
+ // shrinking process is active
+ if ( !iNewTcpWindow )
+ {
+ // Mark new "space" as free, it will be updated to
+ // peer on next operation.
+ iFreeWindow += intValue - iSockInBufSize;
+ }
+ else
+ {
+ // In the middle of shrinking process.
+ if ( iShrinkedWindowSize <= ( intValue - iSockInBufSize ))
+ {
+ // Increment to window size is enough to complete
+ // shrinking process. Update variables and exit
+ // from shrinking process.
+ iFreeWindow = ( intValue - iSockInBufSize ) - iShrinkedWindowSize;
+ iShrinkedWindowSize = 0;
+ iNewTcpWindow = 0;
+ }
+ else
+ {
+ // Not quite there yet but closer. Less to shrink,
+ // update this, but do not exit from shrinking
+ // process
+ iShrinkedWindowSize -= intValue - iSockInBufSize;
+ iNewTcpWindow = intValue;
+ }
+ }
+ }
+ else
+ {
+ // Requested window is smaller than current one. Start or
+ // continue shrinking process. RCV window can be occupied
+ // for two different purpose at the moment
+ // 1. Client data in iSockInQ not read by application
+ // 2. Free window "opened" to peer (iAdvertisedWindow)
+ // When shrinking, we must ensure that when reopening
+ // the window to client there must be truly empty space
+ // in the window. Thus, freeze the right edge of the
+ // window (iRCV.NXT + iRCV.WND stays constant) until
+ // shrinking is completed.
+
+ if ( iNewTcpWindow )
+ {
+ // There is an ongoing shrink process, add the
+ // change to the amount to be shrinked
+ iShrinkedWindowSize += iSockInBufSize - intValue;
+ iNewTcpWindow = intValue;
+ }
+ else
+ {
+ // This is a new shrinking process, count how much
+ // needs to be shrinked
+ iShrinkedWindowSize = iSockInQLen + iRCV.WND;
+ if ( iShrinkedWindowSize >= intValue )
+ {
+ // We need to shrink since the currently occupied
+ // window does not fit to new one
+ iShrinkedWindowSize -= intValue;
+ // There is now free space in the window
+ iFreeWindow = 0;
+ // iNewTcpWindow is used as a state variable for
+ // shrinking
+ iNewTcpWindow = intValue;
+ }
+ else
+ {
+ // No need to shrink since we can fit the current
+ // contents to the new window, update free window
+ // If TCP connection is not yet setup, the free
+ // window will be updated on connection setup,
+ // for existing connection it will be used
+ // next time application reads data
+ if ( iFreeWindow >= ( iSockInBufSize - intValue ))
+ {
+ iFreeWindow -= iSockInBufSize - intValue;
+ }
+ else
+ {
+ // Something wrong. Try to reevaluate...
+ iFreeWindow = intValue - iShrinkedWindowSize;
+ }
+ iShrinkedWindowSize = 0;
+ }
+ }
+ }
+ // Even in case of window shrink we can set the receive buffer size
+ // immediately. This will be helpful, for processing SYN-ACK and other
+ // receiver side processing.
+ // For already connected sockets iNewTcpWindow will be taking care
+ // of shrinking the window size for that TCP session.
+ iSockInBufSize = intValue;
+ }
+ }
}
break;
#endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
@@ -1362,32 +1458,23 @@
//if This is true, then it is a case of TCP window shrink and we need
//to handle it.
if ( iNewTcpWindow )
- {
- //Log this message for information, that Window is shrinked
- LOG(Log::Printf(_L("\ttcp SAP[%u] TCP window shrinking mode on"), (TInt)this));
-
- //Increase the hidden free TCP receive window.
- iHiddenFreeWindow += aLength;
-
- if (iHiddenFreeWindow >= iShrinkedWindowSize)
- {
- //Disable window shrink processing, so that TCP could switch
- //to the normal processing.
- iSockInBufSize = iNewTcpWindow;
-
- //Add the usable window to the free window.
- iFreeWindow += iHiddenFreeWindow - iShrinkedWindowSize;
-
- //There are chances that TCP receive window might further shrink.
- iHiddenFreeWindow = 0;
-
- //TCP Receive window shrink phase is over.
- iNewTcpWindow = 0;
-
- //Log this message for information, that Window is shrinked
- LOG(Log::Printf(_L("\ttcp SAP[%u] TCP window shrinking mode off"), (TInt)this));
- }
- }
+ {
+ // Check if we can complete shrinking process
+ if ( aLength > iShrinkedWindowSize )
+ {
+ // We can exit from the shrinking process. Reset variables and
+ // update free window.
+ iFreeWindow = aLength - iShrinkedWindowSize;
+ iShrinkedWindowSize = 0;
+ iNewTcpWindow = 0;
+ }
+ else
+ {
+ // Substract the needed shrinking amount by the amount of bytes client
+ // read from the buffer
+ iShrinkedWindowSize -= aLength;
+ }
+ }
else
#endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
@@ -1684,7 +1771,8 @@
if (iFlags.iRetransmitPending)
{
iFlags.iRetransmitPending = EFalse;
- RetransmitSegments();
+ if(RetransmitSegments())
+ return;
}
if (iFlags.iTransmitPending)
@@ -2288,7 +2376,12 @@
++iBackoff;
if (iRTO < Protocol()->MaxRTO()) // Avoid RTO overflow
ResetRTO();
-
+
+ if(DetachIfDead())
+ {
+ Expire();
+ return;
+ }
//
// Timeout?
//
@@ -2403,7 +2496,7 @@
// - directly from RetransmitTimeout()
// - from CanSend(), in which case this is a delayed retransmission timeout
//
-void CProviderTCP6::RetransmitSegments()
+TBool CProviderTCP6::RetransmitSegments()
{
ASSERT(iRetransTimer);
@@ -2419,7 +2512,7 @@
{
LOG(Log::Printf(_L("\ttcp SAP[%u] RetransmitSegments(): Flow pending"), (TInt)this));
ReSchedRetransmit();
- return;
+ return EFalse;
}
//
@@ -2477,14 +2570,14 @@
// the receiver suddenly shrinks its window. The current solution covers
// both cases.
//
- return;
+ return EFalse;
}
//
// This is a retransmit timout. Do we have anything to do?
//
if (!unacked)
- return;
+ return EFalse;
LOG(if (iFlags.iFastRetransMode) Log::Printf(_L("\ttcp SAP[%u] RetransmitSegments(): Leaving FAST RETRANS mode"), (TInt)this));
iFlags.iFastRetransMode = EFalse;
@@ -2557,7 +2650,7 @@
// If the server doesn't respond because of broken NAT/FW or other, don't keep interface up.
if (InState(ETcpFinWait1|ETcpClosing|ETcpLastAck))
DetachIfDead();
- return;
+ return EFalse;
}
//
@@ -2567,14 +2660,14 @@
{
// Retransmit SYN
SendSegment(KTcpCtlSYN, iSND.UNA);
- return;
+ return EFalse;
}
if (InState(ETcpSynReceived))
{
// Retransmit SYN,ACK
SendSegment(KTcpCtlSYN|KTcpCtlACK, iSND.UNA);
- return;
+ return EFalse;
}
if (InState(ETcpFinWait1|ETcpClosing|ETcpLastAck))
@@ -2584,18 +2677,22 @@
//TSW error:JHAA-82JBNG -- FIN retransmission
//Depending on the function return value the decision to
//retransmitt FIN is decided
-
- TBool continue_send = DetachIfDead();
+
// Retransmit FIN
- if(continue_send == EFalse)
+ if(DetachIfDead()== EFalse)
+ {
SendSegment(KTcpCtlFIN|KTcpCtlACK, iSND.UNA);
- return;
+ return EFalse;
+ }
}
LOG(Log::Printf(_L("\ttcp SAP[%u] RetransmitSegments(): Retransmitter stopping"), (TInt)this));
if (!iSockFlags.iAttached)
+ {
Expire();
- return;
+ return ETrue;
+ }
+ return EFalse;
}