|
1 // Copyright (c) 2008-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 // |
|
15 |
|
16 #ifndef L2CAPENHANCEDDATACONTROLLER_H |
|
17 #define L2CAPENHANCEDDATACONTROLLER_H |
|
18 |
|
19 #include <e32std.h> |
|
20 #include <bt_sock.h> |
|
21 |
|
22 #include "L2CapPDU.h" |
|
23 #include "L2CapSDUQueue.h" |
|
24 #include "L2CapDataController.h" |
|
25 #include "l2signalmgr.h" |
|
26 |
|
27 |
|
28 NONSHARABLE_CLASS(CL2CapStreamingController) : public CL2CapBasicDataController, public MPduOwner |
|
29 { |
|
30 public: |
|
31 CL2CapStreamingController(TL2CAPPort aLocalCID, TL2CAPPort aRemoteCID, CL2CAPMux& aMuxer, CL2CapSDUQueue& aSDUQueue, TL2CapDataControllerConfig* aConfig); |
|
32 virtual ~CL2CapStreamingController(); |
|
33 |
|
34 virtual void ProcessFlushTimerExpiry(); |
|
35 |
|
36 // MPduOwner |
|
37 virtual void HandlePduSendComplete(HL2CapPDU& aPdu); |
|
38 virtual void HandlePduSendError(HL2CapPDU& aPdu); |
|
39 |
|
40 protected: |
|
41 virtual void HandleIncomingIFrameL(RMBufChain& aIFrame); |
|
42 virtual TInt HandleOutgoingIFrame(HIFramePDU* aIFrame); |
|
43 |
|
44 virtual HL2CapPDU* GetPduL(); |
|
45 |
|
46 protected: |
|
47 // Window related information, as defined in the spec. |
|
48 // Sequencer for outgoing I-Frame numbers. |
|
49 TUint8 iNextTxSeq; |
|
50 // Next expected incoming I-Frame number. |
|
51 TUint8 iExpectedTxSeq; |
|
52 }; |
|
53 |
|
54 |
|
55 NONSHARABLE_CLASS(RL2CapErtmTimerManager) : public RL2CapRetransmissionModeTimerManager |
|
56 { |
|
57 public: |
|
58 RL2CapErtmTimerManager(class CL2CapEnhancedReTxController& aClient); |
|
59 void Close(); |
|
60 |
|
61 void StartLocalBusyDelayTimer(); |
|
62 void StopLocalBusyDelayTimer(); |
|
63 inline TBool IsLocalBusyDelayTimerRunning() const; |
|
64 private: |
|
65 void HandleLocalBusyDelayTimerExpired(); |
|
66 static TInt LocalBusyDelayTimerExpired(TAny* aTimerMan); |
|
67 private: |
|
68 // Peer Retransmission Timer value is divided by this to obtain the LB delay timer |
|
69 // value to use. |
|
70 const static TInt KLocalBusyDelayTimerDenominator = 2; |
|
71 private: |
|
72 TBool iLocalBusyDelayTimerRunning; |
|
73 TDeltaTimerEntry iLocalBusyDelayTimerEntry; |
|
74 }; |
|
75 |
|
76 |
|
77 class CL2CapEnhancedReTxController; |
|
78 class RL2CapErtmOutgoingQueue; |
|
79 |
|
80 // Encapsulates a list of unacknowledged I-Frames and an index for fast TxSeqs |
|
81 // lookups for SREJ retransmissions. |
|
82 NONSHARABLE_CLASS(RL2CapErtmUnacknowledgedIFrames) |
|
83 { |
|
84 public: |
|
85 RL2CapErtmUnacknowledgedIFrames(); |
|
86 void Close(); |
|
87 |
|
88 inline void Append(HIFramePDU& aFrame); |
|
89 inline void Remove(HIFramePDU& aFrame); |
|
90 inline HIFramePDU* First() const; |
|
91 inline HIFramePDU* Last() const; |
|
92 inline HIFramePDU* operator[](TUint8 aTxSeq) const; |
|
93 inline TBool IsEmpty() const; |
|
94 inline TDblQueIter<HIFramePDU> Iterator(); |
|
95 private: |
|
96 // Ordered chronologically, oldest to youngest. |
|
97 TDblQue<HIFramePDU> iFrameList; |
|
98 // Indexed by TxSeq. |
|
99 TFixedArray<HIFramePDU*, KL2CapTxSeqValues> iFrameIndex; |
|
100 }; |
|
101 |
|
102 NONSHARABLE_CLASS(CL2CapErtmDataTransmitter) |
|
103 { |
|
104 public: |
|
105 static CL2CapErtmDataTransmitter* NewL(CL2CapEnhancedReTxController& aController); |
|
106 virtual ~CL2CapErtmDataTransmitter(); |
|
107 |
|
108 void HandleIncomingIFrame(RMBufChain& aIFrame); |
|
109 void HandleIncomingSFrameL(RMBufChain& aSFrame); |
|
110 |
|
111 TBool HaveSpaceInOutgoingWindow() const; |
|
112 HIFramePDU* GetIFrameToSendL(); |
|
113 |
|
114 void HciCompletedIFrame(HIFramePDU& aIFrame); |
|
115 |
|
116 void AckTimerExpired(); |
|
117 |
|
118 inline TBool RemoteBusy() const; |
|
119 |
|
120 inline TBool IsWaitAckStatePending() const; |
|
121 inline void EnterWaitAckState(); |
|
122 inline TBool InWaitAckState() const; |
|
123 |
|
124 inline TUint8 NextTxSeq() const; |
|
125 inline TUint8 ExpectedAckSeq() const; |
|
126 |
|
127 inline TBool IsReqSeqValid(TUint8 aReqSeq); |
|
128 |
|
129 inline TBool HaveUnackedIFrames() const; |
|
130 inline TBool IsRetransmittingUnackedIFrames() const; |
|
131 inline TBool IsNextUnackedIFrameAwaitingHciCompletion() const; |
|
132 |
|
133 private: |
|
134 CL2CapErtmDataTransmitter(CL2CapEnhancedReTxController& aController); |
|
135 |
|
136 void HandleReqSeqAck(TUint8 aReqSeq); |
|
137 void HandleFinalAck(); |
|
138 |
|
139 void HandleIncomingSRejL(RMBufChain& aSRejFrame); |
|
140 |
|
141 void RetransmitUnackedIFrames(); |
|
142 |
|
143 inline void SendOrPendL(HIFramePDU& aIFrame); |
|
144 |
|
145 inline RL2CapRetransmissionModeTimerManager& TimerMan(); |
|
146 inline RL2CapErtmOutgoingQueue& OutgoingQ(); |
|
147 private: |
|
148 CL2CapEnhancedReTxController& iController; |
|
149 |
|
150 // Outgoing window information, as defined by the spec. |
|
151 // Sequencer for outgoing I-Frame numbers. With the little exception that when |
|
152 // a decision to retransmit all unacked I-Frames is made, this gets set to the |
|
153 // first number of the bunch and frames are retransmitted until iUnackedIFrames[iNextTxSeq] |
|
154 // is NULL again. |
|
155 TUint8 iNextTxSeq; |
|
156 // I-Frames preceding this number have been acknowledged by the peer. |
|
157 TUint8 iExpectedAckSeq; |
|
158 |
|
159 RL2CapErtmUnacknowledgedIFrames iUnackedIFrames; |
|
160 |
|
161 // If remote indicates busy condition we keep transmitting within send window limits, |
|
162 // but disable our retransmission timer. |
|
163 TBool iRemoteBusy; |
|
164 |
|
165 // For protecting against duplicates. Explained in HandleIncomingSFrameL(). |
|
166 // See state tables in the spec. |
|
167 TBool iSRejActioned; |
|
168 TUint8 iSRejSaveReqSeq; |
|
169 |
|
170 // Signals to GetPdu that we need to enter WAIT_ACK. |
|
171 TBool iWaitAckStatePending; |
|
172 // Xmit state WAIT_ACK (syncing ReqSeq to start retransmission from) - see spec. |
|
173 TBool iInWaitAckState; |
|
174 }; |
|
175 |
|
176 |
|
177 class CL2CapErtmDataReceiver; |
|
178 |
|
179 NONSHARABLE_CLASS(TL2CapErtmMissingTxSeqs) |
|
180 { |
|
181 public: |
|
182 TL2CapErtmMissingTxSeqs(); |
|
183 |
|
184 // Register SREJ-requested I-Frame TxSeq. |
|
185 inline void AppendTxSeq(TUint8 aTxSeq); |
|
186 |
|
187 // Received an SREJ requested I-Frame. Take note of this fact and indicate whether |
|
188 // it was out of sequence wrt to previous ones. If so, GetNextTxSeqForResend() needs |
|
189 // to be called in a loop to return all the TxSeqs to re-request. |
|
190 TBool ReceivedTxSeq(TUint8 aTxSeq); |
|
191 inline TBool GetNextTxSeqForResend(TUint8& aTxSeq); |
|
192 |
|
193 TBool IsTxSeqOnTheList(TUint8 aTxSeq) const; |
|
194 inline TUint8 LastTxSeq() const; |
|
195 inline TBool IsEmpty() const; |
|
196 |
|
197 inline TBool AllRequestedFramesReceived() const; |
|
198 inline TUint8 ExpectedSRejTxSeq() const; |
|
199 inline TInt NumMissingTxSeqs() const; |
|
200 inline TBool HaveSpaceForNewTxSeqs(TInt aNumTxSeqs) const; |
|
201 inline void Reset(); |
|
202 private: |
|
203 #ifdef __FLOG_ACTIVE |
|
204 void Log(); |
|
205 #endif |
|
206 public: |
|
207 const static TUint KMaxSRejsInFlight = 1; |
|
208 private: |
|
209 TFixedArray<TUint8, KMaxSRejsInFlight> iMissingTxSeqs; |
|
210 // Number of TxSeqs missing since entering SREJ_SENT. |
|
211 // The array is split in two parts - frames already received and the ones we're still |
|
212 // waiting for. |
|
213 TInt iNumMissingTxSeqs; |
|
214 // Frames below this index have been received. |
|
215 TInt iExpectedRecvIdx; |
|
216 // Frames starting from this index need to be re-requested. |
|
217 TInt iResendIdx; |
|
218 }; |
|
219 |
|
220 |
|
221 NONSHARABLE_CLASS(TL2CapErtmReceiverStateBase) |
|
222 { |
|
223 public: |
|
224 // Note: think about the frame parameter as "the frame that caused the transition", |
|
225 // though it's only really used for SREJ_SENT. Still, this is the cleanest form |
|
226 // of passing the required information. |
|
227 virtual void EnterL(RMBufChain* aIFrame); |
|
228 virtual void ExitL(); |
|
229 virtual void HandleIncomingIFrameL(RMBufChain& aIFrame) = 0; |
|
230 virtual void HandlePollL() = 0; |
|
231 virtual TBool IsLocalBusySupported() const; |
|
232 |
|
233 // Called to notify the state that the incoming SDU Q has just consumed some |
|
234 // I-Frames and we could slide the receive window if we can (we can't in SREJ_SENT). |
|
235 virtual void TxSeqExpectedBySduQChanged(TUint8 aTxSeq) = 0; |
|
236 protected: |
|
237 TL2CapErtmReceiverStateBase(CL2CapErtmDataReceiver& aReceiver); |
|
238 protected: |
|
239 CL2CapErtmDataReceiver& iReceiver; |
|
240 }; |
|
241 |
|
242 NONSHARABLE_CLASS(TL2CapErtmReceiverStateRecv) : public TL2CapErtmReceiverStateBase |
|
243 { |
|
244 public: |
|
245 TL2CapErtmReceiverStateRecv(CL2CapErtmDataReceiver& aReceiver); |
|
246 virtual void EnterL(RMBufChain* aIFrame); |
|
247 virtual void HandleIncomingIFrameL(RMBufChain& aIFrame); |
|
248 virtual void HandlePollL(); |
|
249 virtual TBool IsLocalBusySupported() const; |
|
250 virtual void TxSeqExpectedBySduQChanged(TUint8 aTxSeq); |
|
251 }; |
|
252 |
|
253 NONSHARABLE_CLASS(TL2CapErtmReceiverStateRejSent) : public TL2CapErtmReceiverStateBase |
|
254 { |
|
255 public: |
|
256 TL2CapErtmReceiverStateRejSent(CL2CapErtmDataReceiver& aReceiver); |
|
257 virtual void EnterL(RMBufChain* aIFrame); |
|
258 virtual void HandleIncomingIFrameL(RMBufChain& aIFrame); |
|
259 virtual void HandlePollL(); |
|
260 virtual void TxSeqExpectedBySduQChanged(TUint8 aTxSeq); |
|
261 }; |
|
262 |
|
263 NONSHARABLE_CLASS(TL2CapErtmReceiverStateSRejSent) : public TL2CapErtmReceiverStateBase |
|
264 { |
|
265 public: |
|
266 TL2CapErtmReceiverStateSRejSent(CL2CapErtmDataReceiver& aReceiver); |
|
267 virtual void EnterL(RMBufChain* aIFrame); |
|
268 virtual void ExitL(); |
|
269 virtual void HandleIncomingIFrameL(RMBufChain& aIFrame); |
|
270 virtual void HandlePollL(); |
|
271 virtual void TxSeqExpectedBySduQChanged(TUint8 aTxSeq); |
|
272 private: |
|
273 void SendSRejsUpToReceivedIFrameL(RMBufChain& aIFrame); |
|
274 private: |
|
275 TBool iGoToRej; |
|
276 TL2CapErtmMissingTxSeqs iMissingTxSeqs; |
|
277 }; |
|
278 |
|
279 |
|
280 // Incoming I-Frame queue. Used both when the SDU Q is full and we have to buffer incoming |
|
281 // frames (a whole window is buffered) and when SREJ_SENT is entered and we wait for |
|
282 // SREJ-requested retransmissions to come through. |
|
283 NONSHARABLE_CLASS(RL2CapErtmIncomingIFrameQueue) |
|
284 { |
|
285 public: |
|
286 RL2CapErtmIncomingIFrameQueue(); |
|
287 void Close(); |
|
288 |
|
289 // Enqueue the new I-Frame and try to consume as much of the existing ones as possible. |
|
290 void HandleIncomingIFrameL(RMBufChain& aIFrame, const CL2CapErtmDataReceiver& aReceiver); |
|
291 // Pass as many consequent I-Frames to SDU Q ("consume them") as possible. |
|
292 void ConsumeUpToFirstGapL(const CL2CapErtmDataReceiver& aReceiver); |
|
293 inline void DeleteAllFrames(); |
|
294 |
|
295 inline TBool IsEmpty() const; |
|
296 inline TUint8 TxSeqExpectedBySduQ() const; |
|
297 private: |
|
298 void Insert(RMBufChain& aIFrame); |
|
299 #ifdef _DEBUG |
|
300 void LogQ(); |
|
301 #endif |
|
302 private: |
|
303 RMBufPktQ iQueue; |
|
304 // Next TxSeq in sequence for SDU Q. |
|
305 // If we're not in SREJ_SENT, it's = BufferSeq. |
|
306 // If we're in SREJ_SENT, it's >= BufferSeq. |
|
307 TUint8 iTxSeqExpectedBySduQ; |
|
308 }; |
|
309 |
|
310 NONSHARABLE_CLASS(CL2CapErtmDataReceiver) |
|
311 { |
|
312 public: |
|
313 static CL2CapErtmDataReceiver* NewL(CL2CapEnhancedReTxController& aController); |
|
314 virtual ~CL2CapErtmDataReceiver(); |
|
315 |
|
316 void HandleIncomingIFrameL(RMBufChain& aIFrame); |
|
317 void HandleIncomingSFrameL(RMBufChain& aSFrame); |
|
318 |
|
319 // Recv window management. |
|
320 void SendPeerAckTimerExpiredL(); |
|
321 TBool IsEndOfReceiveWindowApproaching() const; |
|
322 template<typename FrameType> |
|
323 void StampWithReqSeq(FrameType& aFrame); |
|
324 |
|
325 // Send SREJ or REJ ? |
|
326 TBool IsSRejPreferredToRej(TUint8 aExpectedTxSeq, TUint8 aReceivedTxSeq); |
|
327 |
|
328 // Incoming SDU Q status/LocalBusy. |
|
329 void SetIncomingSduQFullL(TBool aIncomingSduQFull); |
|
330 void UpdateLocalBusyStatusL(); |
|
331 inline TBool IsIncomingSduQFull() const; |
|
332 inline TBool LocalBusy() const; |
|
333 void LocalBusyDelayTimerExpired(); |
|
334 |
|
335 inline void FlushBufferedIncomingIFrames(); |
|
336 |
|
337 inline TBool IsWaitFStatePending() const; |
|
338 inline void EnterWaitFState(); |
|
339 inline TBool InWaitFState() const; |
|
340 |
|
341 // Window state accessors, both for state objects and the controller. |
|
342 inline TUint8 ExpectedTxSeq() const; |
|
343 inline void SetExpectedTxSeq(TUint8 aTxSeq); |
|
344 inline void IncExpectedTxSeq(); |
|
345 |
|
346 inline TUint8 BufferSeq() const; |
|
347 inline void SetBufferSeq(TUint8 aTxSeq); |
|
348 |
|
349 inline TUint8 LastAckReqSeq() const; |
|
350 |
|
351 inline TUint8 TxSeqExpectedBySduQ() const; |
|
352 |
|
353 inline TBool SendAck() const; |
|
354 |
|
355 // As defined in the spec. |
|
356 inline TBool IsTxSeqUnexpected(TUint8 aTxSeq); |
|
357 inline TBool IsTxSeqInvalid(TUint8 aTxSeq); |
|
358 |
|
359 // Handy helpers. |
|
360 HSFramePDU* GetAckFrameL(TBool aFinal = EFalse); |
|
361 inline void PassToIncomingQL(RMBufChain& aIFrame); |
|
362 inline void PassToSduQL(RMBufChain& aIFrame) const; |
|
363 |
|
364 inline void SetStateRecvL(); |
|
365 inline void SetStateRejSentL(); |
|
366 inline void SetStateSRejSentL(RMBufChain& aUnexpectedIFrame); |
|
367 |
|
368 inline RL2CapErtmTimerManager& TimerMan(); |
|
369 inline RL2CapErtmOutgoingQueue& OutgoingQ(); |
|
370 inline CL2CapEnhancedReTxController& Controller() const; |
|
371 |
|
372 private: |
|
373 CL2CapErtmDataReceiver(CL2CapEnhancedReTxController& aController); |
|
374 void ConstructL(); |
|
375 |
|
376 void SetStateL(TL2CapErtmReceiverStateBase& aState, RMBufChain* aIFrame); |
|
377 |
|
378 void HandleFinalAckL(); |
|
379 |
|
380 void EnterLocalBusyL(); |
|
381 void ExitLocalBusy(); |
|
382 |
|
383 private: |
|
384 // This value represents the number of frames the peer can still send within its current TxWin |
|
385 // when we decide to send an acknowledgement. E.g. if the peer TxWindow is 20 then we'll send |
|
386 // an acknowledgement after receiving the 18th frame, thus moving the peer's window and ready |
|
387 // to receive next 18 frames before sending the next ack. Sending the ack before the end |
|
388 // of the receive window is reached prevents transmission delays caused by the peer waiting |
|
389 // for an ack before it can send more. |
|
390 const static TUint8 KReceiveWinFreeSpaceLeftToTriggerAck = 2; |
|
391 // Used to decide whether to send an SREJ or a REJ. An SREJ will never be sent if the gap |
|
392 // between ExpectedTxSeq and the received frame's TxSeq is wider than this value. |
|
393 const static TUint8 KSRejMissingFrameThreshold = 1; |
|
394 |
|
395 __ASSERT_COMPILE(KSRejMissingFrameThreshold <= TL2CapErtmMissingTxSeqs::KMaxSRejsInFlight); |
|
396 |
|
397 private: |
|
398 CL2CapEnhancedReTxController& iController; |
|
399 |
|
400 // Window variables as defined in the spec. |
|
401 // Next expected I-Frame num. |
|
402 TUint8 iExpectedTxSeq; |
|
403 // Ack num (ReqSeq) that can be sent to the peer. Usually equal to ExpectedTxSeq, |
|
404 // unless SDU Queue is full or we're in SREJ_SENT. IOW the beginning of our receive window. |
|
405 TUint8 iBufferSeq; |
|
406 // Stores the acknowledgment number most recently sent to the peer. |
|
407 // Used to detect that we're reaching the end of peer's send window and hence should |
|
408 // send an ack. |
|
409 TUint8 iLastAckReqSeq; |
|
410 |
|
411 // This means SDU queue won't accept any more data, so we can't acknowledge anything new. |
|
412 // Whether LocalBusy can be entered depends on the receive state (RECV only) and other nasty |
|
413 // details. |
|
414 TBool iIncomingSduQFull; |
|
415 // This means we're sending out RNRs instead of RRs. Proper LocalBusy. |
|
416 TBool iLocalBusy; |
|
417 // Xmit state WAIT_F (exiting Local Busy) - see spec. |
|
418 TBool iInWaitFState; |
|
419 // Signals to GetPdu that we need to enter WAIT_F. |
|
420 TBool iWaitFStatePending; |
|
421 |
|
422 // This is set to True when we're approaching the end of receive window or the send peer ack |
|
423 // timer expires, or sending a generic ack is needed for some other reason. |
|
424 // While flags are bad bad bad in general because they don't store time-ordering information |
|
425 // of related events (that's why we have the outgoing Q instead), it is fine this case - |
|
426 // - it's legitimate to send a vanilla ack at any time. It's an optimization that prevents |
|
427 // multiple acks to be queued when the outgoing pipe gets clogged for a while but we keep |
|
428 // receiving incoming I-Frames. |
|
429 TBool iSendAck; |
|
430 |
|
431 RL2CapErtmIncomingIFrameQueue iIncomingIFrameQ; |
|
432 |
|
433 // "Heavyweight" State pattern. |
|
434 TL2CapErtmReceiverStateBase* iReceiveState; |
|
435 |
|
436 TL2CapErtmReceiverStateRecv iStateRecv; |
|
437 TL2CapErtmReceiverStateRejSent iStateRejSent; |
|
438 TL2CapErtmReceiverStateSRejSent iStateSRejSent; |
|
439 }; |
|
440 |
|
441 // This encapsulates the managament of the outgoing packet queue. |
|
442 // Every packet should go through the queue before it's sent - certain actions need to be |
|
443 // executed when a packet is enqueued/dequeued and to make sure that it's always done |
|
444 // the queue is hidden in this class. |
|
445 NONSHARABLE_CLASS(RL2CapErtmOutgoingQueue) |
|
446 { |
|
447 public: |
|
448 RL2CapErtmOutgoingQueue(CL2CapEnhancedReTxController& aController); |
|
449 void Close(); |
|
450 |
|
451 // These queue frames that can be sent immediately. |
|
452 void QueueIFrameL(HIFramePDU& aIFrame); |
|
453 void QueueAckingSFrame(HSFramePDU& aSFrame); |
|
454 void QueueNonAckingSFrame(HSFramePDU& aSFrame, TUint8 aReqSeq); |
|
455 |
|
456 // This queues the I-Frame onto a separate list pending clearing of WAIT_ACK. |
|
457 // It's used for I-Frames requested with SREJs coming through in WAIT_ACK. |
|
458 void PendRetransmitIFrameL(HIFramePDU& aIFrame); |
|
459 |
|
460 // This requeues the I-Frames from the pending list onto the normal send queue. |
|
461 void SendPendingRetransmitIFramesL(); |
|
462 // Used when we decide to retransmit all I-Frames when we still haven't sent |
|
463 // out the SREJ-requested ones. |
|
464 void CancelPendingRetransmitIFrames(); |
|
465 |
|
466 void DeleteAllFrames(); |
|
467 |
|
468 // Called by controller's GetPdu when the link muxer asks for a frame to send. |
|
469 HL2CapPDU* DequeueNextToSend(); |
|
470 |
|
471 inline TBool HaveFramesToTransmit() const; |
|
472 inline TBool HavePendingRetransmitIFrames() const; |
|
473 private: |
|
474 CL2CapEnhancedReTxController& iController; |
|
475 TSglQue<HL2CapPDU> iOutgoingQ; |
|
476 // I-Frames SREJ-requested by the remote when we're in WAIT_ACK and thus can't send data. |
|
477 TSglQue<HIFramePDU> iPendRetransmitIFrameQ; |
|
478 }; |
|
479 |
|
480 NONSHARABLE_CLASS(CL2CapEnhancedReTxController) |
|
481 : public CL2CapBasicDataController, public MPduOwner, public MRetransmissionModeTimerClient |
|
482 { |
|
483 public: |
|
484 static CL2CapEnhancedReTxController* NewL(TL2CAPPort aLocalCID, TL2CAPPort aRemoteCID, CL2CAPMux& aMuxer, CL2CapSDUQueue& aSDUQueue, TL2CapDataControllerConfig* aConfig); |
|
485 virtual ~CL2CapEnhancedReTxController(); |
|
486 |
|
487 // MPduOwner |
|
488 // Called back by I-Frames on HCI completion. |
|
489 virtual void HandlePduSendComplete(HL2CapPDU& aPdu); |
|
490 virtual void HandlePduSendError(HL2CapPDU& aPdu); |
|
491 |
|
492 // Called back by PDUs going out through the HL2CapPDU::DeliverOutgoingPDU |
|
493 // double-dispatch trickery, in the context of GetPduL. |
|
494 virtual TInt HandleOutgoingIFrame(HIFramePDU* aIFrame); |
|
495 virtual TInt HandleOutgoingSFrame(HSFramePDU* aSFrame); |
|
496 |
|
497 // Called by the SDU Q when it gets full/space frees up. |
|
498 virtual void SetIncomingSduQFull(TBool aIncomingSduQFull); |
|
499 |
|
500 // Called by the SDU Q when the connection is being shutdown by the application |
|
501 // and data needs to be delivered reliably before we disconnect. |
|
502 virtual TBool DeliverOutgoingDataAndSignalToSduQWhenDone(); |
|
503 inline TBool IsOutgoingDataPathClosing(); |
|
504 // The data transmitter calls this when it wants to notify the SDU Q that it has |
|
505 // delivered all outgoing data and so we can now be destroyed. |
|
506 inline void SignalOutgoingDataDeliveredToSduQ(); |
|
507 |
|
508 // Incoming Q calls this to pass an I-Frame to the SDU Q. |
|
509 inline void PassToSduQL(RMBufChain& aIFrame); |
|
510 |
|
511 // Called from SDU Q when it's got new PDUs to send. |
|
512 virtual void OutgoingPduAvailableOnSduQ(); |
|
513 |
|
514 // Called to evaluate whether we want to send anything. |
|
515 inline void NotifyMuxerOfPdusToSendIfHaveSome(); |
|
516 |
|
517 // Puts the current acknowledgement number into the frame being queued for send. |
|
518 // Templated to handle both I-Frames and S-Frames. |
|
519 template<typename FrameType> |
|
520 inline void StampWithReqSeq(FrameType& aFrame); |
|
521 |
|
522 // A helper for when a ReqSeq/Final ack needs to be sent - tries to piggy-back on I-Frames. |
|
523 void SendIOrRrOrRnrL(TBool aFinal); |
|
524 |
|
525 virtual void LocalBusyDelayTimerExpired(); |
|
526 |
|
527 inline TBool IsPollOutstanding() const; |
|
528 inline TBool IsFBitValid(TBool aFinal); |
|
529 |
|
530 inline RL2CapErtmOutgoingQueue& OutgoingQ(); |
|
531 inline RL2CapErtmTimerManager& TimerMan(); |
|
532 |
|
533 protected: |
|
534 CL2CapEnhancedReTxController(TL2CAPPort aLocalCID, TL2CAPPort aRemoteCID, CL2CAPMux& aMuxer, CL2CapSDUQueue& aSDUQueue, TL2CapDataControllerConfig* aConfig); |
|
535 void ConstructL(); |
|
536 |
|
537 // These are the entry points for incoming PDUs, called and trapped by a dispatch routine |
|
538 // in CL2CapBasicDataController. |
|
539 virtual void HandleIncomingIFrameL(RMBufChain& aIFrame); |
|
540 virtual void HandleIncomingSFrameL(RMBufChain& aSFrame); |
|
541 |
|
542 // Provide a PDU for transmission. Called and trapped by GetPdu in CL2CapBasicDataController. |
|
543 virtual HL2CapPDU* GetPduL(); |
|
544 |
|
545 void HandleFinalAck(); |
|
546 |
|
547 // From MErtmModeTimerClient |
|
548 virtual void MonitorTimerExpired(); |
|
549 virtual void AckTimerExpired(); |
|
550 virtual void SendPeerAckTimerExpired(); |
|
551 virtual TUint16 MonitorTimeout(); |
|
552 virtual TUint16 RetransmissionTimeout(); |
|
553 virtual TUint16 PeerRetransmissionTimeout(); |
|
554 private: |
|
555 TUint8 iPollSFrameTransmitCount; |
|
556 TBool iDeliverOutgoingDataAndSignalToSduQWhenDone; |
|
557 |
|
558 RL2CapErtmOutgoingQueue iOutgoingQ; |
|
559 RL2CapErtmTimerManager iTimerMan; |
|
560 CL2CapErtmDataReceiver* iReceiver; |
|
561 CL2CapErtmDataTransmitter* iTransmitter; |
|
562 }; |
|
563 |
|
564 #include "L2CapEnhancedDataController.inl" |
|
565 |
|
566 #endif /*L2CAPENHANCEDDATACONTROLLER_H*/ |