--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/networkprotocols/tcpipv4v6prt/inc/tcp.h Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,907 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// tcp.h - TCP protocol for IPv6/IPv4
+// TCP protocol class declarations for IPv6/IPv4.
+//
+
+
+
+/**
+ @file tcp.h
+ @internalComponent
+*/
+
+#ifndef __TCP_H__
+#define __TCP_H__
+
+#include "in_trans.h"
+#include <ip6_hdr.h>
+#include <tcp_hdr.h>
+#include <in_chk.h>
+#include "frag.h"
+#include "inet6log.h"
+#include <in6_opt.h>
+
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+#include <in_sock.h>
+#endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+
+// Define the following macro here. Do NOT use macro statement in mmp file to define this.
+// The macro will be used in source files to confirm the right modifed header file is used.
+// Using macro statement in mmp file disables the trick.
+//#define FJ_USE_VARIANT_TIMER
+
+#ifdef FJ_USE_VARIANT_TIMER
+#include <FjVariantTimer.h>
+#endif
+
+//
+// Constants affecting protocol performance
+//
+const TUint KOneSecondUs = 1000000; //< Help for converting longer times to microseconds
+
+const TUint KTcpMaximumWindow = 0x3fffffff; //< Maximum receive window size
+const TUint KTcpMinimumWindow = 1024; //< Minimum receive window size
+const TUint KTcpDefaultRcvWnd = 48 * 1024; //< Default receive window size
+const TUint KTcpDefaultSndWnd = 16 * 1024; //< Default send window size
+
+const TUint KTcpDefaultMSS = 65535; //< By default, MSS is not limited by user
+const TUint KTcpStandardMSS = 536; //< Internet standard MSS
+const TUint KTcpMinimumMSS = 64; //< Minimum acceptable MSS.
+const TUint KTcpMaxTransmit = 2; //< Transmit at most this many segments at one time.
+
+const TUint KTcpMinRTO = 1000000; //< us (1s)
+const TUint KTcpMaxRTO = 60000000; //< us (60s)
+const TUint KTcpInitialRTO = 3000000; //< us (3s)
+const TUint KTcpSrttSmooth = 8; //< alpha = 1/8
+const TUint KTcpMdevSmooth = 4; //< beta = 1/4
+const TUint KTcpRTO_K = 4; //< RTO = SRTT = 4 * RTTVAR
+
+const TUint KTcpAckDelay = 200000; //< us (200ms)
+const TUint KTcpMsl2Delay = 60000000; //< us (2x30s)
+
+const TUint KTcpSynRetries = 5; //< Maximum retransmit attempts during connect.
+const TUint KTcpMaxRetries1 = 3; //< Maximum retransmit attempts before MTU reduction.
+const TUint KTcpMaxRetries2 = 12; //< Maximum retransmit attempts during transmission.
+
+const TUint KTcpReordering = 3; //< Worst case packet reordering in network.
+const TUint KTcpInitialCwnd = 2; //< Initial congestion window
+const TUint KTcpLtxWindow = 2; //< Limited transmit window (2 segments)
+
+
+const TUint KTcpNumKeepAlives = 8; //< Number of keepalive probes before quitting.
+const TUint KTcpKeepAliveRxmt = 75; //< Interval for retransmitted keepalives (seconds).
+const TUint KTcpKeepAliveIntv = 2 * 3600; //< Default interval between keepalives (seconds => 2 h).
+const TUint KTcpKeepAliveTH = 30; //< Minimum time between triggered KeepAlives (seconds)
+
+const TInt KTcpFinPersistency = 3; //< Default for tcp_fin_persistency.
+const TInt KTcpMaxLingerTime = 1800; //< Max Linger Timeout in seconds (= 30 min).
+
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+const TUint KTcpDefaultRcvMaxWnd = 0x40000; // TCP Receive Max window = 262144
+#endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+
+//
+// Maximum number of remembered urgent pointers. If the number of
+// separate pending urgent bytes exceeds this number the urgent
+// data bytes will start appearing in the received data (as if
+// inlined).
+//
+// Discussion: We use a fairly light-weight method of removing
+// out-of-band data from the data stream that involves no extra
+// copying. BSD does it the hard way but still sometimes leaves
+// droppings in the data stream. So, why bother? Increasing the
+// number below reduces the probability of an out-of-band character
+// appearing in the data stream. The cost is 4*n bytes state
+// variable space. -ML
+//
+const TInt KTcpUpMax = 5;
+
+
+typedef TInet6Checksum<TInet6HeaderTCP> TTcpPacket;
+
+
+/**
+ * TCP timer
+ */
+#ifdef FJ_USE_VARIANT_TIMER
+class CTcpTimer : public DCM::CVariantTimer
+#else
+class CTcpTimer : public CTimer
+#endif
+ {
+public:
+#ifdef FJ_USE_VARIANT_TIMER
+ CTcpTimer(TCallBack& aCallBack, TInt aPriority = KInet6DefaultPriority)
+ : DCM::CVariantTimer(aPriority), iCallBack(aCallBack.iFunction, aCallBack.iPtr)
+#else
+ CTcpTimer(TCallBack& aCallBack, TInt aPriority = KInet6DefaultPriority)
+ : CTimer(aPriority), iCallBack(aCallBack.iFunction, aCallBack.iPtr)
+#endif
+ { CActiveScheduler::Add(this); }
+ virtual void RunL() { iCallBack.CallBack(); }
+ virtual void InitL() { ConstructL(); }
+ void Start(TUint aMicroSeconds)
+ {
+ if (!IsActive())
+ After(aMicroSeconds);
+ }
+
+ void Restart(TUint aMicroSeconds)
+ {
+ if (IsActive())
+ Cancel();
+ After(aMicroSeconds);
+ }
+
+ private:
+ TCallBack iCallBack;
+ };
+
+
+/**
+ * TCP reassembly queue
+ */
+class RMBufTcpFrag : public RMBufFrag
+ {
+public:
+ TUint Offset();
+ TUint FragmentLength();
+ void Join(RMBufChain& aChain);
+ };
+
+typedef RMBufFragQ<RMBufTcpFrag> RMBufTcpFragQ;
+
+
+/**
+ * TCP Protocol
+ */
+class CProtocolTCP6 : public CProtocolInet6Transport
+ {
+public:
+ CProtocolTCP6();
+ CProtocolTCP6& operator=(const CProtocolTCP6&);
+ virtual ~CProtocolTCP6();
+ virtual CServProviderBase *NewSAPL(TUint aProtocol);
+ virtual void InitL(TDesC& aTag);
+ virtual void StartL();
+ virtual void Identify(TServerProtocolDesc *) const;
+ //virtual TInt GetOption(TUint level,TUint name,TDes8 &option,CProtocolBase* aSourceProtocol=NULL);
+ //virtual TInt SetOption(TUint level, TUint aName,const TDesC8 &option,CProtocolBase* aSourceProtocol=NULL);
+ virtual TInt Send(RMBufChain& aPDU,CProtocolBase* aSourceProtocol=NULL);
+ virtual void Process(RMBufChain& aPacket, CProtocolBase *aSourceProtocol = NULL);
+ static void Describe(TServerProtocolDesc&);
+ TUint32 RandomSequence();
+
+ TInt SendControlSegment(RFlowContext *aFlow,
+ const TSockAddr& aSrcAddr, const TSockAddr& aDstAddr,
+ TUint8 aFlags, TTcpSeqNum aSeq, TTcpSeqNum aAck,
+ TUint32 aWnd = 0, TUint32 aUP = 0);
+
+ //
+ // TCP Configuration Parameters
+ //
+ TUint MSS() const { return iMSS; }
+ TUint RecvBuf() const { return iRecvBuf; }
+ TUint SendBuf() const { return iSendBuf; }
+ TUint MinRTO() const { return iMinRTO; }
+ TUint MaxRTO() const { return iMaxRTO; }
+ TUint InitialRTO() const { return iInitialRTO; }
+ TUint SrttSmooth() const { return iSrttSmooth; }
+ TUint MdevSmooth() const { return iMdevSmooth; }
+ TUint RTO_K() const { return iRTO_K; }
+ TUint RTO_G() const { return iRTO_G; }
+ TUint ClockGranularity() const { return iClockGranularity; }
+ TUint AckDelay() const { return iAckDelay; }
+ TUint Msl2Delay() const { return iMsl2Delay; }
+ TUint SynRetries() const { return iSynRetries; }
+ TUint Retries1() const { return iRetries1; }
+ TUint Retries2() const { return iRetries2; }
+ TUint ProbeStyle() const { return iProbeStyle; }
+ TUint InitialCwnd() const { return iInitialCwnd; }
+ TUint LtxWindow() const { return iLtxWindow; }
+ TUint RFC2414() const { return iRFC2414; }
+ TUint Reordering() const { return iReordering; }
+ TUint MaxBurst() const { return iMaxBurst; }
+ TUint TimeStamps() const { return iTimeStamps; }
+ TUint Sack() const { return iSack; }
+ TUint LocalTimeWait() const { return iLocalTimeWait; }
+ TUint StrictNagle() const { return iStrictNagle; }
+ TUint PushAck() const { return iPushAck; }
+ TUint FRTO() const { return iFRTO; }
+ TUint DSack() const { return iSack && iDSack; }
+ TUint KeepAliveIntv() const { return iKeepAliveIntv; }
+ TUint KeepAliveRxmt() const { return iKeepAliveRxmt; }
+ TUint NumKeepAlives() const { return iNumKeepAlives; }
+ TUint DstCache() const { return iDstCache; }
+ TUint Ecn() const { return iEcn; }
+ TUint FinPersistency() const { return iFinPersistency; }
+ TUint SpuriousRtoResponse() const { return iSpuriousRtoResponse; }
+ TInt WinScale() { return iWinScale; }
+ TInt AlignOpt() const { return iAlignOpt; }
+
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+ //Function to set and get receive window
+ void SetRecvWin(TUint aRecvWin) { iRecvBuf = aRecvWin;}
+ TUint GetRecvWinSize() { return iRecvBuf; }
+ TUint RecvMaxWnd() { return iTcpMaxRecvWin;}
+#endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+
+#ifdef _LOG
+ static void LogPacket(char aDir, RMBufChain& aPacket, RMBufPktInfo *info = 0, TInt aOffset = 0);
+#endif
+
+private:
+
+ TUint iMSS;
+ TUint iRecvBuf;
+ TUint iSendBuf;
+ TUint iMinRTO;
+ TUint iMaxRTO;
+ TUint iInitialRTO;
+ TUint iSrttSmooth;
+ TUint iMdevSmooth;
+ TUint iRTO_G;
+ TUint iRTO_K;
+ TUint iMaxBurst;
+ TUint iAckDelay;
+ TUint iSynRetries;
+ TUint iRetries1;
+ TUint iRetries2;
+ TUint iProbeStyle;
+ TUint iClockGranularity;
+ TUint iMsl2Delay;
+ TUint iInitialCwnd;
+ TUint iLtxWindow;
+ TUint iReordering;
+ TUint iKeepAliveIntv;
+ TUint iKeepAliveRxmt;
+ TUint iNumKeepAlives;
+ TUint iFinPersistency;
+ TInt8 iWinScale; //< value of "tcp_winscale" option: -1 ... 7
+
+ // Flags
+ TUint iTimeStamps:1;
+ TUint iSack:1;
+ TUint iLocalTimeWait:1;
+ TUint iStrictNagle:1;
+ TUint iRFC2414:1;
+ TUint iPushAck:1;
+ TUint iFRTO:1;
+ TUint iDSack:1;
+ TUint iDstCache:1;
+ TUint iAlignOpt:1; //< Set if TCP options should be aligned using NOP option.
+
+ // Ecn has 3 reasonable settings: 0 = disable, 1 = enable with ECT(1), 2 = enable with ECT(0).
+ // Old specification used only ECT(0), so there may be routers out there that only understand
+ // ECT(0) but not ECT(1).
+ TUint iEcn:2;
+
+ // 8 possible values should be enough for spurious response alternatives.
+ TUint iSpuriousRtoResponse:3;
+
+ TUint32 iRandomIncrement;
+ RMBufAllocator iBufAllocator;
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+ TUint iTcpMaxRecvWin;
+#endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+ };
+
+
+/**
+ * TCP Socket Provider.
+ */
+class CProviderTCP6 : public CProviderInet6Transport
+ {
+ friend class CProtocolTCP6;
+
+public:
+ CProviderTCP6(CProtocolInet6Base* aProtocol);
+ virtual ~CProviderTCP6();
+ virtual void InitL();
+ virtual void Start();
+ virtual TInt GetOption(TUint level,TUint name,TDes8 &anOption) const;
+ virtual void Ioctl(TUint level,TUint name,TDes8* anOption);
+ virtual void CancelIoctl(TUint aLevel, TUint aName);
+ virtual TInt SetOption(TUint level,TUint name, const TDesC8 &anOption);
+ virtual TInt SetRemName(TSockAddr &aAddr);
+ virtual void Shutdown(TCloseType option);
+ virtual void ActiveOpen();
+ virtual TInt PassiveOpen(TUint aQueSize);
+ virtual void ErrorExpire(TInt aError);
+ virtual void CanSend();
+
+ // PRTv1.0 send and receive methods
+ virtual TUint Write(const TDesC8 &aDesc,TUint options, TSockAddr* aAddr=NULL);
+ virtual void GetData(TDes8 &aDesc,TUint options,TSockAddr *aAddr=NULL);
+
+ // PRTv1.5 send and receive methods
+ virtual TInt Write(RMBufChain& aData, TUint aOptions, TSockAddr* anAddr=NULL);
+ virtual TInt GetData(RMBufChain& aData, TUint aLength, TUint aOptions, TSockAddr* anAddr=NULL);
+
+ // Parent socket methods
+ TInt CreateChild(CProviderTCP6*& aSAP);
+ void DetachChild(CProviderTCP6* aSAP);
+ TInt CompleteChildConnect(CProviderTCP6* aSAP);
+ inline void SetChildDeleted(TBool aDeleted);
+
+ virtual void Process(RMBufChain& aPacket, CProtocolBase *aSourceProtocol = NULL);
+ CProtocolTCP6* Protocol() const { return (CProtocolTCP6*)iProtocol; }
+
+ virtual void IcmpError(TInt aError, TUint aOperationMask, TInt aType, TInt aCode,
+ const TInetAddr& aSrcAddr, const TInetAddr& aDstAddr, const TInetAddr& aErrAddr);
+
+ inline void LingerTimeout();
+
+ virtual TInt CheckPolicy(const TSecurityPolicy& aPolicy, const char *aDiagnostic);
+
+private:
+ RMBufAllocator iBufAllocator;
+ // Connection state
+ enum TTcpStateEnum
+ {
+ ETcpInitial = 0x0001,
+ ETcpListen = 0x0002,
+ ETcpSynSent = 0x0004,
+ ETcpSynReceived = 0x0008,
+ ETcpEstablished = 0x0010,
+ ETcpFinWait1 = 0x0020,
+ ETcpFinWait2 = 0x0040,
+ ETcpCloseWait = 0x0080,
+ ETcpClosing = 0x0100,
+ ETcpLastAck = 0x0200,
+ ETcpTimeWait = 0x0400,
+ ETcpClosed = 0x0800,
+ ETcpConnect = 0x1000
+ } iState;
+
+ //
+ //. Send Window Management
+ //
+ // SND.UNA - send unacknowledged
+ // SND.NXT - send next
+ // SND.WND - send window
+ // SND.UP - send urgent pointer
+ // SND.WL1 - segment sequence number used for last window update
+ // SND.WL2 - segment acknowledgment number used for last window update
+ // ISS - initial send sequence number
+ //
+ struct TTcpSendSequence
+ {
+ TTcpSeqNum UNA;
+ TTcpSeqNum NXT;
+ TTcpSeqNum WL1;
+ TTcpSeqNum WL2;
+ TTcpSeqNum UP;
+ TUint32 WND;
+ } iSND;
+
+ //
+ // Receive Window Management
+ //
+ // RCV.NXT - receive next
+ // RCV.WND - receive window
+ // RCV.UP - receive urgent pointer
+ // IRS - initial receive sequence number
+ //
+ struct TTcpRecvSequence
+ {
+ TTcpSeqNum NXT;
+ //TTcpSeqNum UP;
+ TUint32 WND;
+ } iRCV;
+ TTcpSeqNum iFinSeq;
+
+ // Window updates
+ TUint32 iFreeWindow;
+ TUint32 iAdvertisedWindow;
+
+ // Retransmission control
+ TTcpSeqNum iLastAck;
+ TTcpSeqNum iTransmitSeq;
+ TTcpSeqNum iRecoverSeq;
+ TTcpSeqNum iSendHigh;
+ TUint iDupAcks;
+ TUint iLastWnd;
+
+ // Queue management
+ RMBufAsyncPktQ iSendQ;
+ RMBufAsyncPktQ iRecvQ;
+ RMBufTcpFragQ iFragQ;
+ RMBufSockQ iSockOutQ;
+ RMBufSockQ iSockInQ;
+ TUint iSockOutQLen;
+ TUint iSockInQLen;
+ TUint iSockOutBufSize;
+ TUint iSockInBufSize;
+ TUint iNewData;
+ TUint iPending;
+
+
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+
+ //Window size for startup case
+ TUint32 iTcpMaxRecvWin;
+ //New window set by the bearer in case of window shrink
+ TUint32 iNewTcpWindow;
+ //Size of buffer read by the application from the TCP receive buffer
+ //but is not transparent while advertising a new TCP window to the sender.
+ TUint32 iHiddenFreeWindow;
+ // Size of Window Shrink
+ TUint32 iShrinkedWindowSize;
+ // Window size set by user. This will override the default values for the bearers
+ TBool iWindowSetByUser;
+#endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+
+ // Maximum Segment Sizes
+ TUint iMSS; //< Maximum set by user
+ TUint iSMSS; //< Send MSS
+ TUint iRMSS; //< Receive MSS
+
+ // Asynchronous events
+ CAsyncCallBack *iTransmitter;
+ CTcpTimer *iDelayAckTimer;
+ CTcpTimer *iRetransTimer;
+ CTcpTimer *iLingerTimer;
+
+ // RTT timing
+ TTime iStartTime; //< Time at the beginning of connection.
+ TUint32 iTimeStamp; //< Last time stamp taken
+ TTcpSeqNum iTimingSeq;
+ TUint32 iTsRecent;
+
+ // RTO calculation
+ TUint32 iRTO;
+ TUint32 iSRTT;
+ TUint32 iMDEV;
+ TUint iBackoff;
+
+ // Delay spike detection
+ TUint32 iLastTimeout; //< Timestamp of last RTO
+
+ // Keep-Alive triggering
+ TUint32 iLastTriggeredKeepAlive; //< Last triggered keep-alive
+
+ // Congestion control
+ TUint32 iCwnd;
+ TUint32 iLwnd;
+ TUint32 iSsthresh;
+ TTcpSeqNum iQuenchSeq; //< Store right window edge at source quench
+ TTcpSeqNum iPartialSeq;
+
+ // TCP options
+ TTcpOptions iOptions;
+
+ // Server socket state
+ TUint iListenQueueSize; //< Listen queue size.
+ TUint iConnectCount; //< Number active connect attempts;
+ CProviderTCP6 *iParent; //< Parent socket
+ CProviderTCP6 **iListenQueue; //< Array holding pointers to child sockets
+ TBool iChildDeleted; //< Flag for notifying parent that a child was deleted by SocketServer
+
+ // Urgent data handling
+ TTcpSeqNum iUpArray[KTcpUpMax];
+ TInt iUpIndex;
+ TInt iUpCount;
+
+ // Large peek offset
+ TInt iCopyOutOffset;
+
+ // SACK book keeping
+ SequenceBlockQueue iSacked;
+
+ // FACK book keeping
+ TUint32 iRetranData;
+
+ // Needed state information for F-RTO/DCLOR retransmission
+ TUint32 iFRTOsent; //< True, if rto was sent and no acks have yet arrived
+ TTcpSeqNum iRealSendHigh; //< iSendHigh is not real with SACK
+
+ // -1=linger disabled, >=0 linger enabled with given time in seconds.
+ TInt iLinger;
+
+ // Window scaling factor for the send window, advertised by the other end.
+ TUint8 iSndWscale:4;
+
+ // Window scaling factor for receive window, based on ini settings.
+ TUint8 iRcvWscale:4;
+
+ TUint iRetryAck; // to keep count of the ACKs that inform missing segments
+
+ // Flags
+ struct TTcpFlags
+ {
+ // Additional TCP state
+ TUint32 iStarted:1; //< Protocol has been started
+ TUint32 iFastRetransMode:1; //< We're in fast retransmit mode
+ TUint32 iTransmitPending:1; //< We have segments waiting for flow
+ TUint32 iRetransmitPending:1; //< We have a retransmission waiting for flow
+ TUint32 iPeerHasReneged:1; //< The peer has reneged and might do it again.
+ TUint32 iTiming:1; //< We're timing a segment round trip
+ TUint32 iCloseNotified:1; //< Application has been notified of received FIN.
+ TUint32 iUrgentMode:1; //< Application is in urgent mode.
+ TUint32 iNextIsUrgent:1; //< Next Write() call contains urgent data.
+ TUint32 iFinReceived:1; //< We have received a FIN from the peer
+ TUint32 iDataSentIoctl:1; //< KIoctlTcpNotifyDataSent ioctl is active
+ TUint32 iCompleteRecv:1; //< Force RSocket::Recv() to complete (urgent data ahead)
+ TUint32 iNotifyUrgent:1; //< Notify application of urgent data.
+ TUint32 iDoPMTUD:1; //< Do path MTU discovery?
+ TUint32 iHaveKeepAlive:1; //< Keep-Alive option is set.
+ TUint32 iHaveTriggeredKeepAlive:1; //< Triggered Keep-Alive option is set.
+ TUint32 iEcnHaveCongestion:1; //< ECN receiver has got CE bit, but not yet CWR.
+ TUint32 iEcnSendCWR:1; //< ECN sender has got ECE. Next seg should have CWR set.
+ TUint32 iKeepInterfaceUp:1; //< Storage for KeepInterfaceUp during connection establishment.
+
+ // Enabled TCP options
+ TUint32 iUseTimeStamps:1; //< We're using timestamps for timing round trips
+ TUint32 iSackOk:1; //< We're using selective acknowledgements
+ TUint32 iOobInline:1; //< Send out-of-band data inline.
+ TUint32 iNoDelay:1; //< Disable Nagle.
+ TUint32 iCork:1; //< Send only full-sized segments.
+ TUint32 iEcn:1; //< We're using Explicit Congestion Notification.
+ } iFlags;
+
+private:
+
+ //
+ // Private implementation methods
+ //
+ inline TInt Min(TInt a, TInt b) const;
+ inline TUint MinUU(TUint a, TUint b) const;
+ inline TInt MinUS(TUint a, TInt b) const;
+ inline TInt MinSU(TInt a, TUint b) const;
+ inline TInt Max(TInt a, TInt b) const;
+
+ void Stop();
+ void FreeQueues();
+ void Close();
+
+ inline void EnterState(TTcpStateEnum aState);
+ inline TBool InState(TUint aStateSet) const;
+
+ TInt SendSegment(TUint8 aFlags, TTcpSeqNum aSeq, TUint32 aLen = 0);
+ TInt SendDataSegment(TTcpSeqNum aSeq, TBool aNagleOverride = EFalse);
+
+ inline TInt SendSegment(TUint8 aFlags);
+ inline void SendDelayACK();
+ inline TInt SendReset(TTcpSeqNum aSequence, const TSockAddr& aDstAddr, const TSockAddr& aSrcAddr);
+ inline TInt SendReset(TTcpSeqNum aSequence);
+ inline TInt SendResetNoSync(TTcpSeqNum aAckSequence, const TSockAddr& aDstAddr, const TSockAddr& aSrcAddr);
+ inline TInt SendResetNoSync(TTcpSeqNum aAckSequence);
+ inline void SchedTransmit();
+ inline void SchedRetransmit();
+ inline void ReSchedRetransmit();
+ inline void CancelTransmit();
+ inline void CancelRetransmit();
+ inline void CancelDelayACK();
+ inline TUint32 TimeStamp();
+ inline TUint32 PathMSS();
+ inline TUint32 EffectiveMSS();
+ inline TUint32 LinkRMSS();
+ inline TInt SockInQOffset(TTcpSeqNum aSeq) const;
+
+ inline TTcpSeqNum UrgentHigh() const;
+ inline TInt UrgentOffset() const;
+ inline TInt UrgentOffset(TInt aIndex) const;
+ inline TInt SockInQLen() const;
+
+ inline TBool CanForwardTransmit();
+ inline void SetEcn(TInt aFlag);
+ inline TBool IsLandAttack(RMBufRecvInfo *aInfo);
+
+ void RememberUrgentPointer(TTcpSeqNum aUp);
+ void ForgetUrgentPointer();
+ TInt GetUrgent(TInt& aChar, TUint aOptions);
+
+ void Transmit();
+ void ClearRTT();
+ void UpdateRTO(TUint32 aRTT);
+ void ResetRTO();
+ void ResetCwnd(TUint aSMSS);
+ void SchedMsl2Wait();
+ void ProcessSegments();
+ void SendSegments(TBool aNagleOverride = EFalse);
+ void RetransmitTimeout();
+ void RetransmitSegments();
+ void ClearSYNSettings();
+
+ /**
+ * Reduce congestion window. The following events may cause this: 1. ICMP Source Quench,
+ * 2. notification from link layer, 3. ECN congestion echo. The method ensures that congestion
+ * window is not reduced more frequently than once in RTT.
+ *
+ * @return ETrue if cwnd was reduced, EFalse if it was not.
+ */
+ TBool SourceQuench();
+
+ void SendSYN();
+ void CompleteIoctl(TInt aError);
+ void Detach();
+ void Expire();
+
+ void ReadDestinationCache();
+ void StoreDestinationCache();
+
+ void DetachIfDead();
+ void DetachFromInterface();
+
+ /**
+ * Check the size of receive buffers and determine if window scaling is needed
+ * on our part.
+ *
+ * @return The scale factor that would be required due to buffer size settings.
+ */
+ TUint8 NeedWindowScale();
+
+ void SpuriousTimeout(TUint aAcked);
+
+ inline void StoreKeepInterfaceUp();
+
+ // small methods for keep-alive option
+ void KeepAliveTimeout(); //< Keep-Alive related timeout has expired.
+ void ResetKeepAlives(); //< Resetting keep-alive probe timer when connection becomes idle
+ inline TBool CanFireKeepAlives() //< ETrue when keep-alive probe timer can be activated
+ { return iSND.NXT == iSND.UNA && iSND.WND > 0 && iFlags.iHaveKeepAlive; }
+ inline TBool CanTriggerKeepAlive(); //< ETrue if TCP should send triggered keep-alive
+
+ TInt Send(TDualBufPtr& aBuf, TInt aLength, TUint aOptions);
+ TInt Recv(TDualBufPtr& aBuf, TInt aLength, TUint aOptions);
+
+ static TInt SenderCallBack(TAny* aProviderTCP);
+ static TInt ReceiverCallBack(TAny* aProviderTCP);
+ static TInt DelayAckCallBack(TAny* aProviderTCP);
+ static TInt TransmitterCallBack(TAny* aProviderTCP);
+ static TInt RetransmitterCallBack(TAny* aProviderTCP);
+ static TInt LingerTimerCallBack(TAny* aProviderTCP);
+
+#ifdef _LOG
+public:
+ const TText *TcpState(TUint aState = ~0L);
+#endif
+
+ };
+
+
+//
+// Private implementation methods
+//
+inline TInt CProviderTCP6::Min(TInt a, TInt b) const { return (a < b) ? a : b; }
+inline TUint CProviderTCP6::MinUU(TUint a, TUint b) const { return (a < b) ? a : b; }
+inline TInt CProviderTCP6::MinUS(TUint a, TInt b) const
+ {
+ if(a > KMaxTInt16)
+ return b;
+ else
+ return Min(TInt(a), b);
+ }
+inline TInt CProviderTCP6::MinSU(TInt a, TUint b) const
+ {
+ if(b > KMaxTInt16)
+ return a;
+ else
+ return Min(a, TInt(b));
+ }
+inline TInt CProviderTCP6::Max(TInt a, TInt b) const { return (a > b) ? a : b; }
+
+inline void CProviderTCP6::EnterState(TTcpStateEnum aState)
+ {
+ LOG(if (aState != iState)
+ Log::Printf(_L("\ttcp SAP[%u] EnterState(): %s --> %s"),
+ (TInt)this, TcpState(), TcpState(aState)));
+ iState = aState;
+ }
+
+inline TBool CProviderTCP6::InState(TUint aStateSet) const
+ {
+ return (aStateSet & iState) != 0;
+ }
+
+
+inline TInt CProviderTCP6::SendSegment(TUint8 aFlags)
+ {
+ return SendSegment(aFlags, iSND.NXT, 0);
+ }
+
+inline void CProviderTCP6::SendDelayACK()
+ {
+ iDelayAckTimer->Start(Protocol()->AckDelay());
+ }
+
+inline TInt CProviderTCP6::SendReset(TTcpSeqNum aSequence, const TSockAddr& aDstAddr, const TSockAddr& aSrcAddr)
+ {
+ return Protocol()->SendControlSegment(iFlow.Status() == EFlow_READY ? &iFlow : NULL,
+ aDstAddr, aSrcAddr,
+ KTcpCtlRST, aSequence, 0);
+ }
+
+inline TInt CProviderTCP6::SendReset(TTcpSeqNum aSequence)
+ {
+ return SendReset(aSequence, iFlow.FlowContext()->RemoteAddr(), iFlow.FlowContext()->LocalAddr());
+ }
+
+inline TInt CProviderTCP6::SendResetNoSync(TTcpSeqNum aAckSequence, const TSockAddr& aDstAddr, const TSockAddr& aSrcAddr)
+ {
+ return Protocol()->SendControlSegment(iFlow.Status() == EFlow_READY ? &iFlow : NULL,
+ aDstAddr, aSrcAddr,
+ KTcpCtlRST|KTcpCtlACK, 0, aAckSequence);
+ }
+
+inline TInt CProviderTCP6::SendResetNoSync(TTcpSeqNum aAckSequence)
+ {
+ return SendResetNoSync(aAckSequence, iFlow.FlowContext()->RemoteAddr(), iFlow.FlowContext()->LocalAddr());
+ }
+
+inline void CProviderTCP6::SchedTransmit()
+ {
+ iTransmitter->CallBack();
+ }
+
+inline void CProviderTCP6::SchedRetransmit()
+ {
+ iRetransTimer->Start(iRTO);
+ }
+
+inline void CProviderTCP6::ReSchedRetransmit()
+ {
+ iRetransTimer->Restart(iRTO);
+ }
+
+inline void CProviderTCP6::CancelTransmit()
+ {
+ iTransmitter->Cancel();
+ iFlags.iTransmitPending = EFalse;
+ }
+
+inline void CProviderTCP6::CancelRetransmit()
+ {
+ iRetransTimer->Cancel();
+ iFlags.iRetransmitPending = EFalse;
+ }
+
+inline void CProviderTCP6::CancelDelayACK()
+ {
+ iDelayAckTimer->Cancel();
+ }
+
+inline TUint32 CProviderTCP6::TimeStamp()
+ {
+ TTime now;
+ now.UniversalTime();
+#ifdef I64LOW
+ return I64LOW(now.Int64());
+#else
+ return (TUint32)now.Int64().GetTInt();
+#endif
+ }
+
+/**
+ * Return maximum segment size allowed by transmission path. Following tradition,
+ * the value represents the maximum number of data bytes that can be passed in
+ * a TCP segment with no option headers.
+ */
+inline TUint32 CProviderTCP6::PathMSS()
+ {
+ ASSERT(iFlow.FlowContext() != 0);
+ return Min(iMSS, iFlow.FlowContext()->PathMtu() - iFlow.FlowContext()->HeaderSize() - KTcpMinHeaderLength);
+ }
+
+/**
+ * Return effective send MSS. Returns the maximum number of data bytes that can
+ * be passed in a TCP segment. Checks both path MTU and MSS advertised by the receiver.
+ * and subtracts the number of bytes taken up by TCP options.
+ * Finally, ensure that MSS is at most half of the socket output buffer size.
+ */
+inline TUint32 CProviderTCP6::EffectiveMSS()
+ {
+ ASSERT(iFlow.FlowContext() != 0);
+ return Min(Max(Min(iSMSS, PathMSS()) - iOptions.Length(), KTcpMinimumMSS), iSockOutBufSize>>1);
+ }
+
+/**
+ * Return maximum segment that can be received through the current network interface.
+ * Following tradition, this method returns the maximum number of data bytes assuming
+ * the TCP header contains no optons.
+ */
+inline TUint32 CProviderTCP6::LinkRMSS()
+ {
+ ASSERT(iFlow.FlowContext() != 0);
+ return Min(iMSS, iFlow.FlowContext()->InterfaceRMtu() -
+ iFlow.FlowContext()->HeaderSize() - KTcpMinHeaderLength);
+ }
+
+/**
+ * Return number of bytes in receive queue without out-of-band data.
+ */
+inline TInt CProviderTCP6::SockInQLen() const
+ {
+ return iFlags.iOobInline ? iSockInQLen : iSockInQLen - iUpCount;
+ }
+
+inline TInt CProviderTCP6::SockInQOffset(TTcpSeqNum aSeq) const
+ {
+ return aSeq - iRCV.NXT + iSockInQLen;
+ }
+
+/**
+ * Return sequence number of highest urgent pointer seen so far.
+ * Assumes iUpCount > 0.
+ */
+inline TTcpSeqNum CProviderTCP6::UrgentHigh() const
+ {
+ return iUpArray[(iUpIndex + iUpCount - 1) % KTcpUpMax];
+ }
+
+/**
+ * Return offset to pending urgent data. A negative value means
+ * there is no pending urgent data.
+ */
+inline TInt CProviderTCP6::UrgentOffset() const
+ {
+ return iUpCount ? SockInQOffset(UrgentHigh()) - 1 : -1;
+ }
+
+/**
+ * Return byte offset of the urgent pointer stored at given index.
+ */
+inline TInt CProviderTCP6::UrgentOffset(TInt aIndex) const
+ {
+ return aIndex < iUpCount ? SockInQOffset(iUpArray[(iUpIndex + aIndex) % KTcpUpMax]) - 1 : KMaxTInt;
+ }
+
+/**
+ * Checks if sending new data is possible without being limited by application or
+ * sender or receiver window. This is used for checking whether F-RTO can be applied for sending
+ * new data instead of retransmitting after RTO.
+ *
+ * @return ETrue if some unsent data can be transmitted.
+ */
+inline TBool CProviderTCP6::CanForwardTransmit()
+ {
+ return Min(iSND.WND, iSockOutQLen) > (iSND.NXT - iSND.UNA);
+ }
+
+
+/**
+ * Set the status of ECN for this SAP. Two things: set the SAP-specific status flag, and
+ * signal the flag to the IP layer (iface.cpp) by using flow options.
+ *
+ * @param aFlag 0 = disable ECN, 1 = enable ECN with ECT(1), 2 = enable ECN with ECT(0)
+ */
+inline void CProviderTCP6::SetEcn(TInt aFlag)
+ {
+ TPckgBuf<TInt> ecnopt(aFlag);
+ iFlow.FlowContext()->SetOption(KSolInetIp, KSoIpEcn, ecnopt);
+ iFlags.iEcn = (aFlag != 0);
+ }
+
+/**
+Stores the value of KeepInterfaceUp set for the current flow.
+*/
+inline void CProviderTCP6::StoreKeepInterfaceUp()
+ {
+ TPckgBuf<TInt> ifup;
+ GetOption(KSolInetIp, KSoKeepInterfaceUp, ifup);
+ iFlags.iKeepInterfaceUp = (ifup() != 0) ? 1 : 0;
+ }
+
+
+/**
+Returns ETrue, if source and destination have equal IP address and port.
+*/
+inline TBool CProviderTCP6::IsLandAttack(RMBufRecvInfo *aInfo)
+ {
+ return TInetAddr::Cast(aInfo->iSrcAddr).CmpAddr(TInetAddr::Cast(aInfo->iDstAddr));
+ }
+
+#endif