networkprotocols/tcpipv4v6prt/src/tcp_sap.cpp
branchRCL_3
changeset 20 7e41d162e158
parent 17 d566d76acea1
child 21 abbed5a4b42a
--- 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