networkprotocols/tcpipv4v6prt/src/tcp_sap.cpp
changeset 0 af10295192d8
child 12 e9cc36e353d4
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // tcp_sap.cpp - TCP service access point
       
    15 // TCP Service Access Point and most of the protocol logic.
       
    16 //
       
    17 
       
    18 
       
    19 
       
    20 /**
       
    21  @file tcp_sap.cpp
       
    22 */
       
    23 
       
    24 #include "tcp.h"
       
    25 #include <in6_dstcache.h>
       
    26 #include <in6_opt.h>
       
    27 #include <in6_if.h>
       
    28 #include <in6_dstcache_internal.h>
       
    29 #include <nifman_internal.h>
       
    30 
       
    31 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
    32 #include <in_sock.h>
       
    33 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
    34 
       
    35 // speed optimisations
       
    36 #ifdef __ARMCC__
       
    37 #pragma push
       
    38 #pragma arm
       
    39 #endif
       
    40 
       
    41 #define SIGNED_UNSIGNED_FIX
       
    42 
       
    43 // Copied from ip6.cpp. Should move to some common definition file?
       
    44 static const TLitC8<sizeof(TInt)> KInetOptionDisable = {sizeof(TInt), {0}};
       
    45 
       
    46 #define SYMBIAN_NETWORKING_UPS
       
    47 
       
    48 //
       
    49 //
       
    50 // TCP state diagram from RFC793
       
    51 //
       
    52 //
       
    53 //                              +---------+ ---------\      active OPEN
       
    54 //                              |  CLOSED |            \    -----------
       
    55 //                              +---------+<---------\   \   create TCB
       
    56 //                                |     ^              \   \  snd SYN
       
    57 //                   passive OPEN |     |   CLOSE        \   \.
       
    58 //                   ------------ |     | ----------       \   \.
       
    59 //                    create TCB  |     | delete TCB         \   \.
       
    60 //                                V     |                      \   \.
       
    61 //                              +---------+            CLOSE    |    \.
       
    62 //                              |  LISTEN |          ---------- |     |
       
    63 //                              +---------+          delete TCB |     |
       
    64 //                   rcv SYN      |     |     SEND              |     |
       
    65 //                  -----------   |     |    -------            |     V
       
    66 // +---------+      snd SYN,ACK  /       \   snd SYN          +---------+
       
    67 // |         |<-----------------           ------------------>|         |
       
    68 // |   SYN   |                    rcv SYN                     |   SYN   |
       
    69 // |   RCVD  |<-----------------------------------------------|   SENT  |
       
    70 // |         |                    snd ACK                     |         |
       
    71 // |         |------------------           -------------------|         |
       
    72 // +---------+   rcv ACK of SYN  \       /  rcv SYN,ACK       +---------+
       
    73 //   |           --------------   |     |   -----------
       
    74 //   |                  x         |     |     snd ACK
       
    75 //   |                            V     V
       
    76 //   |  CLOSE                   +---------+
       
    77 //   | -------                  |  ESTAB  |
       
    78 //   | snd FIN                  +---------+
       
    79 //   |                   CLOSE    |     |    rcv FIN
       
    80 //   V                  -------   |     |    -------
       
    81 // +---------+          snd FIN  /       \   snd ACK          +---------+
       
    82 // |  FIN    |<-----------------           ------------------>|  CLOSE  |
       
    83 // | WAIT-1  |------------------                              |   WAIT  |
       
    84 // +---------+          rcv FIN  \                            +---------+
       
    85 //   | rcv ACK of FIN   -------   |                            CLOSE  |
       
    86 //   | --------------   snd ACK   |                           ------- |
       
    87 //   V        x                   V                           snd FIN V
       
    88 // +---------+                  +---------+                   +---------+
       
    89 // |FINWAIT-2|                  | CLOSING |                   | LAST-ACK|
       
    90 // +---------+                  +---------+                   +---------+
       
    91 //   |                rcv ACK of FIN |                 rcv ACK of FIN |
       
    92 //   |  rcv FIN       -------------- |    Timeout=2MSL -------------- |
       
    93 //   |  -------              x       V    ------------        x       V
       
    94 //    \ snd ACK                 +---------+delete TCB         +---------+
       
    95 //     ------------------------>|TIME WAIT|------------------>| CLOSED  |
       
    96 //                              +---------+                   +---------+
       
    97 //
       
    98 //  LISTEN - represents waiting for a connection request from any remote
       
    99 //  TCP and port.
       
   100 //
       
   101 //  SYN-SENT - represents waiting for a matching connection request
       
   102 //  after having sent a connection request.
       
   103 //
       
   104 //  SYN-RECEIVED - represents waiting for a confirming connection
       
   105 //  request acknowledgment after having both received and sent a
       
   106 //  connection request.
       
   107 //
       
   108 //  ESTABLISHED - represents an open connection, data received can be
       
   109 //  delivered to the user.  The normal state for the data transfer phase
       
   110 //  of the connection.
       
   111 //
       
   112 //  FIN-WAIT-1 - represents waiting for a connection termination request
       
   113 //  from the remote TCP, or an acknowledgment of the connection
       
   114 //  termination request previously sent.
       
   115 //
       
   116 //  FIN-WAIT-2 - represents waiting for a connection termination request
       
   117 //  from the remote TCP.
       
   118 //
       
   119 //  CLOSE-WAIT - represents waiting for a connection termination request
       
   120 //  from the local user.
       
   121 //
       
   122 //  CLOSING - represents waiting for a connection termination request
       
   123 //  acknowledgment from the remote TCP.
       
   124 //
       
   125 //  LAST-ACK - represents waiting for an acknowledgment of the
       
   126 //  connection termination request previously sent to the remote TCP
       
   127 //  (which includes an acknowledgment of its connection termination request).
       
   128 //
       
   129 //  TIME-WAIT - represents waiting for enough time to pass to be sure
       
   130 //  the remote TCP received the acknowledgment of its connection
       
   131 //  termination request.
       
   132 //
       
   133 //  CLOSED - represents no connection state at all.
       
   134 //
       
   135 //  CONNECT - represents waiting for a network path to become ready after
       
   136 //  the user has issued an active OPEN request. The request waits in this
       
   137 //  state until all the necessary negotiations have been accomplished,
       
   138 //  including the establishment of security and mobility bindings. CONNECT is
       
   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.
       
   141 //
       
   142 
       
   143 
       
   144 #ifdef _LOG
       
   145 const TText *CProviderTCP6::TcpState(TUint aState)
       
   146 	{
       
   147 	TInt i;
       
   148 	static const TText* const tcpStates[] = {
       
   149 		_S("CONSTRUCTING"),
       
   150 			_S("INITIAL"),
       
   151 			_S("LISTEN"),
       
   152 			_S("SYN-SENT"),
       
   153 			_S("SYN-RECEIVED"),
       
   154 			_S("ESTABLISHED"),
       
   155 			_S("FIN-WAIT-1"),
       
   156 			_S("FIN-WAIT-2"),
       
   157 			_S("CLOSE-WAIT"),
       
   158 			_S("CLOSING"),
       
   159 			_S("LAST-ACK"),
       
   160 			_S("TIME-WAIT"),
       
   161 			_S("CLOSED"),
       
   162 			_S("CONNECT"),
       
   163 			_S("INVALID"),
       
   164 			NULL
       
   165 			};
       
   166 
       
   167 	if (aState == ~0UL)
       
   168 		aState = iState;
       
   169 	for (i = 0; aState && tcpStates[i+1]; aState >>= 1)
       
   170 		i++;
       
   171 	return tcpStates[i];
       
   172 	}
       
   173 #endif
       
   174 
       
   175 CProviderTCP6::CProviderTCP6(CProtocolInet6Base* aProtocol)
       
   176 	: CProviderInet6Transport(aProtocol)
       
   177 	{
       
   178 	__DECLARE_NAME(_S("CProviderTCP6"));
       
   179 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW	
       
   180 	iWindowSetByUser = EFalse;
       
   181 #endif	
       
   182 	}
       
   183 
       
   184 CProviderTCP6::~CProviderTCP6()
       
   185 	{
       
   186 	LOG(Log::Printf(_L("\ttcp SAP[%u] being deleted"), (TInt)this));
       
   187 	Stop();
       
   188 	FreeQueues();
       
   189 
       
   190 	delete iTransmitter;
       
   191 	delete iDelayAckTimer;
       
   192 	delete iRetransTimer;
       
   193 	delete iLingerTimer;
       
   194 
       
   195 	// Delete server socket state
       
   196 	if (iParent)
       
   197 		{
       
   198 		// Notify parent.
       
   199 		iParent->SetChildDeleted(ETrue);
       
   200 		iParent->DetachChild(this);
       
   201 		}
       
   202 	else if (iListenQueue)
       
   203 		{
       
   204 		//
       
   205 		// Delete all pending child sockets. The child socket destructor will
       
   206 		// call DetachChild(), removing itself from the socket queue. If the
       
   207 		// socket has already been registered with the socket server, we will
       
   208 		// simply detach it here.
       
   209 		//
       
   210 		while (iConnectCount)
       
   211 			{
       
   212 			ASSERT(iListenQueue[0]->iParent == this);
       
   213 			if (iListenQueue[0]->iSockFlags.iAttached)
       
   214 				DetachChild(iListenQueue[0]);
       
   215 			else
       
   216 			    {
       
   217 			    if (iListenQueue[0]->InState(ETcpSynReceived))
       
   218 			    	{
       
   219 			    	iListenQueue[0]->ClearSYNSettings();
       
   220 				    iListenQueue[0]->iSockFlags.iSendClose = ETrue;
       
   221 				    iListenQueue[0]->iSockFlags.iRecvClose = ETrue;
       
   222 				    iListenQueue[0]->SendSegments();
       
   223 				    DetachChild(iListenQueue[0]);
       
   224 			    	}
       
   225 			   	else
       
   226 					delete iListenQueue[0];
       
   227 			    }
       
   228 			}
       
   229 		delete[] iListenQueue;
       
   230 		}
       
   231 	}
       
   232 
       
   233 //
       
   234 // Initialize a SAP with default values
       
   235 //
       
   236 void CProviderTCP6::InitL()
       
   237 	{
       
   238 	TCallBack sender(SenderCallBack, this);
       
   239 	TCallBack receiver(ReceiverCallBack, this);
       
   240 	TCallBack delack(DelayAckCallBack, this);
       
   241 	TCallBack transmitter(TransmitterCallBack, this);
       
   242 	TCallBack retransmitter(RetransmitterCallBack, this);
       
   243 	TCallBack linger(LingerTimerCallBack, this);
       
   244 
       
   245 	CProviderInet6Base::InitL();
       
   246 	iFlow.SetProtocol(KProtocolInetTcp);
       
   247 	iFlow.SetNotify(this);
       
   248 
       
   249 	iSendQ.InitL(transmitter, 13);
       
   250 	iRecvQ.InitL(receiver, 12);
       
   251 
       
   252 	iTransmitter = new CAsyncCallBack(sender, KInet6DefaultPriority);
       
   253 	iDelayAckTimer = new CTcpTimer(delack);
       
   254 	iRetransTimer = new CTcpTimer(retransmitter);
       
   255 	iLingerTimer = new CTcpTimer(linger);
       
   256 	if (!iTransmitter || !iDelayAckTimer || !iRetransTimer || !iLingerTimer)
       
   257 		User::Leave(KErrNoMemory);
       
   258 
       
   259 	iDelayAckTimer->InitL();
       
   260 	iRetransTimer->InitL();
       
   261 	iLingerTimer->InitL();
       
   262 	iSockInBufSize        = Protocol()->RecvBuf();
       
   263 	iSockOutBufSize       = Protocol()->SendBuf();
       
   264 	iSsthresh		= KMaxTInt32;
       
   265 	iRTO			= Protocol()->InitialRTO();
       
   266 	ClearRTT();
       
   267 	iMSS                  = Protocol()->MSS();
       
   268 	iSMSS			= KTcpStandardMSS;
       
   269 	iRMSS			= KTcpStandardMSS;
       
   270 	iLinger		= -1;  // linger disabled
       
   271 	iFlags.iSackOk	    = Protocol()->Sack();
       
   272 	iFlags.iUseTimeStamps	    = Protocol()->TimeStamps();
       
   273 	iFlags.iEcn		    = (Protocol()->Ecn() != 0);
       
   274 
       
   275 	// Report ICMP errors to application
       
   276 	iSockFlags.iReportIcmp    = ETrue;
       
   277 
       
   278 	if (iFlags.iUseTimeStamps)
       
   279 		iOptions.SetTimeStamps(0, 0);
       
   280 
       
   281 	if (iFlags.iSackOk)
       
   282 		iOptions.SetSackOk();
       
   283 
       
   284 	iOptions.SetAlignOpt(Protocol()->AlignOpt());
       
   285 	iStartTime.UniversalTime();
       
   286 
       
   287 	iState = ETcpInitial;
       
   288 	
       
   289 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
   290     iHiddenFreeWindow 	= 0;
       
   291     iNewTcpWindow    	= 0;
       
   292     iTcpMaxRecvWin       = Protocol()->RecvMaxWnd();
       
   293 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
   294 
       
   295 	}
       
   296 
       
   297 
       
   298 void CProviderTCP6::ReadDestinationCache()
       
   299 	{
       
   300 	if (!Protocol()->DstCache())  // Dest. cache is not enabled as ini parameter
       
   301 		{
       
   302 		return;
       
   303 		}
       
   304 
       
   305 	const TInetAddr& dstaddr = iFlow.FlowContext()->RemoteAddr();
       
   306 	if (dstaddr.IsUnspecified())
       
   307 		{
       
   308 		LOG(Log::Printf(_L("\ttcp SAP[%u] ReadDestinationCache() : No destination address"), (TInt)this));
       
   309 		return;
       
   310 		}
       
   311 
       
   312 	TInt err = KErrNone;
       
   313 	MDestinationCache *dcache = NULL;
       
   314 	TRAP(err, dcache = IMPORT_API_L(Protocol()->Interfacer(), MDestinationCache));
       
   315 	if (err != KErrNone || dcache == NULL)
       
   316 		{
       
   317 		LOG(Log::Printf(_L("\ttcp SAP[%u] ReadDestinationCache() : DstCache not available"), (TInt)this));
       
   318 		return;
       
   319 		}
       
   320 
       
   321 	const TCacheInfo *cinfo = dcache->Find(dstaddr);
       
   322 	if (!cinfo)
       
   323 		{
       
   324 		LOG(Log::Printf(_L("\ttcp SAP[%u] ReadDestinationCache() : No match for address in cache"), (TInt)this));
       
   325 		return;
       
   326 		}
       
   327 
       
   328 	if (cinfo->iMetrics[TCacheInfo::ESsThresh])
       
   329 		{
       
   330 		iSsthresh = cinfo->iMetrics[TCacheInfo::ESsThresh];
       
   331 		}
       
   332 	if (cinfo->iMetrics[TCacheInfo::ESRtt])
       
   333 		{
       
   334 		iSRTT = cinfo->iMetrics[TCacheInfo::ESRtt];
       
   335 		}
       
   336 	if (cinfo->iMetrics[TCacheInfo::ERto])
       
   337 		{
       
   338 		iRTO = cinfo->iMetrics[TCacheInfo::ERto];
       
   339 		}
       
   340 
       
   341 	LOG(Log::Printf(_L(
       
   342 		"\ttcp SAP[%u] ReadDestinationCache() : Matching DstCache entry found [0x%08x] - ssthresh: %d"),
       
   343 		(TInt)this, cinfo, iSsthresh));
       
   344 	}
       
   345 
       
   346 void CProviderTCP6::StoreDestinationCache()
       
   347 	{
       
   348 	if (!Protocol()->DstCache() || !iFlow.FlowContext())
       
   349 		{
       
   350 		return;
       
   351 		}
       
   352 
       
   353 	const TInetAddr& dstaddr = iFlow.FlowContext()->RemoteAddr();
       
   354 	if (dstaddr.IsUnspecified())
       
   355 		{
       
   356 		LOG(Log::Printf(_L("\ttcp SAP[%u] StoreDestinationCache() : No destination address"), (TInt)this));
       
   357 		return;
       
   358 		}
       
   359 
       
   360 	TInt err = KErrNone;
       
   361 	MDestinationCache *dcache = NULL;
       
   362 	TRAP(err, dcache = IMPORT_API_L(Protocol()->Interfacer(), MDestinationCache));
       
   363 	if (err != KErrNone || dcache == NULL)
       
   364 		{
       
   365 		LOG(Log::Printf(_L("\ttcp SAP[%u] StoreDestinationCache() : DstCache not available"), (TInt)this));
       
   366 		return;
       
   367 		}
       
   368 
       
   369 	TCacheInfo cinfo;
       
   370 	cinfo.ClearAll();
       
   371 	cinfo.iMetrics[TCacheInfo::ESsThresh] = iSsthresh;
       
   372 	cinfo.iMetrics[TCacheInfo::ESRtt] = iSRTT;
       
   373 	cinfo.iMetrics[TCacheInfo::ERto] = iRTO;
       
   374 
       
   375 	TRAP(err, dcache->StoreL(dstaddr, cinfo));
       
   376 	if (err != KErrNone)
       
   377 		{
       
   378 		LOG(Log::Printf(_L("\ttcp SAP[%u] StoreDestinationCache() : DstCache store failed"), (TInt)this));
       
   379 		return;
       
   380 		}
       
   381 	}
       
   382 
       
   383 
       
   384 void CProviderTCP6::Start()
       
   385 	{
       
   386 	LOG(Log::Printf(_L("Start\ttcp SAP[%u] enter"), (TInt)this));
       
   387 	CProviderInet6Transport::Start();
       
   388 	iFlags.iStarted = ETrue;
       
   389 
       
   390 	//
       
   391 	// Detach from parent socket
       
   392 	//
       
   393 	if (iParent)
       
   394 		{
       
   395 		iSockFlags.iNotify = ETrue;
       
   396 		iParent->DetachChild(this);
       
   397 
       
   398 		//
       
   399 		// Tell ESock which network interface the child socket is using.
       
   400 		//
       
   401 		const MInterface *iface = Protocol()->Interfacer()->Interface(iFlow.FlowContext()->Interface());
       
   402 		if (iface != NULL)
       
   403 			{
       
   404 			TPckgBuf<TSoIfConnectionInfo> netinfo;
       
   405 			netinfo().iIAPId = iface->Scope(EScopeType_IAP);
       
   406 			netinfo().iNetworkId = iface->Scope(EScopeType_NET);
       
   407 			LOG(Log::Printf(_L("\ttcp SAP[%u] Bearer IAP=%d, NID=%d"), (TInt)this, netinfo().iIAPId, netinfo().iNetworkId));
       
   408 			iSocket->Bearer(netinfo);
       
   409 			}
       
   410 		//
       
   411 		// Report error if TCP has been disconnected already
       
   412 		//
       
   413 		if (InState(ETcpClosed))
       
   414 			{
       
   415 			LOG(Log::Printf(_L("\ttcp SAP[%u] %s, Error %d"), (TInt)this, TcpState(), KErrDisconnected));
       
   416 			Error(KErrDisconnected);
       
   417 			}
       
   418 		}
       
   419 
       
   420 	//
       
   421 	// If an error has occurred, we must deliver it to the
       
   422 	// socket server now that the socket notifier has been
       
   423 	// initialised.
       
   424 	//
       
   425 	if (iLastError.iStatus != KErrNone && iErrorMask != 0)
       
   426 		{
       
   427 		LOG(Log::Printf(_L("\ttcp SAP[%u] Delayed error %d, mask %b delivered."),
       
   428 			(TInt)this, iLastError.iStatus, iErrorMask));
       
   429 		iSocket->Error(iLastError.iStatus, iErrorMask);
       
   430 		}
       
   431 
       
   432 	// Wake up the receiver. We might have something to do.
       
   433 	iRecvQ.Wake();
       
   434 	LOG(Log::Printf(_L("Start\ttcp SAP[%u] exit"), (TInt)this));
       
   435 	}
       
   436 
       
   437 
       
   438 //
       
   439 // Stop all transmission (except for iSendQ, which will be allowed to drain)
       
   440 //
       
   441 void CProviderTCP6::Stop()
       
   442 	{
       
   443 	if (iTransmitter)
       
   444 		CancelTransmit();
       
   445 	if (iRetransTimer)
       
   446 		CancelRetransmit();
       
   447 	if (iDelayAckTimer)
       
   448 		CancelDelayACK();
       
   449 	if (iLingerTimer)
       
   450 		iLingerTimer->Cancel();
       
   451 	}
       
   452 
       
   453 
       
   454 //
       
   455 // Empty all queues
       
   456 //
       
   457 void CProviderTCP6::FreeQueues()
       
   458 	{
       
   459 	iSockInQ.Free();
       
   460 	iSockInQLen = 0;
       
   461 	iSockOutQ.Free();
       
   462 	iSockOutQLen = 0;
       
   463 	iFragQ.Free();
       
   464 	iRecvQ.Free();
       
   465 	iSendQ.Cancel();
       
   466 	iSendQ.Free();
       
   467 	}
       
   468 
       
   469 
       
   470 //
       
   471 // Close the socket down
       
   472 //
       
   473 void CProviderTCP6::Close()
       
   474 	{
       
   475 	StoreDestinationCache();
       
   476 
       
   477 	iSockFlags.iSendClose = ETrue;
       
   478 	iSockFlags.iRecvClose = ETrue;
       
   479 	Protocol()->UnbindProvider(this);
       
   480 	Stop();
       
   481 	FreeQueues();
       
   482 	EnterState(ETcpClosed);
       
   483 	}
       
   484 
       
   485 
       
   486 void CProviderTCP6::Ioctl(TUint aLevel, TUint aName, TDes8* aOption)
       
   487 	{
       
   488 	LOG(Log::Printf(_L("Ioctl\ttcp SAP[%u] %x, %x"), (TInt)this, aLevel, aName));
       
   489 	if (aLevel == KSolInetTcp && aName == KIoctlTcpNotifyDataSent)
       
   490 		{
       
   491 		iFlags.iDataSentIoctl = ETrue;
       
   492 		CompleteIoctl(KErrNone);
       
   493 		}
       
   494 	else
       
   495 		CProviderInet6Transport::Ioctl(aLevel, aName, aOption);
       
   496 	}
       
   497 
       
   498 
       
   499 void CProviderTCP6::CancelIoctl(TUint aLevel, TUint aName)
       
   500 	{
       
   501 	LOG(Log::Printf(_L("CancelIoctl\ttcp SAP[%u] %x, %x"), (TInt)this, aLevel, aName));
       
   502 	if (aLevel == KSolInetTcp && aName == KIoctlTcpNotifyDataSent)
       
   503 		CompleteIoctl(KErrCancel);
       
   504 	else
       
   505 		CProviderInet6Transport::CancelIoctl(aLevel, aName);
       
   506 	}
       
   507 
       
   508 
       
   509 TInt CProviderTCP6::SetOption(TUint aLevel, TUint aName, const TDesC8& aOption)
       
   510 	{
       
   511 	TInt ret = KErrNotSupported;
       
   512 
       
   513 	if (aLevel == KSolInetTcp)
       
   514 		{
       
   515 		TInt intValue;
       
   516 		ret = GetOptionInt(aOption, intValue);
       
   517 
       
   518 #ifdef _LOG
       
   519 		if (ret == KErrNone)
       
   520 			Log::Printf(_L("SetOpt\ttcp SAP[%u] KSolInetTcp, %d, %d"), (TInt)this, aName, intValue);
       
   521 		else
       
   522 			Log::Printf(_L("SetOpt\ttcp SAP[%u] KSolInetTcp, %d"), (TInt)this, aName);
       
   523 #endif
       
   524 
       
   525 		switch (aName)
       
   526 			{
       
   527 		case KSoTcpAsync2MslWait:
       
   528 			// Not implemented. Not very useful.
       
   529 			ret = KErrNotSupported;
       
   530 			break;
       
   531 
       
   532 		case KSoTcpKeepAlive:
       
   533 			if (ret == KErrNone)
       
   534 				{
       
   535 				if (!intValue)
       
   536 					{
       
   537 					iFlags.iHaveKeepAlive = FALSE;
       
   538 					iFlags.iHaveTriggeredKeepAlive = FALSE;
       
   539 					}
       
   540 				if (intValue & 1)
       
   541 					iFlags.iHaveKeepAlive = TRUE;
       
   542 				if (intValue & 2)
       
   543 					iFlags.iHaveTriggeredKeepAlive = TRUE;
       
   544 				}
       
   545 			break;
       
   546 
       
   547 		case KSoTcpMaxSegSize:
       
   548 			if (ret == KErrNone)
       
   549 				{
       
   550 				if (!InState(ETcpInitial))
       
   551 					ret = KErrLocked;
       
   552 				else if (intValue < STATIC_CAST(TInt, KTcpMinimumMSS))
       
   553 					ret = KErrArgument;
       
   554 				else
       
   555 					{
       
   556 					iMSS = intValue;
       
   557 					iSMSS = iMSS;
       
   558 					iRMSS = iMSS;
       
   559 					}
       
   560 				}
       
   561 			break;
       
   562 
       
   563 		case KSoTcpNextSendUrgentData:
       
   564 			if (ret == KErrNone)
       
   565 				iFlags.iNextIsUrgent = intValue ? TRUE : FALSE;
       
   566 			break;
       
   567 
       
   568 		case KSoTcpNoDelay:
       
   569 			if (ret == KErrNone)
       
   570 				iFlags.iNoDelay = intValue ? TRUE : FALSE;
       
   571 			break;
       
   572 
       
   573 		case KSoTcpCork:
       
   574 		case KSoTcpNoPush:
       
   575 			if (ret == KErrNone)
       
   576 				{
       
   577 				iFlags.iCork = intValue ? TRUE : FALSE;
       
   578 				if (iFlags.iCork == EFalse && aName == KSoTcpCork)
       
   579 					{
       
   580 					// When turning Cork off, send pending data from output queue immediately.
       
   581 					// This is the only difference between Cork and NoPush
       
   582 					SchedTransmit();
       
   583 					}
       
   584 				}
       
   585 			break;
       
   586 
       
   587 		case KSoTcpOobInline:
       
   588 			if (ret == KErrNone)
       
   589 				iFlags.iOobInline = intValue ? TRUE : FALSE;
       
   590 			break;
       
   591 		
       
   592 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW	
       
   593 		case KSoTcpMaxRecvWin:
       
   594 			//Case to set the Max window size from shim.
       
   595 			if(ret == KErrNone)
       
   596 				{
       
   597 				if (InState(ETcpClosed|ETcpFinWait2|ETcpCloseWait|ETcpLastAck))
       
   598 					ret = KErrLocked;
       
   599 				else	
       
   600 				    if(intValue > iTcpMaxRecvWin)
       
   601 				    {
       
   602 				    iTcpMaxRecvWin = intValue;
       
   603 				    }
       
   604 				
       
   605 				}
       
   606 			break;
       
   607 		case KSoTcpRecvWinAuto:
       
   608 		    {
       
   609 		    // If user sets the window size, we have to give the preference for user setting. Automatic
       
   610 		    // window setting will be then disabled by default, once user calls the SetOption to set the 
       
   611 		    // receive window, this feature will be diabled by default till the socket is opened.
       
   612 		    if(iWindowSetByUser)
       
   613 		        {
       
   614 		        return KErrNone;
       
   615 		        }
       
   616 		    else if (InState(ETcpClosed|ETcpFinWait2|ETcpCloseWait|ETcpLastAck))
       
   617 		        ret = KErrLocked;
       
   618             else if (intValue < STATIC_CAST(TInt, KTcpMinimumWindow))
       
   619                 iSockInBufSize = KTcpMinimumWindow;
       
   620             else
       
   621                 {
       
   622 
       
   623 		        //If new TCP window is larger then the previous window, increase the 
       
   624 		        //iSockInBufSize right now. TCP recv function takes  care of
       
   625 		        //advertising a new effective TCP window. 
       
   626 		            if (intValue >= iSockInBufSize)
       
   627 		                {
       
   628 		                //Make it Zero so TCP could avoid the
       
   629 		                //TCP window shrinking processing in Recv.  
       
   630 		                iNewTcpWindow = 0;
       
   631 		                //FreeWindow has to be increased at the same time.
       
   632 		                iFreeWindow += intValue - iSockInBufSize;
       
   633 		                // Make the new TCP receive buffer change effective now.
       
   634 		                iSockInBufSize = intValue;                                                          
       
   635 		                }
       
   636 		            else
       
   637 		                {
       
   638 		                //This sets iNewTcpWindow to a non-zero value, which indicates 
       
   639 		                //to the TCP that window is shrunk and process TCP segments
       
   640 		                //which are in air before setting a new TCP receive buffer.         
       
   641 		                //TCP Receive window starts moving only when TCP hidden window
       
   642 		                //size exceeds the size of the shrunk window.
       
   643 		                   
       
   644 		                iNewTcpWindow = intValue;
       
   645 		                //Even in case of window shrink we can set the receive buffer size
       
   646 		                //immediately. This will be helpful, for processing SYN-ACK and other
       
   647 		                //receiver side processing.
       
   648 		                //For already connected sockets iNewTcpWindow will be taking care
       
   649 		                //of shrinking the window size for that TCP session.
       
   650 		                iSockInBufSize = iNewTcpWindow;
       
   651 		                if( iAdvertisedWindow > iNewTcpWindow )
       
   652 		                    {
       
   653 		                    iShrinkedWindowSize = iAdvertisedWindow - iNewTcpWindow;
       
   654 		                    }
       
   655 		                else
       
   656 		                    {
       
   657 		                    // No Need to process TCP receive window processing.
       
   658 		                    iNewTcpWindow = 0;
       
   659 		                    }
       
   660 		                }
       
   661 					
       
   662                 } 
       
   663 
       
   664 		    }
       
   665 		    break;
       
   666 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
   667 			case KSoTcpRecvWinSize:
       
   668 			    {
       
   669 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW  
       
   670                 iWindowSetByUser = ETrue;
       
   671 #endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW                
       
   672                 if (ret == KErrNone)
       
   673                     {
       
   674                     if (!InState(ETcpInitial))
       
   675                         ret = KErrLocked;
       
   676                     else if (intValue < STATIC_CAST(TInt, KTcpMinimumWindow))
       
   677                         iSockInBufSize = KTcpMinimumWindow;
       
   678                     else
       
   679                         {
       
   680                         iSockInBufSize = intValue;
       
   681                         }
       
   682                     }
       
   683 			    }
       
   684 			break;
       
   685 
       
   686 		case KSoTcpSendWinSize:
       
   687 			if (ret == KErrNone)
       
   688 				{
       
   689 				if (!InState(ETcpInitial))
       
   690 					ret = KErrLocked;
       
   691 				else if (intValue < STATIC_CAST(TInt, KTcpMinimumWindow))
       
   692 					iSockOutBufSize = KTcpMinimumWindow;
       
   693 				else
       
   694 					iSockOutBufSize = intValue;
       
   695 				}
       
   696 			break;
       
   697 
       
   698 		case KSoTcpLinger:
       
   699 			if (aOption.Length() < (TInt)sizeof(TSoTcpLingerOpt))
       
   700 				{
       
   701 				return KErrArgument;
       
   702 				}
       
   703 			if (iSockFlags.iSendClose)
       
   704 				{
       
   705 				return KErrInUse;
       
   706 				}
       
   707 
       
   708 				{
       
   709 				TSoTcpLingerOpt *opt = (TSoTcpLingerOpt *)aOption.Ptr();
       
   710 				if (opt->iOnOff != 0 && opt->iLinger >= 0)
       
   711 					{
       
   712 					if (opt->iLinger > KTcpMaxLingerTime)
       
   713 						{
       
   714 						return KErrArgument;
       
   715 						}
       
   716 					iLinger = opt->iLinger;  // linger enabled.
       
   717 					}
       
   718 				else
       
   719 					{
       
   720 					iLinger = -1;  // linger disabled.
       
   721 					}
       
   722 				}
       
   723 			break;
       
   724 
       
   725 		default:
       
   726 			ret = KErrNotSupported;
       
   727 			break;
       
   728 			}
       
   729 		}
       
   730 
       
   731 	if (aLevel == KSolInetIp)
       
   732 		{
       
   733 		TInt intValue;
       
   734 		ret = GetOptionInt(aOption, intValue);
       
   735 
       
   736 		switch(aName)
       
   737         	{
       
   738 		case KSoIpTOS:
       
   739 			// Silently filter out the ECN bits from TOS setting.
       
   740             // We're assuming that Protocol->Ecn() (based on ini params) holds the correct
       
   741             // values for ECN bits.
       
   742             	{
       
   743 	            intValue = (intValue & 0xfc) | Protocol()->Ecn();
       
   744             	TPckgBuf<TInt> tosopt(intValue);
       
   745 
       
   746 	            // Rest of the option processing is done at the lower levels.
       
   747     	        return CProviderInet6Transport::SetOption(aLevel, aName, tosopt);
       
   748     	        }
       
   749 
       
   750 		case KSoHeaderIncluded:
       
   751 		case KSoRawMode:
       
   752 			// The base class implements HeaderIncluded and RawMode by default.
       
   753 			// Force "Not Supported" for TCP here!
       
   754 			return KErrNotSupported;
       
   755 		default:
       
   756         	ret = KErrNotSupported;
       
   757             }
       
   758 		}
       
   759 
       
   760 
       
   761 	if (ret == KErrNotSupported)
       
   762 		ret = CProviderInet6Transport::SetOption(aLevel, aName, aOption);
       
   763 	
       
   764 	return ret;
       
   765 	}
       
   766 
       
   767 
       
   768 TInt CProviderTCP6::GetOption(TUint aLevel, TUint aName, TDes8& aOption) const
       
   769 	{
       
   770 	LOG(Log::Printf(_L("GetOpt\ttcp SAP[%u] %d, %d"), (TInt)this, aLevel, aName));
       
   771 	CProviderTCP6 *This = CONST_CAST(CProviderTCP6*, this);
       
   772 	TInt ret = KErrNotSupported, urgentChar;
       
   773 
       
   774 	switch (aLevel)
       
   775 		{
       
   776 	case KSOLSocket:
       
   777 		switch (aName)
       
   778 			{
       
   779 		case KSOReadBytesPending:
       
   780 			ret = SetOptionInt(aOption, iPending);
       
   781 			break;
       
   782 
       
   783 		case KSOUrgentDataOffset:
       
   784 			ret = SetOptionInt(aOption, iUpCount ? UrgentOffset() - iUpCount + 1 : 0);
       
   785 			LOG(Log::Printf(_L("\ttcp SAP[%u] Urgent data offset = %d"),
       
   786 				(TInt)this, iUpCount ? UrgentOffset() : 0));
       
   787 			break;
       
   788 
       
   789 		default:
       
   790 			break;
       
   791 			}
       
   792 		break;
       
   793 
       
   794 	case KSolInetTcp:
       
   795 		switch (aName)
       
   796 			{
       
   797 		case KSoTcpAsync2MslWait:
       
   798 			// XXX - Not implemented. Not very useful.
       
   799 			break;
       
   800 
       
   801 		case KSoTcpKeepAlive:
       
   802 			ret = SetOptionInt(aOption, iFlags.iHaveKeepAlive);
       
   803 			break;
       
   804 
       
   805 		case KSoTcpMaxSegSize:
       
   806 			ret = SetOptionInt(aOption, iMSS);
       
   807 			break;
       
   808 
       
   809 		case KSoTcpNextSendUrgentData:
       
   810 			ret = SetOptionInt(aOption, iFlags.iNextIsUrgent);
       
   811 			break;
       
   812 
       
   813 		case KSoTcpNoDelay:
       
   814 			ret = SetOptionInt(aOption, iFlags.iNoDelay);
       
   815 			break;
       
   816 
       
   817 		case KSoTcpCork:
       
   818 		case KSoTcpNoPush:
       
   819 			ret = SetOptionInt(aOption, iFlags.iCork);
       
   820 			break;
       
   821 
       
   822 		case KSoTcpOobInline:
       
   823 			ret = SetOptionInt(aOption, iFlags.iOobInline);
       
   824 			break;
       
   825 
       
   826 		case KSoTcpRecvWinSize:
       
   827 			ret = SetOptionInt(aOption, iSockInBufSize);
       
   828 			break;
       
   829 
       
   830 		case KSoTcpSendWinSize:
       
   831 			ret = SetOptionInt(aOption, iSockOutBufSize);
       
   832 			break;
       
   833 
       
   834 		case KSoTcpListening:
       
   835 			ret = SetOptionInt(aOption, InState(ETcpListen) ? 1 : 0);
       
   836 			break;
       
   837 
       
   838 		case KSoTcpNumSockets:
       
   839 			ret = SetOptionInt(aOption, Protocol()->SapCount());
       
   840 			break;
       
   841 
       
   842 		case KSoTcpLinger:
       
   843 			if (aOption.MaxLength() < (TInt)sizeof(TSoTcpLingerOpt))
       
   844 				{
       
   845 				return KErrTooBig;
       
   846 				}
       
   847 
       
   848 			TSoTcpLingerOpt opt;
       
   849 			if (iLinger == -1)
       
   850 				{
       
   851 				opt.iOnOff = 0;
       
   852 				opt.iLinger = 0;
       
   853 				}
       
   854 			else
       
   855 				{
       
   856 				opt.iOnOff = 1;
       
   857 				opt.iLinger = iLinger;
       
   858 				}
       
   859 			aOption.SetLength(sizeof(opt));
       
   860 			aOption.Copy((TUint8*)&opt, sizeof(opt));
       
   861 			ret = KErrNone;
       
   862 			break;
       
   863 
       
   864 		case KSoTcpPeekUrgentData:
       
   865 			if (ret = This->GetUrgent(urgentChar, KSockReadPeek), ret == KErrNone)
       
   866 				ret = SetOptionInt(aOption, urgentChar);
       
   867 			break;
       
   868 
       
   869 		case KSoTcpRcvAtMark:
       
   870 			ret = SetOptionInt(aOption, (UrgentOffset() == 0) ? 1 : 0);
       
   871 			break;
       
   872 
       
   873 		case KSoTcpReadBytesPending:
       
   874 			ret = SetOptionInt(aOption, iPending);
       
   875 			break;
       
   876 
       
   877 		case KSoTcpReadUrgentData:
       
   878 			if (ret = This->GetUrgent(urgentChar, 0), ret == KErrNone)
       
   879 				ret = SetOptionInt(aOption, urgentChar);
       
   880 			break;
       
   881 
       
   882 		case KSoTcpSendBytesPending:
       
   883 			ret = SetOptionInt(aOption, iSockOutQLen);
       
   884 			break;
       
   885 
       
   886 		default:
       
   887 			break;
       
   888 			}
       
   889 		break;
       
   890 
       
   891 	case KSolInetIp:
       
   892 		switch(aName)
       
   893 			{
       
   894         case KSoIpTOS:
       
   895 			// Clear the ECN bits from the returned value before delivering it to socket.
       
   896             ret = CProviderInet6Transport::GetOption(aLevel, aName, aOption);
       
   897             if (ret != KErrNone)
       
   898             	{
       
   899                 TInt intValue;
       
   900                 if (GetOptionInt(aOption, intValue) == KErrNone)
       
   901                 	ret = SetOptionInt(aOption, intValue & 0xfc);
       
   902                 }
       
   903             break;
       
   904 		case KSoHeaderIncluded:
       
   905 		case KSoRawMode:
       
   906 			// The base class implements HeaderIncluded and RawMode by default.
       
   907 			// Force "Not Supported" for TCP here!
       
   908 			return KErrNotSupported;
       
   909         default:
       
   910         	break;
       
   911 			}
       
   912 		break;
       
   913 
       
   914 	default:
       
   915 		break;
       
   916 		}
       
   917 
       
   918 	if (ret == KErrNotSupported)
       
   919 		ret = CProviderInet6Transport::GetOption(aLevel, aName, aOption);
       
   920 
       
   921 	return ret;
       
   922 	}
       
   923 
       
   924 
       
   925 TInt CProviderTCP6::SetRemName(TSockAddr &aAddr)
       
   926 	{
       
   927 	TInt err;
       
   928 	TInetAddr addr = aAddr;
       
   929 
       
   930 	// Check port range
       
   931 	if (addr.Port() < 1 || addr.Port() > 65535)
       
   932 		return KErrGeneral;
       
   933 
       
   934 	// Check address
       
   935 	if (addr.IsUnspecified() || !addr.IsUnicast())
       
   936 		return KErrBadName;	
       
   937 
       
   938 	if (addr.Family() == KAfInet)
       
   939 		addr.ConvertToV4Mapped();
       
   940 
       
   941 	TInt family = addr.IsV4Mapped() ? KAfInet : KAfInet6;
       
   942 
       
   943 	if(iSockFamily == KAFUnspec)
       
   944 		iSockFamily = family;
       
   945 	else if (iSockFamily != family)
       
   946 		return KErrBadName;		
       
   947 		
       
   948 	//
       
   949 	// If we're reusing a local address we must check for an existing
       
   950 	// connection before we can accept the remote address.
       
   951 	//
       
   952 	if (iSockFlags.iReuse && iFlow.FlowContext()->LocalPort() != KInetPortNone)
       
   953 		{
       
   954 		if (Protocol()->LocateSap(EMatchConnection, KAFUnspec, iFlow.FlowContext()->LocalAddr(), addr))
       
   955 			return KErrInUse;
       
   956 		}
       
   957 
       
   958 	// Set remote address and port.. use original to get iAppFamily valid.
       
   959 	if (err = CProviderInet6Transport::SetRemName(aAddr), err != KErrNone)
       
   960 		return err;
       
   961 
       
   962 	return KErrNone;
       
   963 	}
       
   964 
       
   965 
       
   966 void CProviderTCP6::ActiveOpen()
       
   967 	{
       
   968 	LOG(Log::Printf(_L("ActiveOpen\ttcp SAP[%u]"), (TInt)this));
       
   969 	ASSERT(InState(ETcpInitial));
       
   970 
       
   971 	TInt status = iFlow.Connect();
       
   972 	if (status < 0)
       
   973 		{
       
   974 		LOG(Log::Printf(_L("\ttcp SAP[%u] Flow status = %d"), (TInt)this, status));
       
   975 		iSockFlags.iConnected = EFalse;
       
   976 		Error(status, MSocketNotify::EErrorConnect);
       
   977 		return;
       
   978 		}
       
   979 
       
   980 	// Store KeepInterfaceUp to be restored when entering Established state.
       
   981 	StoreKeepInterfaceUp();
       
   982 
       
   983 	EnterState(ETcpConnect);
       
   984 	if (status == EFlow_READY)
       
   985 		SendSYN();
       
   986 	}
       
   987 
       
   988 
       
   989 TInt CProviderTCP6::PassiveOpen(TUint aQueSize)
       
   990 	{
       
   991 	ASSERT(InState(ETcpInitial));
       
   992 	ASSERT(!iListenQueue);
       
   993 	LOG(Log::Printf(_L("PassiveOpen\ttcp SAP[%u] QueSize=%d"), (TInt)this, aQueSize));
       
   994 
       
   995 	//
       
   996 	// On EPOC you can only call listen once, so it is safe to do this here.
       
   997 	//
       
   998 	iListenQueue = new CProviderTCP6*[aQueSize];
       
   999 	if (!iListenQueue)
       
  1000 		return KErrNoMemory;
       
  1001 
       
  1002 	iListenQueueSize = aQueSize;
       
  1003 	for (TUint i=0; i < iListenQueueSize; i++)
       
  1004 		iListenQueue[i] = 0;
       
  1005 	EnterState(ETcpListen);
       
  1006 	return KErrNone;
       
  1007 	}
       
  1008 
       
  1009 //
       
  1010 // This routine tries to detach the socket from the socket server.
       
  1011 // Detach() is called from Shutdown(), when the user has called
       
  1012 // Close() or Shutdown(ENormal).
       
  1013 //
       
  1014 // If linger timeout is active, Shutdown() will complete with
       
  1015 // error KErrWouldBlock.
       
  1016 //
       
  1017 void CProviderTCP6::Detach()
       
  1018 	{
       
  1019 	LOG(Log::Printf(_L("\ttcp SAP[%u] Detach()"), (TInt)this));
       
  1020 
       
  1021 	StoreDestinationCache();
       
  1022 
       
  1023 	CompleteIoctl(KErrCancel);
       
  1024 	if (iLinger > 0)
       
  1025 		{
       
  1026 		iLingerTimer->Cancel();
       
  1027 		Error(KErrWouldBlock, MSocketNotify::EErrorClose);
       
  1028 		}
       
  1029 	iLinger = -1;
       
  1030 	NoSecurityChecker();				// The checker will be unusable.
       
  1031 	iSocket->CanClose(MSocketNotify::EDetach);
       
  1032 	iSockFlags.iNotify = EFalse;            // No more upcalls
       
  1033 	iSockFlags.iAttached = (iSocket != 0);  // Did we get detached?
       
  1034 	LOG(if (iSockFlags.iAttached) Log::Printf(_L("\ttcp SAP[%u] DETACH FAILED!"), (TInt)this));
       
  1035 	ASSERT(!iSockFlags.iAttached);
       
  1036 	}
       
  1037 
       
  1038 void CProviderTCP6::Expire()
       
  1039 	{
       
  1040 	if (!iSockFlags.iAttached)
       
  1041 		{
       
  1042 		LOG(Log::Printf(_L("\ttcp SAP[%u] Expire(): SELF DESTRUCT!"), (TInt)this));
       
  1043 		delete this;
       
  1044 		return;
       
  1045 		}
       
  1046 	if (iSockFlags.iNotify)
       
  1047 		{
       
  1048 		LOG(Log::Printf(_L("\ttcp SAP[%u] Expire(): DISCONNECT!"), (TInt)this));
       
  1049 		Close();
       
  1050 		iSockFlags.iNotify = EFalse;
       
  1051 		iSocket->Disconnect();
       
  1052 		}
       
  1053 	}
       
  1054 
       
  1055 void CProviderTCP6::Shutdown(TCloseType aOption)
       
  1056 	{
       
  1057 	LOG(Log::Printf(_L("Shutdown\ttcp SAP[%u] TCloseType=%d"), (TInt)this, aOption));
       
  1058 
       
  1059 	switch(aOption)
       
  1060 		{
       
  1061 	case ENormal:
       
  1062 		if (InState(ETcpListen|ETcpInitial|ETcpConnect|ETcpSynSent|ETcpClosed))
       
  1063 			{
       
  1064 			// Just do a brutal shutdown in these states.
       
  1065 			Close();
       
  1066 			break;
       
  1067 			}
       
  1068 		
       
  1069 		// No need to negotiate parameters as we only want to notify other end point.
       
  1070 		if (InState(ETcpSynReceived))
       
  1071 			ClearSYNSettings();
       
  1072 
       
  1073 		// Send RST if receive queue is not empty.
       
  1074 		if (iLinger == 0 || SockInQLen() || !iFragQ.IsEmpty())
       
  1075 			{
       
  1076 			SendReset(iSND.NXT);
       
  1077 			if (FatalState())
       
  1078 				break;
       
  1079 
       
  1080 			// If linger is enabled and timer==0, close the socket immediately
       
  1081 			if (iLinger == 0)
       
  1082 				{
       
  1083 				Close();
       
  1084 				break;
       
  1085 				}
       
  1086 			}
       
  1087 
       
  1088 		iSockFlags.iSendClose = ETrue;
       
  1089 		iSockFlags.iRecvClose = ETrue;
       
  1090 		iSockInQ.Free();
       
  1091 		iSockInQLen = 0;
       
  1092 		iFragQ.Free();
       
  1093 		iNewData = 0;
       
  1094 
       
  1095 		if (iLinger == -1 || iSockOutQLen == 0)
       
  1096 			{
       
  1097 			Detach();
       
  1098 			}
       
  1099 		else
       
  1100 			{
       
  1101 			//
       
  1102 			// Start linger timer. RSocket::Close() returns when timer
       
  1103 			// expires or when all data has been succesfully transmitted.
       
  1104 			//
       
  1105 			iLingerTimer->Start(iLinger * KOneSecondUs);
       
  1106 			}
       
  1107 		SchedTransmit();
       
  1108 
       
  1109 		break;
       
  1110 
       
  1111 	case EStopInput:
       
  1112 	case EStopOutput:
       
  1113 		if (InState(ETcpListen|ETcpInitial))
       
  1114 			{
       
  1115 			Error(KErrNotSupported, MSocketNotify::EErrorClose);
       
  1116 			return;
       
  1117 			}
       
  1118 
       
  1119 		if (aOption == EStopInput)
       
  1120 			{
       
  1121 			iSockFlags.iRecvClose = ETrue;
       
  1122 
       
  1123 			// Send RST if receive queue is not empty.
       
  1124 			if (SockInQLen() || !iFragQ.IsEmpty())
       
  1125 				{
       
  1126 				SendReset(iSND.NXT);
       
  1127 				if (FatalState())
       
  1128 					break;
       
  1129 				}
       
  1130 			iSockInQ.Free();
       
  1131 			iFragQ.Free();
       
  1132 			iNewData = 0;
       
  1133 			}
       
  1134 		else
       
  1135 			{
       
  1136 			// HalfDuplex Close and simultaneous SYN_RCVD -> FIN_WAIT_1 is not supported.
       
  1137 			iSockFlags.iSendClose = ETrue;
       
  1138 			SchedTransmit();
       
  1139 			}
       
  1140 
       
  1141 		Error(KErrNone, MSocketNotify::EErrorClose);
       
  1142 		Nif::SetSocketState(ENifSocketConnected, this);
       
  1143 		break;
       
  1144 
       
  1145 	case EImmediate:
       
  1146 		if (InState(ETcpSynReceived|ETcpEstablished|ETcpFinWait1|ETcpFinWait2|ETcpCloseWait))
       
  1147 			SendReset(iSND.NXT);
       
  1148 		CompleteIoctl(KErrCancel);
       
  1149 		Close();
       
  1150 		return;
       
  1151 
       
  1152 	default:
       
  1153 		Panic(EInet6Panic_NotSupported);
       
  1154 		break;
       
  1155 		}
       
  1156 
       
  1157 	//
       
  1158 	// If we encountered a fatal error during the above processing,
       
  1159 	// stop everything and enter CLOSED state.
       
  1160 	//
       
  1161 	if (FatalState())
       
  1162 		Close();
       
  1163 
       
  1164 	if (InState(ETcpFinWait2) && iSockFlags.iRecvClose)
       
  1165 		{
       
  1166 		LOG(Log::Printf(_L("\ttcp SAP[%u] Setting FIN-WAIT-2 timeout"), (TInt)this));
       
  1167 		SchedMsl2Wait();
       
  1168 		}
       
  1169 
       
  1170 	//
       
  1171 	// If we're in CLOSED state and we're not detached,
       
  1172 	// tell the socket server that we're ready to die.
       
  1173 	//
       
  1174 	if (iSocket && InState(ETcpClosed))
       
  1175 		iSocket->CanClose();
       
  1176 
       
  1177 	//
       
  1178 	// Note!  The socket server can immediately delete the socket
       
  1179 	//        within CanClose(). Don't add anything here!
       
  1180 	//
       
  1181 	}
       
  1182 
       
  1183 
       
  1184 //
       
  1185 // PRTv1.0 API
       
  1186 //
       
  1187 TUint CProviderTCP6::Write(const TDesC8 & aDesc, TUint aOptions, TSockAddr* /*aAddr*/ /*=NULL*/)
       
  1188 	{
       
  1189 	TDualBufPtr buf(aDesc);
       
  1190 	return Send(buf, aDesc.Length(), aOptions);
       
  1191 	}
       
  1192 
       
  1193 void CProviderTCP6::GetData(TDes8 & aDesc, TUint aOptions, TSockAddr* /*aAddr*/)
       
  1194 	{
       
  1195 	TDualBufPtr aBuf(aDesc);
       
  1196 	Recv(aBuf, aDesc.Length(), aOptions);
       
  1197 	}
       
  1198 
       
  1199 //
       
  1200 // PRTv1.5 API
       
  1201 //
       
  1202 TInt CProviderTCP6::Write(RMBufChain& aData, TUint aOptions, TSockAddr* /* anAddr*/)
       
  1203 	{
       
  1204 	TDualBufPtr buf(aData);
       
  1205 	return Send(buf, aData.Length(), aOptions);
       
  1206 	}
       
  1207 
       
  1208 TInt CProviderTCP6::GetData(RMBufChain& aData, TUint aLength, TUint aOptions, TSockAddr* /*aAddr*/)
       
  1209 	{
       
  1210 	TDualBufPtr aBuf(aData);
       
  1211 	return Recv(aBuf, aLength, aOptions);
       
  1212 	}
       
  1213 
       
  1214 TInt CProviderTCP6::Send(TDualBufPtr& aBuf, TInt aLength, TUint aOptions)
       
  1215 	{
       
  1216 	LOG(Log::Printf(_L("Write\ttcp SAP[%u] len=%d, options=%d"), (TInt)this, aLength, aOptions));
       
  1217 	ASSERT(aLength > 0);
       
  1218 
       
  1219 	//
       
  1220 	// Limit queue size to maximum socket buffer size rounded down to nearest multiple segment.
       
  1221 	// Note: during fast recover we allow the socket buffer to expand in order to have enough
       
  1222 	// data to keep the transmission going.
       
  1223 	//
       
  1224 	TInt effMSS = EffectiveMSS();
       
  1225 	TInt bufSize = iSockOutBufSize +
       
  1226 		(iSacked.Count() ? (iSacked.Last()->iRight - iSND.UNA) : (iDupAcks * iSMSS));
       
  1227 	TInt reserve = (bufSize - (iSND.NXT - iSND.UNA)) % effMSS;
       
  1228 	TInt space = bufSize - iSockOutQLen - reserve;
       
  1229 
       
  1230 	LOG(Log::Printf(_L("\ttcp SAP[%u] len=%d space=%d"), (TInt)this, aLength, space));
       
  1231 
       
  1232 	if ((aOptions & KSockWriteUrgent) || iFlags.iNextIsUrgent)
       
  1233 		{
       
  1234 		//
       
  1235 		// According to RFC1122 the urgent pointer should point to the
       
  1236 		// last byte of urgent data. However, practically all TCP stacks
       
  1237 		// today choose to conform to BSD unix and follow the original
       
  1238 		// behaviour stated in RFC793. Therefore, we set the urgent pointer
       
  1239 		// to point to the first non-urgent byte following the urgent data.
       
  1240 		//
       
  1241 		iFlags.iNextIsUrgent = EFalse;
       
  1242 		iSND.UP = iSND.UNA + iSockOutQLen + aLength;
       
  1243 		LOG(Log::Printf(_L("\ttcp SAP[%u] Urgent pointer set, seq = %u"), (TInt)this, iSND.UP.Uint32()));
       
  1244 		}
       
  1245 
       
  1246 	if (space <= 0)
       
  1247 		{
       
  1248 		LOG(Log::Printf(_L("\ttcp SAP[%u] FLOW STOPPED"), (TInt)this));
       
  1249 		iSockFlags.iFlowStopped = ETrue;
       
  1250 		return 0;
       
  1251 		}
       
  1252 
       
  1253 	// Append data to socket queue. 
       
  1254 	aLength = aBuf.Append(iSockOutQ, (aLength < space) ? aLength : space);
       
  1255 	iSockOutQLen += aLength;
       
  1256 
       
  1257 	// We make a simple Nagle check here to avoid starting the transmitter unnecessarily.
       
  1258 	// To spell it out:
       
  1259 	// - If Cork option is set, always wait for full-sized segment before sending.
       
  1260 	// - Without Cork option one under-sized segment is allowed to be outstanding.
       
  1261 	// - TODO: With NoPush option segments are only sent when send buffer is full or
       
  1262 	//   when the connection is closed.
       
  1263 	if (!iSND.WND)
       
  1264 		{
       
  1265 		// Start probing
       
  1266 		SchedRetransmit();
       
  1267 		}
       
  1268 	else if ((iPartialSeq <= iSND.UNA && !iFlags.iCork) ||
       
  1269 		iSND.UNA + iSockOutQLen + aLength >= iSND.NXT + effMSS ||
       
  1270 		iFlags.iNoDelay)
       
  1271 		{
       
  1272 		// Start transmitter
       
  1273 		SchedTransmit();
       
  1274 		}
       
  1275 
       
  1276 	return aLength;
       
  1277 	}
       
  1278 
       
  1279 
       
  1280 TInt CProviderTCP6::Recv(TDualBufPtr& aBuf, TInt aLength, TUint aOptions)
       
  1281 	{
       
  1282 	LOG(Log::Printf(_L("GetData\ttcp SAP[%u] len=%d, options=%d"), (TInt)this, aLength, aOptions));
       
  1283 
       
  1284 	// Update iPending
       
  1285 	if (!(aOptions & KSocketInternalReadBit))
       
  1286 		iPending -= aLength;
       
  1287 
       
  1288 	// This might happen when aborting a connection.
       
  1289 	if (iSockInQ.IsEmpty())
       
  1290 		{
       
  1291 		LOG(Log::Printf(_L("\ttcp SAP[%u] No data available!"), (TInt)this));
       
  1292 		return 0;
       
  1293 		}
       
  1294 
       
  1295 	//
       
  1296 	// Discard in-band urgent data junk
       
  1297 	//
       
  1298 	while (iUpCount && UrgentOffset(0) == 0 && (!iFlags.iUrgentMode || UrgentOffset() > 0))
       
  1299 		{
       
  1300 		iSockInQ.TrimStart(1);
       
  1301 		--iSockInQLen;
       
  1302 		++iFreeWindow;
       
  1303 		ForgetUrgentPointer();
       
  1304 		}
       
  1305 
       
  1306 	ASSERT((aOptions & KSockReadPeek) || !iCopyOutOffset);
       
  1307 	ASSERT(iCopyOutOffset + aLength <= (TInt)iSockInQLen);
       
  1308 
       
  1309 	//
       
  1310 	// Peek. Copy from queue, fix counters and force receiver restart.
       
  1311 	//
       
  1312 	if (aOptions & KSockReadPeek)
       
  1313 		{
       
  1314 		LOG(Log::Printf(_L("\ttcp SAP[%u] Peek"), (TInt)this));
       
  1315 
       
  1316 		TInt err = aBuf.CopyIn(iSockInQ, iCopyOutOffset, aLength);
       
  1317 		if (err != KErrNone)
       
  1318 			return KErrNoMBufs;
       
  1319 
       
  1320 		if (!(aOptions & KSocketInternalReadBit))
       
  1321 			{
       
  1322 			iFlags.iCompleteRecv = ETrue;
       
  1323 			iNewData += aLength;
       
  1324 			iCopyOutOffset += aLength;
       
  1325 			iRecvQ.Wake();
       
  1326 			}
       
  1327 
       
  1328 		return aLength;
       
  1329 		}
       
  1330 
       
  1331 	//
       
  1332 	// Normal read. Consume data from the queue.
       
  1333 	//
       
  1334 	// Note: aBuf.Consume() may return less than we asked
       
  1335 	// if it is unable to allocate an MBuf for splitting the
       
  1336 	// inbound queue. This can only happen with PRTv1.5.
       
  1337 	// If we get nothing at all we return KErrNoMBufs here.
       
  1338 	//
       
  1339 	aLength = aBuf.Consume(iSockInQ, aLength, iBufAllocator);
       
  1340 	if (aLength == 0)
       
  1341 		return KErrNoMBufs;
       
  1342 
       
  1343 	//
       
  1344 	// If we are now reading the actual urgent data, force the
       
  1345 	// application level read operation to complete and exit
       
  1346 	// urgent mode.
       
  1347 	//
       
  1348 	if (iFlags.iUrgentMode && UrgentOffset() == 0)
       
  1349 		{
       
  1350 		LOG(Log::Printf(_L("\ttcp SAP[%u] Reading urgent data. Clear urgent mode"), (TInt)this));
       
  1351 		iFlags.iUrgentMode = EFalse;
       
  1352 		iFlags.iCompleteRecv = !(aOptions & KSocketInternalReadBit);
       
  1353 		ForgetUrgentPointer();
       
  1354 		}
       
  1355 		
       
  1356 	iSockInQLen -= aLength;
       
  1357 	
       
  1358 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
  1359 	//Application is reading the data from the receive Q buffer
       
  1360 	//We need to make sure, that we will show that window is not shrinked
       
  1361 	//to the sender, so tha right edge of the sender window remains constant.
       
  1362 	//if This is true, then it is a case of TCP window shrink and we need 
       
  1363 	//to handle it.
       
  1364 	if ( iNewTcpWindow )
       
  1365 		{
       
  1366 	   	//Log  this message for information, that Window is shrinked
       
  1367 	   	LOG(Log::Printf(_L("\ttcp SAP[%u] TCP window shrinking mode on"), (TInt)this));
       
  1368 	   
       
  1369 	   	//Increase the hidden free TCP receive window.
       
  1370 	   	iHiddenFreeWindow += aLength;
       
  1371 	   
       
  1372 	   	if (iHiddenFreeWindow >= iShrinkedWindowSize)
       
  1373 			{
       
  1374 			//Disable window shrink processing, so that TCP could switch
       
  1375 			//to the normal processing.    
       
  1376 			iSockInBufSize = iNewTcpWindow;
       
  1377 			
       
  1378 			//Add the usable window to the free window.
       
  1379 			iFreeWindow += iHiddenFreeWindow - iShrinkedWindowSize;
       
  1380 			
       
  1381 			//There are chances that TCP receive window might further shrink.
       
  1382 			iHiddenFreeWindow = 0;
       
  1383 			
       
  1384 			//TCP Receive window shrink phase is over.
       
  1385 			iNewTcpWindow = 0;
       
  1386 			
       
  1387 			//Log  this message for information, that Window is shrinked
       
  1388 			LOG(Log::Printf(_L("\ttcp SAP[%u] TCP window shrinking mode off"), (TInt)this));
       
  1389 			}
       
  1390 		}
       
  1391 	else
       
  1392 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
  1393 	
       
  1394 		{
       
  1395 		iFreeWindow += aLength;	
       
  1396 		}
       
  1397 
       
  1398 	//
       
  1399 	// If we have read everything upto the urgent data,
       
  1400 	// force the application level read to complete.
       
  1401 	// If the urgent data has not yet been read, signal
       
  1402 	// the application again (read completion will clear
       
  1403 	// the signal).
       
  1404 	//
       
  1405 	if (UrgentOffset() == 0)
       
  1406 		{
       
  1407 		iFlags.iCompleteRecv = ETrue;
       
  1408 		if (iFlags.iUrgentMode)
       
  1409 			{
       
  1410 			LOG(Log::Printf(_L("\ttcp SAP[%u] Now at urgent data"), (TInt)this));
       
  1411 			iFlags.iNotifyUrgent = ETrue;
       
  1412 			}
       
  1413 		}
       
  1414 
       
  1415 	//
       
  1416 	// Increase receive window in multiples of RMSS
       
  1417 	//
       
  1418 	// The following assumes that the path MTU is symmetric and that
       
  1419 	// the peer uses the same options as we do. We could use some
       
  1420 	// kind of peer effective MSS detection heuristic in order to
       
  1421 	// make this smarter.
       
  1422 	//
       
  1423 	TUint effMSS = EffectiveMSS();
       
  1424 	if (iFreeWindow >= effMSS)
       
  1425 		{
       
  1426 		//
       
  1427 		// Round down to nearest multiple of RMSS. However, be careful not to
       
  1428 		// shrink a previously advertised window.
       
  1429 		//
       
  1430 		iFreeWindow += iRCV.WND;
       
  1431 		iRCV.WND = Max(iRCV.WND, effMSS * (iFreeWindow / effMSS));
       
  1432 		iFreeWindow -= iRCV.WND;                   // Leave reminder for later.
       
  1433 
       
  1434 		//
       
  1435 		// If our last advertised window is so small that the sender might
       
  1436 		// block before we would normally send our next ack, we will send
       
  1437 		// a window update. This will prevent the sender from unnecessarily
       
  1438 		// going into probe mode. We will only do this if we can advertise
       
  1439 		// at least half a window.
       
  1440 		//
       
  1441 		if (InState(ETcpEstablished|ETcpFinWait1|ETcpFinWait2))
       
  1442 			{
       
  1443 			if ((TInt)iAdvertisedWindow <= iSockInBufSize/4 && iRCV.WND >= iSockInBufSize/2)
       
  1444 				{
       
  1445 				LOG(Log::Printf(_L("\ttcp SAP[%u] Sending window update %d -> %d"), (TInt)this, iAdvertisedWindow, iRCV.WND));
       
  1446 				SendSegment(KTcpCtlACK);
       
  1447 				}
       
  1448 			}
       
  1449 		}
       
  1450 
       
  1451 	//
       
  1452 	// If we have data that has not yet been announced to the socket server,
       
  1453 	// make sure we get around to it.
       
  1454 	//
       
  1455 	if (iNewData)
       
  1456 		iRecvQ.Wake();
       
  1457 
       
  1458 	LOG(Log::Printf(_L("GetData\ttcp SAP[%u] returns %d bytes, %d bytes pending"), (TInt)this, aLength, iPending));
       
  1459 	return aLength;
       
  1460 	}
       
  1461 
       
  1462 
       
  1463 //
       
  1464 // Process ICMP Error. Treat it as a soft error unless we're trying to connect.
       
  1465 //
       
  1466 void CProviderTCP6::IcmpError(TInt aError, TUint aOperationMask, TInt aType, TInt aCode,
       
  1467 	const TInetAddr& aSrcAddr, const TInetAddr& aDstAddr, const TInetAddr& aErrAddr)
       
  1468 	{
       
  1469 	CProviderInet6Transport::IcmpError(aError,InState(ETcpSynSent|ETcpSynReceived) ?
       
  1470 		MSocketNotify::EErrorAllOperations : aOperationMask,
       
  1471 		aType, aCode, aSrcAddr, aDstAddr, aErrAddr);
       
  1472 	}
       
  1473 
       
  1474 //
       
  1475 // This routine maintains a sorted rotating array of detected urgent pointers.
       
  1476 // The lowest detected UP is always stored in iUpArray[iUpIndex] and the highest
       
  1477 // one is stored in iUpArray[(iUpIndex + iUpCount - 1) % KTcpUpMax].
       
  1478 // If the array overflows, the lowest UP is always discarded.
       
  1479 //
       
  1480 void CProviderTCP6::RememberUrgentPointer(TTcpSeqNum aUp)
       
  1481 	{
       
  1482 	// Insert new UP into the sorted list.
       
  1483 	TInt i;
       
  1484 	TTcpSeqNum up;
       
  1485 	
       
  1486 	for (i = iUpIndex + iUpCount; i > iUpIndex; --i)
       
  1487 		{
       
  1488 		up = iUpArray[(i - 1) % KTcpUpMax];
       
  1489 		if (aUp > up)
       
  1490 			break;
       
  1491 		if (aUp == up)
       
  1492 			return;
       
  1493 		}
       
  1494 
       
  1495 	if (i == iUpIndex && iUpCount == KTcpUpMax)
       
  1496 		return;
       
  1497 	TUint index;
       
  1498 	while (i < iUpIndex + iUpCount)
       
  1499 		{
       
  1500 		index = i % KTcpUpMax;
       
  1501 		up = iUpArray[index];
       
  1502 		iUpArray[index] = aUp;
       
  1503 		aUp = up;
       
  1504 		++i;
       
  1505 		}
       
  1506 
       
  1507 	iUpArray[i % KTcpUpMax] = aUp;
       
  1508 	if (iUpCount < KTcpUpMax)
       
  1509 	    {
       
  1510 	    ++iUpCount;
       
  1511 	    }
       
  1512 	else
       
  1513 	    {
       
  1514 	    iUpIndex += 1;
       
  1515 	    if(iUpIndex >= KTcpUpMax)
       
  1516 	        iUpIndex -= KTcpUpMax;
       
  1517 	    }
       
  1518 
       
  1519 	iFlags.iUrgentMode = ETrue;
       
  1520 	iFlags.iNotifyUrgent = !iFlags.iOobInline;
       
  1521 	}
       
  1522 
       
  1523 void CProviderTCP6::ForgetUrgentPointer()
       
  1524 	{
       
  1525 	if (iUpCount)
       
  1526 		{
       
  1527 		if (++iUpIndex >= KTcpUpMax)
       
  1528 			iUpIndex = 0;
       
  1529 		--iUpCount;
       
  1530 		}
       
  1531 	}
       
  1532 
       
  1533 
       
  1534 TInt CProviderTCP6::GetUrgent(TInt& aUrgentChar, TUint aOptions)
       
  1535 	{
       
  1536 	TTcpSeqNum up;
       
  1537 	RMBuf *m;
       
  1538 	TBool found = EFalse;
       
  1539 	TInt urgentOffset = UrgentOffset();
       
  1540 
       
  1541 	if (!iFlags.iUrgentMode || iFlags.iOobInline)
       
  1542 		return KErrNotFound;
       
  1543 
       
  1544 	up = UrgentHigh();
       
  1545 	if (up <= iRCV.NXT)
       
  1546 		{
       
  1547 		// It's in the socket queue.
       
  1548 		if (urgentOffset == 0 && !(aOptions & KSockReadPeek))
       
  1549 			{
       
  1550 			//
       
  1551 			// It's first in queue. Fetch it with Recv(), so that receive
       
  1552 			// window is correctly updated.
       
  1553 			//
       
  1554 			TBuf8<1> buf(1);
       
  1555 			TDualBufPtr p(buf);
       
  1556 			iNewData--;
       
  1557 			Recv(p, 1, aOptions | KSocketInternalReadBit);
       
  1558 			aUrgentChar = buf[0];
       
  1559 			LOG(Log::Printf(_L("\ttcp SAP[%u] GetUrgent(): Urgent char first in socket queue = %02x"), (TInt)this, aUrgentChar));
       
  1560 			found = ETrue;
       
  1561 			}
       
  1562 		else
       
  1563 			{
       
  1564 			for (m = iSockInQ.First(); m != NULL; m = m->Next())
       
  1565 				{
       
  1566 				if (urgentOffset < m->Length())
       
  1567 					{
       
  1568 					aUrgentChar = *(m->Ptr() + urgentOffset);
       
  1569 					LOG(Log::Printf(_L("\ttcp SAP[%u] GetUrgent(): Urgent char in socket queue = %02x"), (TInt)this, aUrgentChar));
       
  1570 					found = ETrue;
       
  1571 					break;
       
  1572 					}
       
  1573 				urgentOffset -= m->Length();
       
  1574 				}
       
  1575 			}
       
  1576 		}
       
  1577 	else if (up <= iSND.WL1 + iRMSS)
       
  1578 		{
       
  1579 		// Maybe it's in the fragment queue.
       
  1580 		TMBufPktQIter iter(iFragQ);
       
  1581 		for (iter.SetToFirst(); iter.More(); iter++)
       
  1582 			{
       
  1583 			RMBufTcpFrag& frag = (RMBufTcpFrag&)iter.Current();
       
  1584 			TTcpSeqNum seq = frag.Offset();
       
  1585 			TUint32 len = frag.FragmentLength();
       
  1586 
       
  1587 			if (up <= seq)
       
  1588 				break;
       
  1589 
       
  1590 			if (up <= seq + len)
       
  1591 				{
       
  1592 				TTcpPacket seg(frag);
       
  1593 				RMBuf *m, *prev;
       
  1594 				TInt off, len;
       
  1595 				frag.Goto(seg.iHdr->HeaderLength() + (up - seq) - 1,
       
  1596 					m, off, len, prev);
       
  1597 				aUrgentChar = *(m->Ptr() + off);
       
  1598 				LOG(Log::Printf(_L("\ttcp SAP[%u] GetUrgent(): Urgent char in fragment queue = %02x"), (TInt)this, aUrgentChar));
       
  1599 				found = ETrue;
       
  1600 				break;
       
  1601 				}
       
  1602 			}
       
  1603 		}
       
  1604 
       
  1605 	if (!found)
       
  1606 		{
       
  1607 		LOG(Log::Printf(_L("\ttcp SAP[%u] GetUrgent(): Would block"), (TInt)this));
       
  1608 		return KErrWouldBlock;
       
  1609 		}
       
  1610 
       
  1611 	if (!(aOptions & KSockReadPeek))
       
  1612 		{
       
  1613 		iFlags.iUrgentMode = EFalse;
       
  1614 
       
  1615 		// Clear urgent mode exception flag
       
  1616 		if (iSockFlags.iNotify)
       
  1617 			iSocket->Error(KErrNone, 0);
       
  1618 		}
       
  1619 
       
  1620 	return KErrNone;
       
  1621 	}
       
  1622 
       
  1623 
       
  1624 void CProviderTCP6::Process(RMBufChain& aPacket, CProtocolBase* /*aSourceProtocol*/)
       
  1625 	{
       
  1626 	RMBufRecvInfo *const info = RMBufRecvPacket::PeekInfoInChain(aPacket);
       
  1627 #ifdef SYMBIAN_NETWORKING_UPS
       
  1628 	if (info == NULL || (!HasNetworkServices() && (ConnectionInfoSet() == EFalse) && (info->iFlags & KIpLoopbackPacket) == 0))
       
  1629 #else
       
  1630 	if (info == NULL || (!HasNetworkServices() && (info->iFlags & KIpLoopbackPacket) == 0))
       
  1631 #endif
       
  1632 		{
       
  1633 		LOG(Log::Printf(_L("\ttcp SAP[%u] Not allowed to receive external packets"), (TInt)this));
       
  1634 		aPacket.Free();
       
  1635 		return;
       
  1636 		}
       
  1637 	iRecvQ.Append(aPacket);
       
  1638 	iRecvQ.Wake();
       
  1639 	}
       
  1640 
       
  1641 
       
  1642 void CProviderTCP6::ErrorExpire(TInt aError)
       
  1643 	{
       
  1644 	LOG(Log::Printf(_L("\ttcp SAP[%u] ErrorExpire(): Closing SAP on fatal error: %d"), (TInt)this, aError));
       
  1645 	if (!iSockFlags.iAttached)
       
  1646 		{
       
  1647 		Expire();
       
  1648 		return;
       
  1649 		}
       
  1650 	Close();
       
  1651 	CProviderInet6Transport::Error(aError);
       
  1652 	}
       
  1653 
       
  1654 void CProviderTCP6::CanSend()
       
  1655 	{
       
  1656 	LOG(Log::Printf(_L("\ttcp SAP[%u] CanSend()"), (TInt)this));
       
  1657 
       
  1658 	//
       
  1659 	// If the flow has become unblocked, process all missed events
       
  1660 	// and restart transmitter.
       
  1661 	//
       
  1662 	TInt flowStatus = iFlow.Status();
       
  1663 	if (flowStatus < 0)
       
  1664 		{
       
  1665 		ErrorExpire(flowStatus);
       
  1666 		return;
       
  1667 		}
       
  1668 
       
  1669 	if (flowStatus == EFlow_READY)
       
  1670 		{
       
  1671 		LOG(Log::Printf(_L("\ttcp SAP[%u] CanSend(): Flow UNBLOCKED"), (TInt)this));
       
  1672 
       
  1673 		if (InState(ETcpListen|ETcpConnect))
       
  1674 			{
       
  1675 			//
       
  1676 			// Get the SAP started.
       
  1677 			//
       
  1678 			if (InState(ETcpConnect))
       
  1679 				SendSYN();
       
  1680 			else if (InState(ETcpListen) && !iRecvQ.IsEmpty())
       
  1681 				iRecvQ.Wake();
       
  1682 			}
       
  1683 
       
  1684 		if (iFlags.iRetransmitPending)
       
  1685 			{
       
  1686 			iFlags.iRetransmitPending = EFalse;
       
  1687 			RetransmitSegments();
       
  1688 			}
       
  1689 
       
  1690 		if (iFlags.iTransmitPending)
       
  1691 			{
       
  1692 			iFlags.iTransmitPending = EFalse;
       
  1693 			SendSegments();
       
  1694 			}
       
  1695 
       
  1696 		if (!iSendQ.IsEmpty())
       
  1697 			iSendQ.Wake();
       
  1698 			
       
  1699 		if (CanTriggerKeepAlive())
       
  1700 			{
       
  1701 			// The heaviest time check only if we are otherwise allowed to send the keepalive.
       
  1702 			TUint32 time_now = TimeStamp();
       
  1703 			if (time_now - iLastTriggeredKeepAlive > KTcpKeepAliveTH * KOneSecondUs)
       
  1704 				{
       
  1705 				iLastTriggeredKeepAlive = time_now;
       
  1706 				LOG(Log::Printf(_L("\ttcp SAP[%u] CanSend(): Sending a Keep-Alive probe"), (TInt)this));
       
  1707 				SendSegment(KTcpCtlACK, iSND.UNA - 1, 0);
       
  1708 				}
       
  1709 			}
       
  1710 		}
       
  1711 	}
       
  1712 
       
  1713 
       
  1714 //
       
  1715 // This is the actual event driven asynchronous transmitter loop.
       
  1716 //
       
  1717 void CProviderTCP6::Transmit()
       
  1718 	{
       
  1719 	LOG(Log::Printf(_L("\ttcp SAP[%u] Transmit"), (TInt)this));
       
  1720 
       
  1721 	RMBufSendPacket packet;
       
  1722 	TInt flowStatus;
       
  1723 	LOG(TInt count = 0);
       
  1724 
       
  1725 	ASSERT(!iSendQ.IsEmpty());
       
  1726 	RMBufSendInfo *info  = NULL;
       
  1727 	// Transmit packets when flow is ready
       
  1728 	while ((flowStatus = iFlow.Status()) == EFlow_READY && iSendQ.Remove(packet))
       
  1729 		{
       
  1730 		info = packet.PeekInfo();
       
  1731 		info->iFlow.Open(iFlow);
       
  1732 		Protocol()->Send(packet);
       
  1733 		LOG(count++);
       
  1734 		}
       
  1735 
       
  1736 	// Local congestion control
       
  1737 	if (flowStatus == EFlow_HOLD && !iSendQ.IsEmpty())
       
  1738 		SourceQuench();
       
  1739 
       
  1740 	LOG(Log::Printf(_L("\ttcp SAP[%u] %d segments transmitted"), (TInt)this, count));
       
  1741 	LOG(if (flowStatus > EFlow_READY) Log::Printf(_L("\ttcp SAP[%u] Flow BLOCKED"), (TInt)this));
       
  1742 	//LOG(if (flowStatus != EFlow_READY) Log::Printf(_L("CProviderTCP6::Transmit(): Flow status = %d.\r\n"), flowStatus));
       
  1743 
       
  1744 	if (flowStatus < 0)
       
  1745 		{
       
  1746 		LOG(Log::Printf(_L("\ttcp SAP[%u] Error %d. Segments"), (TInt)this, flowStatus));
       
  1747 		ErrorExpire(flowStatus);
       
  1748 		}
       
  1749 	}
       
  1750 
       
  1751 
       
  1752 // NOTE: There are a few tricks in the ECN implementation that should be considered. ECT bit MUST NOT
       
  1753 // be set in IP packets in the following cases [RFC 3168, Sec. 6.1.4 -- 6.1.6]:
       
  1754 // 1) pure ACKs
       
  1755 // 2) retransmitted segments
       
  1756 // 3) zero window probes
       
  1757 
       
  1758 
       
  1759 //
       
  1760 // This routine generates and transmits a TCP segment.
       
  1761 //
       
  1762 TInt CProviderTCP6::SendSegment(TUint8 aFlags, TTcpSeqNum aSeq, TUint32 aDataLen)
       
  1763 	{
       
  1764 	//LOG(Log::Printf(_L("CProviderTCP6::SendSegment(%06b,%d,%d)\r\n"),aFlags,aSeq,aMaxLen));
       
  1765 
       
  1766 	ASSERT(!(aFlags & KTcpCtlRST));
       
  1767 
       
  1768 	RMBufSendPacket seg;
       
  1769 	RMBufSendInfo *info = NULL;
       
  1770 	TInt err;
       
  1771 	TInt up = iSND.UP - aSeq;
       
  1772 	TInt seqLen = aDataLen;
       
  1773 	if (aFlags & (KTcpCtlSYN|KTcpCtlFIN))
       
  1774 	    ++seqLen;
       
  1775 
       
  1776 	if (iFlags.iEcnHaveCongestion)
       
  1777 		{
       
  1778 		aFlags |= KTcpCtlECE;
       
  1779 		}
       
  1780 
       
  1781 	if (iFlags.iEcnSendCWR)
       
  1782 		{
       
  1783 		aFlags |= KTcpCtlCWR;
       
  1784 		iFlags.iEcnSendCWR = EFalse;
       
  1785 		}
       
  1786 
       
  1787 	//
       
  1788 	// Don't output SACK blocks with data segments
       
  1789 	//
       
  1790 	iOptions.SuppressSack(aDataLen > 0);
       
  1791 	TUint headerLen = KTcpMinHeaderLength + iOptions.Length();
       
  1792 
       
  1793 	//
       
  1794 	// Allocate memory for TCP segment and IP headers.
       
  1795 	//
       
  1796 	// Important: we assume that, when using the TimeStamps option,
       
  1797 	// iOptions always contains timestamps, so that the header length
       
  1798 	// does not change when we update them below.
       
  1799 	//
       
  1800 	for (;;)
       
  1801 		{
       
  1802 		TInt hdrReserve = iFlow.FlowContext()->HeaderSize() + headerLen;
       
  1803 		if (aDataLen)
       
  1804 			{
       
  1805 			err = iSockOutQ.Copy(seg, aSeq - iSND.UNA, aDataLen, hdrReserve);
       
  1806 			if(err == KErrNone)
       
  1807 				{
       
  1808 				err = seg.Prepend(hdrReserve, iBufAllocator);
       
  1809 				}
       
  1810 			}
       
  1811 		else
       
  1812 			{
       
  1813 			err = seg.Alloc(hdrReserve, iBufAllocator);
       
  1814 			}
       
  1815 		if(err == KErrNone)
       
  1816 			{
       
  1817 			info = seg.NewInfo();
       
  1818 			if(info)
       
  1819 				{
       
  1820 				break;
       
  1821 				}
       
  1822 			else
       
  1823 				{
       
  1824 				err = KErrNoMBufs;
       
  1825 				}
       
  1826 			}
       
  1827 
       
  1828 		// Allocation failed. Try to recover.
       
  1829 		seg.Free();
       
  1830 
       
  1831 		// Try to free up some memory. XXX - We could do better here.
       
  1832 		if (!iFragQ.IsEmpty())
       
  1833 			{
       
  1834 			LOG(Log::Printf(_L("\ttcp SAP[%u] SendSegment(): RENEGE!!!"), (TInt)this));
       
  1835 			iFragQ.Free();
       
  1836 			continue;
       
  1837 			}
       
  1838 
       
  1839 		// If we can't scrounge up a buffer, the packet will be dropped.
       
  1840 		LOG(Log::Printf(_L("\ttcp SAP[%u] SendSegment(): No memory, packet DROPPED!"), (TInt)this));
       
  1841 		break;
       
  1842 		}
       
  1843 
       
  1844 	if (err == KErrNone)
       
  1845 		{
       
  1846 		// Reserve space for IP headers
       
  1847 		seg.TrimStart(iFlow.FlowContext()->HeaderSize());
       
  1848 
       
  1849 		// Check for urgent data
       
  1850 		if (up > 0 && up < 0x10000)
       
  1851 			aFlags |= KTcpCtlURG;
       
  1852 		else
       
  1853 			up = 0;
       
  1854 
       
  1855 		//
       
  1856 		// Fill in TCP header. Note that the header length has already
       
  1857 		// been set and the checksum will be calculated later.
       
  1858 		//
       
  1859 		// Note: If we're probing or the receiver has shrunk its advertised
       
  1860 		// window our iSND.NXT may be pointing beyond its advertised window.
       
  1861 		// If the packet we're trying to send does not occupy any sequence
       
  1862 		// space, we will adjust the sequence number so that it falls withín
       
  1863 		// the receiver's window. This will make sure that our ACK and RST
       
  1864 		// packets will be accepted. In the worst case, a buggy receiver
       
  1865 		// might still ignore our window updates, which might lead to a probe
       
  1866 		// deadlock. Well, a TCP that shrinks its window without adjusting
       
  1867 		// SND.WL1 deserves what it gets...
       
  1868 		//
       
  1869 		TTcpPacket pkt(seg);
       
  1870 		TTcpSeqNum windowEdge = iSND.UNA + iSND.WND;
       
  1871 		pkt.iHdr->SetSrcPort(iFlow.FlowContext()->LocalPort());
       
  1872 		pkt.iHdr->SetDstPort(iFlow.FlowContext()->RemotePort());
       
  1873 		pkt.iHdr->SetSequence(seqLen > 0 || aSeq <= windowEdge ? aSeq : windowEdge);
       
  1874 		pkt.iHdr->SetAcknowledgment((aFlags & KTcpCtlACK) ? iRCV.NXT.Uint32() : 0);
       
  1875 		if (aFlags & KTcpCtlSYN)
       
  1876 			{
       
  1877 			// Window scale must not be used in SYN or SYN-ACK segments.
       
  1878 			// We do not truncate window size to be divisible by MSS.
       
  1879 			// The next window advertisments are properly aligned, though.
       
  1880 			pkt.iHdr->SetWindow(Min(iRCV.WND, 0xffff));
       
  1881 			}
       
  1882 		else
       
  1883 			{
       
  1884 			pkt.iHdr->SetWindow(iRCV.WND >> iRcvWscale);
       
  1885 			}
       
  1886 		pkt.iHdr->SetUrgent(up);
       
  1887 		pkt.iHdr->SetControl(aFlags);
       
  1888 
       
  1889 		//
       
  1890 		// Fill in info struct
       
  1891 		//
       
  1892 		// coverity[dead_error_condition]
       
  1893 		// ASSERT statement required here as the condition "info != NULL" could be false
       
  1894 		ASSERT(info != NULL);
       
  1895 		info->iProtocol = KProtocolInetTcp;
       
  1896 		info->iSrcAddr  = iFlow.FlowContext()->LocalAddr();
       
  1897 		info->iDstAddr  = iFlow.FlowContext()->RemoteAddr();
       
  1898 		info->iLength   = headerLen + aDataLen;
       
  1899 		info->iFlags    = iFlags.iDoPMTUD ? KIpDontFragment : 0;
       
  1900 
       
  1901 		// Check if we have to clear the ECN ECT flag because of the few exception cases listed above.
       
  1902 		if (iFlags.iEcn && (aSeq < iSND.NXT || aDataLen < 1))
       
  1903 			{
       
  1904 			info->iFlags |= KIpNoEcnEct;
       
  1905 			}
       
  1906 
       
  1907 		//
       
  1908 		// Output TCP options (except for RST packets)
       
  1909 		//
       
  1910 		if (!(aFlags & KTcpCtlRST))
       
  1911 			{
       
  1912 			// Get current time
       
  1913 			TUint32 usec = TimeStamp();
       
  1914 
       
  1915 			//
       
  1916 			// Measure RTT
       
  1917 			//
       
  1918 			if (iFlags.iUseTimeStamps)
       
  1919 				{
       
  1920 #if 0
       
  1921 				// XXX - This code can cause tsVal to go backwards.
       
  1922 				TUint32 lastSent, lastEchoed;
       
  1923 				iOptions.TimeStamps(lastSent, lastEchoed);
       
  1924 				if (usec == lastSent)
       
  1925 					usec++;
       
  1926 #endif
       
  1927 				iOptions.SetTimeStamps(usec, iTsRecent);
       
  1928 				}
       
  1929 			if (iFlags.iTiming)
       
  1930 				{
       
  1931 				// Check for retransmission. We shouldn't do RTT measurements on
       
  1932 				// retransmitted segments because of ambiguity (Karn algorithm).
       
  1933 				if (iTimingSeq > aSeq && iTimingSeq <= aSeq + aDataLen)
       
  1934 					iFlags.iTiming = EFalse;
       
  1935 				}
       
  1936 			else if (aSeq == iSND.NXT && seqLen > 0 && iSND.WND > 0)
       
  1937 				{
       
  1938 				// New segment and not a probe. Start timing.
       
  1939 				iFlags.iTiming = ETrue;
       
  1940 				iTimingSeq = aSeq + aDataLen;
       
  1941 				iTimeStamp = usec;
       
  1942 				}
       
  1943 
       
  1944 			//
       
  1945 			// Output TCP options into the segment header.
       
  1946 			//
       
  1947 			pkt.iHdr->SetOptions(iOptions);
       
  1948 			}
       
  1949 
       
  1950 		//
       
  1951 		// Compute checksum and send the segment.
       
  1952 		//
       
  1953 		pkt.ComputeChecksum(seg, info);
       
  1954 		LOG(CProtocolTCP6::LogPacket('>', seg, info));
       
  1955 		seg.Pack();
       
  1956 
       
  1957        if(!iFlags.iFastRetransMode)
       
  1958            {
       
  1959            iSendQ.Append(seg);
       
  1960            }
       
  1961        else
       
  1962            {
       
  1963            //If the fast retransmission mode is set then add the segment in the begining of the sendqueue.
       
  1964            iSendQ.Prepend(seg);
       
  1965            }
       
  1966 		iSendQ.Wake();
       
  1967 		}
       
  1968 
       
  1969 	CancelDelayACK();
       
  1970 
       
  1971 	// Schedule a retransmission. Restart RTO if there was no outstanding segments, otherwise
       
  1972 	// it is only restarted if it was not running already.
       
  1973 	if (seqLen)
       
  1974 		{
       
  1975 		if (iSND.NXT == iSND.UNA)
       
  1976 			ReSchedRetransmit();
       
  1977 		else
       
  1978 			SchedRetransmit();
       
  1979 		}
       
  1980 
       
  1981 	aSeq += seqLen;
       
  1982 	if (aSeq > iSND.NXT)
       
  1983 		iSND.NXT = aSeq;
       
  1984 	iLastAck = iRCV.NXT;
       
  1985 	iAdvertisedWindow = iRCV.WND;
       
  1986 
       
  1987 	return aDataLen;
       
  1988 	}
       
  1989 
       
  1990 //
       
  1991 // Transmit one data segment at given position. Use current
       
  1992 // MTU, send window, and congestion window to limit segment
       
  1993 // size. Return number of bytes advanced in the transmit queue.
       
  1994 // This may be less than transmitted bytes if SACK is being used.
       
  1995 //
       
  1996 TInt CProviderTCP6::SendDataSegment(TTcpSeqNum aSeq, TBool aNagleOverride)
       
  1997 	{
       
  1998 	TInt effMSS = EffectiveMSS();
       
  1999 #ifdef SIGNED_UNSIGNED_FIX //if user app set the value which is bigger than 0x7ffffff,The largest possible value for a TInt16.
       
  2000 	TUint effWND = MinUU(iSND.WND, iSockOutQLen); 
       
  2001 #else
       
  2002 	TUint effWND = Min(iSND.WND, iSockOutQLen);
       
  2003 #endif
       
  2004 	TTcpSeqNum seq = aSeq;
       
  2005 	TUint8 flags = KTcpCtlACK;
       
  2006 	TInt len;
       
  2007 
       
  2008 	// If RTO just occurred and F-RTO processing is underway, override Nagle.
       
  2009 	if (iFRTOsent)
       
  2010 		{
       
  2011 		aNagleOverride = ETrue;
       
  2012 		}
       
  2013 
       
  2014 	//
       
  2015 	// Transmission guided by SACK (RFC2018)
       
  2016 	//
       
  2017 	if (iFlags.iSackOk)
       
  2018 		{
       
  2019 		TTcpSeqNum limitSeq, limit;
       
  2020 		TInt awnd, sacked;
       
  2021 
       
  2022 		// Find a slot between SACKed blocks
       
  2023 		sacked = iSacked.FindGap(seq, limit);
       
  2024 
       
  2025 		if (iFlags.iFastRetransMode)
       
  2026 			{
       
  2027 			// Apply the FACK algorithm
       
  2028 			TTcpSeqNum fack = iSacked.Count() ? iSacked.Last()->iRight : iSND.UNA;
       
  2029 			awnd = iCwnd - (iSND.NXT - fack);
       
  2030 			//
       
  2031 			// Allow at least one segment if there are no retransmits out.
       
  2032 			// This combines new-Reno style retransmit behaviour with the
       
  2033 			// FACK algorithm. Pure FACK is somewhat tardy sending out the
       
  2034 			// first retransmit, which causes problems in the usual single
       
  2035 			// segment loss case.
       
  2036 			//
       
  2037 			if (iRetranData)
       
  2038 				awnd -= iRetranData;
       
  2039 			else if (awnd < (TInt)iSMSS)
       
  2040 				awnd = iSMSS;
       
  2041 			limitSeq = iSND.UNA + effWND;
       
  2042 			LOG(Log::Printf(_L("\ttcp SAP[%u] SendDataSegment(): FAST RECOVERY: una=%u fack=%u awnd=%d"), (TInt)this, (iSND.UNA).Uint32(), fack.Uint32(), awnd));
       
  2043 			}
       
  2044 		else
       
  2045 			{
       
  2046 			//
       
  2047 			// Apply congestion window and limited transmit window
       
  2048 			//
       
  2049 			// Note: if there are SACKed blocks within the congestion window,
       
  2050 			// the window is extended accordingly. This is compatible with
       
  2051 			// the congestion control principles, since we will not be
       
  2052 			// retransmitting the SACKed blocks.
       
  2053 			//
       
  2054 #ifdef SIGNED_UNSIGNED_FIX
       
  2055 			awnd = (TInt)MinUU(effWND, iCwnd + iLwnd + (TUint)Max(sacked, 0));
       
  2056 #else
       
  2057 			awnd = Min(effWND, iCwnd + iLwnd + (sacked < 0 ? 0 : sacked));
       
  2058 #endif
       
  2059 			limitSeq = iSND.UNA + awnd;
       
  2060 			LOG(Log::Printf(_L("\ttcp SAP[%u] SendDataSegment(): NORMAL MODE: una=%u limit=%u wnd=%u"), (TInt)this, (iSND.UNA).Uint32(), limitSeq.Uint32(), awnd));
       
  2061 			}
       
  2062 
       
  2063 		if (sacked >= 0)
       
  2064 			{
       
  2065 			if (limit < limitSeq)
       
  2066 				{
       
  2067 				LOG(Log::Printf(_L("\ttcp SAP[%u] SendDataSegment(): SACK Adjust: RIGHT %u -> %u"), (TInt)this, limitSeq.Uint32(), limit.Uint32()));
       
  2068 				limitSeq = limit;
       
  2069 				if (limit <= seq + awnd)
       
  2070 					{
       
  2071 					LOG(Log::Printf(_L("\ttcp SAP[%u] SendDataSegment(): NAGLE override (SACK)"), (TInt)this));
       
  2072 					aNagleOverride = ETrue;
       
  2073 					}
       
  2074 				}
       
  2075 			}
       
  2076 		else if (iFlags.iFastRetransMode)
       
  2077 			{
       
  2078 			//
       
  2079 			// We are beyond the last SACK block. Skip to new data.
       
  2080 			//
       
  2081 			LOG(Log::Printf(_L("\ttcp SAP[%u] SendDataSegment(): SACK Adjust: SEND NEW DATA"), (TInt)this));
       
  2082 			iSendHigh = seq;  // Store position of SACK transmit
       
  2083 			seq = iSND.NXT;   // Start transmitting new data
       
  2084 			}
       
  2085 
       
  2086 		LOG(if (seq > aSeq) Log::Printf(_L("\ttcp SAP[%u] SendDataSegment(): SACK Adjust: LEFT %u -> %u"), (TInt)this, aSeq.Uint32(), seq.Uint32()));
       
  2087 #ifdef SIGNED_UNSIGNED_FIX
       
  2088 		if(limitSeq > seq)
       
  2089 			{
       
  2090 			len = (TInt)MinUS(limitSeq - seq, awnd);
       
  2091 			}
       
  2092 		else
       
  2093 			{
       
  2094 			len = Min(limitSeq - seq, awnd);
       
  2095 			}
       
  2096 #else
       
  2097 		len = Min(limitSeq - seq, awnd);
       
  2098 #endif
       
  2099 		}
       
  2100 	else
       
  2101 		{
       
  2102 #ifdef SIGNED_UNSIGNED_FIX
       
  2103 		len = iSND.UNA + MinUU(effWND, iCwnd + iLwnd) - seq;
       
  2104 #else
       
  2105 		len = iSND.UNA + Min(effWND, iCwnd + iLwnd) - seq;
       
  2106 #endif
       
  2107 		}
       
  2108 	LOG(Log::Printf(_L("\ttcp SAP[%u] SendDataSegment(%u, %d): una=%u nxt=%u off=%d noff=%d len=%d"),
       
  2109 		(TInt)this, aSeq.Uint32(), aNagleOverride, (iSND.UNA).Uint32(), (iSND.NXT).Uint32(), aSeq - iSND.UNA, seq - iSND.UNA, len));
       
  2110 	LOG(Log::Printf(_L("\ttcp SAP[%u] Transmit state:  effMSS=%d iCwnd=%d iLwnd=%d effWND=%d iRetranData=%d recovery=%d"),
       
  2111 		(TInt)this, effMSS, iCwnd, iLwnd, effWND, iRetranData, iFlags.iFastRetransMode));
       
  2112 
       
  2113 	//
       
  2114 	// Sender side SWS avoidance and Nagle.
       
  2115 	//
       
  2116 	if (len <= 0)
       
  2117 		len = 0;
       
  2118 	else if (len >= effMSS)
       
  2119 		len = effMSS;
       
  2120 	else if (seq > iSND.NXT && seq + len < iSND.UNA + iSockOutQLen && !aNagleOverride)
       
  2121 		//
       
  2122 	// Nagle override is not on and we're trying to send a partial
       
  2123 	// segment from the middle of the send queue. Therefore, we must
       
  2124 	// be constrained by the receiver window or the congestion window.
       
  2125 	//
       
  2126 	// If receiver window is very small we must allow a small packet out.
       
  2127 	//
       
  2128 	len = 0;
       
  2129 	else
       
  2130 		{
       
  2131 		//
       
  2132 		// Minshall's modification to the Nagle algorithm. We are
       
  2133 		// allowed to transmit a partial segment if there are no
       
  2134 		// other unacknowledged partial segments in flight.
       
  2135 		//
       
  2136 		if (iPartialSeq <= iSND.UNA && !Protocol()->StrictNagle() && !iFlags.iCork)
       
  2137 			{
       
  2138 			LOG(Log::Printf(_L("\ttcp SAP[%u] SendDataSegment(): NAGLE override (Minshall), seq=%u"), (TInt)this, seq.Uint32()));
       
  2139 			aNagleOverride = ETrue;
       
  2140 			iPartialSeq = seq + len;
       
  2141 			}
       
  2142 
       
  2143 		//
       
  2144 		// Standard Nagle algorithm. Do not send partial packets
       
  2145 		// if there are outstanding unacknowledged segments.
       
  2146 		// We also refrain from sending small packets if we have
       
  2147 		// blocked the application as that means our send buffer
       
  2148 		// is full.
       
  2149 		//
       
  2150 		// Update: With Cork option enabled, only full-sized segments are sent
       
  2151 		//
       
  2152 		// Note that we temporarily disable Nagle if we have
       
  2153 		// some urgent data to send or if the user has already
       
  2154 		// closed the outgoing direction of the connection.
       
  2155 		//
       
  2156 		if((iSockFlags.iFlowStopped || iSND.UNA < seq || iFlags.iCork)
       
  2157 			&& iSND.UP <= seq && !iFlags.iNoDelay
       
  2158 			&& !iSockFlags.iSendClose && !aNagleOverride)
       
  2159 			{
       
  2160 			LOG(Log::Printf(_L("\ttcp SAP[%u] SendDataSegment(): NAGLE kicked in"), (TInt)this));
       
  2161 			len = 0;
       
  2162 			}
       
  2163 		else
       
  2164 			flags |= KTcpCtlPSH;  // Set PSH on all partial segments
       
  2165 		}
       
  2166 
       
  2167 	if (len)
       
  2168 		{
       
  2169 		if (seq + len == iSND.UNA + iSockOutQLen)
       
  2170 			{
       
  2171 			// Send queue has drained. Set PSH if application is not blocked.
       
  2172 			if (!iSockFlags.iFlowStopped)
       
  2173 				flags |= KTcpCtlPSH;
       
  2174 
       
  2175 			// Set FIN if the socket is closing.
       
  2176 			if (iSockFlags.iSendClose)
       
  2177 				{
       
  2178 				flags |= KTcpCtlFIN;
       
  2179 				if (InState(ETcpEstablished|ETcpCloseWait))
       
  2180 					EnterState(InState(ETcpEstablished) ? ETcpFinWait1 : ETcpLastAck);
       
  2181 				}
       
  2182 			}
       
  2183 
       
  2184 		if (len = SendSegment(flags, seq, len), len >= 0)
       
  2185 			{
       
  2186 			// Count retransmitted data for FACK
       
  2187 			if (iSacked.Count() && seq < iSacked.Last()->iRight)
       
  2188 				{
       
  2189 				iSendHigh = seq + len;
       
  2190 				if (iFlags.iFastRetransMode)
       
  2191 					iRetranData += len;
       
  2192 				}
       
  2193 
       
  2194 			// Take SACK advance into account
       
  2195 			len += (seq - aSeq);
       
  2196 			}
       
  2197 		}
       
  2198 	else if (iSND.WND < (TUint)effMSS)
       
  2199 		SchedRetransmit(); // Start probing
       
  2200 
       
  2201 	//
       
  2202 	// Return the number of bytes by which to advance transmit sequence.
       
  2203 	// Note: With SACK this is not necessarily the number of bytes sent.
       
  2204 	//
       
  2205 	return len;
       
  2206 	}
       
  2207 
       
  2208 
       
  2209 //
       
  2210 // Send multiple data segments.
       
  2211 //
       
  2212 void CProviderTCP6::SendSegments(TBool aNagleOverride)
       
  2213 	{
       
  2214 	LOG(Log::Printf(_L("\ttcp SAP[%u] SendSegments(): queue=%u wnd=%u cwnd=%u, ssthresh=%u"),
       
  2215 		(TInt)this, iSockOutQLen, iSND.WND, iCwnd, iSsthresh));
       
  2216 
       
  2217 	iFlags.iTransmitPending = (iFlow.Status() == EFlow_PENDING);
       
  2218 	if (iFlags.iTransmitPending)
       
  2219 		{
       
  2220 		LOG(Log::Printf(_L("\ttcp SAP[%u] SendSegments(): Flow pending"), (TInt)this));
       
  2221 		return;
       
  2222 		}
       
  2223 
       
  2224 	if (InState(ETcpSynReceived|ETcpEstablished|ETcpCloseWait|ETcpLastAck|ETcpFinWait1|ETcpClosing))
       
  2225 		{
       
  2226 		TInt advance;
       
  2227 		TUint count = 0;
       
  2228 
       
  2229 		if (iTransmitSeq < iSND.UNA)
       
  2230 			iTransmitSeq = iSND.UNA;
       
  2231 
       
  2232 		// Transmit segments from queue
       
  2233 		while (advance = SendDataSegment(iTransmitSeq, aNagleOverride), advance > 0)
       
  2234 			{
       
  2235 			iTransmitSeq += advance;
       
  2236 			//
       
  2237 			// Limit transmission to KTcpMaxTransmit segments during
       
  2238 			// fast retransmit/recovery.
       
  2239 			//
       
  2240 			if (iFlags.iFastRetransMode && ++count >= Protocol()->MaxBurst())
       
  2241 				break;
       
  2242 			}
       
  2243 
       
  2244 		//
       
  2245 		// User has closed the connection and send queue has drained?
       
  2246 		//
       
  2247 		// Note: Normally the FIN bit is slapped on the last data segment
       
  2248 		// in SendDataSegment(). However, if we have to send a FIN segement
       
  2249 		// with no data, we do it here.
       
  2250 		//
       
  2251 		if (iSockFlags.iSendClose && 
       
  2252 			((InState(ETcpEstablished|ETcpCloseWait) &&	iSND.NXT == iSND.UNA + iSockOutQLen && advance >= 0) ||
       
  2253 			(InState(ETcpSynReceived) && iSockFlags.iRecvClose)))
       
  2254 			{
       
  2255 			EnterState(InState(ETcpSynReceived|ETcpEstablished) ? ETcpFinWait1 : ETcpLastAck);
       
  2256 			SendSegment(KTcpCtlFIN|KTcpCtlACK);
       
  2257 			}
       
  2258 		}
       
  2259 	}
       
  2260 
       
  2261 
       
  2262 //
       
  2263 // Handle retransmission timeout
       
  2264 //
       
  2265 // The retransmission timer is shared for multiple purposes.
       
  2266 // There are different reasons why we might end up here:
       
  2267 //
       
  2268 //   1) A normal retransmission timeout. In this case, iSND.NXT > iSND.UNA.
       
  2269 //   2) We are probing a zero window. In this case iSND.WND == 0.
       
  2270 //   3) The Nagle override timeout has expired. In this case,
       
  2271 //      iSND.WND != 0 and unsent < effMSS.
       
  2272 //   4) TIME-WAIT or FIN-WAIT-2 timeout.
       
  2273 //   5) If TCP keepalive option is set, expiry of the keepalive timer
       
  2274 //
       
  2275 void CProviderTCP6::RetransmitTimeout()
       
  2276 	{
       
  2277 	LOG(Log::Printf(_L("\ttcp SAP[%u] RetransmitTimeout(): backoff=%d"), (TInt)this, iBackoff));
       
  2278 
       
  2279 	TUint maxRetries = InState(ETcpSynSent|ETcpSynReceived)
       
  2280 		? Protocol()->SynRetries() : Protocol()->Retries2();
       
  2281 
       
  2282 	// Handle backoff and expiration
       
  2283 	if (iSND.NXT > iSND.UNA || iSND.WND == 0)
       
  2284 		{
       
  2285 		//
       
  2286 		// Exponential backoff.
       
  2287 		//
       
  2288 		++iBackoff;
       
  2289 		if (iRTO < Protocol()->MaxRTO())  // Avoid RTO overflow
       
  2290 			ResetRTO();
       
  2291 
       
  2292 		//
       
  2293 		// Timeout?
       
  2294 		//
       
  2295 		// Note: we time out if this is a connect attempt or a retransmission,
       
  2296 		// but we must not time out if we're probing a zero window.
       
  2297 		// Exception: probing timeouts if application has closed and we have zero window
       
  2298 		//
       
  2299 		if ((iBackoff > maxRetries) &&
       
  2300 			(iSND.WND > 0 
       
  2301 			|| InState(ETcpSynSent|ETcpSynReceived) 
       
  2302 			|| (iSockFlags.iSendClose && iSockFlags.iRecvClose)))
       
  2303 			{
       
  2304 			LOG(Log::Printf(_L("\ttcp SAP[%u] RetransmitTimeout(): TCP timed out"), (TInt)this));
       
  2305 			ErrorExpire(iLastError.iStatus != KErrNone ? iLastError.iStatus : KErrTimedOut);
       
  2306 			return;
       
  2307 			}
       
  2308 		//
       
  2309 		// Simple black hole detection for PMTUD. Currently, we never try to re-enable
       
  2310 		// PMTUD after hitting a black hole.
       
  2311 		//
       
  2312 		if (iBackoff > Protocol()->Retries1() && iSND.WND > 0)
       
  2313 			{
       
  2314 			iFlags.iDoPMTUD = EFalse;
       
  2315 			iSMSS = Min(iSMSS, KTcpStandardMSS);
       
  2316 			}
       
  2317 		}
       
  2318 
       
  2319 	else if (iFlags.iHaveKeepAlive && !iSockOutQLen && InState(ETcpEstablished | ETcpCloseWait))
       
  2320 		{
       
  2321 		KeepAliveTimeout();
       
  2322 		return;
       
  2323 		}
       
  2324 
       
  2325 	// TIME-WAIT or FIN-WAIT-2 timeout
       
  2326 	if (InState(ETcpTimeWait) || (InState(ETcpFinWait2) && iSockFlags.iRecvClose))
       
  2327 		{
       
  2328 		Expire();
       
  2329 		return;
       
  2330 		}
       
  2331 
       
  2332 	// Not dead yet. Go retransmit some segments.
       
  2333 	RetransmitSegments();
       
  2334 	}
       
  2335 
       
  2336 
       
  2337 void CProviderTCP6::KeepAliveTimeout()
       
  2338 	{
       
  2339 	// Keepalive timer expired. Because 32-bit microseconds are not enough for the minimum keepalive
       
  2340 	// timeout of two hours, the keepalive interval needs to be consumed one hour at a time.
       
  2341 
       
  2342 	ASSERT(iRetransTimer);
       
  2343 
       
  2344 	if (iBackoff >= Protocol()->NumKeepAlives())
       
  2345 		{
       
  2346 		// No response from the peer. Terminate connection
       
  2347 		LOG(Log::Printf(_L("\ttcp SAP[%u] KeepAliveTimeout(): No response to Keep-Alive probes. Closing connection"), (TInt)this));
       
  2348 		ErrorExpire(KErrTimedOut);
       
  2349 		return;
       
  2350 		}
       
  2351 
       
  2352 	TUint32 usec = TimeStamp();
       
  2353 
       
  2354 	if (!iLastTimeout)
       
  2355 		iLastTimeout = usec;
       
  2356 
       
  2357 	TUint32 distance = (usec - iLastTimeout) / KOneSecondUs;  // seconds
       
  2358 	TUint32 interval = iBackoff ? Protocol()->KeepAliveRxmt() : Protocol()->KeepAliveIntv();
       
  2359 
       
  2360 	if (distance > interval)
       
  2361 		{
       
  2362 		// Send a keepalive probe. If no ack arrives, next one is sent after a shorter time (75 s)
       
  2363 		LOG(Log::Printf(_L("\ttcp SAP[%u] KeepAliveTimeout(): Sending a Keep-Alive probe"), (TInt)this));
       
  2364 		SendSegment(KTcpCtlACK, iSND.UNA - 1, 0);
       
  2365 		iBackoff++;
       
  2366 		iRetransTimer->Restart(Protocol()->KeepAliveRxmt() * KOneSecondUs);
       
  2367 		}
       
  2368 	else
       
  2369 		{
       
  2370 		// This branch is entered when the first keepalive has to be issued after an idle period.
       
  2371 		distance = Protocol()->KeepAliveIntv() - distance;
       
  2372 		iRetransTimer->Restart((distance > 1800) ?
       
  2373 			1800 * KOneSecondUs : (distance * KOneSecondUs));
       
  2374 		}
       
  2375 	}
       
  2376 
       
  2377 
       
  2378 void CProviderTCP6::ResetKeepAlives()
       
  2379 	{
       
  2380 	ASSERT(iRetransTimer);
       
  2381 	iRetransTimer->Restart((Protocol()->KeepAliveIntv() > 1800) ?
       
  2382 		1800 * KOneSecondUs : (Protocol()->KeepAliveIntv() * KOneSecondUs));
       
  2383 	// Backoff is used for counting unacknowledged keepalive retransmissions during idle periods
       
  2384 	iBackoff = 0;
       
  2385 	iLastTimeout = TimeStamp();
       
  2386 	}
       
  2387 
       
  2388 inline TBool CProviderTCP6::CanTriggerKeepAlive()
       
  2389 	{ 
       
  2390 	//
       
  2391 	// We can only send keep-alive if we're idle and established.
       
  2392 	//
       
  2393 	return iFlags.iHaveTriggeredKeepAlive
       
  2394 		&& !iSockOutQLen 
       
  2395 		&& iSendQ.IsEmpty()
       
  2396 		&& InState(ETcpEstablished) 
       
  2397 		&& iSND.NXT == iSND.UNA 
       
  2398 		&& iSND.WND > 0;
       
  2399 	}
       
  2400 
       
  2401 //
       
  2402 // Try to retransmit segments. This routine gets called from two places:
       
  2403 //  - directly from RetransmitTimeout()
       
  2404 //  - from CanSend(), in which case this is a delayed retransmission timeout
       
  2405 //
       
  2406 void CProviderTCP6::RetransmitSegments()
       
  2407 	{
       
  2408 	ASSERT(iRetransTimer);
       
  2409 
       
  2410 	LOG(Log::Printf(_L("\ttcp SAP[%u] RetransmitSegments(): queue=%u wnd=%u cwnd=%u, ssthresh=%u dupacks=%d"),
       
  2411 		(TInt)this, iSockOutQLen, iSND.WND, iCwnd, iSsthresh, iDupAcks));
       
  2412 
       
  2413 	TInt unacked = Min(iSND.NXT - iSND.UNA, iSockOutQLen);  // Adjust for FIN
       
  2414 	TInt effMSS = EffectiveMSS();
       
  2415 
       
  2416 	// Delay retransmission if the flow is pending
       
  2417 	iFlags.iRetransmitPending = (iFlow.Status() == EFlow_PENDING);
       
  2418 	if (iFlags.iRetransmitPending)
       
  2419 		{
       
  2420 		LOG(Log::Printf(_L("\ttcp SAP[%u] RetransmitSegments(): Flow pending"), (TInt)this));
       
  2421 		ReSchedRetransmit();
       
  2422 		return;
       
  2423 		}
       
  2424 
       
  2425 	//
       
  2426 	// Handle retransmission of data segments and zero window probing.
       
  2427 	// We must have something in output queue. SYN or FIN retransmissions
       
  2428 	// and TIME-WAIT or FIN-WAIT-2 timeouts are handled later.
       
  2429 	//
       
  2430 	if (iSockOutQLen && InState(ETcpEstablished|ETcpFinWait1|ETcpClosing|ETcpCloseWait|ETcpLastAck))
       
  2431 		{
       
  2432 		if (iSND.WND == 0)
       
  2433 			{
       
  2434 			LOG(Log::Printf(_L("\ttcp SAP[%u] RetransmitSegments(): Window PROBE"), (TInt)this));
       
  2435 
       
  2436 			//
       
  2437 			// We are probing a zero window.
       
  2438 			//
       
  2439 			switch (Protocol()->ProbeStyle())
       
  2440 				{
       
  2441 			case 1:
       
  2442 				// Probe with a full segment (BSD style)
       
  2443 				SendSegment(KTcpCtlACK, iSND.UNA, Min(iSockOutQLen - unacked, effMSS));
       
  2444 				break;
       
  2445 
       
  2446 			case 2:
       
  2447 				//
       
  2448 				// Probe with a below-window ACK (Linux style).
       
  2449 				//
       
  2450 				// Note:   SendSegment() does not allow sending an above-window ACK.
       
  2451 				//         Below-window ACK is fine, though.
       
  2452 				//
       
  2453 				// Note 2: If we have urgent data to send, we fall back on standard probe.
       
  2454 				//         since a pure ack can not deliver the urgent pointer.
       
  2455 				//
       
  2456 				if (iSND.UP <= iSND.UNA)
       
  2457 					{
       
  2458 					SendSegment(KTcpCtlACK, iSND.UNA - 1);
       
  2459 					SchedRetransmit();
       
  2460 					break;
       
  2461 					}
       
  2462 				// Fall through
       
  2463 
       
  2464 			default:
       
  2465 				// Standard probe. We use a single byte to probe a zero window.
       
  2466 				SendSegment(KTcpCtlACK, iSND.UNA, 1);
       
  2467 				}
       
  2468 			//
       
  2469 			// Note 1: With probes including data iSND.NXT will now be pointing beyond
       
  2470 			// the advertised window of the receiver! This will allow us to accept the
       
  2471 			// incoming probe ack without any special hacks. However, it also means
       
  2472 			// that if we send an ACK or RST, we need to make sure the sequence number
       
  2473 			// is within the receiver window! SendSegment() now makes this adjustment
       
  2474 			// as a special case.
       
  2475 			//
       
  2476 			// Note 2: We may also end up with iSND.NXT pointing beyond the window if
       
  2477 			// the receiver suddenly shrinks its window. The current solution covers
       
  2478 			// both cases.
       
  2479 			//
       
  2480 			return;
       
  2481 			}
       
  2482 
       
  2483 		//
       
  2484 		// This is a retransmit timout. Do we have anything to do?
       
  2485 		//
       
  2486 		if (!unacked)
       
  2487 			return;
       
  2488 
       
  2489 		LOG(if (iFlags.iFastRetransMode) Log::Printf(_L("\ttcp SAP[%u] RetransmitSegments(): Leaving FAST RETRANS mode"), (TInt)this));
       
  2490 		iFlags.iFastRetransMode = EFalse;
       
  2491 		iDupAcks = 0;
       
  2492 
       
  2493 		//
       
  2494 		// Congestion control
       
  2495 		//
       
  2496 		iSsthresh = Max((iSND.NXT - iSND.UNA) / 2, 2 * iSMSS);
       
  2497 		iCwnd = EffectiveMSS();
       
  2498 		iLwnd = 0;
       
  2499 		iRetranData = 0;
       
  2500 		iPartialSeq = iSND.UNA;
       
  2501 
       
  2502 		//
       
  2503 		// The receiver may have reneged. Clear SACK info.
       
  2504 		//
       
  2505 		// Only clear the SACK queue if we have a SACKed block immediately
       
  2506 		// after iSND.UNA. In this case the sender has clearly reneged.
       
  2507 		// If the peer does this even once, we will no longer trust it
       
  2508 		// to retain its above-sequence queue and will revert to the normal
       
  2509 		// RFC2018 behaviour of clearing all SACK info on retransmit timeout.
       
  2510 		//
       
  2511 		if (!iFlags.iSackOk || (iFlags.iPeerHasReneged ||
       
  2512 			(iSacked.Count() && iSacked.First()->iLeft == iSND.UNA)))
       
  2513 			{
       
  2514 			if (iFlags.iSackOk)
       
  2515 				{
       
  2516 				LOG(if(!iFlags.iPeerHasReneged) Log::Printf(_L("\ttcp SAP[%u] RetransmitSegments(): Peer reneged"), (TInt)this));
       
  2517 				iFlags.iPeerHasReneged = ETrue;
       
  2518 				iSacked.Clear();
       
  2519 				}
       
  2520 
       
  2521 			//
       
  2522 			// New reno "bugfix" [RFC2582] is applied only if we are forced
       
  2523 			// to discard the SACK info. If we can keep the info we will
       
  2524 			// never send spurious retransmits and thus there will be no
       
  2525 			// dupacks to trigger fast recovery, unless segments have
       
  2526 			// really been lost.
       
  2527 			//
       
  2528 			iSendHigh = iSND.NXT;
       
  2529 			}
       
  2530 
       
  2531 		iRealSendHigh = iSND.NXT;
       
  2532 
       
  2533 		// Save timestamp for delay spike detection
       
  2534 		if (iFlags.iUseTimeStamps)
       
  2535 			iLastTimeout = TimeStamp();
       
  2536 
       
  2537 		//
       
  2538 		// Retransmit segments.
       
  2539 		//
       
  2540 		if (Protocol()->FRTO())
       
  2541 			{
       
  2542 			// F-RTO: Send first unacknowledged segment and continue transmitting new data
       
  2543 			iFRTOsent = 1;
       
  2544 			SendDataSegment(iSND.UNA, ETrue);
       
  2545 			}
       
  2546 		else
       
  2547 			{
       
  2548 			// Normal retransmit
       
  2549 			iTransmitSeq = iSND.UNA;
       
  2550 			SendSegments(ETrue);
       
  2551 			}
       
  2552 
       
  2553 		// Store retransmit sequence for SACK retransmit
       
  2554 		if (iTransmitSeq > iSendHigh && !iFRTOsent)
       
  2555 			iSendHigh = iTransmitSeq;
       
  2556 
       
  2557 		// If the server doesn't respond because of broken NAT/FW or other, don't keep interface up.
       
  2558 		if (InState(ETcpFinWait1|ETcpClosing|ETcpLastAck))
       
  2559 			DetachIfDead();
       
  2560 		return;
       
  2561 		}
       
  2562 
       
  2563 	//
       
  2564 	// Ok, this is either a SYN/FIN retransmit or a TIME-WAIT/FIN-WAIT-2 timeout.
       
  2565 	//
       
  2566 	if (InState(ETcpSynSent))
       
  2567 		{
       
  2568 		// Retransmit SYN
       
  2569 		SendSegment(KTcpCtlSYN, iSND.UNA);
       
  2570 		return;
       
  2571 		}
       
  2572 
       
  2573 	if (InState(ETcpSynReceived))
       
  2574 		{
       
  2575 		// Retransmit SYN,ACK
       
  2576 		SendSegment(KTcpCtlSYN|KTcpCtlACK, iSND.UNA);
       
  2577 		return;
       
  2578 		}
       
  2579 
       
  2580 	if (InState(ETcpFinWait1|ETcpClosing|ETcpLastAck))
       
  2581 		{
       
  2582 		// If the server doesn't respond because of broken NAT/FW or other, don't keep interface up.
       
  2583 		DetachIfDead();
       
  2584 		// Retransmit FIN
       
  2585 		SendSegment(KTcpCtlFIN|KTcpCtlACK, iSND.UNA);
       
  2586 		return;
       
  2587 		}
       
  2588 
       
  2589 	LOG(Log::Printf(_L("\ttcp SAP[%u] RetransmitSegments(): Retransmitter stopping"), (TInt)this));
       
  2590 	if (!iSockFlags.iAttached)
       
  2591 		Expire();
       
  2592 	return;
       
  2593 	}
       
  2594 
       
  2595 
       
  2596 //
       
  2597 // Respond to an explicit congestion control signal.
       
  2598 // Currently, the signal can come from the link layer
       
  2599 // or from the network as an ICMP source quench.
       
  2600 //
       
  2601 TBool CProviderTCP6::SourceQuench()
       
  2602 	{
       
  2603 	//
       
  2604 	// Allow source quenching approximately once per window.
       
  2605 	// Note: the test is written in such a way that iQuenchSeq
       
  2606 	// does not need to be updated during normal TCP operation.
       
  2607 	//
       
  2608 	// Do not shrink the congestion window if we're doing fast
       
  2609 	// retransmits. That would mess up the congestion window
       
  2610 	// deflation when exiting fast retransmit mode.
       
  2611 	//
       
  2612 	if (iQuenchSeq.Outside(iSND.NXT, iSND.NXT + iSND.WND) && !iFlags.iFastRetransMode)
       
  2613 		{
       
  2614 		iSsthresh = Max((iSND.NXT - iSND.UNA) / 2, 2 * iSMSS);
       
  2615 		iCwnd = iSsthresh;
       
  2616 		iQuenchSeq = iSND.NXT + iSND.WND;
       
  2617 		LOG(Log::Printf(_L("\ttcp SAP[%u] SourceQuench(): flight=%d, cwnd=%d, ssthresh=%d"),
       
  2618 			(TInt)this, iSND.NXT - iSND.UNA, iCwnd, iSsthresh));
       
  2619 		return ETrue;
       
  2620 		}
       
  2621 	return EFalse;
       
  2622 	}
       
  2623 
       
  2624 
       
  2625 TInt CProviderTCP6::SenderCallBack(TAny* aProviderTCP)
       
  2626 	{
       
  2627 	LOG(Log::Printf(_L("<>\ttcp SAP[%u] SenderCallBack"), (TInt)aProviderTCP));
       
  2628 	((CProviderTCP6*)aProviderTCP)->SendSegments();
       
  2629 	return 0;
       
  2630 	}
       
  2631 
       
  2632 TInt CProviderTCP6::ReceiverCallBack(TAny* aProviderTCP)
       
  2633 	{
       
  2634 	LOG(Log::Printf(_L("<>\ttcp SAP[%u] ReceiverCallBack"), (TInt)aProviderTCP));
       
  2635 	((CProviderTCP6*)aProviderTCP)->ProcessSegments();
       
  2636 	return 0;
       
  2637 	}
       
  2638 
       
  2639 TInt CProviderTCP6::DelayAckCallBack(TAny* aProviderTCP)
       
  2640 	{
       
  2641 	LOG(Log::Printf(_L("<>\ttcp SAP[%u] DelayAckCallBack"), (TInt)aProviderTCP));
       
  2642 	((CProviderTCP6*)aProviderTCP)->SendSegment(KTcpCtlACK);
       
  2643 	return 0;
       
  2644 	}
       
  2645 
       
  2646 TInt CProviderTCP6::TransmitterCallBack(TAny* aProviderTCP)
       
  2647 	{
       
  2648 	LOG(Log::Printf(_L("<>\ttcp SAP[%u] TransmitterCallBack"), (TInt)aProviderTCP));
       
  2649 	((CProviderTCP6*)aProviderTCP)->Transmit();
       
  2650 	return 0;
       
  2651 	}
       
  2652 
       
  2653 TInt CProviderTCP6::RetransmitterCallBack(TAny* aProviderTCP)
       
  2654 	{
       
  2655 	LOG(Log::Printf(_L("<>\ttcp SAP[%u] RetransmitterCallback"), (TInt)aProviderTCP));
       
  2656 	((CProviderTCP6*)aProviderTCP)->RetransmitTimeout();
       
  2657 	return 0;
       
  2658 	}
       
  2659 
       
  2660 
       
  2661 TInt CProviderTCP6::LingerTimerCallBack(TAny *aProviderTCP)
       
  2662 	{
       
  2663 	LOG(Log::Printf(_L("<>\ttcp SAP[%u] Linger timeout()"), (TInt)aProviderTCP));
       
  2664 	((CProviderTCP6*)aProviderTCP)->Detach();
       
  2665 	return 0;
       
  2666 	}
       
  2667 
       
  2668 
       
  2669 //
       
  2670 // Initialize SRTT measurement
       
  2671 //
       
  2672 void CProviderTCP6::ClearRTT()
       
  2673 	{
       
  2674 	iSRTT = 0;
       
  2675 	iMDEV = Protocol()->MdevSmooth() * Protocol()->InitialRTO();
       
  2676 	if (Protocol()->RTO_K())
       
  2677 		iMDEV /= Protocol()->RTO_K();
       
  2678 	}
       
  2679 
       
  2680 
       
  2681 //
       
  2682 // Update RTO using van Jacobson's algorithm
       
  2683 //
       
  2684 void CProviderTCP6::UpdateRTO(TUint32 aRTT)
       
  2685 	{
       
  2686 	if (!iSRTT && aRTT > Protocol()->InitialRTO() / 2)
       
  2687 		{
       
  2688 		iSRTT = Protocol()->SrttSmooth() * aRTT;
       
  2689 		iMDEV = Protocol()->MdevSmooth() * aRTT / 2;
       
  2690 		}
       
  2691 	else
       
  2692 		{
       
  2693 		TInt delta = aRTT - (iSRTT / Protocol()->SrttSmooth()); // delta >= -iSRTT
       
  2694 		iSRTT += delta;
       
  2695 		if (!iSRTT)
       
  2696 			iSRTT = 1;
       
  2697 		if (delta < 0)
       
  2698 			delta = -delta;
       
  2699 		delta -= (iMDEV / Protocol()->MdevSmooth()); // delta >= -iMDEV
       
  2700 		iMDEV += delta;
       
  2701 		}
       
  2702 
       
  2703 	ResetRTO();
       
  2704 	LOG(Log::Printf(_L("\ttcp SAP[%u] UpdateRTO(): RTT=%d SRTT=%d MDEV=%d BACKOFF=%d RTO=%d"),
       
  2705 		(TInt)this, aRTT, iSRTT / Protocol()->SrttSmooth(), iMDEV / Protocol()->MdevSmooth(), iBackoff, iRTO));
       
  2706 	}
       
  2707 
       
  2708 //
       
  2709 // Calculate RTO with backoff
       
  2710 //
       
  2711 void CProviderTCP6::ResetRTO()
       
  2712 	{
       
  2713 	iRTO = (iSRTT / Protocol()->SrttSmooth()) +
       
  2714 		Max(Protocol()->RTO_K() * iMDEV / Protocol()->MdevSmooth(), Protocol()->RTO_G());
       
  2715 	if (iRTO < Protocol()->MinRTO())
       
  2716 		iRTO = Protocol()->MinRTO();
       
  2717 	iRTO <<= iBackoff;
       
  2718 	if (iRTO > Protocol()->MaxRTO())
       
  2719 		iRTO = Protocol()->MaxRTO();
       
  2720 	LOG(Log::Printf(_L("\ttcp SAP[%u] ResetRTO(): SRTT=%d MDEV=%d BACKOFF=%d RTO=%d"),
       
  2721 		(TInt)this, iSRTT / Protocol()->SrttSmooth(), iMDEV / Protocol()->MdevSmooth(), iBackoff, iRTO));
       
  2722 	}
       
  2723 
       
  2724 //
       
  2725 // Set initial congestion window
       
  2726 //
       
  2727 void CProviderTCP6::ResetCwnd(TUint aSMSS)
       
  2728 	{
       
  2729 	if (Protocol()->RFC2414())
       
  2730 		iCwnd = Min(4 * aSMSS, Max(2 * aSMSS, 4380));
       
  2731 	else
       
  2732 		iCwnd = Protocol()->InitialCwnd() * aSMSS;
       
  2733 	LOG(Log::Printf(_L("\ttcp SAP[%u] ResetCwnd(): cwnd=%d"), (TInt)this, iCwnd));
       
  2734 	}
       
  2735 
       
  2736 
       
  2737 //
       
  2738 // Schedule a FIN-WAIT-2 or TIME-WAIT timeout
       
  2739 //
       
  2740 void CProviderTCP6::SchedMsl2Wait()
       
  2741 	{
       
  2742 	ASSERT(iRetransTimer);
       
  2743 
       
  2744 	iBackoff = 0;
       
  2745 	iRetransTimer->Restart(Protocol()->Msl2Delay());
       
  2746 
       
  2747 	//
       
  2748 	// Remove this SAP from the user socket count.
       
  2749 	//
       
  2750 	DetachFromInterface();
       
  2751 	}
       
  2752 
       
  2753 //
       
  2754 // Detach the SAP if the application has closed and we seem to keep resending stuff.
       
  2755 //
       
  2756 void CProviderTCP6::DetachIfDead()
       
  2757 	{
       
  2758 	if (iSockFlags.iRecvClose && iSockFlags.iSendClose && Protocol()->FinPersistency()
       
  2759 		&& iBackoff >= Protocol()->FinPersistency())
       
  2760 		{
       
  2761 		LOG(Log::Printf(_L("\ttcp SAP[%u] Peer looks dead while %d bytes unacked data. Detach!"), 
       
  2762 			(TInt)this, Min(iSND.NXT - iSND.UNA, iSockOutQLen)));
       
  2763 		DetachFromInterface();
       
  2764 		}
       
  2765 	}
       
  2766 
       
  2767 void CProviderTCP6::DetachFromInterface()
       
  2768 /**
       
  2769 Removes this SAP from the user socket count and interface flow count.
       
  2770 This allows link layer and TCP/IP stack go down if no one else uses it.
       
  2771 */
       
  2772 	{
       
  2773 	const TInt off = 0;
       
  2774 	SetOption(KSolInetIp, KSoUserSocket, TPtr8((TUint8*)&off, sizeof(TInt), sizeof(TInt)));
       
  2775 	SetOption(KSolInetIp, KSoKeepInterfaceUp, TPtr8((TUint8*)&off, sizeof(TInt), sizeof(TInt)));
       
  2776 	}
       
  2777 
       
  2778 
       
  2779 //
       
  2780 // Check ioctl completion
       
  2781 //
       
  2782 void CProviderTCP6::CompleteIoctl(TInt aError)
       
  2783 	{
       
  2784 	if (iFlags.iDataSentIoctl && iSockFlags.iNotify)
       
  2785 		{
       
  2786 		if (!iSockOutQLen)
       
  2787 			{
       
  2788 			iFlags.iDataSentIoctl = EFalse;
       
  2789 			iSocket->IoctlComplete(0);
       
  2790 			}
       
  2791 		else if (aError != KErrNone)
       
  2792 			{
       
  2793 			iFlags.iDataSentIoctl = EFalse;
       
  2794 			Error(KErrCancel, MSocketNotify::EErrorIoctl);
       
  2795 			}
       
  2796 		}
       
  2797 	}
       
  2798 
       
  2799 //
       
  2800 //  Main incoming segment processing loop
       
  2801 //
       
  2802 void CProviderTCP6::ProcessSegments()
       
  2803 	{
       
  2804 	LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments()"), (TInt)this));
       
  2805 
       
  2806 	ASSERT(iRetransTimer);
       
  2807 
       
  2808 	RMBufRecvPacket packet;
       
  2809 	TBool immediateAck = EFalse;
       
  2810 
       
  2811 	while (iRecvQ.Remove(packet))
       
  2812 		{
       
  2813 		RMBufRecvInfo* info = packet.Unpack();
       
  2814 		TIpHeader *ip = ((RMBufPacketPeek &)packet).GetIpHeader();
       
  2815 		TTcpPacket seg(packet, info->iOffset);
       
  2816 		TTcpOptions opt;
       
  2817 		seg.iHdr->Options(opt);
       
  2818 		TInt len = packet.Length() - seg.iHdr->HeaderLength() - info->iOffset;
       
  2819 		TTcpSeqNum seq = seg.iHdr->Sequence();
       
  2820 		TTcpSeqNum ack = seg.iHdr->ACK() ? seg.iHdr->Acknowledgment() : TTcpSeqNum(0);
       
  2821 		TInt fin = seg.iHdr->FIN();  // Save this for FIN processing
       
  2822 		CProviderTCP6 *nSAP = NULL;
       
  2823 		TTcpSeqNum rcvNxt = iRCV.NXT; // Used in SYN_RECEIVED state
       
  2824 
       
  2825 		// Get current time
       
  2826 		TUint32 usec = TimeStamp();
       
  2827 
       
  2828 		if (InState(ETcpListen))
       
  2829 			{
       
  2830 			TUint32 tsEcr;
       
  2831 
       
  2832 			if (!iParent)
       
  2833 				{
       
  2834 				//
       
  2835 				// Server socket LISTEN state processing.
       
  2836 				//
       
  2837 
       
  2838 				// Sanity checks.
       
  2839 				if (iConnectCount >= iListenQueueSize || seg.iHdr->RST())
       
  2840 					goto discard;
       
  2841 
       
  2842 				// Check invalid address.
       
  2843 				if (!TInetAddr::Cast(info->iSrcAddr).IsUnicast() ||
       
  2844 					!TInetAddr::Cast(info->iDstAddr).IsUnicast())
       
  2845 					goto discard;
       
  2846 
       
  2847 				if (IsLandAttack(info))
       
  2848 					goto discard;
       
  2849 				
       
  2850 				if (seg.iHdr->ACK())
       
  2851 					{
       
  2852 					LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): ACK received in LISTEN state. Sending RST"), (TInt)this));
       
  2853 					SendReset(ack, info->iDstAddr, info->iSrcAddr);
       
  2854 					goto discard;
       
  2855 					}
       
  2856 
       
  2857 				if (!seg.iHdr->SYN())
       
  2858 					goto discard;
       
  2859 
       
  2860 				if (opt.Error())
       
  2861 					{
       
  2862 					LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Invalid TCP options"), (TInt)this));
       
  2863 					SendResetNoSync(seq+len+1, info->iDstAddr, info->iSrcAddr);
       
  2864 					goto discard;
       
  2865 					}
       
  2866 
       
  2867 				if (opt.MSS() > 0 && opt.MSS() < STATIC_CAST(TInt, KTcpMinimumMSS))
       
  2868 					{
       
  2869 					LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Invalid MSS option"), (TInt)this));
       
  2870 					SendResetNoSync(seq+len+1, info->iDstAddr, info->iSrcAddr);
       
  2871 					goto discard;
       
  2872 					}
       
  2873 
       
  2874 				//
       
  2875 				// Sometimes SYN retransmissions get compressed in the network
       
  2876 				// and get queued in the listen socket. If this happens we just
       
  2877 				// punt the SYN packet to the correct SAP.
       
  2878 				//
       
  2879 #ifndef SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
       
  2880 				nSAP = (CProviderTCP6*)Protocol()->LocateSap(EMatchConnection, KAFUnspec,
       
  2881 					info->iDstAddr, info->iSrcAddr);
       
  2882 #else
       
  2883 				nSAP = (CProviderTCP6*)Protocol()->LocateSap(EMatchConnection, KAFUnspec,
       
  2884 					info->iDstAddr, info->iSrcAddr, NULL, info->iInterfaceIndex);
       
  2885 #endif //SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
       
  2886 				if (nSAP == NULL)
       
  2887 					{
       
  2888 					// Create a new SAP and initialize it
       
  2889 					if (CreateChild(nSAP) != KErrNone)
       
  2890 						goto discard;
       
  2891 					
       
  2892 #ifdef SYMBIAN_NETWORKING_UPS					
       
  2893 					nSAP->iConnectionInfoReceived = 1;
       
  2894 #endif
       
  2895 					RFlowContext flowCtxt = nSAP->iFlow;
       
  2896 					flowCtxt.SetLocalAddr(info->iDstAddr);
       
  2897 					flowCtxt.SetRemoteAddr(info->iSrcAddr);
       
  2898 					nSAP->EnterState(ETcpListen);
       
  2899 
       
  2900 					// Create a flow context
       
  2901 					TInt status = flowCtxt.Connect();
       
  2902 					if (status < KErrNone)
       
  2903 						{
       
  2904 						LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSYN(): Error %d opening flow context"), (TInt)this, status));
       
  2905 						delete nSAP;
       
  2906 						SendResetNoSync(seq+len+1, info->iDstAddr, info->iSrcAddr);
       
  2907 						goto discard;
       
  2908 						}
       
  2909 
       
  2910 					// Disable on-demand interface setup for the child
       
  2911 					flowCtxt.FlowContext()->iInfo.iNoInterfaceUp = 1;
       
  2912 					nSAP->iSockFlags.iConnected = ETrue;
       
  2913 					Protocol()->BindProvider(nSAP);
       
  2914 					}
       
  2915 
       
  2916 				// Get the new SAP started. It will handle the rest,
       
  2917 				packet.Pack();
       
  2918 				nSAP->Process(packet);
       
  2919 				continue;
       
  2920 				}
       
  2921 
       
  2922 
       
  2923 			//
       
  2924 			// Child socket LISTEN state processing.
       
  2925 			//
       
  2926 
       
  2927 	  /*
       
  2928 	      Set RCV.NXT to SEG.SEQ+1, IRS is set to SEG.SEQ and any other
       
  2929 	      control or text should be queued for processing later.  ISS
       
  2930 	      should be selected and a SYN segment sent of the form:
       
  2931 
       
  2932 		<SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
       
  2933 
       
  2934 	      SND.NXT is set to ISS+1 and SND.UNA to ISS.  The connection
       
  2935 	      state should be changed to SYN-RECEIVED.  Note that any other
       
  2936 	      incoming control or data (combined with SYN) will be processed
       
  2937 	      in the SYN-RECEIVED state, but processing of SYN and ACK should
       
  2938 	      not be repeated.  If the listen was not fully specified (i.e.,
       
  2939 	      the foreign socket was not fully specified), then the
       
  2940 	      unspecified fields should be filled in now.
       
  2941 			*/
       
  2942 
       
  2943 			// Peer groks timestamps?
       
  2944 			iFlags.iUseTimeStamps &= opt.TimeStamps(iTsRecent, tsEcr);
       
  2945 			if (!iFlags.iUseTimeStamps)
       
  2946 				iOptions.ClearTimeStamps();
       
  2947 
       
  2948 			// Peer groks SACK?
       
  2949 			iFlags.iSackOk &= opt.SackOk();
       
  2950 			if (!iFlags.iSackOk)
       
  2951 				iOptions.ClearSackOk();
       
  2952 
       
  2953 			// Peer denies ECN
       
  2954 			if (!seg.iHdr->ECE() || !seg.iHdr->CWR())
       
  2955 				{
       
  2956 				iFlags.iEcn = EFalse;
       
  2957 				}
       
  2958 
       
  2959 			// Note: the parent does error checking before instantiating a child socket.
       
  2960 			if (opt.MSS() >= 0)
       
  2961 				iSMSS = opt.MSS();
       
  2962 
       
  2963 			//
       
  2964 			// The following is based on network interface MTU.
       
  2965 			// We limit the advertised MSS to window size divided by four,
       
  2966 			// in case the interface supportes a large (or infinite) MTU.
       
  2967 			//
       
  2968 			iRMSS = Min(LinkRMSS(), iSockInBufSize / 2);
       
  2969 			iOptions.SetMSS(iRMSS);
       
  2970 
       
  2971 			// Initialise send sequence number
       
  2972 			iTransmitSeq = iSND.NXT = Protocol()->RandomSequence();
       
  2973 
       
  2974 			if (!opt.WindowScale() || Protocol()->WinScale() == -1)
       
  2975 				{
       
  2976 				iRcvWscale = 0;
       
  2977 				iOptions.SetWindowScale(0);
       
  2978 				iSockInBufSize = Min(iSockInBufSize, 0xffff);
       
  2979 				}
       
  2980 			else
       
  2981 				{
       
  2982 				iSndWscale = opt.WindowScale() - 1;
       
  2983 				iRcvWscale = (Protocol()->WinScale() > 0 ?
       
  2984 					Protocol()->WinScale() - 1 : NeedWindowScale());
       
  2985 				iOptions.SetWindowScale((TUint8)(iRcvWscale + 1));
       
  2986 				}
       
  2987 				
       
  2988 			// Initialize receiver sequence and window
       
  2989 			iFreeWindow = iSockInBufSize % iRMSS;
       
  2990 			iRCV.WND = iSockInBufSize - iFreeWindow;
       
  2991 			iRCV.NXT = seg.iHdr->Sequence() + 1;
       
  2992 
       
  2993 			TUint8 flags = KTcpCtlSYN|KTcpCtlACK;
       
  2994 			if (iFlags.iEcn)
       
  2995 				{
       
  2996 				flags |= KTcpCtlECE;
       
  2997 				}
       
  2998 
       
  2999 			// Do not kick idle timers until we are in established state
       
  3000 			StoreKeepInterfaceUp();
       
  3001 			iFlow.FlowContext()->SetOption(KSolInetIp, KSoKeepInterfaceUp, KInetOptionDisable);
       
  3002 
       
  3003 			// Send SYN-ACK
       
  3004 			iSND.UNA = iSND.NXT;
       
  3005 			SendSegment(flags);
       
  3006 			++iTransmitSeq;
       
  3007 
       
  3008 			// Make sure we don't miss our window update.
       
  3009 			iSND.WL1 = iRCV.NXT;
       
  3010 			iSND.WL2 = iSND.NXT;
       
  3011 
       
  3012 			iPartialSeq = iSND.UNA;
       
  3013 
       
  3014 			EnterState(ETcpSynReceived);
       
  3015 			goto accept;
       
  3016 			}
       
  3017 
       
  3018 		if (InState(ETcpSynSent))
       
  3019 			{
       
  3020 			if (seg.iHdr->ACK() && ack.Outside(iSND.UNA, iSND.NXT))
       
  3021 				{
       
  3022 				LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Invalid ack=%u"), (TInt)this, ack.Uint32()));
       
  3023 				if (!seg.iHdr->RST())
       
  3024 					SendReset(ack);
       
  3025 				goto discard;
       
  3026 				}
       
  3027 
       
  3028 			if (seg.iHdr->RST())
       
  3029 				{
       
  3030 				if (seg.iHdr->ACK())  // No need to check ack sequence because it was tested above
       
  3031 					{
       
  3032 					LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): RST packet"), (TInt)this));
       
  3033 					Error(KErrCouldNotConnect, MSocketNotify::EErrorConnect);
       
  3034 					EnterState(ETcpClosed);
       
  3035 					goto wrapup;
       
  3036 					}
       
  3037 				else
       
  3038 					goto discard;
       
  3039 				}
       
  3040 
       
  3041 			if (!seg.iHdr->SYN())
       
  3042 				goto discard;
       
  3043 
       
  3044 			// Process options for SYN packet.
       
  3045 			if (opt.Error())
       
  3046 				{
       
  3047 				// In case we receive invalid optons, we should just report an error and reset the connection.
       
  3048 				LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Invalid options, reset connection"), (TInt)this));
       
  3049 				if (seg.iHdr->ACK())
       
  3050 					SendReset(ack);
       
  3051 				else
       
  3052 					SendResetNoSync(seq+len+1);
       
  3053 				Error(KErrCouldNotConnect, MSocketNotify::EErrorConnect);
       
  3054 				EnterState(ETcpClosed);
       
  3055 				goto wrapup;
       
  3056 				}
       
  3057 
       
  3058 			if (opt.MSS() > 0)
       
  3059 				{
       
  3060 				if (opt.MSS() < STATIC_CAST(TInt, KTcpMinimumMSS))
       
  3061 					{
       
  3062 					LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Invalid MSS option"), (TInt)this));
       
  3063 					if (seg.iHdr->ACK())
       
  3064 						SendReset(ack);
       
  3065 					else
       
  3066 						SendResetNoSync(seq+len+1);
       
  3067 					goto discard;
       
  3068 					}
       
  3069 				iSMSS = opt.MSS();
       
  3070 				}
       
  3071 
       
  3072 			iFlags.iUseTimeStamps &= opt.TimeStamps();
       
  3073 			iFlags.iSackOk &= opt.SackOk();
       
  3074 
       
  3075 			if (opt.WindowScale())
       
  3076 				{
       
  3077 				iSndWscale = opt.WindowScale() - 1;
       
  3078 				iFreeWindow = iSockInBufSize % iRMSS;
       
  3079 				iRCV.WND = iSockInBufSize - iFreeWindow;
       
  3080 				}
       
  3081 			else
       
  3082 				{
       
  3083 				// iFreeWindow and iRCV.WND were confirmed to be less than 0xffff with SYN
       
  3084 				iRcvWscale = 0;
       
  3085 				iSockInBufSize = Min(iSockInBufSize, 0xffff);
       
  3086 				}
       
  3087 
       
  3088 			iRCV.NXT = seq+1;
       
  3089 
       
  3090 			// Our SYN was acked?
       
  3091 			if (seg.iHdr->ACK() && ack == iSND.NXT)
       
  3092 				{
       
  3093 				iSND.UNA = ack;
       
  3094 				iPartialSeq = ack;
       
  3095 
       
  3096 				TUint32 tsEcr;
       
  3097 				// Check that the timestamp echo has sane values
       
  3098 				if (iFlags.iUseTimeStamps && opt.TimeStamps(iTsRecent, tsEcr)
       
  3099 						&& tsEcr && usec > tsEcr && usec - tsEcr <= Protocol()->MaxRTO())
       
  3100 					UpdateRTO(usec - tsEcr);
       
  3101 				else if (iFlags.iTiming)
       
  3102 					UpdateRTO(usec - iTimeStamp);
       
  3103 				iFlags.iTiming = EFalse;
       
  3104 
       
  3105 				//
       
  3106 				// Initial window update as per RFC1122.
       
  3107 				//
       
  3108 				//LOG(Log::Printf(_L("CProviderTCP6::ProcessSegments(): Window update.\r\n")));
       
  3109 				iSND.WND = seg.iHdr->Window(); // no scaling in SYN
       
  3110 				iSND.WL1 = seq;
       
  3111 				iSND.WL2 = ack;
       
  3112 				iLastWnd = seg.iHdr->Window(); // no scaling in SYN
       
  3113 
       
  3114 				ResetCwnd(iSMSS);
       
  3115 				iSsthresh = KMaxTInt;
       
  3116 
       
  3117 				ClearSYNSettings();
       
  3118 
       
  3119 				// Peer denies ECN with SYN-ACK.
       
  3120 				if (!seg.iHdr->ECE())
       
  3121 					{
       
  3122 					iFlags.iEcn = EFalse;
       
  3123 					}
       
  3124 
       
  3125 				ReadDestinationCache();
       
  3126 
       
  3127 				// Open up the window for sender
       
  3128 				SendSegment(KTcpCtlACK);
       
  3129 				EnterState(ETcpEstablished);
       
  3130 				//__ASSERT_DEBUG(iSockFlags.iNotify, User::Panic(_L("notifier"),0));
       
  3131 				// Assert removed. There's a rare case when the stack is unloading. -MikaL
       
  3132 
       
  3133 				// if ECN negotiation was succesful, tell IP layer (iface.cpp) that ECT bit can be enabled.
       
  3134 				if (iFlags.iEcn)
       
  3135 					{
       
  3136 					SetEcn(Protocol()->Ecn());
       
  3137 					}
       
  3138 
       
  3139 				if (iSockFlags.iNotify)
       
  3140 					iSocket->ConnectComplete();
       
  3141 					
       
  3142 				// SYN uses one slot in sequence number space. Account for it before processing data.
       
  3143 				++seq;
       
  3144 					
       
  3145 				goto process_data;
       
  3146 				}
       
  3147 
       
  3148 			//
       
  3149 			// Simultaneous open, send SYN+ACK
       
  3150 			//
       
  3151 			--iSND.NXT;
       
  3152 
       
  3153 			// Peer denies ECN in SYN
       
  3154 			if (!seg.iHdr->ECE() || !seg.iHdr->CWR())
       
  3155 				{
       
  3156 				iFlags.iEcn = EFalse;
       
  3157 				}
       
  3158 
       
  3159 			TUint8 flags = KTcpCtlSYN|KTcpCtlACK;
       
  3160 			if (iFlags.iEcn)
       
  3161 				{
       
  3162 				flags |= KTcpCtlECE;
       
  3163 				}
       
  3164 			SendSegment(flags);
       
  3165 			EnterState(ETcpSynReceived);
       
  3166 			//
       
  3167 			// According to RFC793 we should queue any additional data
       
  3168 			// and controls (e.g. URG) for processing once the established
       
  3169 			// state has been reached.
       
  3170 			//
       
  3171 			// No current TCP implementations actually do this (aside from
       
  3172 			// T/TCP), because of its vulnerability to DoS attacks. In any
       
  3173 			// case, we're compatible with a peer that wants to send data with
       
  3174 			// the SYN packet, since the peer will retransmit the data after
       
  3175 			// we only ack the SYN.
       
  3176 			//
       
  3177 			goto accept;
       
  3178 			}
       
  3179 
       
  3180 		if (!InState(ETcpSynReceived|ETcpEstablished|ETcpFinWait1|ETcpFinWait2|
       
  3181 			ETcpCloseWait|ETcpClosing|ETcpLastAck|ETcpTimeWait))
       
  3182 			{
       
  3183 			if (InState(ETcpClosed))
       
  3184 				{
       
  3185 				// We have extra segments after entering CLOSED state. Send RST.
       
  3186 				if (seg.iHdr->ACK())
       
  3187 					SendReset(ack, info->iDstAddr, info->iSrcAddr);
       
  3188 				else
       
  3189 					SendResetNoSync(seq+len, info->iDstAddr, info->iSrcAddr);
       
  3190 				}
       
  3191  			goto wrapup;
       
  3192 			}
       
  3193 
       
  3194 /*
       
  3195       Four cases From RFC793 to test in order to determine whether
       
  3196       an arriving segment is acceptable:
       
  3197 
       
  3198       Segment Receive  Test
       
  3199       Length  Window
       
  3200       ------- -------  -------------------------------------------
       
  3201 	 0       0     SEG.SEQ = RCV.NXT
       
  3202 	 0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
       
  3203 	>0       0     not acceptable
       
  3204 	>0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
       
  3205 		    or RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND
       
  3206 
       
  3207       We transform these into two basic tests, both of which must evaluate
       
  3208       true in order to DISCARD a segment. The first test clears the majority
       
  3209       of segments that are correctly within receive window. The second test
       
  3210       clears special cases where receive window is zero or the incoming segment
       
  3211       is only partially within receive window.
       
  3212 
       
  3213       Note that we accept a segment that is straddling iRCV.NXT even if
       
  3214       the receive window is zero. In this case the segment is discarded
       
  3215       later during data segment processing.
       
  3216 		*/
       
  3217 
       
  3218 		// Eliminate earlier DSACK blocks. One duplicate segment can be reported only once.
       
  3219 		if (iFlags.iSackOk && Protocol()->DSack())
       
  3220 			iOptions.SackBlocks().Prune(iRCV.NXT);
       
  3221 
       
  3222 		if (InState(ETcpSynReceived))
       
  3223 			{
       
  3224 			// In case of simultanous connections TCP retransmits SYN with initial sequence
       
  3225 			// number when it gets incoming SYN in SYN_SENT state
       
  3226 			// (it acks received SYN+1 in that case).
       
  3227 			// Since RCV.NXT is increased after receiving the first SYN, the SYN retransmission
       
  3228 			// would appear as out-of-order segment, in which case it would be ignored and the TCP
       
  3229 			// session would never get to ESTABLISHED state.
       
  3230 			//
       
  3231 			// This adjustment is meant to avoid the above problem while causing minimal compromise
       
  3232 			// to TCP sequence number check safety.
       
  3233 			rcvNxt = iRCV.NXT - 1;
       
  3234 			}
       
  3235 
       
  3236 		//      if ((seq < iRCV.NXT || seq >= iRCV.NXT + iRCV.WND) &&                          // 1st test
       
  3237 		//	  ((iRCV.WND > 0) ? (seq + len <= iRCV.NXT) : (len > 0 || seq > iRCV.NXT)))  // 2nd test
       
  3238 		// PeLu: The above test passed case where seq > nxt+wnd
       
  3239 		if ((seq < rcvNxt || seq >= iRCV.NXT + iRCV.WND) &&                          // 1st test
       
  3240 			((iRCV.WND > 0) ? ((len > 0) ? (seq+len <= iRCV.NXT) || (seq+len > iRCV.NXT + iRCV.WND) : 1)
       
  3241 			: ((len > 0) ? 1 : (seq.Outside(rcvNxt, iRCV.NXT)))))
       
  3242 			{
       
  3243 			LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Segment out of window"), (TInt)this));
       
  3244 			if (!seg.iHdr->RST())
       
  3245 				{
       
  3246 				// if receiving data partially below RCV.NXT,
       
  3247 				// generate DSACK only for the duplicate portion
       
  3248 				if (iFlags.iSackOk && Protocol()->DSack() && seq < iRCV.NXT && len > 0)
       
  3249 					{
       
  3250 					if (seq + len <= iRCV.NXT)
       
  3251 						{
       
  3252 						iOptions.SackBlocks().AddUnordered(seq, seq + len);
       
  3253 						}
       
  3254 					else
       
  3255 						{
       
  3256 						iOptions.SackBlocks().AddUnordered(seq, iRCV.NXT);
       
  3257 						}
       
  3258 					iOptions.SackBlocks().Limit(4);
       
  3259 					}
       
  3260 				SendSegment(KTcpCtlACK);
       
  3261 				}
       
  3262 			if (InState(ETcpTimeWait|ETcpFinWait2))
       
  3263 				SchedMsl2Wait();
       
  3264 			// Accept RST segments that fit within the last advertised window.
       
  3265 			if (seg.iHdr->RST() && !seq.Outside(iLastAck, iLastAck + iRCV.WND))
       
  3266 				LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Lagged RST"), (TInt)this));
       
  3267 			else if (iRCV.WND > 0 || iRCV.NXT.Outside(seq, seq+len))
       
  3268 				goto discard;
       
  3269 			}
       
  3270 
       
  3271 		if (seg.iHdr->RST())
       
  3272 			{
       
  3273 			// Ignore RST in TIME-WAIT state to prevent TIME-WAIT assassination
       
  3274 			if (InState(ETcpTimeWait))
       
  3275 				goto discard;
       
  3276 
       
  3277 			// Stop processing and enter CLOSED state
       
  3278 			LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): RST packet"), (TInt)this));
       
  3279 			Error(KErrDisconnected);
       
  3280 			EnterState(ETcpClosed);
       
  3281 			goto wrapup;
       
  3282 			}
       
  3283 
       
  3284 		if (seg.iHdr->SYN() && seq >= iRCV.NXT)
       
  3285 			{
       
  3286 	  		/*  If the SYN is in the window it is an error, send a reset, any
       
  3287 	  		outstanding RECEIVEs and SEND should receive "reset" responses,
       
  3288  		 	all segment queues should be flushed, the user should also
       
  3289 			receive an unsolicited general "connection reset" signal, enter
       
  3290 			the CLOSED state, delete the TCB, and return.
       
  3291 				
       
  3292 			Note: the extra test against RCV.NXT is there to let through a SYN-ACK
       
  3293 			with the sequence number RCV.NXT-1. This may happen in a simultaneous
       
  3294 			connect case, where the SYN-ACK packet is retransmitted. The SYN-ACK
       
  3295 			will be hanled below as part of SYN-RECEIVED state processing.
       
  3296 
       
  3297 			Otherwise, if the SYN is not in the window this step would not be
       
  3298 			reached and an ack would have been sent in the first step (sequence
       
  3299 			number check).
       
  3300 			*/
       
  3301 			SendReset(iSND.NXT);
       
  3302 			Error(KErrDisconnected);
       
  3303 			EnterState(ETcpClosed);
       
  3304 			goto wrapup;
       
  3305 			}
       
  3306 
       
  3307 
       
  3308 		//
       
  3309 		//  ACK PROCESSING
       
  3310 		//
       
  3311 		if (!seg.iHdr->ACK())
       
  3312 			{
       
  3313 			LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): No ACK"), (TInt)this));
       
  3314 			goto discard;
       
  3315 			}
       
  3316 
       
  3317 		// Check options
       
  3318 		if (opt.Error())
       
  3319 			{
       
  3320 			LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Invalid options"), (TInt)this));
       
  3321 			SendReset(ack);
       
  3322 			goto discard;
       
  3323 			}
       
  3324 
       
  3325 		if (InState(ETcpSynReceived))
       
  3326 			if(ack.Inside(iSND.UNA, iSND.NXT))
       
  3327 			{
       
  3328 			EnterState(ETcpEstablished);
       
  3329 
       
  3330 			const TInt ifup = iFlags.iKeepInterfaceUp;
       
  3331 			SetOption(KSolInetIp, KSoKeepInterfaceUp, TPtr8((TUint8*)&ifup, sizeof(TInt), sizeof(TInt)));
       
  3332 
       
  3333 			// if ECN negotiation was succesful, tell IP layer that ECT bit can be enabled.
       
  3334 			if (iFlags.iEcn)
       
  3335 				{
       
  3336 				SetEcn(Protocol()->Ecn());
       
  3337 				}
       
  3338 
       
  3339 			//
       
  3340 			// Initial window update as per RFC1122.
       
  3341 			//
       
  3342 			//LOG(Log::Printf(_L("CProviderTCP6::ProcessSegments(): Window update.\r\n")));
       
  3343 			iSND.WND = seg.iHdr->Window() << iSndWscale;
       
  3344 			iSND.WL1 = seq;
       
  3345 			iSND.WL2 = ack;
       
  3346 			iLastWnd = seg.iHdr->Window() << iSndWscale;
       
  3347 
       
  3348 			ResetCwnd(iSMSS);
       
  3349 			iCwnd -= iSMSS;   // Compensate for cwnd increase below during ack processing
       
  3350 			iSsthresh = KMaxTInt;
       
  3351 
       
  3352 			ClearSYNSettings();
       
  3353 
       
  3354 			ReadDestinationCache();
       
  3355 
       
  3356 			// The following causes the socket server to (eventually) call Start()
       
  3357 			if (iParent)
       
  3358 				{
       
  3359 				iSockFlags.iAttached = ETrue;
       
  3360 				ASSERT(iParent->iSockFlags.iNotify);
       
  3361 				if (iParent->CompleteChildConnect(this) == KErrAbort)
       
  3362 					{
       
  3363 					LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): SAP Deleted, abort ProcessSegments()"), (TInt)this));
       
  3364 					// Object in use was deleted. Just free the packet and return.
       
  3365 					packet.Free();
       
  3366 					return;
       
  3367 					}
       
  3368 				}
       
  3369 			else
       
  3370 				{
       
  3371 				//__ASSERT_DEBUG(iSockFlags.iNotify, User::Panic(_L("notifier"), 0));
       
  3372 				// Assert removed. There's a rare case when the stack is unloading. -MikaL
       
  3373 				if (iSockFlags.iNotify)
       
  3374 					iSocket->ConnectComplete();
       
  3375 				}
       
  3376 			}
       
  3377 		else
       
  3378 			{
       
  3379 			LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Bad SYN-ACK"), (TInt)this));
       
  3380 			SendReset(ack);
       
  3381 			goto discard;
       
  3382 			}
       
  3383 
       
  3384 		//
       
  3385 		// Check ack sequence for all remaining states
       
  3386 		//
       
  3387 		if(ack > iSND.NXT)
       
  3388 			{
       
  3389 			LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): ACK above window"), (TInt)this));
       
  3390 			SendSegment(KTcpCtlACK);
       
  3391 			goto discard;
       
  3392 			}
       
  3393 
       
  3394 		// A good packet arrived and the connection is idle, reset the keep-alives state
       
  3395 		if (CanFireKeepAlives())
       
  3396 			ResetKeepAlives();
       
  3397 
       
  3398 		// Check for ECN congestion established bit.
       
  3399 		if (info->iVersion == 4)
       
  3400 			{
       
  3401 			if (iFlags.iEcn && ip->ip4.EcnIsCongestion())
       
  3402 				{
       
  3403 				iFlags.iEcnHaveCongestion = ETrue;
       
  3404 				LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Have ECN CE bit in IPv4 packet"), (TInt)this));
       
  3405 				}
       
  3406 			}
       
  3407 		else
       
  3408 			{
       
  3409 			if (iFlags.iEcn && ip->ip6.EcnIsCongestion())
       
  3410 				{
       
  3411 				iFlags.iEcnHaveCongestion = ETrue;
       
  3412 				LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Have ECN CE bit in IPv6 packet"), (TInt)this));
       
  3413 				}
       
  3414 			}
       
  3415 		
       
  3416 		if (InState(ETcpEstablished|ETcpFinWait1|ETcpFinWait2|ETcpCloseWait|ETcpClosing|ETcpLastAck))
       
  3417 			{
       
  3418 			TInt acked = ack - iSND.UNA;
       
  3419 
       
  3420 			if (acked >= 0)
       
  3421 				{
       
  3422 				// ECN CWR means that receiver has noticed our Congestion Echo. No more congestion.
       
  3423 				if (seg.iHdr->CWR())
       
  3424 					{
       
  3425 					iFlags.iEcnHaveCongestion = EFalse;
       
  3426 					}
       
  3427 
       
  3428 				if (iFlags.iUseTimeStamps)
       
  3429 					{
       
  3430 					TUint32 tsVal, tsEcr;
       
  3431 					// Check that tsEcr has sane values
       
  3432 					if (opt.TimeStamps(tsVal, tsEcr) && tsEcr && usec - tsEcr <= KTcpMaxRTO)
       
  3433 						{
       
  3434 						if (acked > 0)
       
  3435 							{
       
  3436 							UpdateRTO(usec - tsEcr);
       
  3437 
       
  3438 							// Got one RTT with timestamps. Don't take another.
       
  3439 							if (iFlags.iTiming && ack >= iTimingSeq)
       
  3440 								iFlags.iTiming = EFalse;
       
  3441 
       
  3442 							//
       
  3443 							// Delay spike detection. If the echoed timestamp predates
       
  3444 							// our last retransmission timeout we abort the retransmission
       
  3445 							// sequence. However, we do not inflate the congestion window
       
  3446 							// for two reasons: 1) a long delay might also be a sign of
       
  3447 							// congestion, and 2) this feature could potentially be used
       
  3448 							// by a hostile peer to artificially inflate our congestion
       
  3449 							// window.
       
  3450 							//
       
  3451 							// PS: Delay spike detection with timestamps is not in use with F-RTO
       
  3452 							if (!Protocol()->FRTO() && tsEcr < iLastTimeout &&
       
  3453 								!opt.SackBlocks().Count())
       
  3454 								{
       
  3455 								iTransmitSeq = iSND.NXT;
       
  3456 								SpuriousTimeout(acked);
       
  3457 								}
       
  3458 							}
       
  3459 
       
  3460 						//
       
  3461 						// The condition in RFC1323 is buggy(?):
       
  3462 						//
       
  3463 						//    SEG.SEQ <= Last.ACK.sent < SEG.SEQ + SEG.LEN
       
  3464 						//
       
  3465 						// The best current practise is the following, because it updates
       
  3466 						// TSrecent also on pure ACKs:
       
  3467 						//
       
  3468 						//    SEG.TSval >= TSrecent and SEG.SEQ <= Last.ACK.sent
       
  3469 						//
       
  3470 						if (tsVal > iTsRecent && seq <= iLastAck)
       
  3471 							iTsRecent = tsVal;
       
  3472 						}
       
  3473 					}
       
  3474 				if (iFlags.iTiming && ack >= iTimingSeq)
       
  3475 					{
       
  3476 					UpdateRTO(usec - iTimeStamp);
       
  3477 					iFlags.iTiming = EFalse;
       
  3478 					}
       
  3479 
       
  3480 				// SACK book keeping
       
  3481 				if (iFlags.iSackOk)
       
  3482 					{
       
  3483 					// Remove acknowledged blocks
       
  3484 					if (opt.SackBlocks().Count())
       
  3485 						{
       
  3486 						SequenceBlockQueueIter iter(opt.SackBlocks());
       
  3487 						SequenceBlock *block;
       
  3488 						while (block = iter++, block != NULL)
       
  3489 							{
       
  3490 							//
       
  3491 							// Record SACK block but do some sanity checking first.
       
  3492 							//
       
  3493 							if (ack < block->iLeft && block->iLeft < block->iRight
       
  3494 								&& block->iRight <= iSND.NXT)
       
  3495 								{
       
  3496 								iSacked.AddOrdered(block);
       
  3497 								}
       
  3498 							}
       
  3499 
       
  3500 						// Take RTT estimate using SACK info
       
  3501 						if (iFlags.iTiming && iSacked.Count() && iSacked.Last()->iRight >= iTimingSeq)
       
  3502 							{
       
  3503 							UpdateRTO(usec - iTimeStamp);
       
  3504 							iFlags.iTiming = EFalse;
       
  3505 							}
       
  3506 						}
       
  3507 					iSacked.Prune(ack);
       
  3508 
       
  3509 					// Update iRetranData
       
  3510 					if (iSacked.Count() && ack < iSendHigh)
       
  3511 						{
       
  3512 						iRetranData = iSendHigh - ack;
       
  3513 						SequenceBlockQueueIter iter(opt.SackBlocks());
       
  3514 						SequenceBlock *block;
       
  3515 						while (block = iter++, block != NULL && block->iLeft < iSendHigh)
       
  3516 							{
       
  3517 							if (block->iRight < iSendHigh)
       
  3518 								iRetranData -= (block->iRight - block->iLeft);
       
  3519 							else
       
  3520 								iRetranData -= (iSendHigh - block->iLeft);
       
  3521 							}
       
  3522 						}
       
  3523 					else
       
  3524 						iRetranData = 0;
       
  3525 
       
  3526 					LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): acked=%d iRetranData = %d"),
       
  3527 						(TInt)this, acked, iRetranData));
       
  3528 					}
       
  3529 
       
  3530 				// Did they acknowledge any new data?
       
  3531 				if (acked > 0)
       
  3532 					{
       
  3533 					// Reset retransmit backoff
       
  3534 					if (iBackoff && iSND.WND > 0)
       
  3535 						{
       
  3536 						LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Some data ACKed, clearing Backoff"), (TInt)this));
       
  3537 						iBackoff = 0;
       
  3538 						}
       
  3539 
       
  3540 					// Trim send queue
       
  3541 					iSND.UNA = ack;
       
  3542 					if ((TInt)iSockOutQLen > acked) // Avoid barfing on acked SYN or FIN packet
       
  3543 						{
       
  3544 						iSockOutQ.TrimStart(acked);
       
  3545 						iSockOutQLen -= acked;
       
  3546 						}
       
  3547 					else
       
  3548 						{
       
  3549 						iSockOutQ.Free();
       
  3550 						iSockOutQLen = 0;
       
  3551 						CompleteIoctl(KErrNone);
       
  3552 						}
       
  3553 
       
  3554 					// Tag along
       
  3555 					if (iSND.UP < ack)
       
  3556 						iSND.UP = ack - 1;
       
  3557 
       
  3558 					// Tag along
       
  3559 					if (iPartialSeq < ack)
       
  3560 						iPartialSeq = ack;
       
  3561 
       
  3562 					// Tag along
       
  3563 					if (iSendHigh < ack)
       
  3564 						iSendHigh = ack - 1;
       
  3565 
       
  3566 					if (iFlags.iFastRetransMode)
       
  3567 						{
       
  3568 						if (iFlags.iSackOk ? !iSacked.Count() : ack >= iRecoverSeq)
       
  3569 							{
       
  3570 							LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Leaving FAST RETRANS mode"), (TInt)this));
       
  3571 							iFlags.iFastRetransMode = EFalse;
       
  3572 							iDupAcks = 0;
       
  3573 							// Deflate congestion window
       
  3574 							iCwnd = Min(iSsthresh, iSND.NXT - iSND.UNA + iSMSS);
       
  3575 							}
       
  3576 						else if (!iFlags.iSackOk)
       
  3577 							{
       
  3578 							// NewReno partial ACK processing.
       
  3579 
       
  3580 			  /* From RFC2582:
       
  3581 			   If this ACK does *not* acknowledge all of the data up to and
       
  3582 			   including "recover", then this is a partial ACK.  In this case,
       
  3583 			   retransmit the first unacknowledged segment.  Deflate the
       
  3584 			   congestion window by the amount of new data acknowledged, then
       
  3585 			   add back one MSS and send a new segment if permitted by the new
       
  3586 			   value of cwnd.  This "partial window deflation" attempts to
       
  3587 			   ensure that, when Fast Recovery eventually ends, approximately
       
  3588 			   ssthresh amount of data will be outstanding in the network.  Do
       
  3589 			   not exit the Fast Recovery procedure (i.e., if any duplicate ACKs
       
  3590 			   subsequently arrive, execute Steps 3 and 4 above).
       
  3591 
       
  3592 			   For the first partial ACK that arrives during Fast Recovery, also
       
  3593 			   reset the retransmit timer.
       
  3594 							*/
       
  3595 
       
  3596 							iCwnd -= acked;
       
  3597 							iCwnd += iSMSS;
       
  3598 							LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): FAST RETRANSMIT on PARTIAL ACK"), (TInt)this));
       
  3599 							SendDataSegment(ack);
       
  3600 
       
  3601 							//
       
  3602 							// Socket write makes use of the duplicate ack count to
       
  3603 							// temporarily extend the send buffer during fast recovery.
       
  3604 							// We deflate the buffer here.
       
  3605 							//
       
  3606 							ASSERT(iSMSS);
       
  3607 							iDupAcks = Max(iDupAcks - acked / (TInt)iSMSS, 0);
       
  3608 							}
       
  3609 						}
       
  3610 
       
  3611 					// Reset limited transmit window
       
  3612 					iLwnd = 0;
       
  3613 
       
  3614 					// Everything acked?
       
  3615 					if (ack == iSND.NXT)
       
  3616 						{
       
  3617 						iTransmitSeq = iSND.NXT;
       
  3618 						}
       
  3619 					else
       
  3620 						{
       
  3621 						// Restart retransmission timeout
       
  3622 						ReSchedRetransmit();
       
  3623 						}
       
  3624 
       
  3625 					//
       
  3626 					// Adjust congestion window.
       
  3627 					//
       
  3628 					TUint incr = iSMSS;
       
  3629 
       
  3630 					if (iCwnd < iSsthresh)
       
  3631 						iCwnd += incr;			    // Slow-start
       
  3632 					else
       
  3633 						iCwnd += Max(incr * incr / iCwnd, 1); // Congestion avoidance
       
  3634 					}
       
  3635 
       
  3636 				else if (ack < iSND.NXT)
       
  3637 
       
  3638 					{
       
  3639 					//
       
  3640 					// Fast retransmit algorithm.
       
  3641 					//
       
  3642 					// Note! We only reset the duplicate ack count if the received
       
  3643 					// segment acknowledges some new data or if a timeout has
       
  3644 					// occurred. However, we simply ignore window updates and piggy-back
       
  3645 					// acknowledgements unless they also acknowledge new data. Other
       
  3646 					// duplicate acknowledgements increase the duplicate ack count and
       
  3647 					// may trigger a fast retransmission.
       
  3648 					//
       
  3649 					if (len == 0 && (seg.iHdr->Window() << iSndWscale) == iLastWnd)
       
  3650 						{
       
  3651 						if (iFlags.iSackOk)
       
  3652 							{
       
  3653 							TTcpSeqNum fack = iSacked.Count() ? iSacked.Last()->iRight : iSND.UNA;
       
  3654 
       
  3655 							// Acks caused by out-of-window segments don't count
       
  3656 							if (opt.SackBlocks().Count() && opt.SackBlocks().First()->iRight > iSND.UNA)
       
  3657 								iDupAcks++;
       
  3658 
       
  3659 							 //Removed the conditional checking ack > iSendHigh as it is only being used for if SACK option is not set.
       
  3660 							 // Set the retransmission mode as the fast retransmit if the three TCP duplicate ACKs are received from the server and
       
  3661                              //send the lost segment(s) to the server.
       
  3662 							if (
       
  3663 								(iDupAcks >= Protocol()->Reordering() ||
       
  3664 								fack > iSND.UNA + Protocol()->Reordering() * iRMSS))
       
  3665 								{
       
  3666 								LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): SACK RETRANSMIT!"), (TInt)this));
       
  3667 								iFlags.iFastRetransMode = ETrue;
       
  3668 								iSsthresh = Max((iSND.NXT - iSND.UNA) / 2, 2 * iSMSS);
       
  3669 								iCwnd = iSsthresh;
       
  3670 								iSendHigh = ack;
       
  3671 								ReSchedRetransmit();    // Restart retransmission timeout
       
  3672 								iTransmitSeq = iSendHigh; // Rewind transmitter for SACK retransmit
       
  3673 								SendSegments(ETrue);
       
  3674 	                            iDupAcks = 0;
       
  3675 
       
  3676 								}
       
  3677 							}
       
  3678 						else
       
  3679 							{
       
  3680 							if (ack > iSendHigh)        // Never retransmitted?
       
  3681 								iDupAcks++;
       
  3682 							if (iFlags.iFastRetransMode)
       
  3683 								{
       
  3684 								iCwnd += iSMSS;         // Inflate congestion window
       
  3685 								}
       
  3686 							else if (iDupAcks == Protocol()->Reordering())
       
  3687 								{
       
  3688 								LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): FAST RETRANSMIT!"), (TInt)this));
       
  3689 								iFlags.iFastRetransMode = ETrue;
       
  3690 								iSsthresh = Max((iSND.NXT - iSND.UNA) / 2, 2 * iSMSS);
       
  3691 								iCwnd = iSsthresh + 3 * iSMSS;
       
  3692 								iRecoverSeq = iSND.NXT;
       
  3693 								iLwnd = 0;                    // Reset limited transmit window
       
  3694 								ReSchedRetransmit();	    // Restart retransmission timeout
       
  3695 								SendDataSegment(ack);         // Retransmit a single segment
       
  3696 								}
       
  3697 							}
       
  3698 						if (!iFlags.iFastRetransMode)
       
  3699 							{
       
  3700 							//
       
  3701 							// Increment limited transmit window
       
  3702 							//
       
  3703 							if (iSND.UNA + iCwnd >= iSND.NXT)  // FIXME. Prevent lwnd increase during RTO
       
  3704 								iLwnd = Min(iLwnd + iSMSS, iSMSS * Protocol()->LtxWindow());
       
  3705 							ReSchedRetransmit();
       
  3706 							}
       
  3707 						}
       
  3708 
       
  3709 					}
       
  3710 				else
       
  3711 					iDupAcks = 0;
       
  3712 
       
  3713 				// F-RTO stuff. If we enter here, RTO has just occurred, and e.g. iDupAcks should be 0
       
  3714 				if (iFRTOsent)
       
  3715 					{
       
  3716 					LOG(Log::Printf(_L("\ttcp SAP[%u] F-RTO: iFRTOsent=%d   acked=%d   ack-sndhigh=%d"),
       
  3717 						(TInt)this, iFRTOsent, acked, (ack - iSendHigh)));
       
  3718 
       
  3719 					// The ack following the RTO did not advance window, or we cannot transmit new
       
  3720 					// unsent data => conventional recovery
       
  3721 					//
       
  3722 					// The last term of the condition below is due to special case:
       
  3723 					// If the first ack after RTO covers all outstanding data, the RTO was due
       
  3724 					// to lost retransmit and fixed the whole outstanding window).
       
  3725 					if (!acked || !CanForwardTransmit() || (ack >= iRealSendHigh && iFRTOsent == 1))
       
  3726 						{
       
  3727 
       
  3728 						LOG(Log::Printf(_L("\ttcp SAP[%u] F-RTO: Doing go-back-N"), (TInt)this));
       
  3729 						iTransmitSeq = iSND.UNA;
       
  3730 						if (iFRTOsent == 1 && !acked)
       
  3731 							{
       
  3732 							// dupack arrives before RTO retransmission is acknowledged.
       
  3733 							// don't retransmit the same segment again.
       
  3734 							iTransmitSeq += EffectiveMSS();
       
  3735 							}
       
  3736 						iCwnd = EffectiveMSS() * iFRTOsent; // number of RTTs after RTO
       
  3737 						iFRTOsent = 0;
       
  3738 						}
       
  3739 					else
       
  3740 						{
       
  3741 						// Force 2 segments out on first ack after RTO. For that purpose we have to
       
  3742 						// estimate the current flightsize (-> iCwnd) and set iLwnd to 2.
       
  3743 						// Note that after this step iCwnd is set either to 2*MSS or iSsthresh, so
       
  3744 						// the setup below is very temporary.
       
  3745 						if (iFRTOsent == 1)  // first new ACK after RTO
       
  3746 							{
       
  3747 							iCwnd = iSND.NXT - iSND.UNA - iSacked.ByteCount() + 2 * iSMSS;
       
  3748 							}
       
  3749 						else if (iFRTOsent == 2)
       
  3750 							{
       
  3751 							// Spurious RTO.
       
  3752 							// second new ACK after RTO, continue in earlier state because the second
       
  3753 							// ACK was delayed and the RTO was likely spurious.
       
  3754 							SpuriousTimeout(acked);
       
  3755 							}
       
  3756 						// coverity[write_write_order]
       
  3757 						iFRTOsent = (++iFRTOsent) % 3;
       
  3758 						}
       
  3759 					}
       
  3760 
       
  3761 				iLastWnd = seg.iHdr->Window() << iSndWscale;
       
  3762 
       
  3763 				if (iSND.WL1 < seq || (iSND.WL1 == seq && iSND.WL2 <= ack))
       
  3764 					{
       
  3765 					iSND.WND = seg.iHdr->Window() << iSndWscale;
       
  3766 					iSND.WL1 = seq;
       
  3767 					iSND.WL2 = ack;
       
  3768 					//LOG(Log::Printf(_L("CProviderTCP6::ProcessSegments(): Window update: %d.\r\n"), iSND.WND));
       
  3769 					}
       
  3770 
       
  3771 				// if we are not yet in recovery, reduce congestion window on ECN CE Echo.
       
  3772 				if (iFlags.iEcn && seg.iHdr->ECE())
       
  3773 					{
       
  3774 					LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Got ECN echo"), (TInt)this));
       
  3775 
       
  3776 					// SourceQuench returns False, if congestion window was reduced for some other
       
  3777 					// reason in the last RTT. However, if it was reduced due to FR
       
  3778 					// (i.e. last QuenchSeq was more than one RTT ago), we better send CWR to suppress
       
  3779 					// ECE flags at the other end.
       
  3780 					if (SourceQuench() || iQuenchSeq.Outside(iSND.NXT, iSND.NXT + iSND.WND))
       
  3781 						{
       
  3782 						iFlags.iEcnSendCWR = ETrue;
       
  3783 						}
       
  3784 					}
       
  3785 				if((iSND.NXT - ack) >0 && InState(ETcpEstablished) && (acked ==0))
       
  3786 					{
       
  3787 					iRetryAck++;
       
  3788 					if(iRetryAck >=4) // 4 an arbitary number; as this count does not refer to dup_ack, this will not interfere with Fast retransmission
       
  3789 						{
       
  3790 						LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): retransmitting the segment"), (TInt)this));
       
  3791 						SendSegments(ETrue);
       
  3792 						iRetryAck = 0; // reset the retry count
       
  3793 						}
       
  3794 					}
       
  3795 					
       
  3796 				}
       
  3797 			}
       
  3798 
       
  3799 		//
       
  3800 		// Everything acked? Check if we need to do a state transition.
       
  3801 		//
       
  3802 		if (ack == iSND.NXT)
       
  3803 			{
       
  3804 			if (InState(ETcpFinWait1))
       
  3805 				{
       
  3806 				EnterState(ETcpFinWait2);
       
  3807 
       
  3808 				//
       
  3809 				// If the peer does not send a FIN for some reason,
       
  3810 				// we might hang in FIN-WAIT-2 indefinitely. We use
       
  3811 				// a 2*MSL timeout to break out of FIN-WAIT-2.
       
  3812 				//
       
  3813 				// Note that we can only do this if the application
       
  3814 				// has closed both directions of the connection.
       
  3815 				// However, this should take care of cleanup in the
       
  3816 				// the most common case where a server socket hangs
       
  3817 				// in FIN-WAIT-2, because the client has crashed or
       
  3818 				// disappeared before sending a FIN-ACK.
       
  3819 				//
       
  3820 				if (iSockFlags.iRecvClose)
       
  3821 					{
       
  3822 					LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Setting FIN-WAIT-2 timeout"), (TInt)this));
       
  3823 					SchedMsl2Wait();
       
  3824 					}
       
  3825 				}
       
  3826 
       
  3827 			//
       
  3828 			// If we have a lingering Close() or Shutdown(ENormal), complete it with KErrNone.
       
  3829 			//
       
  3830 			if (iLinger > 0 && InState(ETcpFinWait2|ETcpClosing|ETcpLastAck))
       
  3831 				{
       
  3832 				/*
       
  3833 				In addition to the processing for the ESTABLISHED state, if
       
  3834 				the retransmission queue is empty, the user's CLOSE can be
       
  3835 				acknowledged ("ok") but do not delete the TCB.*/
       
  3836 				iLinger = -1;
       
  3837 				iLingerTimer->Cancel();
       
  3838 				Detach();
       
  3839 				}
       
  3840 
       
  3841 			if (InState(ETcpClosing))
       
  3842 				{
       
  3843 				EnterState(ETcpTimeWait);
       
  3844 				}
       
  3845 
       
  3846 			if (InState(ETcpLastAck))
       
  3847 				{
       
  3848 				if (!Protocol()->LocalTimeWait())
       
  3849 					{
       
  3850 					//
       
  3851 					// Local resource optimization. If the peer is on localhost,
       
  3852 					// we will terminate it here. Normally, it would wait for
       
  3853 					// a duration of 2*MSL in TIME-WAIT state before deleting
       
  3854 					// itself.
       
  3855 					//
       
  3856 					CFlowContext *flow = iFlow.FlowContext();
       
  3857 #ifndef SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
       
  3858 					CProviderTCP6 *sap =
       
  3859 						(CProviderTCP6*)Protocol()->LocateSap(EMatchConnection,
       
  3860 						KAFUnspec,
       
  3861 						flow->RemoteAddr(),
       
  3862 						flow->LocalAddr());
       
  3863 #else
       
  3864 					CProviderTCP6 *sap =
       
  3865 						(CProviderTCP6*)Protocol()->LocateSap(EMatchConnection,
       
  3866 						KAFUnspec,
       
  3867 						flow->RemoteAddr(),
       
  3868 						flow->LocalAddr(),
       
  3869 						NULL, info->iInterfaceIndex);
       
  3870 #endif //SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
       
  3871 					if (sap != NULL && sap->InState(ETcpTimeWait))
       
  3872 						{
       
  3873 						LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Deleting local peer"), (TInt)this));
       
  3874 						sap->Expire();
       
  3875 						}
       
  3876 					}
       
  3877 				/*
       
  3878 				The only thing that can arrive in this state is an
       
  3879 				acknowledgment of our FIN.  If our FIN is now acknowledged,
       
  3880 				delete the TCB, enter the CLOSED state, and return.*/
       
  3881 				EnterState(ETcpClosed);
       
  3882 				goto wrapup;
       
  3883 				}
       
  3884 			}
       
  3885 
       
  3886 		if (InState(ETcpTimeWait))
       
  3887 			{
       
  3888 	  /*
       
  3889           The only thing that can arrive in this state is a
       
  3890           retransmission of the remote FIN.  Acknowledge it, and restart
       
  3891 			the 2 MSL timeout.*/
       
  3892 			//
       
  3893 			// RFC793 appears to be wrong here. A retransmitted FIN should
       
  3894 			// already have been acknowledged as an out-of-sequence packet.
       
  3895 			// Also, a simultaneous close can cause both end points to send
       
  3896 			// an ack and enter the TIME-WAIT state at the same time. In this
       
  3897 			// rare case, the following line will cause an ack storm, where
       
  3898 			// each side is acknowledging ack packets from the other side.
       
  3899 			//
       
  3900 			//SendSegment(KTcpCtlACK);
       
  3901 			SchedMsl2Wait();
       
  3902 			}
       
  3903 
       
  3904 	process_data:
       
  3905 
       
  3906 		//
       
  3907 		//  DATA SEGMENT PROCESSING
       
  3908 		//
       
  3909 		if (InState(ETcpEstablished|ETcpFinWait1|ETcpFinWait2))
       
  3910 			{
       
  3911 			if (seg.iHdr->URG())
       
  3912 				{
       
  3913 				TTcpSeqNum up = seq + seg.iHdr->Urgent();
       
  3914 				/*
       
  3915 				If the URG bit is set, RCV.UP <- max(RCV.UP,SEG.UP), and signal
       
  3916 				the user that the remote side has urgent data if the urgent
       
  3917 				pointer (RCV.UP) is in advance of the data consumed.  If the
       
  3918 				user has already been signaled (or is still in the "urgent
       
  3919 				mode") for this continuous sequence of urgent data, do not
       
  3920 				signal the user again.*/
       
  3921 				if (up > seq)
       
  3922 					RememberUrgentPointer(up);
       
  3923 				}
       
  3924 
       
  3925 			//
       
  3926 			//  Process data segments.
       
  3927 			//
       
  3928 			if (len > 0)
       
  3929 				{
       
  3930 				if (iSockFlags.iRecvClose)
       
  3931 					{
       
  3932 					// Receive direction has been shut down. Send RST.
       
  3933 					SendReset(ack);
       
  3934 					}
       
  3935 				else
       
  3936 					{
       
  3937 					//
       
  3938 					// Zero window? We will already have sent and ACK in response,
       
  3939 					// so we can just discard the segment.
       
  3940 					//
       
  3941 					if (!iRCV.WND)
       
  3942 						goto accept;
       
  3943 
       
  3944 					TInt maxLen = iRCV.NXT + iRCV.WND - seq;
       
  3945 					if (len > maxLen)
       
  3946 						{
       
  3947 						//
       
  3948 						// Part of segment is above window -> truncate. This
       
  3949 						// can happen when peer is probing a zero window.
       
  3950 						//
       
  3951 						LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Above window payload: %u"), (TInt)this, len - maxLen));
       
  3952 						if (maxLen <= 0)  // Sanity check
       
  3953 							goto accept;
       
  3954 
       
  3955 						len = maxLen;
       
  3956 						packet.TrimEnd(seg.iHdr->HeaderLength() + info->iOffset + len);
       
  3957 						fin = 0;    // Cannot process FIN yet.
       
  3958 						}
       
  3959 
       
  3960 					// Remember to ack a pushed segment immediately
       
  3961 					if (seg.iHdr->PSH() && Protocol()->PushAck())
       
  3962 						immediateAck = ETrue;
       
  3963 
       
  3964 					if (seq <= iRCV.NXT)
       
  3965 						{
       
  3966 						//
       
  3967 						// WARNING! This will destroy the segment header!
       
  3968 						//
       
  3969 						LOG(if(seq<iRCV.NXT)Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Below window payload: %d"), (TInt)this, iRCV.NXT - seq));
       
  3970 
       
  3971 						// Remove segment header and below-window payload.
       
  3972 						packet.TrimStart(iRCV.NXT - seq + seg.iHdr->HeaderLength() + info->iOffset);
       
  3973 
       
  3974 						// Put in receive queue.
       
  3975 						iSockInQ.Append(packet);
       
  3976 						len -= (iRCV.NXT - seq);
       
  3977 						iSockInQLen += len;
       
  3978 						iNewData += len;
       
  3979 						iRCV.NXT += len;
       
  3980 						iRCV.WND -= len;
       
  3981 
       
  3982 						//
       
  3983 						// Check if we can take something out of the reassembly queue.
       
  3984 						//
       
  3985 						TTcpSeqNum fragOff;
       
  3986 						TBool fastAck = !iFragQ.IsEmpty();
       
  3987 						while (!iFragQ.IsEmpty())
       
  3988 							{
       
  3989 							fragOff = iFragQ.First().Offset();
       
  3990 							if (fragOff > iRCV.NXT)
       
  3991 								break;
       
  3992 
       
  3993 							RMBufTcpFrag frag;
       
  3994 							iFragQ.Remove(frag);
       
  3995 							TUint32 fragLen = frag.FragmentLength();
       
  3996 
       
  3997 							// Already got this?
       
  3998 							if (fragOff + fragLen <= iRCV.NXT)
       
  3999 								{
       
  4000 								frag.Free();
       
  4001 								continue;
       
  4002 								}
       
  4003 
       
  4004 							// Ok. Trim it and put it in receive queue.
       
  4005 							TTcpPacket seg(frag);
       
  4006 
       
  4007 							frag.TrimStart(seg.iHdr->HeaderLength() + (iRCV.NXT - fragOff));
       
  4008 							fragLen -= (iRCV.NXT - fragOff);
       
  4009 
       
  4010 							ASSERT(fragLen == (TUint)frag.Length());
       
  4011 
       
  4012 							iSockInQ.Append(frag);
       
  4013 							iSockInQLen += fragLen;
       
  4014 							iNewData += fragLen;
       
  4015 
       
  4016 							ASSERT((TUint)iSockInQLen >= iNewData);
       
  4017 
       
  4018 							LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Took %d:%d(%d) from reassembly queue"),
       
  4019 								(TInt)this, iRCV.NXT.Uint32(), (iRCV.NXT + fragLen).Uint32(), fragLen));
       
  4020 
       
  4021 							iRCV.NXT += fragLen;
       
  4022 							iRCV.WND -= fragLen;
       
  4023 
       
  4024 							}
       
  4025 						//
       
  4026 						// Update SACK book keeping
       
  4027 						//
       
  4028 						if (iFlags.iSackOk)
       
  4029 							iOptions.SackBlocks().Prune(iRCV.NXT);
       
  4030 
       
  4031 						/*
       
  4032                       	To provide feedback to senders recovering from losses, the receiver
       
  4033                       	SHOULD send an immediate ACK when it receives a data segment that
       
  4034 						fills in all or part of a gap in the sequence space. */
       
  4035 						if (fastAck)
       
  4036 							SendSegment(KTcpCtlACK);
       
  4037 						}
       
  4038 					else
       
  4039 						{
       
  4040 						LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Processing out-of-order segment!"), (TInt)this));
       
  4041 						TTcpSeqNum blockSeq;
       
  4042 						TUint32 blockLen;
       
  4043 
       
  4044 						// Fragment queue assumes packet starts from TCP header
       
  4045 						packet.TrimStart(info->iOffset);
       
  4046 
       
  4047 						//packet.FreeInfo(); --  Leave the info. We need it below.
       
  4048 						RMBufTcpFrag frag;
       
  4049 						frag.Assign(packet);
       
  4050 						iFragQ.Add(frag, (TUint32*)&blockSeq, &blockLen);
       
  4051 						if (iFlags.iSackOk)
       
  4052 							{
       
  4053 							iOptions.SackBlocks().AddUnordered(blockSeq, blockSeq + blockLen);
       
  4054 							iOptions.SackBlocks().Limit(4);
       
  4055 							}
       
  4056 
       
  4057                       /*
       
  4058                       Out-of-order data segments SHOULD be acknowledged immediately, in
       
  4059                       order to accelerate loss recovery.  To trigger the fast retransmit
       
  4060                       algorithm, the receiver SHOULD send an immediate duplicate ACK when
       
  4061 						it receives a data segment above a gap in the sequence space. */
       
  4062 						SendSegment(KTcpCtlACK);
       
  4063 						}
       
  4064 					}
       
  4065 				}
       
  4066 			}
       
  4067 
       
  4068 
       
  4069 		//
       
  4070 		//  FIN PROCESSING
       
  4071 		//
       
  4072 
       
  4073 /*
       
  4074       If the FIN bit is set, signal the user "connection closing" and
       
  4075       return any pending RECEIVEs with same message, advance RCV.NXT
       
  4076       over the FIN, and send an acknowledgment for the FIN.  Note that
       
  4077       FIN implies PUSH for any segment text not yet delivered to the
       
  4078       user.
       
  4079 		*/
       
  4080 		//
       
  4081 		// Remember that we have received a FIN. Note: the FIN may have
       
  4082 		// been received as part of an out-of-sequence segment, in which
       
  4083 		// case we may not be ready to process it yet.
       
  4084 		//
       
  4085 		if (fin && !iFlags.iFinReceived)
       
  4086 			{
       
  4087 			iFlags.iFinReceived = ETrue;
       
  4088 			iFinSeq = seq + len;
       
  4089 			}
       
  4090 
       
  4091 		//
       
  4092 		// Process FIN when all data has been received.
       
  4093 		//
       
  4094 		if (iFlags.iFinReceived && iRCV.NXT == iFinSeq)
       
  4095 			{
       
  4096 			//
       
  4097 			// Advance iRCV.NXT past the FIN. This also ensures
       
  4098 			// that we never end up here again.
       
  4099 			//
       
  4100 			iRCV.NXT++;
       
  4101 
       
  4102 			if (InState(ETcpFinWait1|ETcpFinWait2))
       
  4103 				{
       
  4104 				//LOG(Log::Printf(_L("IMMEDIATE FIN ACK\r\n")));
       
  4105 				SendSegment(KTcpCtlACK);
       
  4106 				}
       
  4107 			else
       
  4108 				{
       
  4109 				//LOG(Log::Printf(_L("DELAYED FIN ACK\r\n")));
       
  4110 				SendDelayACK();
       
  4111 				}
       
  4112 
       
  4113 /*
       
  4114         SYN-RECEIVED STATE
       
  4115         ESTABLISHED STATE
       
  4116 
       
  4117           Enter the CLOSE-WAIT state.
       
  4118 			*/
       
  4119 			if (InState(ETcpSynReceived|ETcpEstablished))
       
  4120 				{
       
  4121 				EnterState(ETcpCloseWait);
       
  4122 				}
       
  4123 
       
  4124 /*
       
  4125         FIN-WAIT-1 STATE
       
  4126 
       
  4127           If our FIN has been ACKed (perhaps in this segment), then
       
  4128           enter TIME-WAIT, start the time-wait timer, turn off the other
       
  4129           timers; otherwise enter the CLOSING state.
       
  4130 			*/
       
  4131 			if (InState(ETcpFinWait1))
       
  4132 				{
       
  4133 	      /*
       
  4134 	      If our FIN has been ACKed (perhaps in this segment), then
       
  4135 	      enter TIME-WAIT, start the time-wait timer, turn off the other
       
  4136 				timers; otherwise enter the CLOSING state.*/
       
  4137 				if (iSND.UNA == iSND.NXT)
       
  4138 					{
       
  4139 					EnterState(ETcpTimeWait);
       
  4140 					SchedMsl2Wait();
       
  4141 					}
       
  4142 				else
       
  4143 					EnterState(ETcpClosing);
       
  4144 				}
       
  4145 
       
  4146 /*
       
  4147         FIN-WAIT-2 STATE
       
  4148 
       
  4149           Enter the TIME-WAIT state.  Start the time-wait timer, turn
       
  4150           off the other timers.
       
  4151 			*/
       
  4152 			if (InState(ETcpFinWait2))
       
  4153 				{
       
  4154 	      /*
       
  4155 	      Enter the TIME-WAIT state.  Start the time-wait timer, turn
       
  4156 				off the other timers.*/
       
  4157 				Stop();
       
  4158 				EnterState(ETcpTimeWait);
       
  4159 				SchedMsl2Wait();
       
  4160 				}
       
  4161 
       
  4162 			//
       
  4163 			// Anything that could arrive in TIME-WAIT is an out-of-window
       
  4164 			// segment and should never end up here.
       
  4165 			//
       
  4166 #ifdef notdef
       
  4167 /*
       
  4168         TIME-WAIT STATE
       
  4169 
       
  4170           Remain in the TIME-WAIT state.  Restart the 2 MSL time-wait
       
  4171           timeout.
       
  4172 			*/
       
  4173 			if (InState(ETcpTimeWait))
       
  4174 				{
       
  4175 	      /*
       
  4176 	      Remain in the TIME-WAIT state.  Restart the 2 MSL time-wait
       
  4177 				timeout.*/
       
  4178 				SchedMsl2Wait();
       
  4179 				}
       
  4180 #endif
       
  4181 			}
       
  4182 
       
  4183 	wrapup:
       
  4184 		//
       
  4185 		// Time to die.
       
  4186 		//
       
  4187 		if (InState(ETcpClosed) && iRecvQ.IsEmpty())
       
  4188 			{
       
  4189 			packet.Free();
       
  4190 			Close();
       
  4191 			Expire();
       
  4192 			return;
       
  4193 			}
       
  4194 
       
  4195 	accept:
       
  4196 			// Reset idle timers
       
  4197 		Protocol()->Interfacer()->PacketAccepted(info->iOriginalIndex);
       
  4198 
       
  4199 	discard:
       
  4200 			packet.Free();
       
  4201 		}
       
  4202 
       
  4203 	// Complete application level read.
       
  4204 	if (iFlags.iCompleteRecv)
       
  4205 		{
       
  4206 		LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Complete application read"), (TInt)this));
       
  4207 		iFlags.iCompleteRecv = EFalse;
       
  4208 		iCopyOutOffset = 0;
       
  4209       if (iSockFlags.iNotify)
       
  4210 		iSocket->Error(KErrNone, MSocketNotify::EErrorRecv);
       
  4211 		}
       
  4212 
       
  4213 	// This may cause an immediate ACK to be sent from within GetData()
       
  4214 	if (iNewData)
       
  4215 		{
       
  4216 		TInt newData = iNewData, up = 0;
       
  4217 
       
  4218 		// Adjust for urgent data.
       
  4219 		if (iUpCount)
       
  4220 			{
       
  4221 			//
       
  4222 			// Find the offset of an urgent byte following a block of
       
  4223 			// non-urgent data. The number of junked (already delivered)
       
  4224 			// urgent bytes will be left in <up>. This looks complicated
       
  4225 			// but should normally be very quick.
       
  4226 			//
       
  4227 			newData = iSockInQLen;
       
  4228 			for (up = 0; up < iUpCount; up++)
       
  4229 				{
       
  4230 				TInt offset = UrgentOffset(up);
       
  4231 				if (offset > up)
       
  4232 					{
       
  4233 					newData = Min(offset, iSockInQLen);
       
  4234 					break;
       
  4235 					}
       
  4236 				}
       
  4237 
       
  4238 			// We have an undelivered urgent byte within the block.
       
  4239 			if (iFlags.iUrgentMode && !iFlags.iOobInline && newData > UrgentOffset())
       
  4240 				newData = UrgentOffset();
       
  4241 
       
  4242 			ASSERT(newData <= (TInt)iSockInQLen);
       
  4243 
       
  4244 			// Subtract bytes that have already been advertised to ESock
       
  4245 			newData -= (iSockInQLen - iNewData);
       
  4246 
       
  4247 			// Subtract out-of-band bytes
       
  4248 			if (!iFlags.iOobInline)
       
  4249 				newData -= up;
       
  4250 			}
       
  4251 
       
  4252 		// Do we have something?
       
  4253 		if (newData > 0 && iFlags.iStarted && iSockFlags.iNotify)
       
  4254 			{
       
  4255 			ASSERT(newData + (iFlags.iOobInline ? 0 : up) <= (TInt)iNewData);
       
  4256 			iNewData -= newData;
       
  4257 			if (!iFlags.iOobInline)
       
  4258 				iNewData -= up;
       
  4259 
       
  4260 			LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): NewData(%d), %d urgent bytes %s, %d bytes not reported"),
       
  4261 				(TInt)this, newData, up, iFlags.iOobInline ? _S("inline") : _S("junked"), iNewData));
       
  4262 			iPending += newData;
       
  4263 			iSocket->NewData(newData);
       
  4264 			}
       
  4265 		}
       
  4266 
       
  4267 	// Notify urgent data to application
       
  4268 	if (iFlags.iNotifyUrgent && iSockFlags.iNotify)
       
  4269 		{
       
  4270 		LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Urgent data notification"), (TInt)this));
       
  4271 		iFlags.iNotifyUrgent = EFalse;
       
  4272 		iSocket->Error(KErrUrgentData, 0);
       
  4273 		}
       
  4274 
       
  4275 	// Notify application that connection has been closed by peer.
       
  4276 	if (InState(ETcpCloseWait|ETcpClosing|ETcpTimeWait) && !iFlags.iCloseNotified && !iNewData)
       
  4277 		{
       
  4278 		iFlags.iCloseNotified = ETrue;
       
  4279 		if (iFlags.iStarted && iSockFlags.iNotify && !iSockFlags.iRecvClose)
       
  4280 			{
       
  4281 			LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Calling NewData(KNewDataEndOfData)"), (TInt)this));
       
  4282 			if(iSocket)
       
  4283 			iSocket->NewData(KNewDataEndofData);
       
  4284 			}
       
  4285 		}
       
  4286 
       
  4287 	if (iLastAck < iRCV.NXT)
       
  4288 		{
       
  4289 		//
       
  4290 		// We are required to send an ACK for at least every two full sized
       
  4291 		// segments but at most once every full sized segment.
       
  4292 		//
       
  4293 		// In steady state the following rule will acknowledge every second
       
  4294 		// segment regardless of the options in the segments (unless maximum
       
  4295 		// segment size is VERY small). However, if we receive segments smaller
       
  4296 		// than MSS/2, we will send an ACK roughly once for every full segment
       
  4297 		// of received data. This works out pretty good. However, if the
       
  4298 		// received segments are significantly smaller, we will start to
       
  4299 		// experience stretch ACK problems. This might happen, for instance,
       
  4300 		// if peer is using PMTUD and the path is constrained. Currently, we
       
  4301 		// ignore the problem.
       
  4302 		//
       
  4303 		// We ack all pushed segments immediately. This improves performance
       
  4304 		// for interactive traffic, since partial segments typically have the
       
  4305 		// PSH bit set.
       
  4306 		//
       
  4307 		if (iLastAck + iRMSS < iRCV.NXT || immediateAck)
       
  4308 			SendSegment(KTcpCtlACK);
       
  4309 		else
       
  4310 			SendDelayACK();
       
  4311 		}
       
  4312 
       
  4313 	// Wake up transmitter.
       
  4314 	SchedTransmit();
       
  4315 
       
  4316 	//
       
  4317 	// Wake up application
       
  4318 	//
       
  4319 	// Note: We do this even if send window is zero, because
       
  4320 	// new data from application will trigger zero window probing.
       
  4321 	//
       
  4322 	// Note 2: Do not wake up app, if lingering close is pending.
       
  4323 	//
       
  4324 	if (iSockFlags.iFlowStopped)
       
  4325 		{
       
  4326 		LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): FLOW STARTED"), (TInt)this));
       
  4327 		iSockFlags.iFlowStopped = EFalse;
       
  4328 		if (iSocket && iSockFlags.iNotify && (iLinger == -1 || !iSockFlags.iSendClose))
       
  4329 			iSocket->CanSend();
       
  4330 		}
       
  4331 	}
       
  4332 
       
  4333 
       
  4334 void CProviderTCP6::SpuriousTimeout(TUint aAcked)
       
  4335 /**
       
  4336 Spurious timeout occurred.
       
  4337 
       
  4338 Sets the congestion control parameters depending on the ini setting "tcp_spurious_rto_recovery".
       
  4339 
       
  4340 @param aAcked	Number of bytes acknowledged with the ACK that triggered this method.
       
  4341 */
       
  4342 	{
       
  4343 	// TODO: if ACK has ECN-Echo flag, congestion control should not be reverted
       
  4344 	LOG(Log::Printf(_L("\ttcp SAP[%u] SpuriousTimeout(%u) ENTER: cwnd: %u  ssthresh: %u"), 
       
  4345 			(TInt)this, aAcked, iCwnd, iSsthresh));
       
  4346 
       
  4347 	switch(Protocol()->SpuriousRtoResponse())
       
  4348 		{
       
  4349 	case 1:
       
  4350 	default:
       
  4351 		// Eifel response (draft uses initial window as burst limit, we use MaxBurst)
       
  4352 		// Assume that ssthresh was set to FlightSize / 2 when RTO occurred.
       
  4353 		iSsthresh = iSsthresh << 1;
       
  4354 		iCwnd = iSND.NXT - iSND.UNA + Min(aAcked, Protocol()->MaxBurst());
       
  4355 		break;
       
  4356 		
       
  4357 	case 2:
       
  4358 		// Half sending rate (ssthresh has been adjusted when RTO occurred)
       
  4359 		iCwnd = iSsthresh;
       
  4360 		break;
       
  4361 		
       
  4362 	case 3:
       
  4363 		// DCLOR - like behaviour (from earlier draft versions)
       
  4364 		iSsthresh = iSsthresh << 1;
       
  4365 		iCwnd = 1;
       
  4366 		}
       
  4367 	LOG(Log::Printf(_L("\ttcp SAP[%u] SpuriousTimeout() EXIT: cwnd: %u  ssthresh: %u"), 
       
  4368 			(TInt)this, iCwnd, iSsthresh));
       
  4369 	// TODO: Do we want to do the RTO adjustment required in Eifel Response draft? Maybe not. -PS
       
  4370 	}
       
  4371 
       
  4372 
       
  4373 //
       
  4374 // Initiate a connection by sending the first SYN.
       
  4375 //
       
  4376 // Note: The flow MUST be ready when calling this method.
       
  4377 //
       
  4378 void CProviderTCP6::SendSYN()
       
  4379 	{
       
  4380 	ASSERT(iState == ETcpConnect);
       
  4381 	ASSERT(iFlow.FlowContext() != 0);
       
  4382 
       
  4383 	// Initialise send sequence number
       
  4384 	iTransmitSeq = iSND.NXT = Protocol()->RandomSequence();
       
  4385 
       
  4386 	if (Protocol()->WinScale() != -1)
       
  4387 		{
       
  4388 		iRcvWscale = (Protocol()->WinScale() > 0 ? Protocol()->WinScale() - 1 : NeedWindowScale());
       
  4389 		iOptions.SetWindowScale((TUint8)(iRcvWscale + 1));
       
  4390 		}
       
  4391 
       
  4392 	iRMSS = Min(LinkRMSS(), iSockInBufSize / 2);
       
  4393 	iOptions.SetMSS(iRMSS);
       
  4394 	iFreeWindow = Min(iSockInBufSize, 0xffff) % iRMSS;
       
  4395 	iRCV.WND = Min(iSockInBufSize, 0xffff) - iFreeWindow;
       
  4396 	iSND.UNA = iSND.NXT;
       
  4397 
       
  4398 	TUint8 flags = KTcpCtlSYN;
       
  4399 	// Start ECN negotiation by setting both ECN bits on in a SYN packet [RFC 3168].
       
  4400 	if (iFlags.iEcn)
       
  4401 		{
       
  4402 		flags |= KTcpCtlECE | KTcpCtlCWR;
       
  4403 		}
       
  4404 
       
  4405 	SendSegment(flags);
       
  4406 	iTransmitSeq++;
       
  4407 	EnterState(ETcpSynSent);
       
  4408 
       
  4409 	// Disable on-demand interface setup for this flow
       
  4410 	iFlow.FlowContext()->iInfo.iNoInterfaceUp = 1;
       
  4411 
       
  4412 	// Lock source address for this flow. It needs to persist over link change events.
       
  4413 	iFlow.FlowContext()->iInfo.iLocalSet = 1;
       
  4414 	}
       
  4415 
       
  4416 
       
  4417 TInt CProviderTCP6::CreateChild(CProviderTCP6*& aSAP)
       
  4418 	{
       
  4419 	ASSERT(iConnectCount < iListenQueueSize);
       
  4420 	ASSERT(iListenQueue);
       
  4421 
       
  4422 	// Create a new SAP and initialize it
       
  4423 	TRAPD(err, aSAP = (CProviderTCP6*)Protocol()->NewSAPL(KSockStream));
       
  4424 	if (err == KErrNone) //lint -save -esym(613, aSAP) Possible NULL trapped here
       
  4425 		{
       
  4426 		aSAP->iParent = this;
       
  4427 		aSAP->iSockFamily = iSockFamily;
       
  4428 		aSAP->iAppFamily = iAppFamily;
       
  4429 
       
  4430 		// The new SAP is not yet known to socket server
       
  4431 		aSAP->iSockFlags.iAttached  = EFalse;
       
  4432 		aSAP->iSockFlags.iNotify    = EFalse;
       
  4433 		aSAP->iHasNetworkServices = HasNetworkServices();
       
  4434 		// Copy TCP options to the new socket.
       
  4435 		aSAP->iSockInBufSize        = iSockInBufSize;
       
  4436 		aSAP->iSockOutBufSize       = iSockOutBufSize;
       
  4437 		aSAP->iMSS                  = iMSS;
       
  4438 		aSAP->iSockFlags.iReuse     = iSockFlags.iReuse;
       
  4439 		aSAP->iFlags.iOobInline     = iFlags.iOobInline;
       
  4440 		aSAP->iFlags.iNoDelay       = iFlags.iNoDelay;
       
  4441 		aSAP->iFlags.iEcn		  = iFlags.iEcn;
       
  4442 
       
  4443 		// Clone the flow. Lower layer socket options get copied to the new flow.
       
  4444 		aSAP->iFlow.Clone(iFlow);
       
  4445 
       
  4446 		// Clone currently resets the notifier, so we reinstall it here
       
  4447 		aSAP->iFlow.SetNotify(aSAP);
       
  4448 
       
  4449 		// If the listen queue is full, kill a random connection.
       
  4450 		if (iConnectCount == iListenQueueSize)
       
  4451 			{
       
  4452 			TInt i = Protocol()->Random(iListenQueueSize);
       
  4453 			CProviderTCP6 *sap = iListenQueue[i];
       
  4454 			sap->iParent = 0;
       
  4455 			iListenQueue[i] = iListenQueue[--iConnectCount];
       
  4456 			iListenQueue[iConnectCount] = 0;
       
  4457 			sap->Expire();
       
  4458 			}
       
  4459 
       
  4460 		// Add the new connection into listen queue.
       
  4461 		iListenQueue[iConnectCount++] = aSAP;
       
  4462 		} //lint -restore
       
  4463 	return err;
       
  4464 	}
       
  4465 
       
  4466 
       
  4467 void CProviderTCP6::DetachChild(CProviderTCP6* aSAP)
       
  4468 	{
       
  4469 	ASSERT(iConnectCount > 0);
       
  4470 	ASSERT(iListenQueue);
       
  4471 
       
  4472 	// Remove child from listen queue
       
  4473 	for (TUint i = 0; i < iConnectCount; i++)
       
  4474 		if (iListenQueue[i] == aSAP)
       
  4475 		{
       
  4476 		aSAP->iParent = 0;
       
  4477 		iListenQueue[i] = iListenQueue[--iConnectCount];
       
  4478 		iListenQueue[iConnectCount] = 0;
       
  4479 		return;
       
  4480 		}
       
  4481 
       
  4482 #ifdef _DEBUG
       
  4483 	User::Panic(_L("CProviderTCP6::DetachChild()"), 0);
       
  4484 #endif
       
  4485 	}
       
  4486 
       
  4487 TInt CProviderTCP6::CompleteChildConnect(CProviderTCP6* aSAP)
       
  4488 	{
       
  4489 	ASSERT(aSAP);
       
  4490 	ASSERT(iSocket);
       
  4491 	iChildDeleted = EFalse;
       
  4492 	iSocket->ConnectComplete(*aSAP);
       
  4493 	// In some cases SocketServer might have destroyed SAP.
       
  4494 	// If this happens, return error for deleted SAP.
       
  4495 	return iChildDeleted ? KErrAbort : KErrNone;
       
  4496 	}
       
  4497 
       
  4498 inline void CProviderTCP6::SetChildDeleted(TBool aDeleted)
       
  4499 	{
       
  4500 	iChildDeleted = aDeleted;
       
  4501 	}
       
  4502 
       
  4503 
       
  4504 //
       
  4505 // Clear all set option bits for SYNs
       
  4506 //
       
  4507 void CProviderTCP6::ClearSYNSettings()
       
  4508 	{
       
  4509 	// Remove SYN options from active TCP options.
       
  4510 	iOptions.SetWindowScale(0);
       
  4511 	iOptions.ClearMSS();
       
  4512 	iOptions.ClearSackOk();
       
  4513 	if (!iFlags.iUseTimeStamps)
       
  4514 		iOptions.ClearTimeStamps();	
       
  4515 	}
       
  4516 
       
  4517 TUint8 CProviderTCP6::NeedWindowScale()
       
  4518 	{
       
  4519 	TUint bufbits = 0;
       
  4520 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
  4521 	//Window scaling factor needs to be negotiated if the iMaxRecvWin
       
  4522 	//is more than the 64K, irrespective of the socket receive buffer
       
  4523 	//size. This will help in achieving the maximum throughput in case
       
  4524 	//modulation changes
       
  4525 	if(iTcpMaxRecvWin > iSockInBufSize )
       
  4526 		{
       
  4527 		bufbits = iTcpMaxRecvWin >> 16;
       
  4528 		}
       
  4529 	else
       
  4530 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
  4531 		{
       
  4532 		bufbits = iSockInBufSize >> 16;
       
  4533 		}
       
  4534 	TUint8 scale = 0;
       
  4535 
       
  4536 	while (bufbits)
       
  4537 		{
       
  4538 		scale++;
       
  4539 		bufbits >>= 1;
       
  4540 		}
       
  4541 
       
  4542 	return scale;
       
  4543 	}
       
  4544 
       
  4545 TInt CProviderTCP6::CheckPolicy(const TSecurityPolicy& aPolicy, const char *aDiagnostic)
       
  4546 	{
       
  4547 	return iParent ? iParent->CheckPolicy(aPolicy, aDiagnostic) : CProviderInet6Transport::CheckPolicy(aPolicy, aDiagnostic);
       
  4548 	}
       
  4549 //
       
  4550 // TCP reassembly queue implementation
       
  4551 //
       
  4552 TUint RMBufTcpFrag::Offset()
       
  4553 	{
       
  4554 	//LOG(Log::Printf(_L("RMBufTcpFrag::FragOffset()\r\n")));
       
  4555 
       
  4556 	TTcpPacket seg(*this);
       
  4557 	return seg.iHdr->Sequence().Uint32();
       
  4558 	}
       
  4559 
       
  4560 TUint RMBufTcpFrag::FragmentLength()
       
  4561 	{
       
  4562 	//LOG(Log::Printf(_L("RMBufTcpFrag::FragLength(): length = %d\r\n"), Length()));
       
  4563 
       
  4564 	TTcpPacket seg(*this);
       
  4565 	return Length() - seg.iHdr->HeaderLength();
       
  4566 	}
       
  4567 
       
  4568 void RMBufTcpFrag::Join(RMBufChain& aSeg)
       
  4569 	{
       
  4570 	//LOG(Log::Printf(_L("RMBufTcpFrag::Join()\r\n")));
       
  4571 
       
  4572 	TTcpPacket thisSeg(*this), newSeg(aSeg);
       
  4573 
       
  4574 	// Remove header and overlapping data from aSeg.
       
  4575 	aSeg.TrimStart(newSeg.iHdr->HeaderLength() +
       
  4576 		(Length() - thisSeg.iHdr->HeaderLength()) -
       
  4577 		(newSeg.iHdr->Sequence() - thisSeg.iHdr->Sequence()));
       
  4578 
       
  4579 	// Append.
       
  4580 	Append(aSeg);
       
  4581 	}
       
  4582 
       
  4583 #ifdef __ARMCC__
       
  4584 #pragma pop
       
  4585 #endif