diff -r 3652a10b304a -r 7e41d162e158 networkprotocols/tcpipv4v6prt/src/tcp_sap.cpp --- a/networkprotocols/tcpipv4v6prt/src/tcp_sap.cpp Thu Jul 15 20:25:02 2010 +0300 +++ b/networkprotocols/tcpipv4v6prt/src/tcp_sap.cpp Thu Aug 19 11:25:30 2010 +0300 @@ -140,7 +140,8 @@ // state chart above. It would be located between CLOSED and SYN-SENT. // - +//The below is UID of the client(http client) using this option. We are not exposing this right now... +const TUint32 KSoTcpLingerinMicroSec = 0x101F55F6; #ifdef _LOG const TText *CProviderTCP6::TcpState(TUint aState) { @@ -260,6 +261,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 +627,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 @@ -695,6 +792,11 @@ } break; + case KSoTcpLingerinMicroSec: + RDebug::Printf("TSoTcpLingerinMicroSec is set"); + //Enable micro sec calculation for TCP linger timer. User (currently just exposed to browser) + //will specify linger time in microsecs. + iMicroSecCalcFlag=ETrue; case KSoTcpLinger: if (aOption.Length() < (TInt)sizeof(TSoTcpLingerOpt)) { @@ -1102,7 +1204,16 @@ // Start linger timer. RSocket::Close() returns when timer // expires or when all data has been succesfully transmitted. // - iLingerTimer->Start(iLinger * KOneSecondInUs); + if(iMicroSecCalcFlag) + { + //expecting iLinger timer to be specified in microsec.This will be set currently by browser where in + //it is expected to be close with in certian time + iLingerTimer->Start(iLinger * 1); + } + else + { + iLingerTimer->Start(iLinger * KOneSecondInUs); + } } SchedTransmit(); @@ -1362,32 +1473,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