networkprotocols/tcpipv4v6prt/src/tcp_sap.cpp
branchRCL_3
changeset 75 c1029e558ef5
parent 58 8d540f55e491
equal deleted inserted replaced
67:bb2423252ea3 75:c1029e558ef5
   139 //  specific to this TCP implementation and is therefore not visible in the
   139 //  specific to this TCP implementation and is therefore not visible in the
   140 //  state chart above. It would be located between CLOSED and SYN-SENT.
   140 //  state chart above. It would be located between CLOSED and SYN-SENT.
   141 //
   141 //
   142 
   142 
   143 //The below is UID of the client(http client) using this option. We are not exposing this right now...
   143 //The below is UID of the client(http client) using this option. We are not exposing this right now...
   144 const TUint32 KSoTcpLingerinMicroSec = 0x101F55F6;
   144 const TUint32 TSoTcpLingerinMicroSec = 0x101F55F6;
   145 #ifdef _LOG
   145 #ifdef _LOG
   146 const TText *CProviderTCP6::TcpState(TUint aState)
   146 const TText *CProviderTCP6::TcpState(TUint aState)
   147 	{
   147 	{
   148 	TInt i;
   148 	TInt i;
   149 	static const TText* const tcpStates[] = {
   149 	static const TText* const tcpStates[] = {
   259 
   259 
   260 	iDelayAckTimer->InitL();
   260 	iDelayAckTimer->InitL();
   261 	iRetransTimer->InitL();
   261 	iRetransTimer->InitL();
   262 	iLingerTimer->InitL();
   262 	iLingerTimer->InitL();
   263 	iSockInBufSize        = Protocol()->RecvBuf();
   263 	iSockInBufSize        = Protocol()->RecvBuf();
   264 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
   265 	if(iSockInBufSize == Protocol()->RecvBufFromIniFile())
       
   266 	    iSocketStartupCase = ETrue;
       
   267 	else
       
   268 	    iSocketStartupCase = EFalse;
       
   269 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW    	
       
   270 	
       
   271 	iSockOutBufSize       = Protocol()->SendBuf();
   264 	iSockOutBufSize       = Protocol()->SendBuf();
   272 	iSsthresh		= KMaxTInt32;
   265 	iSsthresh		= KMaxTInt32;
   273 	iRTO			= Protocol()->InitialRTO();
   266 	iRTO			= Protocol()->InitialRTO();
   274 	ClearRTT();
   267 	ClearRTT();
   275 	iMSS                  = Protocol()->MSS();
   268 	iMSS                  = Protocol()->MSS();
   625 		        ret = KErrLocked;
   618 		        ret = KErrLocked;
   626             else if (intValue < STATIC_CAST(TInt, KTcpMinimumWindow))
   619             else if (intValue < STATIC_CAST(TInt, KTcpMinimumWindow))
   627                 iSockInBufSize = KTcpMinimumWindow;
   620                 iSockInBufSize = KTcpMinimumWindow;
   628             else
   621             else
   629                 {
   622                 {
   630                 //If its the startup case, then there should be no algorithm used to shrink
   623 
   631 				//or expand the window size from the default value provided in the ini file
   624 		        //If new TCP window is larger then the previous window, increase the 
   632                 //the new value should be set directly
   625 		        //iSockInBufSize right now. TCP recv function takes  care of
   633                 if(iSocketStartupCase)
   626 		        //advertising a new effective TCP window. 
   634                     {
   627 		            if (intValue >= iSockInBufSize)
   635 					//Add the extra window to free window pool
   628 		                {
   636 					//if the window being set is greater than what is specified in ini file (startup case), then just overwrite the new window.
   629 		                //Make it Zero so TCP could avoid the
   637 					//Add difference to free window
   630 		                //TCP window shrinking processing in Recv.  
   638 					//else set free window to zero
   631 		                iNewTcpWindow = 0;
   639 					if(intValue > iSockInBufSize)
   632 		                //FreeWindow has to be increased at the same time.
   640 						iFreeWindow += intValue - iSockInBufSize;
   633 		                iFreeWindow += intValue - iSockInBufSize;
   641 					else
   634 		                // Make the new TCP receive buffer change effective now.
   642 						iFreeWindow = 0;
   635 		                iSockInBufSize = intValue;                                                          
   643 					//set the buffer
   636 		                }
   644                     iSockInBufSize = intValue;
   637 		            else
   645 					//disable startup flag.
   638 		                {
   646                     iSocketStartupCase = EFalse;
   639 		                //This sets iNewTcpWindow to a non-zero value, which indicates 
   647                     }
   640 		                //to the TCP that window is shrunk and process TCP segments
   648                 else 
   641 		                //which are in air before setting a new TCP receive buffer.         
   649                 {
   642 		                //TCP Receive window starts moving only when TCP hidden window
   650 					// Check for minimum value
   643 		                //size exceeds the size of the shrunk window.
   651 	                if (intValue < STATIC_CAST(TInt, KTcpMinimumWindow))
   644 		                   
   652 	                    {
   645 		                iNewTcpWindow = intValue;
   653 	                    intValue = STATIC_CAST(TInt, KTcpMinimumWindow);
   646 		                //Even in case of window shrink we can set the receive buffer size
   654 	                    }
   647 		                //immediately. This will be helpful, for processing SYN-ACK and other
   655 	                // Handle the situation where the connection has been established and 
   648 		                //receiver side processing.
   656 	                // window scaling is not in use
   649 		                //For already connected sockets iNewTcpWindow will be taking care
   657 	                if ( InState( ETcpSynReceived | ETcpEstablished ) && !iRcvWscale )
   650 		                //of shrinking the window size for that TCP session.
   658 	                    {
   651 		                iSockInBufSize = iNewTcpWindow;
   659 	                    // Do not allow window sizes larger than 0xFFFF
   652 		                if( iAdvertisedWindow > iNewTcpWindow )
   660 	                    intValue = Min ( intValue, 0xFFFF );
   653 		                    {
   661 	                    }
   654 		                    iShrinkedWindowSize = iAdvertisedWindow - iNewTcpWindow;
   662 
   655 		                    }
   663 	                // Check whether we are increasing or decreasing window size
   656 		                else
   664 	                if ( intValue >= iSockInBufSize )
   657 		                    {
   665 	                    {
   658 		                    // No Need to process TCP receive window processing.
   666 	                    // New window is larger than current one, check if a
   659 		                    iNewTcpWindow = 0;
   667 	                    // shrinking process is active
   660 		                    }
   668 	                    if ( !iNewTcpWindow )
   661 		                }
   669 	                        {
   662 					
   670 	                        // Mark new "space" as free, it will be updated to
   663                 } 
   671 	                        // peer on next operation.
   664 
   672 	                        iFreeWindow += intValue - iSockInBufSize;
       
   673 	                        }
       
   674 	                    else
       
   675 	                        {
       
   676 	                        // In the middle of shrinking process.
       
   677                       if ( iShrinkedWindowSize <= ( intValue - iSockInBufSize ))
       
   678 	                            {
       
   679 	                            // Increment to window size is enough to complete
       
   680 	                            // shrinking process. Update variables and exit
       
   681 	                            // from shrinking process.
       
   682                           iFreeWindow = ( intValue - iSockInBufSize ) - iShrinkedWindowSize;
       
   683 	                            iShrinkedWindowSize = 0;
       
   684 	                            iNewTcpWindow = 0;
       
   685 	                            }
       
   686 	                        else
       
   687 	                            {
       
   688 	                            // Not quite there yet but closer. Less to shrink,
       
   689 	                            // update this, but do not exit from shrinking
       
   690 	                            // process
       
   691                           iShrinkedWindowSize -= intValue - iSockInBufSize;
       
   692 	                            iNewTcpWindow = intValue;
       
   693 	                            }
       
   694 	                        }
       
   695 	                    }
       
   696 	                else
       
   697 	                    {
       
   698 	                    // Requested window is smaller than current one. Start or
       
   699 	                    // continue shrinking process. RCV window can be occupied
       
   700 	                    // for two different purpose at the moment
       
   701 	                    // 1. Client data in iSockInQ not read by application
       
   702 	                    // 2. Free window "opened" to peer (iAdvertisedWindow)
       
   703 	                    // When shrinking, we must ensure that when reopening
       
   704 	                    // the window to client there must be truly empty space
       
   705 	                    // in the window. Thus, freeze the right edge of the
       
   706 	                    // window (iRCV.NXT + iRCV.WND stays constant) until
       
   707 	                    // shrinking is completed.
       
   708 	                
       
   709 	                    if ( iNewTcpWindow )
       
   710 	                        {
       
   711 	                        // There is an ongoing shrink process, add the
       
   712 	                        // change to the amount to be shrinked
       
   713 	                        iShrinkedWindowSize += iSockInBufSize - intValue;
       
   714 	                        iNewTcpWindow = intValue;
       
   715 	                        }
       
   716 	                    else
       
   717 	                        {
       
   718 	                        // This is a new shrinking process, count how much
       
   719 	                        // needs to be shrinked
       
   720                       iShrinkedWindowSize = iSockInQLen + iRCV.WND;
       
   721 	                        if ( iShrinkedWindowSize >= intValue )
       
   722 	                            {
       
   723 	                            // We need to shrink since the currently occupied
       
   724 	                            // window does not fit to new one
       
   725 	                            iShrinkedWindowSize -= intValue;
       
   726 	                            // There is now free space in the window
       
   727 	                            iFreeWindow = 0;
       
   728 	                            // iNewTcpWindow is used as a state variable for
       
   729 	                            // shrinking
       
   730 	                            iNewTcpWindow = intValue;
       
   731 	                            }
       
   732 	                        else
       
   733 	                            {
       
   734 	                            // No need to shrink since we can fit the current
       
   735 	                            // contents to the new window, update free window
       
   736 	                            // If TCP connection is not yet setup, the free
       
   737 	                            // window will be updated on connection setup, 
       
   738 	                            // for existing connection it will be used
       
   739 	                            // next time application reads data
       
   740 	                            if ( iFreeWindow >= ( iSockInBufSize - intValue ))
       
   741 	                                {
       
   742 	                                iFreeWindow -= iSockInBufSize - intValue;
       
   743 	                                }
       
   744 	                            else 
       
   745 	                                {
       
   746 	                                // Something wrong. Try to reevaluate...
       
   747 	                                iFreeWindow = intValue - iShrinkedWindowSize;
       
   748 	                                }
       
   749 	                            iShrinkedWindowSize = 0;
       
   750 	                            }
       
   751 	                        }
       
   752 	                    }
       
   753 	                // Even in case of window shrink we can set the receive buffer size
       
   754 	                // immediately. This will be helpful, for processing SYN-ACK and other
       
   755 	                // receiver side processing.
       
   756 	                // For already connected sockets iNewTcpWindow will be taking care
       
   757 	                // of shrinking the window size for that TCP session.
       
   758 	                iSockInBufSize = intValue;
       
   759 	                }
       
   760 	            } 
       
   761 		    }
   665 		    }
   762 		    break;
   666 		    break;
   763 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
   667 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
   764 			case KSoTcpRecvWinSize:
   668 			case KSoTcpRecvWinSize:
   765 			    {
   669 			    {
   790 				else
   694 				else
   791 					iSockOutBufSize = intValue;
   695 					iSockOutBufSize = intValue;
   792 				}
   696 				}
   793 			break;
   697 			break;
   794 
   698 
   795 		case KSoTcpLingerinMicroSec:
   699 		case TSoTcpLingerinMicroSec:
   796             RDebug::Printf("TSoTcpLingerinMicroSec is set");
   700 		    RDebug::Printf("TSoTcpLingerinMicroSec is set");
   797             //Enable micro sec calculation for TCP linger timer. User (currently just exposed to browser)
   701 		    //Enable micro sec calculation for TCP linger timer. User (currently just exposed to browser)
   798             //will specify linger time in microsecs. 
   702 		    //will specify linger time in microsecs. 
   799             iMicroSecCalcFlag=ETrue;           
   703 		    iMicroSecCalcFlag=ETrue;
   800 		case KSoTcpLinger:
   704 		case KSoTcpLinger:
   801 			if (aOption.Length() < (TInt)sizeof(TSoTcpLingerOpt))
   705 			if (aOption.Length() < (TInt)sizeof(TSoTcpLingerOpt))
   802 				{
   706 				{
   803 				return KErrArgument;
   707 				return KErrArgument;
   804 				}
   708 				}
  1198 			{
  1102 			{
  1199 			Detach();
  1103 			Detach();
  1200 			}
  1104 			}
  1201 		else
  1105 		else
  1202 			{
  1106 			{
  1203 			//
  1107 		    // Start linger timer. RSocket::Close() returns when timer
  1204 			// Start linger timer. RSocket::Close() returns when timer
  1108             // expires or when all data has been succesfully transmitted.
  1205 			// expires or when all data has been succesfully transmitted.
  1109             if(iMicroSecCalcFlag)
  1206 			//
       
  1207 		    if(iMicroSecCalcFlag)
       
  1208                 {
  1110                 {
  1209                 //expecting iLinger timer to be specified in microsec.This will be set currently by browser where in
  1111                 //expecting iLinger timer to be specified in microsec.This will be set currently by browser where in
  1210                 //it is expected to be close with in certian time
  1112                 //it is expected to be close with in certian time
  1211                 iLingerTimer->Start(iLinger * 1);
  1113                 iLingerTimer->Start(iLinger * 1);
  1212                 }
  1114                 }
  1213             else
  1115             else
  1214                 {
  1116                 {
  1215                 iLingerTimer->Start(iLinger * KOneSecondInUs);
  1117                 iLingerTimer->Start(iLinger * KOneSecondInUs);
  1216                 }			
  1118                 }
  1217 			}
  1119 			}
  1218 		SchedTransmit();
  1120 		SchedTransmit();
  1219 
  1121 
  1220 		break;
  1122 		break;
  1221 
  1123 
  1471 	//We need to make sure, that we will show that window is not shrinked
  1373 	//We need to make sure, that we will show that window is not shrinked
  1472 	//to the sender, so tha right edge of the sender window remains constant.
  1374 	//to the sender, so tha right edge of the sender window remains constant.
  1473 	//if This is true, then it is a case of TCP window shrink and we need 
  1375 	//if This is true, then it is a case of TCP window shrink and we need 
  1474 	//to handle it.
  1376 	//to handle it.
  1475 	if ( iNewTcpWindow )
  1377 	if ( iNewTcpWindow )
  1476 	    {
  1378 		{
  1477 	    // Check if we can complete shrinking process
  1379 	   	//Log  this message for information, that Window is shrinked
  1478 	    if ( aLength > iShrinkedWindowSize )
  1380 	   	LOG(Log::Printf(_L("\ttcp SAP[%u] TCP window shrinking mode on"), (TInt)this));
  1479 	        {
  1381 	   
  1480 	        // We can exit from the shrinking process. Reset variables and
  1382 	   	//Increase the hidden free TCP receive window.
  1481 	        // update free window.
  1383 	   	iHiddenFreeWindow += aLength;
  1482 	        iFreeWindow = aLength - iShrinkedWindowSize;
  1384 	   
  1483 	        iShrinkedWindowSize = 0;
  1385 	   	if (iHiddenFreeWindow >= iShrinkedWindowSize)
  1484 	        iNewTcpWindow = 0;
  1386 			{
  1485 	        }
  1387 			//Disable window shrink processing, so that TCP could switch
  1486 	    else
  1388 			//to the normal processing.    
  1487 	        {
  1389 			iSockInBufSize = iNewTcpWindow;
  1488 	        // Substract the needed shrinking amount by the amount of bytes client
  1390 			
  1489 	        // read from the buffer
  1391 			//Add the usable window to the free window.
  1490 	        iShrinkedWindowSize -= aLength;
  1392 			iFreeWindow += iHiddenFreeWindow - iShrinkedWindowSize;
  1491 	        }
  1393 			
  1492 	    }
  1394 			//There are chances that TCP receive window might further shrink.
       
  1395 			iHiddenFreeWindow = 0;
       
  1396 			
       
  1397 			//TCP Receive window shrink phase is over.
       
  1398 			iNewTcpWindow = 0;
       
  1399 			
       
  1400 			//Log  this message for information, that Window is shrinked
       
  1401 			LOG(Log::Printf(_L("\ttcp SAP[%u] TCP window shrinking mode off"), (TInt)this));
       
  1402 			}
       
  1403 		}
  1493 	else
  1404 	else
  1494 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
  1405 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
  1495 	
  1406 	
  1496 		{
  1407 		{
  1497 		iFreeWindow += aLength;	
  1408 		iFreeWindow += aLength;