networkprotocols/tcpipv4v6prt/src/tcp_sap.cpp
branchRCL_3
changeset 58 8d540f55e491
parent 57 abbed5a4b42a
child 75 c1029e558ef5
equal deleted inserted replaced
57:abbed5a4b42a 58:8d540f55e491
   138 //  including the establishment of security and mobility bindings. CONNECT is
   138 //  including the establishment of security and mobility bindings. CONNECT is
   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 
   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 #ifdef _LOG
   145 #ifdef _LOG
   145 const TText *CProviderTCP6::TcpState(TUint aState)
   146 const TText *CProviderTCP6::TcpState(TUint aState)
   146 	{
   147 	{
   147 	TInt i;
   148 	TInt i;
   148 	static const TText* const tcpStates[] = {
   149 	static const TText* const tcpStates[] = {
   789 				else
   790 				else
   790 					iSockOutBufSize = intValue;
   791 					iSockOutBufSize = intValue;
   791 				}
   792 				}
   792 			break;
   793 			break;
   793 
   794 
       
   795 		case KSoTcpLingerinMicroSec:
       
   796             RDebug::Printf("TSoTcpLingerinMicroSec is set");
       
   797             //Enable micro sec calculation for TCP linger timer. User (currently just exposed to browser)
       
   798             //will specify linger time in microsecs. 
       
   799             iMicroSecCalcFlag=ETrue;           
   794 		case KSoTcpLinger:
   800 		case KSoTcpLinger:
   795 			if (aOption.Length() < (TInt)sizeof(TSoTcpLingerOpt))
   801 			if (aOption.Length() < (TInt)sizeof(TSoTcpLingerOpt))
   796 				{
   802 				{
   797 				return KErrArgument;
   803 				return KErrArgument;
   798 				}
   804 				}
  1196 			{
  1202 			{
  1197 			//
  1203 			//
  1198 			// Start linger timer. RSocket::Close() returns when timer
  1204 			// Start linger timer. RSocket::Close() returns when timer
  1199 			// expires or when all data has been succesfully transmitted.
  1205 			// expires or when all data has been succesfully transmitted.
  1200 			//
  1206 			//
  1201 			iLingerTimer->Start(iLinger * KOneSecondUs);
  1207 		    if(iMicroSecCalcFlag)
       
  1208                 {
       
  1209                 //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
       
  1211                 iLingerTimer->Start(iLinger * 1);
       
  1212                 }
       
  1213             else
       
  1214                 {
       
  1215                 iLingerTimer->Start(iLinger * KOneSecondInUs);
       
  1216                 }			
  1202 			}
  1217 			}
  1203 		SchedTransmit();
  1218 		SchedTransmit();
  1204 
  1219 
  1205 		break;
  1220 		break;
  1206 
  1221 
  1786 			
  1801 			
  1787 		if (CanTriggerKeepAlive())
  1802 		if (CanTriggerKeepAlive())
  1788 			{
  1803 			{
  1789 			// The heaviest time check only if we are otherwise allowed to send the keepalive.
  1804 			// The heaviest time check only if we are otherwise allowed to send the keepalive.
  1790 			TUint32 time_now = TimeStamp();
  1805 			TUint32 time_now = TimeStamp();
  1791 			if (time_now - iLastTriggeredKeepAlive > KTcpKeepAliveTH * KOneSecondUs)
  1806 			if (time_now - iLastTriggeredKeepAlive > KTcpKeepAliveTH * KOneSecondInMs)
  1792 				{
  1807 				{
  1793 				iLastTriggeredKeepAlive = time_now;
  1808 				iLastTriggeredKeepAlive = time_now;
  1794 				LOG(Log::Printf(_L("\ttcp SAP[%u] CanSend(): Sending a Keep-Alive probe"), (TInt)this));
  1809 				LOG(Log::Printf(_L("\ttcp SAP[%u] CanSend(): Sending a Keep-Alive probe"), (TInt)this));
  1795 				SendSegment(KTcpCtlACK, iSND.UNA - 1, 0);
  1810 				SendSegment(KTcpCtlACK, iSND.UNA - 1, 0);
  1796 				}
  1811 				}
  2445 	TUint32 usec = TimeStamp();
  2460 	TUint32 usec = TimeStamp();
  2446 
  2461 
  2447 	if (!iLastTimeout)
  2462 	if (!iLastTimeout)
  2448 		iLastTimeout = usec;
  2463 		iLastTimeout = usec;
  2449 
  2464 
  2450 	TUint32 distance = (usec - iLastTimeout) / KOneSecondUs;  // seconds
  2465 	TUint32 distance = (usec - iLastTimeout) / KOneSecondInMs;  // seconds
  2451 	TUint32 interval = iBackoff ? Protocol()->KeepAliveRxmt() : Protocol()->KeepAliveIntv();
  2466 	TUint32 interval = iBackoff ? Protocol()->KeepAliveRxmt() : Protocol()->KeepAliveIntv();
  2452 
  2467 
  2453 	if (distance > interval)
  2468 	if (distance > interval)
  2454 		{
  2469 		{
  2455 		// Send a keepalive probe. If no ack arrives, next one is sent after a shorter time (75 s)
  2470 		// Send a keepalive probe. If no ack arrives, next one is sent after a shorter time (75 s)
  2456 		LOG(Log::Printf(_L("\ttcp SAP[%u] KeepAliveTimeout(): Sending a Keep-Alive probe"), (TInt)this));
  2471 		LOG(Log::Printf(_L("\ttcp SAP[%u] KeepAliveTimeout(): Sending a Keep-Alive probe"), (TInt)this));
  2457 		SendSegment(KTcpCtlACK, iSND.UNA - 1, 0);
  2472 		SendSegment(KTcpCtlACK, iSND.UNA - 1, 0);
  2458 		iBackoff++;
  2473 		iBackoff++;
  2459 		iRetransTimer->Restart(Protocol()->KeepAliveRxmt() * KOneSecondUs);
  2474 		iRetransTimer->Restart(Protocol()->KeepAliveRxmt() * KOneSecondInUs);
  2460 		}
  2475 		}
  2461 	else
  2476 	else
  2462 		{
  2477 		{
  2463 		// This branch is entered when the first keepalive has to be issued after an idle period.
  2478 		// This branch is entered when the first keepalive has to be issued after an idle period.
  2464 		distance = Protocol()->KeepAliveIntv() - distance;
  2479 		distance = Protocol()->KeepAliveIntv() - distance;
  2465 		iRetransTimer->Restart((distance > 1800) ?
  2480 		iRetransTimer->Restart((distance > 1800) ?
  2466 			1800 * KOneSecondUs : (distance * KOneSecondUs));
  2481 			1800 * KOneSecondInUs : (distance * KOneSecondInUs));
  2467 		}
  2482 		}
  2468 	}
  2483 	}
  2469 
  2484 
  2470 
  2485 
  2471 void CProviderTCP6::ResetKeepAlives()
  2486 void CProviderTCP6::ResetKeepAlives()
  2472 	{
  2487 	{
  2473 	ASSERT(iRetransTimer);
  2488 	ASSERT(iRetransTimer);
  2474 	iRetransTimer->Restart((Protocol()->KeepAliveIntv() > 1800) ?
  2489 	iRetransTimer->Restart((Protocol()->KeepAliveIntv() > 1800) ?
  2475 		1800 * KOneSecondUs : (Protocol()->KeepAliveIntv() * KOneSecondUs));
  2490 		1800 * KOneSecondInUs : (Protocol()->KeepAliveIntv() * KOneSecondInUs));
  2476 	// Backoff is used for counting unacknowledged keepalive retransmissions during idle periods
  2491 	// Backoff is used for counting unacknowledged keepalive retransmissions during idle periods
  2477 	iBackoff = 0;
  2492 	iBackoff = 0;
  2478 	iLastTimeout = TimeStamp();
  2493 	iLastTimeout = TimeStamp();
  2479 	}
  2494 	}
  2480 
  2495 
  3686 							}
  3701 							}
  3687 						else if (!iFlags.iSackOk)
  3702 						else if (!iFlags.iSackOk)
  3688 							{
  3703 							{
  3689 							// NewReno partial ACK processing.
  3704 							// NewReno partial ACK processing.
  3690 
  3705 
  3691 			  /* From RFC2582:
  3706 						  /* From RFC2582:
  3692 			   If this ACK does *not* acknowledge all of the data up to and
  3707 						   If this ACK does *not* acknowledge all of the data up to and
  3693 			   including "recover", then this is a partial ACK.  In this case,
  3708 						   including "recover", then this is a partial ACK.  In this case,
  3694 			   retransmit the first unacknowledged segment.  Deflate the
  3709 						   retransmit the first unacknowledged segment.  Deflate the
  3695 			   congestion window by the amount of new data acknowledged, then
  3710 						   congestion window by the amount of new data acknowledged, then
  3696 			   add back one MSS and send a new segment if permitted by the new
  3711 						   add back one MSS and send a new segment if permitted by the new
  3697 			   value of cwnd.  This "partial window deflation" attempts to
  3712 						   value of cwnd.  This "partial window deflation" attempts to
  3698 			   ensure that, when Fast Recovery eventually ends, approximately
  3713 						   ensure that, when Fast Recovery eventually ends, approximately
  3699 			   ssthresh amount of data will be outstanding in the network.  Do
  3714 						   ssthresh amount of data will be outstanding in the network.  Do
  3700 			   not exit the Fast Recovery procedure (i.e., if any duplicate ACKs
  3715 						   not exit the Fast Recovery procedure (i.e., if any duplicate ACKs
  3701 			   subsequently arrive, execute Steps 3 and 4 above).
  3716 						   subsequently arrive, execute Steps 3 and 4 above).
  3702 
  3717 
  3703 			   For the first partial ACK that arrives during Fast Recovery, also
  3718 						   For the first partial ACK that arrives during Fast Recovery, also
  3704 			   reset the retransmit timer.
  3719 						   reset the retransmit timer.
  3705 							*/
  3720 							*/
  3706 
  3721 
  3707 							iCwnd -= acked;
  3722 							iCwnd -= acked;
  3708 							iCwnd += iSMSS;
  3723 							iCwnd += iSMSS;
  3709 							LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): FAST RETRANSMIT on PARTIAL ACK"), (TInt)this));
  3724 							LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): FAST RETRANSMIT on PARTIAL ACK"), (TInt)this));
  3716 							//
  3731 							//
  3717 							ASSERT(iSMSS);
  3732 							ASSERT(iSMSS);
  3718 							iDupAcks = Max(iDupAcks - acked / (TInt)iSMSS, 0);
  3733 							iDupAcks = Max(iDupAcks - acked / (TInt)iSMSS, 0);
  3719 							}
  3734 							}
  3720 						}
  3735 						}
       
  3736 					else if ( iDupAcks )
       
  3737                         {
       
  3738                         // New data acknowledged, and not ongoing any recovery action
       
  3739                         // Reset duplicate ack count
       
  3740                         LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Reset iDupAcks to 0"), (TInt)this));
       
  3741                         iDupAcks = 0;
       
  3742                         }
  3721 
  3743 
  3722 					// Reset limited transmit window
  3744 					// Reset limited transmit window
  3723 					iLwnd = 0;
  3745 					iLwnd = 0;
  3724 
  3746 
  3725 					// Everything acked?
  3747 					// Everything acked?
  3891 					if (SourceQuench() || iQuenchSeq.Outside(iSND.NXT, iSND.NXT + iSND.WND))
  3913 					if (SourceQuench() || iQuenchSeq.Outside(iSND.NXT, iSND.NXT + iSND.WND))
  3892 						{
  3914 						{
  3893 						iFlags.iEcnSendCWR = ETrue;
  3915 						iFlags.iEcnSendCWR = ETrue;
  3894 						}
  3916 						}
  3895 					}
  3917 					}
  3896 				if((iSND.NXT - ack) >0 && InState(ETcpEstablished) && (acked ==0))
  3918 				// This section used to hold the RetryACK concept, a reference can be checked
  3897 					{
  3919 				// from older versions(9.2/9.3). Its being removed as not required.	
  3898 					iRetryAck++;
       
  3899 					if(iRetryAck >=4) // 4 an arbitary number; as this count does not refer to dup_ack, this will not interfere with Fast retransmission
       
  3900 						{
       
  3901 						LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): retransmitting the segment"), (TInt)this));
       
  3902 						SendSegments(ETrue);
       
  3903 						iRetryAck = 0; // reset the retry count
       
  3904 						}
       
  3905 					}
       
  3906 					
  3920 					
  3907 				}
  3921 				}
  3908 			}
  3922 			}
  3909 
  3923 
  3910 		//
  3924 		//