|
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.h - TCP protocol for IPv6/IPv4 |
|
15 // TCP protocol class declarations for IPv6/IPv4. |
|
16 // |
|
17 |
|
18 |
|
19 |
|
20 /** |
|
21 @file tcp.h |
|
22 @internalComponent |
|
23 */ |
|
24 |
|
25 #ifndef __TCP_H__ |
|
26 #define __TCP_H__ |
|
27 |
|
28 #include "in_trans.h" |
|
29 #include <ip6_hdr.h> |
|
30 #include <tcp_hdr.h> |
|
31 #include <in_chk.h> |
|
32 #include "frag.h" |
|
33 #include "inet6log.h" |
|
34 #include <in6_opt.h> |
|
35 |
|
36 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
37 #include <in_sock.h> |
|
38 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
39 |
|
40 // Define the following macro here. Do NOT use macro statement in mmp file to define this. |
|
41 // The macro will be used in source files to confirm the right modifed header file is used. |
|
42 // Using macro statement in mmp file disables the trick. |
|
43 //#define FJ_USE_VARIANT_TIMER |
|
44 |
|
45 #ifdef FJ_USE_VARIANT_TIMER |
|
46 #include <FjVariantTimer.h> |
|
47 #endif |
|
48 |
|
49 // |
|
50 // Constants affecting protocol performance |
|
51 // |
|
52 const TUint KOneSecondUs = 1000000; //< Help for converting longer times to microseconds |
|
53 |
|
54 const TUint KTcpMaximumWindow = 0x3fffffff; //< Maximum receive window size |
|
55 const TUint KTcpMinimumWindow = 1024; //< Minimum receive window size |
|
56 const TUint KTcpDefaultRcvWnd = 48 * 1024; //< Default receive window size |
|
57 const TUint KTcpDefaultSndWnd = 16 * 1024; //< Default send window size |
|
58 |
|
59 const TUint KTcpDefaultMSS = 65535; //< By default, MSS is not limited by user |
|
60 const TUint KTcpStandardMSS = 536; //< Internet standard MSS |
|
61 const TUint KTcpMinimumMSS = 64; //< Minimum acceptable MSS. |
|
62 const TUint KTcpMaxTransmit = 2; //< Transmit at most this many segments at one time. |
|
63 |
|
64 const TUint KTcpMinRTO = 1000000; //< us (1s) |
|
65 const TUint KTcpMaxRTO = 60000000; //< us (60s) |
|
66 const TUint KTcpInitialRTO = 3000000; //< us (3s) |
|
67 const TUint KTcpSrttSmooth = 8; //< alpha = 1/8 |
|
68 const TUint KTcpMdevSmooth = 4; //< beta = 1/4 |
|
69 const TUint KTcpRTO_K = 4; //< RTO = SRTT = 4 * RTTVAR |
|
70 |
|
71 const TUint KTcpAckDelay = 200000; //< us (200ms) |
|
72 const TUint KTcpMsl2Delay = 60000000; //< us (2x30s) |
|
73 |
|
74 const TUint KTcpSynRetries = 5; //< Maximum retransmit attempts during connect. |
|
75 const TUint KTcpMaxRetries1 = 3; //< Maximum retransmit attempts before MTU reduction. |
|
76 const TUint KTcpMaxRetries2 = 12; //< Maximum retransmit attempts during transmission. |
|
77 |
|
78 const TUint KTcpReordering = 3; //< Worst case packet reordering in network. |
|
79 const TUint KTcpInitialCwnd = 2; //< Initial congestion window |
|
80 const TUint KTcpLtxWindow = 2; //< Limited transmit window (2 segments) |
|
81 |
|
82 |
|
83 const TUint KTcpNumKeepAlives = 8; //< Number of keepalive probes before quitting. |
|
84 const TUint KTcpKeepAliveRxmt = 75; //< Interval for retransmitted keepalives (seconds). |
|
85 const TUint KTcpKeepAliveIntv = 2 * 3600; //< Default interval between keepalives (seconds => 2 h). |
|
86 const TUint KTcpKeepAliveTH = 30; //< Minimum time between triggered KeepAlives (seconds) |
|
87 |
|
88 const TInt KTcpFinPersistency = 3; //< Default for tcp_fin_persistency. |
|
89 const TInt KTcpMaxLingerTime = 1800; //< Max Linger Timeout in seconds (= 30 min). |
|
90 |
|
91 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
92 const TUint KTcpDefaultRcvMaxWnd = 0x40000; // TCP Receive Max window = 262144 |
|
93 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
94 |
|
95 // |
|
96 // Maximum number of remembered urgent pointers. If the number of |
|
97 // separate pending urgent bytes exceeds this number the urgent |
|
98 // data bytes will start appearing in the received data (as if |
|
99 // inlined). |
|
100 // |
|
101 // Discussion: We use a fairly light-weight method of removing |
|
102 // out-of-band data from the data stream that involves no extra |
|
103 // copying. BSD does it the hard way but still sometimes leaves |
|
104 // droppings in the data stream. So, why bother? Increasing the |
|
105 // number below reduces the probability of an out-of-band character |
|
106 // appearing in the data stream. The cost is 4*n bytes state |
|
107 // variable space. -ML |
|
108 // |
|
109 const TInt KTcpUpMax = 5; |
|
110 |
|
111 |
|
112 typedef TInet6Checksum<TInet6HeaderTCP> TTcpPacket; |
|
113 |
|
114 |
|
115 /** |
|
116 * TCP timer |
|
117 */ |
|
118 #ifdef FJ_USE_VARIANT_TIMER |
|
119 class CTcpTimer : public DCM::CVariantTimer |
|
120 #else |
|
121 class CTcpTimer : public CTimer |
|
122 #endif |
|
123 { |
|
124 public: |
|
125 #ifdef FJ_USE_VARIANT_TIMER |
|
126 CTcpTimer(TCallBack& aCallBack, TInt aPriority = KInet6DefaultPriority) |
|
127 : DCM::CVariantTimer(aPriority), iCallBack(aCallBack.iFunction, aCallBack.iPtr) |
|
128 #else |
|
129 CTcpTimer(TCallBack& aCallBack, TInt aPriority = KInet6DefaultPriority) |
|
130 : CTimer(aPriority), iCallBack(aCallBack.iFunction, aCallBack.iPtr) |
|
131 #endif |
|
132 { CActiveScheduler::Add(this); } |
|
133 virtual void RunL() { iCallBack.CallBack(); } |
|
134 virtual void InitL() { ConstructL(); } |
|
135 void Start(TUint aMicroSeconds) |
|
136 { |
|
137 if (!IsActive()) |
|
138 After(aMicroSeconds); |
|
139 } |
|
140 |
|
141 void Restart(TUint aMicroSeconds) |
|
142 { |
|
143 if (IsActive()) |
|
144 Cancel(); |
|
145 After(aMicroSeconds); |
|
146 } |
|
147 |
|
148 private: |
|
149 TCallBack iCallBack; |
|
150 }; |
|
151 |
|
152 |
|
153 /** |
|
154 * TCP reassembly queue |
|
155 */ |
|
156 class RMBufTcpFrag : public RMBufFrag |
|
157 { |
|
158 public: |
|
159 TUint Offset(); |
|
160 TUint FragmentLength(); |
|
161 void Join(RMBufChain& aChain); |
|
162 }; |
|
163 |
|
164 typedef RMBufFragQ<RMBufTcpFrag> RMBufTcpFragQ; |
|
165 |
|
166 |
|
167 /** |
|
168 * TCP Protocol |
|
169 */ |
|
170 class CProtocolTCP6 : public CProtocolInet6Transport |
|
171 { |
|
172 public: |
|
173 CProtocolTCP6(); |
|
174 CProtocolTCP6& operator=(const CProtocolTCP6&); |
|
175 virtual ~CProtocolTCP6(); |
|
176 virtual CServProviderBase *NewSAPL(TUint aProtocol); |
|
177 virtual void InitL(TDesC& aTag); |
|
178 virtual void StartL(); |
|
179 virtual void Identify(TServerProtocolDesc *) const; |
|
180 //virtual TInt GetOption(TUint level,TUint name,TDes8 &option,CProtocolBase* aSourceProtocol=NULL); |
|
181 //virtual TInt SetOption(TUint level, TUint aName,const TDesC8 &option,CProtocolBase* aSourceProtocol=NULL); |
|
182 virtual TInt Send(RMBufChain& aPDU,CProtocolBase* aSourceProtocol=NULL); |
|
183 virtual void Process(RMBufChain& aPacket, CProtocolBase *aSourceProtocol = NULL); |
|
184 static void Describe(TServerProtocolDesc&); |
|
185 TUint32 RandomSequence(); |
|
186 |
|
187 TInt SendControlSegment(RFlowContext *aFlow, |
|
188 const TSockAddr& aSrcAddr, const TSockAddr& aDstAddr, |
|
189 TUint8 aFlags, TTcpSeqNum aSeq, TTcpSeqNum aAck, |
|
190 TUint32 aWnd = 0, TUint32 aUP = 0); |
|
191 |
|
192 // |
|
193 // TCP Configuration Parameters |
|
194 // |
|
195 TUint MSS() const { return iMSS; } |
|
196 TUint RecvBuf() const { return iRecvBuf; } |
|
197 TUint SendBuf() const { return iSendBuf; } |
|
198 TUint MinRTO() const { return iMinRTO; } |
|
199 TUint MaxRTO() const { return iMaxRTO; } |
|
200 TUint InitialRTO() const { return iInitialRTO; } |
|
201 TUint SrttSmooth() const { return iSrttSmooth; } |
|
202 TUint MdevSmooth() const { return iMdevSmooth; } |
|
203 TUint RTO_K() const { return iRTO_K; } |
|
204 TUint RTO_G() const { return iRTO_G; } |
|
205 TUint ClockGranularity() const { return iClockGranularity; } |
|
206 TUint AckDelay() const { return iAckDelay; } |
|
207 TUint Msl2Delay() const { return iMsl2Delay; } |
|
208 TUint SynRetries() const { return iSynRetries; } |
|
209 TUint Retries1() const { return iRetries1; } |
|
210 TUint Retries2() const { return iRetries2; } |
|
211 TUint ProbeStyle() const { return iProbeStyle; } |
|
212 TUint InitialCwnd() const { return iInitialCwnd; } |
|
213 TUint LtxWindow() const { return iLtxWindow; } |
|
214 TUint RFC2414() const { return iRFC2414; } |
|
215 TUint Reordering() const { return iReordering; } |
|
216 TUint MaxBurst() const { return iMaxBurst; } |
|
217 TUint TimeStamps() const { return iTimeStamps; } |
|
218 TUint Sack() const { return iSack; } |
|
219 TUint LocalTimeWait() const { return iLocalTimeWait; } |
|
220 TUint StrictNagle() const { return iStrictNagle; } |
|
221 TUint PushAck() const { return iPushAck; } |
|
222 TUint FRTO() const { return iFRTO; } |
|
223 TUint DSack() const { return iSack && iDSack; } |
|
224 TUint KeepAliveIntv() const { return iKeepAliveIntv; } |
|
225 TUint KeepAliveRxmt() const { return iKeepAliveRxmt; } |
|
226 TUint NumKeepAlives() const { return iNumKeepAlives; } |
|
227 TUint DstCache() const { return iDstCache; } |
|
228 TUint Ecn() const { return iEcn; } |
|
229 TUint FinPersistency() const { return iFinPersistency; } |
|
230 TUint SpuriousRtoResponse() const { return iSpuriousRtoResponse; } |
|
231 TInt WinScale() { return iWinScale; } |
|
232 TInt AlignOpt() const { return iAlignOpt; } |
|
233 |
|
234 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
235 //Function to set and get receive window |
|
236 void SetRecvWin(TUint aRecvWin) { iRecvBuf = aRecvWin;} |
|
237 TUint GetRecvWinSize() { return iRecvBuf; } |
|
238 TUint RecvMaxWnd() { return iTcpMaxRecvWin;} |
|
239 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
240 |
|
241 #ifdef _LOG |
|
242 static void LogPacket(char aDir, RMBufChain& aPacket, RMBufPktInfo *info = 0, TInt aOffset = 0); |
|
243 #endif |
|
244 |
|
245 private: |
|
246 |
|
247 TUint iMSS; |
|
248 TUint iRecvBuf; |
|
249 TUint iSendBuf; |
|
250 TUint iMinRTO; |
|
251 TUint iMaxRTO; |
|
252 TUint iInitialRTO; |
|
253 TUint iSrttSmooth; |
|
254 TUint iMdevSmooth; |
|
255 TUint iRTO_G; |
|
256 TUint iRTO_K; |
|
257 TUint iMaxBurst; |
|
258 TUint iAckDelay; |
|
259 TUint iSynRetries; |
|
260 TUint iRetries1; |
|
261 TUint iRetries2; |
|
262 TUint iProbeStyle; |
|
263 TUint iClockGranularity; |
|
264 TUint iMsl2Delay; |
|
265 TUint iInitialCwnd; |
|
266 TUint iLtxWindow; |
|
267 TUint iReordering; |
|
268 TUint iKeepAliveIntv; |
|
269 TUint iKeepAliveRxmt; |
|
270 TUint iNumKeepAlives; |
|
271 TUint iFinPersistency; |
|
272 TInt8 iWinScale; //< value of "tcp_winscale" option: -1 ... 7 |
|
273 |
|
274 // Flags |
|
275 TUint iTimeStamps:1; |
|
276 TUint iSack:1; |
|
277 TUint iLocalTimeWait:1; |
|
278 TUint iStrictNagle:1; |
|
279 TUint iRFC2414:1; |
|
280 TUint iPushAck:1; |
|
281 TUint iFRTO:1; |
|
282 TUint iDSack:1; |
|
283 TUint iDstCache:1; |
|
284 TUint iAlignOpt:1; //< Set if TCP options should be aligned using NOP option. |
|
285 |
|
286 // Ecn has 3 reasonable settings: 0 = disable, 1 = enable with ECT(1), 2 = enable with ECT(0). |
|
287 // Old specification used only ECT(0), so there may be routers out there that only understand |
|
288 // ECT(0) but not ECT(1). |
|
289 TUint iEcn:2; |
|
290 |
|
291 // 8 possible values should be enough for spurious response alternatives. |
|
292 TUint iSpuriousRtoResponse:3; |
|
293 |
|
294 TUint32 iRandomIncrement; |
|
295 RMBufAllocator iBufAllocator; |
|
296 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
297 TUint iTcpMaxRecvWin; |
|
298 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
299 }; |
|
300 |
|
301 |
|
302 /** |
|
303 * TCP Socket Provider. |
|
304 */ |
|
305 class CProviderTCP6 : public CProviderInet6Transport |
|
306 { |
|
307 friend class CProtocolTCP6; |
|
308 |
|
309 public: |
|
310 CProviderTCP6(CProtocolInet6Base* aProtocol); |
|
311 virtual ~CProviderTCP6(); |
|
312 virtual void InitL(); |
|
313 virtual void Start(); |
|
314 virtual TInt GetOption(TUint level,TUint name,TDes8 &anOption) const; |
|
315 virtual void Ioctl(TUint level,TUint name,TDes8* anOption); |
|
316 virtual void CancelIoctl(TUint aLevel, TUint aName); |
|
317 virtual TInt SetOption(TUint level,TUint name, const TDesC8 &anOption); |
|
318 virtual TInt SetRemName(TSockAddr &aAddr); |
|
319 virtual void Shutdown(TCloseType option); |
|
320 virtual void ActiveOpen(); |
|
321 virtual TInt PassiveOpen(TUint aQueSize); |
|
322 virtual void ErrorExpire(TInt aError); |
|
323 virtual void CanSend(); |
|
324 |
|
325 // PRTv1.0 send and receive methods |
|
326 virtual TUint Write(const TDesC8 &aDesc,TUint options, TSockAddr* aAddr=NULL); |
|
327 virtual void GetData(TDes8 &aDesc,TUint options,TSockAddr *aAddr=NULL); |
|
328 |
|
329 // PRTv1.5 send and receive methods |
|
330 virtual TInt Write(RMBufChain& aData, TUint aOptions, TSockAddr* anAddr=NULL); |
|
331 virtual TInt GetData(RMBufChain& aData, TUint aLength, TUint aOptions, TSockAddr* anAddr=NULL); |
|
332 |
|
333 // Parent socket methods |
|
334 TInt CreateChild(CProviderTCP6*& aSAP); |
|
335 void DetachChild(CProviderTCP6* aSAP); |
|
336 TInt CompleteChildConnect(CProviderTCP6* aSAP); |
|
337 inline void SetChildDeleted(TBool aDeleted); |
|
338 |
|
339 virtual void Process(RMBufChain& aPacket, CProtocolBase *aSourceProtocol = NULL); |
|
340 CProtocolTCP6* Protocol() const { return (CProtocolTCP6*)iProtocol; } |
|
341 |
|
342 virtual void IcmpError(TInt aError, TUint aOperationMask, TInt aType, TInt aCode, |
|
343 const TInetAddr& aSrcAddr, const TInetAddr& aDstAddr, const TInetAddr& aErrAddr); |
|
344 |
|
345 inline void LingerTimeout(); |
|
346 |
|
347 virtual TInt CheckPolicy(const TSecurityPolicy& aPolicy, const char *aDiagnostic); |
|
348 |
|
349 private: |
|
350 RMBufAllocator iBufAllocator; |
|
351 // Connection state |
|
352 enum TTcpStateEnum |
|
353 { |
|
354 ETcpInitial = 0x0001, |
|
355 ETcpListen = 0x0002, |
|
356 ETcpSynSent = 0x0004, |
|
357 ETcpSynReceived = 0x0008, |
|
358 ETcpEstablished = 0x0010, |
|
359 ETcpFinWait1 = 0x0020, |
|
360 ETcpFinWait2 = 0x0040, |
|
361 ETcpCloseWait = 0x0080, |
|
362 ETcpClosing = 0x0100, |
|
363 ETcpLastAck = 0x0200, |
|
364 ETcpTimeWait = 0x0400, |
|
365 ETcpClosed = 0x0800, |
|
366 ETcpConnect = 0x1000 |
|
367 } iState; |
|
368 |
|
369 // |
|
370 //. Send Window Management |
|
371 // |
|
372 // SND.UNA - send unacknowledged |
|
373 // SND.NXT - send next |
|
374 // SND.WND - send window |
|
375 // SND.UP - send urgent pointer |
|
376 // SND.WL1 - segment sequence number used for last window update |
|
377 // SND.WL2 - segment acknowledgment number used for last window update |
|
378 // ISS - initial send sequence number |
|
379 // |
|
380 struct TTcpSendSequence |
|
381 { |
|
382 TTcpSeqNum UNA; |
|
383 TTcpSeqNum NXT; |
|
384 TTcpSeqNum WL1; |
|
385 TTcpSeqNum WL2; |
|
386 TTcpSeqNum UP; |
|
387 TUint32 WND; |
|
388 } iSND; |
|
389 |
|
390 // |
|
391 // Receive Window Management |
|
392 // |
|
393 // RCV.NXT - receive next |
|
394 // RCV.WND - receive window |
|
395 // RCV.UP - receive urgent pointer |
|
396 // IRS - initial receive sequence number |
|
397 // |
|
398 struct TTcpRecvSequence |
|
399 { |
|
400 TTcpSeqNum NXT; |
|
401 //TTcpSeqNum UP; |
|
402 TUint32 WND; |
|
403 } iRCV; |
|
404 TTcpSeqNum iFinSeq; |
|
405 |
|
406 // Window updates |
|
407 TUint32 iFreeWindow; |
|
408 TUint32 iAdvertisedWindow; |
|
409 |
|
410 // Retransmission control |
|
411 TTcpSeqNum iLastAck; |
|
412 TTcpSeqNum iTransmitSeq; |
|
413 TTcpSeqNum iRecoverSeq; |
|
414 TTcpSeqNum iSendHigh; |
|
415 TUint iDupAcks; |
|
416 TUint iLastWnd; |
|
417 |
|
418 // Queue management |
|
419 RMBufAsyncPktQ iSendQ; |
|
420 RMBufAsyncPktQ iRecvQ; |
|
421 RMBufTcpFragQ iFragQ; |
|
422 RMBufSockQ iSockOutQ; |
|
423 RMBufSockQ iSockInQ; |
|
424 TUint iSockOutQLen; |
|
425 TUint iSockInQLen; |
|
426 TUint iSockOutBufSize; |
|
427 TUint iSockInBufSize; |
|
428 TUint iNewData; |
|
429 TUint iPending; |
|
430 |
|
431 |
|
432 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
433 |
|
434 //Window size for startup case |
|
435 TUint32 iTcpMaxRecvWin; |
|
436 //New window set by the bearer in case of window shrink |
|
437 TUint32 iNewTcpWindow; |
|
438 //Size of buffer read by the application from the TCP receive buffer |
|
439 //but is not transparent while advertising a new TCP window to the sender. |
|
440 TUint32 iHiddenFreeWindow; |
|
441 // Size of Window Shrink |
|
442 TUint32 iShrinkedWindowSize; |
|
443 // Window size set by user. This will override the default values for the bearers |
|
444 TBool iWindowSetByUser; |
|
445 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
446 |
|
447 // Maximum Segment Sizes |
|
448 TUint iMSS; //< Maximum set by user |
|
449 TUint iSMSS; //< Send MSS |
|
450 TUint iRMSS; //< Receive MSS |
|
451 |
|
452 // Asynchronous events |
|
453 CAsyncCallBack *iTransmitter; |
|
454 CTcpTimer *iDelayAckTimer; |
|
455 CTcpTimer *iRetransTimer; |
|
456 CTcpTimer *iLingerTimer; |
|
457 |
|
458 // RTT timing |
|
459 TTime iStartTime; //< Time at the beginning of connection. |
|
460 TUint32 iTimeStamp; //< Last time stamp taken |
|
461 TTcpSeqNum iTimingSeq; |
|
462 TUint32 iTsRecent; |
|
463 |
|
464 // RTO calculation |
|
465 TUint32 iRTO; |
|
466 TUint32 iSRTT; |
|
467 TUint32 iMDEV; |
|
468 TUint iBackoff; |
|
469 |
|
470 // Delay spike detection |
|
471 TUint32 iLastTimeout; //< Timestamp of last RTO |
|
472 |
|
473 // Keep-Alive triggering |
|
474 TUint32 iLastTriggeredKeepAlive; //< Last triggered keep-alive |
|
475 |
|
476 // Congestion control |
|
477 TUint32 iCwnd; |
|
478 TUint32 iLwnd; |
|
479 TUint32 iSsthresh; |
|
480 TTcpSeqNum iQuenchSeq; //< Store right window edge at source quench |
|
481 TTcpSeqNum iPartialSeq; |
|
482 |
|
483 // TCP options |
|
484 TTcpOptions iOptions; |
|
485 |
|
486 // Server socket state |
|
487 TUint iListenQueueSize; //< Listen queue size. |
|
488 TUint iConnectCount; //< Number active connect attempts; |
|
489 CProviderTCP6 *iParent; //< Parent socket |
|
490 CProviderTCP6 **iListenQueue; //< Array holding pointers to child sockets |
|
491 TBool iChildDeleted; //< Flag for notifying parent that a child was deleted by SocketServer |
|
492 |
|
493 // Urgent data handling |
|
494 TTcpSeqNum iUpArray[KTcpUpMax]; |
|
495 TInt iUpIndex; |
|
496 TInt iUpCount; |
|
497 |
|
498 // Large peek offset |
|
499 TInt iCopyOutOffset; |
|
500 |
|
501 // SACK book keeping |
|
502 SequenceBlockQueue iSacked; |
|
503 |
|
504 // FACK book keeping |
|
505 TUint32 iRetranData; |
|
506 |
|
507 // Needed state information for F-RTO/DCLOR retransmission |
|
508 TUint32 iFRTOsent; //< True, if rto was sent and no acks have yet arrived |
|
509 TTcpSeqNum iRealSendHigh; //< iSendHigh is not real with SACK |
|
510 |
|
511 // -1=linger disabled, >=0 linger enabled with given time in seconds. |
|
512 TInt iLinger; |
|
513 |
|
514 // Window scaling factor for the send window, advertised by the other end. |
|
515 TUint8 iSndWscale:4; |
|
516 |
|
517 // Window scaling factor for receive window, based on ini settings. |
|
518 TUint8 iRcvWscale:4; |
|
519 |
|
520 TUint iRetryAck; // to keep count of the ACKs that inform missing segments |
|
521 |
|
522 // Flags |
|
523 struct TTcpFlags |
|
524 { |
|
525 // Additional TCP state |
|
526 TUint32 iStarted:1; //< Protocol has been started |
|
527 TUint32 iFastRetransMode:1; //< We're in fast retransmit mode |
|
528 TUint32 iTransmitPending:1; //< We have segments waiting for flow |
|
529 TUint32 iRetransmitPending:1; //< We have a retransmission waiting for flow |
|
530 TUint32 iPeerHasReneged:1; //< The peer has reneged and might do it again. |
|
531 TUint32 iTiming:1; //< We're timing a segment round trip |
|
532 TUint32 iCloseNotified:1; //< Application has been notified of received FIN. |
|
533 TUint32 iUrgentMode:1; //< Application is in urgent mode. |
|
534 TUint32 iNextIsUrgent:1; //< Next Write() call contains urgent data. |
|
535 TUint32 iFinReceived:1; //< We have received a FIN from the peer |
|
536 TUint32 iDataSentIoctl:1; //< KIoctlTcpNotifyDataSent ioctl is active |
|
537 TUint32 iCompleteRecv:1; //< Force RSocket::Recv() to complete (urgent data ahead) |
|
538 TUint32 iNotifyUrgent:1; //< Notify application of urgent data. |
|
539 TUint32 iDoPMTUD:1; //< Do path MTU discovery? |
|
540 TUint32 iHaveKeepAlive:1; //< Keep-Alive option is set. |
|
541 TUint32 iHaveTriggeredKeepAlive:1; //< Triggered Keep-Alive option is set. |
|
542 TUint32 iEcnHaveCongestion:1; //< ECN receiver has got CE bit, but not yet CWR. |
|
543 TUint32 iEcnSendCWR:1; //< ECN sender has got ECE. Next seg should have CWR set. |
|
544 TUint32 iKeepInterfaceUp:1; //< Storage for KeepInterfaceUp during connection establishment. |
|
545 |
|
546 // Enabled TCP options |
|
547 TUint32 iUseTimeStamps:1; //< We're using timestamps for timing round trips |
|
548 TUint32 iSackOk:1; //< We're using selective acknowledgements |
|
549 TUint32 iOobInline:1; //< Send out-of-band data inline. |
|
550 TUint32 iNoDelay:1; //< Disable Nagle. |
|
551 TUint32 iCork:1; //< Send only full-sized segments. |
|
552 TUint32 iEcn:1; //< We're using Explicit Congestion Notification. |
|
553 } iFlags; |
|
554 |
|
555 private: |
|
556 |
|
557 // |
|
558 // Private implementation methods |
|
559 // |
|
560 inline TInt Min(TInt a, TInt b) const; |
|
561 inline TUint MinUU(TUint a, TUint b) const; |
|
562 inline TInt MinUS(TUint a, TInt b) const; |
|
563 inline TInt MinSU(TInt a, TUint b) const; |
|
564 inline TInt Max(TInt a, TInt b) const; |
|
565 |
|
566 void Stop(); |
|
567 void FreeQueues(); |
|
568 void Close(); |
|
569 |
|
570 inline void EnterState(TTcpStateEnum aState); |
|
571 inline TBool InState(TUint aStateSet) const; |
|
572 |
|
573 TInt SendSegment(TUint8 aFlags, TTcpSeqNum aSeq, TUint32 aLen = 0); |
|
574 TInt SendDataSegment(TTcpSeqNum aSeq, TBool aNagleOverride = EFalse); |
|
575 |
|
576 inline TInt SendSegment(TUint8 aFlags); |
|
577 inline void SendDelayACK(); |
|
578 inline TInt SendReset(TTcpSeqNum aSequence, const TSockAddr& aDstAddr, const TSockAddr& aSrcAddr); |
|
579 inline TInt SendReset(TTcpSeqNum aSequence); |
|
580 inline TInt SendResetNoSync(TTcpSeqNum aAckSequence, const TSockAddr& aDstAddr, const TSockAddr& aSrcAddr); |
|
581 inline TInt SendResetNoSync(TTcpSeqNum aAckSequence); |
|
582 inline void SchedTransmit(); |
|
583 inline void SchedRetransmit(); |
|
584 inline void ReSchedRetransmit(); |
|
585 inline void CancelTransmit(); |
|
586 inline void CancelRetransmit(); |
|
587 inline void CancelDelayACK(); |
|
588 inline TUint32 TimeStamp(); |
|
589 inline TUint32 PathMSS(); |
|
590 inline TUint32 EffectiveMSS(); |
|
591 inline TUint32 LinkRMSS(); |
|
592 inline TInt SockInQOffset(TTcpSeqNum aSeq) const; |
|
593 |
|
594 inline TTcpSeqNum UrgentHigh() const; |
|
595 inline TInt UrgentOffset() const; |
|
596 inline TInt UrgentOffset(TInt aIndex) const; |
|
597 inline TInt SockInQLen() const; |
|
598 |
|
599 inline TBool CanForwardTransmit(); |
|
600 inline void SetEcn(TInt aFlag); |
|
601 inline TBool IsLandAttack(RMBufRecvInfo *aInfo); |
|
602 |
|
603 void RememberUrgentPointer(TTcpSeqNum aUp); |
|
604 void ForgetUrgentPointer(); |
|
605 TInt GetUrgent(TInt& aChar, TUint aOptions); |
|
606 |
|
607 void Transmit(); |
|
608 void ClearRTT(); |
|
609 void UpdateRTO(TUint32 aRTT); |
|
610 void ResetRTO(); |
|
611 void ResetCwnd(TUint aSMSS); |
|
612 void SchedMsl2Wait(); |
|
613 void ProcessSegments(); |
|
614 void SendSegments(TBool aNagleOverride = EFalse); |
|
615 void RetransmitTimeout(); |
|
616 void RetransmitSegments(); |
|
617 void ClearSYNSettings(); |
|
618 |
|
619 /** |
|
620 * Reduce congestion window. The following events may cause this: 1. ICMP Source Quench, |
|
621 * 2. notification from link layer, 3. ECN congestion echo. The method ensures that congestion |
|
622 * window is not reduced more frequently than once in RTT. |
|
623 * |
|
624 * @return ETrue if cwnd was reduced, EFalse if it was not. |
|
625 */ |
|
626 TBool SourceQuench(); |
|
627 |
|
628 void SendSYN(); |
|
629 void CompleteIoctl(TInt aError); |
|
630 void Detach(); |
|
631 void Expire(); |
|
632 |
|
633 void ReadDestinationCache(); |
|
634 void StoreDestinationCache(); |
|
635 |
|
636 void DetachIfDead(); |
|
637 void DetachFromInterface(); |
|
638 |
|
639 /** |
|
640 * Check the size of receive buffers and determine if window scaling is needed |
|
641 * on our part. |
|
642 * |
|
643 * @return The scale factor that would be required due to buffer size settings. |
|
644 */ |
|
645 TUint8 NeedWindowScale(); |
|
646 |
|
647 void SpuriousTimeout(TUint aAcked); |
|
648 |
|
649 inline void StoreKeepInterfaceUp(); |
|
650 |
|
651 // small methods for keep-alive option |
|
652 void KeepAliveTimeout(); //< Keep-Alive related timeout has expired. |
|
653 void ResetKeepAlives(); //< Resetting keep-alive probe timer when connection becomes idle |
|
654 inline TBool CanFireKeepAlives() //< ETrue when keep-alive probe timer can be activated |
|
655 { return iSND.NXT == iSND.UNA && iSND.WND > 0 && iFlags.iHaveKeepAlive; } |
|
656 inline TBool CanTriggerKeepAlive(); //< ETrue if TCP should send triggered keep-alive |
|
657 |
|
658 TInt Send(TDualBufPtr& aBuf, TInt aLength, TUint aOptions); |
|
659 TInt Recv(TDualBufPtr& aBuf, TInt aLength, TUint aOptions); |
|
660 |
|
661 static TInt SenderCallBack(TAny* aProviderTCP); |
|
662 static TInt ReceiverCallBack(TAny* aProviderTCP); |
|
663 static TInt DelayAckCallBack(TAny* aProviderTCP); |
|
664 static TInt TransmitterCallBack(TAny* aProviderTCP); |
|
665 static TInt RetransmitterCallBack(TAny* aProviderTCP); |
|
666 static TInt LingerTimerCallBack(TAny* aProviderTCP); |
|
667 |
|
668 #ifdef _LOG |
|
669 public: |
|
670 const TText *TcpState(TUint aState = ~0L); |
|
671 #endif |
|
672 |
|
673 }; |
|
674 |
|
675 |
|
676 // |
|
677 // Private implementation methods |
|
678 // |
|
679 inline TInt CProviderTCP6::Min(TInt a, TInt b) const { return (a < b) ? a : b; } |
|
680 inline TUint CProviderTCP6::MinUU(TUint a, TUint b) const { return (a < b) ? a : b; } |
|
681 inline TInt CProviderTCP6::MinUS(TUint a, TInt b) const |
|
682 { |
|
683 if(a > KMaxTInt16) |
|
684 return b; |
|
685 else |
|
686 return Min(TInt(a), b); |
|
687 } |
|
688 inline TInt CProviderTCP6::MinSU(TInt a, TUint b) const |
|
689 { |
|
690 if(b > KMaxTInt16) |
|
691 return a; |
|
692 else |
|
693 return Min(a, TInt(b)); |
|
694 } |
|
695 inline TInt CProviderTCP6::Max(TInt a, TInt b) const { return (a > b) ? a : b; } |
|
696 |
|
697 inline void CProviderTCP6::EnterState(TTcpStateEnum aState) |
|
698 { |
|
699 LOG(if (aState != iState) |
|
700 Log::Printf(_L("\ttcp SAP[%u] EnterState(): %s --> %s"), |
|
701 (TInt)this, TcpState(), TcpState(aState))); |
|
702 iState = aState; |
|
703 } |
|
704 |
|
705 inline TBool CProviderTCP6::InState(TUint aStateSet) const |
|
706 { |
|
707 return (aStateSet & iState) != 0; |
|
708 } |
|
709 |
|
710 |
|
711 inline TInt CProviderTCP6::SendSegment(TUint8 aFlags) |
|
712 { |
|
713 return SendSegment(aFlags, iSND.NXT, 0); |
|
714 } |
|
715 |
|
716 inline void CProviderTCP6::SendDelayACK() |
|
717 { |
|
718 iDelayAckTimer->Start(Protocol()->AckDelay()); |
|
719 } |
|
720 |
|
721 inline TInt CProviderTCP6::SendReset(TTcpSeqNum aSequence, const TSockAddr& aDstAddr, const TSockAddr& aSrcAddr) |
|
722 { |
|
723 return Protocol()->SendControlSegment(iFlow.Status() == EFlow_READY ? &iFlow : NULL, |
|
724 aDstAddr, aSrcAddr, |
|
725 KTcpCtlRST, aSequence, 0); |
|
726 } |
|
727 |
|
728 inline TInt CProviderTCP6::SendReset(TTcpSeqNum aSequence) |
|
729 { |
|
730 return SendReset(aSequence, iFlow.FlowContext()->RemoteAddr(), iFlow.FlowContext()->LocalAddr()); |
|
731 } |
|
732 |
|
733 inline TInt CProviderTCP6::SendResetNoSync(TTcpSeqNum aAckSequence, const TSockAddr& aDstAddr, const TSockAddr& aSrcAddr) |
|
734 { |
|
735 return Protocol()->SendControlSegment(iFlow.Status() == EFlow_READY ? &iFlow : NULL, |
|
736 aDstAddr, aSrcAddr, |
|
737 KTcpCtlRST|KTcpCtlACK, 0, aAckSequence); |
|
738 } |
|
739 |
|
740 inline TInt CProviderTCP6::SendResetNoSync(TTcpSeqNum aAckSequence) |
|
741 { |
|
742 return SendResetNoSync(aAckSequence, iFlow.FlowContext()->RemoteAddr(), iFlow.FlowContext()->LocalAddr()); |
|
743 } |
|
744 |
|
745 inline void CProviderTCP6::SchedTransmit() |
|
746 { |
|
747 iTransmitter->CallBack(); |
|
748 } |
|
749 |
|
750 inline void CProviderTCP6::SchedRetransmit() |
|
751 { |
|
752 iRetransTimer->Start(iRTO); |
|
753 } |
|
754 |
|
755 inline void CProviderTCP6::ReSchedRetransmit() |
|
756 { |
|
757 iRetransTimer->Restart(iRTO); |
|
758 } |
|
759 |
|
760 inline void CProviderTCP6::CancelTransmit() |
|
761 { |
|
762 iTransmitter->Cancel(); |
|
763 iFlags.iTransmitPending = EFalse; |
|
764 } |
|
765 |
|
766 inline void CProviderTCP6::CancelRetransmit() |
|
767 { |
|
768 iRetransTimer->Cancel(); |
|
769 iFlags.iRetransmitPending = EFalse; |
|
770 } |
|
771 |
|
772 inline void CProviderTCP6::CancelDelayACK() |
|
773 { |
|
774 iDelayAckTimer->Cancel(); |
|
775 } |
|
776 |
|
777 inline TUint32 CProviderTCP6::TimeStamp() |
|
778 { |
|
779 TTime now; |
|
780 now.UniversalTime(); |
|
781 #ifdef I64LOW |
|
782 return I64LOW(now.Int64()); |
|
783 #else |
|
784 return (TUint32)now.Int64().GetTInt(); |
|
785 #endif |
|
786 } |
|
787 |
|
788 /** |
|
789 * Return maximum segment size allowed by transmission path. Following tradition, |
|
790 * the value represents the maximum number of data bytes that can be passed in |
|
791 * a TCP segment with no option headers. |
|
792 */ |
|
793 inline TUint32 CProviderTCP6::PathMSS() |
|
794 { |
|
795 ASSERT(iFlow.FlowContext() != 0); |
|
796 return Min(iMSS, iFlow.FlowContext()->PathMtu() - iFlow.FlowContext()->HeaderSize() - KTcpMinHeaderLength); |
|
797 } |
|
798 |
|
799 /** |
|
800 * Return effective send MSS. Returns the maximum number of data bytes that can |
|
801 * be passed in a TCP segment. Checks both path MTU and MSS advertised by the receiver. |
|
802 * and subtracts the number of bytes taken up by TCP options. |
|
803 * Finally, ensure that MSS is at most half of the socket output buffer size. |
|
804 */ |
|
805 inline TUint32 CProviderTCP6::EffectiveMSS() |
|
806 { |
|
807 ASSERT(iFlow.FlowContext() != 0); |
|
808 return Min(Max(Min(iSMSS, PathMSS()) - iOptions.Length(), KTcpMinimumMSS), iSockOutBufSize>>1); |
|
809 } |
|
810 |
|
811 /** |
|
812 * Return maximum segment that can be received through the current network interface. |
|
813 * Following tradition, this method returns the maximum number of data bytes assuming |
|
814 * the TCP header contains no optons. |
|
815 */ |
|
816 inline TUint32 CProviderTCP6::LinkRMSS() |
|
817 { |
|
818 ASSERT(iFlow.FlowContext() != 0); |
|
819 return Min(iMSS, iFlow.FlowContext()->InterfaceRMtu() - |
|
820 iFlow.FlowContext()->HeaderSize() - KTcpMinHeaderLength); |
|
821 } |
|
822 |
|
823 /** |
|
824 * Return number of bytes in receive queue without out-of-band data. |
|
825 */ |
|
826 inline TInt CProviderTCP6::SockInQLen() const |
|
827 { |
|
828 return iFlags.iOobInline ? iSockInQLen : iSockInQLen - iUpCount; |
|
829 } |
|
830 |
|
831 inline TInt CProviderTCP6::SockInQOffset(TTcpSeqNum aSeq) const |
|
832 { |
|
833 return aSeq - iRCV.NXT + iSockInQLen; |
|
834 } |
|
835 |
|
836 /** |
|
837 * Return sequence number of highest urgent pointer seen so far. |
|
838 * Assumes iUpCount > 0. |
|
839 */ |
|
840 inline TTcpSeqNum CProviderTCP6::UrgentHigh() const |
|
841 { |
|
842 return iUpArray[(iUpIndex + iUpCount - 1) % KTcpUpMax]; |
|
843 } |
|
844 |
|
845 /** |
|
846 * Return offset to pending urgent data. A negative value means |
|
847 * there is no pending urgent data. |
|
848 */ |
|
849 inline TInt CProviderTCP6::UrgentOffset() const |
|
850 { |
|
851 return iUpCount ? SockInQOffset(UrgentHigh()) - 1 : -1; |
|
852 } |
|
853 |
|
854 /** |
|
855 * Return byte offset of the urgent pointer stored at given index. |
|
856 */ |
|
857 inline TInt CProviderTCP6::UrgentOffset(TInt aIndex) const |
|
858 { |
|
859 return aIndex < iUpCount ? SockInQOffset(iUpArray[(iUpIndex + aIndex) % KTcpUpMax]) - 1 : KMaxTInt; |
|
860 } |
|
861 |
|
862 /** |
|
863 * Checks if sending new data is possible without being limited by application or |
|
864 * sender or receiver window. This is used for checking whether F-RTO can be applied for sending |
|
865 * new data instead of retransmitting after RTO. |
|
866 * |
|
867 * @return ETrue if some unsent data can be transmitted. |
|
868 */ |
|
869 inline TBool CProviderTCP6::CanForwardTransmit() |
|
870 { |
|
871 return Min(iSND.WND, iSockOutQLen) > (iSND.NXT - iSND.UNA); |
|
872 } |
|
873 |
|
874 |
|
875 /** |
|
876 * Set the status of ECN for this SAP. Two things: set the SAP-specific status flag, and |
|
877 * signal the flag to the IP layer (iface.cpp) by using flow options. |
|
878 * |
|
879 * @param aFlag 0 = disable ECN, 1 = enable ECN with ECT(1), 2 = enable ECN with ECT(0) |
|
880 */ |
|
881 inline void CProviderTCP6::SetEcn(TInt aFlag) |
|
882 { |
|
883 TPckgBuf<TInt> ecnopt(aFlag); |
|
884 iFlow.FlowContext()->SetOption(KSolInetIp, KSoIpEcn, ecnopt); |
|
885 iFlags.iEcn = (aFlag != 0); |
|
886 } |
|
887 |
|
888 /** |
|
889 Stores the value of KeepInterfaceUp set for the current flow. |
|
890 */ |
|
891 inline void CProviderTCP6::StoreKeepInterfaceUp() |
|
892 { |
|
893 TPckgBuf<TInt> ifup; |
|
894 GetOption(KSolInetIp, KSoKeepInterfaceUp, ifup); |
|
895 iFlags.iKeepInterfaceUp = (ifup() != 0) ? 1 : 0; |
|
896 } |
|
897 |
|
898 |
|
899 /** |
|
900 Returns ETrue, if source and destination have equal IP address and port. |
|
901 */ |
|
902 inline TBool CProviderTCP6::IsLandAttack(RMBufRecvInfo *aInfo) |
|
903 { |
|
904 return TInetAddr::Cast(aInfo->iSrcAddr).CmpAddr(TInetAddr::Cast(aInfo->iDstAddr)); |
|
905 } |
|
906 |
|
907 #endif |