|
1 // Copyright (c) 2004-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 L2CAPSDUQUEUE_H_ |
|
17 #define L2CAPSDUQUEUE_H_ |
|
18 |
|
19 #include <bt_sock.h> |
|
20 |
|
21 #include "L2CapSDU.h" |
|
22 |
|
23 |
|
24 class TL2CapDataControllerConfig; |
|
25 class CL2CapBasicDataController; |
|
26 class CL2CAPMux; |
|
27 class CL2CAPConnectionSAP; |
|
28 |
|
29 NONSHARABLE_CLASS(CL2CapSDUQueue) : public CBase, |
|
30 public ML2CapSDUHandler |
|
31 { |
|
32 public: |
|
33 // Can buffer this many outgoing SDUs. |
|
34 const static TUint8 KDefaultOutboundQueueSize = 2; |
|
35 |
|
36 // Can buffer this many incoming SDUs. That's after reassembly, doesn't |
|
37 // include I-Frames that a data controller can buffer on its own. |
|
38 // Note: leaving this at 5 until the problem with legacy data controllers putting |
|
39 // frames on the Q even when they've been told not to is fixed - then should probably |
|
40 // decrease to 2. |
|
41 const static TUint8 KInboundQueueFlowCtrlThreshold = 5; |
|
42 |
|
43 // During normal shutdown initiated by our upper layer we try to deliver |
|
44 // all outstanding data, but kill it brutally if this time is exceeded. |
|
45 const static TUint8 KOutgoingQueueClosingTimer = 60; |
|
46 |
|
47 enum TIncomingSDUQueueCloseAction |
|
48 { |
|
49 EDrainIncomingQueue, |
|
50 EImmediatelyCloseIncomingQueue, |
|
51 }; |
|
52 |
|
53 enum TOutgoingSDUQueueCloseAction |
|
54 { |
|
55 EDrainOutgoingQueue, |
|
56 EImmediatelyCloseOutgoingQueue, |
|
57 }; |
|
58 |
|
59 static CL2CapSDUQueue* NewLC(CL2CAPConnectionSAP& aL2CapSap, |
|
60 TL2CAPPort aLocalCID, |
|
61 TL2CAPPort aRemoteCID, |
|
62 CL2CAPMux& aMuxer, |
|
63 TUint16 aPDUSize, |
|
64 TUint8 aOutboundQueueSize, |
|
65 TL2CapDataControllerConfig* aConfig, |
|
66 TUint16 aFlushTimeout, |
|
67 TUint16 aMaxOutgoingMTU, |
|
68 TUint16 aMaxIncomingMTU, |
|
69 TBool aCanDropSdus); |
|
70 static CL2CapSDUQueue* NewL(CL2CAPConnectionSAP& aL2CapSap, |
|
71 TL2CAPPort aLocalCID, |
|
72 TL2CAPPort aRemoteCID, |
|
73 CL2CAPMux& aMuxer, |
|
74 TUint16 aPDUSize, |
|
75 TUint8 aOutboundQueueSize, |
|
76 TL2CapDataControllerConfig* aConfig, |
|
77 TUint16 aFlushTimeout, |
|
78 TUint16 aMaxOutgoingMTU, |
|
79 TUint16 aMaxIncomingMTU, |
|
80 TBool aCanDropSdus); |
|
81 |
|
82 ~CL2CapSDUQueue(); |
|
83 |
|
84 static TInt CanSendAsyncCallBack(TAny *aSDUQueue); |
|
85 static TInt SDUsSentAsyncCallBack(TAny *aSDUQueue); |
|
86 static TInt QueueClosingAsyncCallBack(TAny *aSDUQueue); |
|
87 |
|
88 static TInt OutgoingQueueClosingTimerExpired(TAny *aSDUQueue); |
|
89 |
|
90 void ProcessFlushTimerExpiry(CL2CapSDU& aL2CapSDU); |
|
91 |
|
92 HL2CapPDU* GetPDU(); |
|
93 inline TBool HavePDUToSend() const; |
|
94 |
|
95 TInt PutIFramePDU(RMBufChain& dataFrame); |
|
96 void PutBFramePDU(RMBufChain& dataFrame); |
|
97 |
|
98 void FlushCurrentlyAssembledSdu(); |
|
99 void FlushOldestIncomingSdu(); |
|
100 inline TBool IsIncomingQueueFull() const; |
|
101 |
|
102 |
|
103 TInt Write(RMBufChain& aSDUData); |
|
104 void Read(RMBufChain& readData); |
|
105 |
|
106 void CloseSDUQueue(TIncomingSDUQueueCloseAction aIncomingQueueAction = EImmediatelyCloseIncomingQueue, |
|
107 TOutgoingSDUQueueCloseAction aOutgoingQueueAction = EImmediatelyCloseOutgoingQueue); |
|
108 |
|
109 void DataControllerDeliveredOutgoingData(); |
|
110 |
|
111 inline void SuspendSDUQueue(); |
|
112 void ResumeSDUQueue(TL2CapDataControllerConfig* aConfig, |
|
113 TUint16 aFlushTimeout, |
|
114 TUint16 aPDUSize, |
|
115 TUint16 aMaxOutgoingMTU, |
|
116 TUint16 aMaxIncomingMTU); |
|
117 void UpdateChannelPriority(TUint8 aNewPriority); |
|
118 void ErrorD(TInt aErrorCode); |
|
119 |
|
120 #ifdef _DEBUG |
|
121 TInt GetDataPlaneConfig(TL2DataPlaneConfig& conf) const; |
|
122 void PretendIncomingSduQFull(TBool aIncomingSduQFull); |
|
123 #endif |
|
124 |
|
125 inline TUint16 MaxOutgoingMTU() const; |
|
126 inline TUint16 MaxIncomingMTU() const; |
|
127 |
|
128 inline TUint16 MaximumPDUSize() const; |
|
129 inline TUint16 OptimalPDUSize() const; |
|
130 inline void SetOptimalPDUSize(TUint16 aPDUSize); |
|
131 |
|
132 TBool IsBasicDataVersion() const; |
|
133 |
|
134 private: |
|
135 void ConstructL(TL2CAPPort aLocalCID, TL2CAPPort aRemoteCID, CL2CAPMux& aMuxer, TL2CapDataControllerConfig* aConfig); |
|
136 |
|
137 CL2CapSDUQueue(CL2CAPConnectionSAP& aL2CapSap, |
|
138 TUint8 aOutboundQueueSize, |
|
139 TUint16 aPDUSize, |
|
140 TUint16 aFlushTimeout, |
|
141 TUint16 aMaxOutgoingMTU, |
|
142 TUint16 aMaxIncomingMTU, |
|
143 TBool aCanDropSdus); |
|
144 |
|
145 |
|
146 void SDURemovedFromOutboundQueue(); |
|
147 void CanSend(); |
|
148 void SDUsSent(); |
|
149 |
|
150 TInt HandleIncompleteSDU(RMBufChain& aIncompleteSDU); |
|
151 |
|
152 void TryToCloseQueue(); |
|
153 void SDUQueueClosed(); |
|
154 |
|
155 void StartOutgoingQueueClosingTimer(); |
|
156 void CancelOutgoingQueueClosingTimer(); |
|
157 void HandleOutgoingQueueClosingTimerExpired(); |
|
158 |
|
159 private: |
|
160 CL2CAPConnectionSAP& iL2CapSap; |
|
161 TUint8 iOutboundQueueSize; |
|
162 |
|
163 CL2CapBasicDataController* iDataController; |
|
164 |
|
165 TDblQue<CL2CapSDU> iOutgoingSDUs; |
|
166 TDblQue<CL2CapSDU> iOutgoingPulledSDUs; |
|
167 |
|
168 RMBufPktQ iIncomingSDUs; |
|
169 RMBufChain iCurrentIncomingSDU; |
|
170 TUint16 iCurrentIncomingSDULength; |
|
171 |
|
172 TUint16 iFlushTimeout; |
|
173 TUint16 iCurrentPDUSize; |
|
174 TUint16 iMaximumPDUSize; |
|
175 TUint16 iNegotiatedPDUSize; |
|
176 |
|
177 TUint8 iCurrentOutboundQueueLength; |
|
178 TUint16 iCurrentInboundQueueLength; |
|
179 TBool iOutboundSendingBlocked; |
|
180 TBool iOutboundQueueSuspended; |
|
181 |
|
182 CAsyncCallBack* iCanSendAsyncCallBack; |
|
183 CAsyncCallBack* iSDUSentAsyncCallBack; |
|
184 CAsyncCallBack* iQueueClosingCallBack; |
|
185 |
|
186 TBool iSDUQueuesClosing; |
|
187 TBool iIncomingQueueClosed; |
|
188 TBool iOutgoingQueueClosed; |
|
189 |
|
190 TDeltaTimerEntry iOutgoingQueueClosingTimer; |
|
191 TBool iOutgoingQueueClosingTimerRunning; |
|
192 |
|
193 TUint16 iMaxOutgoingMTU; |
|
194 TUint16 iMaxIncomingMTU; |
|
195 |
|
196 TBool iCanDropSdus; |
|
197 }; |
|
198 |
|
199 |
|
200 inline TBool CL2CapSDUQueue::IsIncomingQueueFull() const |
|
201 { |
|
202 return iCurrentInboundQueueLength >= KInboundQueueFlowCtrlThreshold; |
|
203 } |
|
204 |
|
205 inline TUint16 CL2CapSDUQueue::MaxOutgoingMTU() const |
|
206 { |
|
207 return iMaxOutgoingMTU; |
|
208 } |
|
209 |
|
210 inline TUint16 CL2CapSDUQueue::MaxIncomingMTU() const |
|
211 { |
|
212 return iMaxIncomingMTU; |
|
213 } |
|
214 |
|
215 inline TUint16 CL2CapSDUQueue::MaximumPDUSize() const |
|
216 { |
|
217 return iMaximumPDUSize; |
|
218 } |
|
219 |
|
220 inline TUint16 CL2CapSDUQueue::OptimalPDUSize() const |
|
221 { |
|
222 return iCurrentPDUSize; |
|
223 } |
|
224 |
|
225 inline void CL2CapSDUQueue::SetOptimalPDUSize(TUint16 aPDUSize) |
|
226 { |
|
227 iCurrentPDUSize = aPDUSize; |
|
228 } |
|
229 |
|
230 inline void CL2CapSDUQueue::SuspendSDUQueue() |
|
231 { |
|
232 iOutboundQueueSuspended = ETrue; |
|
233 } |
|
234 |
|
235 inline TBool CL2CapSDUQueue::HavePDUToSend() const |
|
236 { |
|
237 TBool havePDU = EFalse; |
|
238 if(!iOutgoingSDUs.IsEmpty()) |
|
239 { |
|
240 CL2CapSDU* sdu = iOutgoingSDUs.First(); |
|
241 // If the outbound queue is suspended, and this is the start |
|
242 // of a new SDU. Then don't send a PDU. |
|
243 if(!(iOutboundQueueSuspended && sdu->CurrentPDUIsFirstPDU())) |
|
244 { |
|
245 if (!sdu->IsSDUEmpty()) |
|
246 { |
|
247 havePDU = ETrue; |
|
248 } |
|
249 } |
|
250 } |
|
251 return havePDU; |
|
252 } |
|
253 |
|
254 #endif |