|
1 // Copyright (c) 1997-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 // MBuf Packet Info Headers |
|
15 // |
|
16 // |
|
17 |
|
18 #include <nifmbuf.h> |
|
19 |
|
20 |
|
21 // |
|
22 // MBuf Manager Extensions |
|
23 // |
|
24 |
|
25 __IMPLEMENT_CLEANUP(RMBufPacketBase, Free) |
|
26 |
|
27 EXPORT_C RMBufPacketBase::RMBufPacketBase() |
|
28 /** |
|
29 Constructor |
|
30 */ |
|
31 { |
|
32 iInfo=NULL; |
|
33 } |
|
34 |
|
35 EXPORT_C void RMBufPacketBase::CopyInfoL(RMBufPacketBase& aNewPkt) |
|
36 /** |
|
37 Copy the information header |
|
38 @param aNewPkt the new packet where the header is copied to |
|
39 */ |
|
40 { |
|
41 aNewPkt.iInfo = (RMBufPktInfo*)iInfo->CopyL(); |
|
42 } |
|
43 |
|
44 |
|
45 EXPORT_C RMBufPktInfo* RMBufPacketBase::PeekInfo() |
|
46 /** |
|
47 Allows the packet info header to be accessed without unpacking |
|
48 @return the packet info header |
|
49 */ |
|
50 { |
|
51 __ASSERT_DEBUG(iInfo==NULL, MBufExtPanic(EMbExtPanic_PacketHeader)); |
|
52 __ASSERT_ALWAYS(!IsEmpty(), MBufExtPanic(EMbExtPanic_PacketHeaderEmpty)); |
|
53 __ASSERT_ALWAYS(First()->Type()==EMBufHeader, MBufExtPanic(EMbExtPanic_PacketHeader)); |
|
54 return (RMBufPktInfo*)(First()->Ptr()); |
|
55 } |
|
56 |
|
57 |
|
58 EXPORT_C RMBufPktInfo* RMBufPacketBase::Unpack() |
|
59 /** |
|
60 Splits off the info header |
|
61 @return the packet info header |
|
62 */ |
|
63 { |
|
64 __ASSERT_DEBUG(iInfo==NULL, MBufExtPanic(EMbExtPanic_PacketHeader)); |
|
65 __ASSERT_ALWAYS(!IsEmpty(), MBufExtPanic(EMbExtPanic_PacketHeaderEmpty)); |
|
66 __ASSERT_ALWAYS(First()->Type()==EMBufHeader, MBufExtPanic(EMbExtPanic_PacketHeader)); |
|
67 iInfo = (RMBufPktInfo*)(Remove()->Ptr()); |
|
68 return Info(); |
|
69 } |
|
70 |
|
71 |
|
72 EXPORT_C void RMBufPacketBase::Pack() |
|
73 /** |
|
74 Combine info header with data ready for queueing |
|
75 */ |
|
76 { |
|
77 __ASSERT_ALWAYS(iInfo!=NULL, MBufExtPanic(EMbExtPanic_PacketHeader)); |
|
78 Prepend(iInfo->MBuf()); |
|
79 iInfo = NULL; |
|
80 } |
|
81 |
|
82 |
|
83 EXPORT_C void RMBufPacketBase::SetInfo(RMBufPktInfo* aInfo) |
|
84 /** |
|
85 Associate an info header with packet |
|
86 (Also used to disassociate if aInfo==NULL) |
|
87 @param aInfo the info header |
|
88 */ |
|
89 { |
|
90 iInfo = aInfo; |
|
91 } |
|
92 |
|
93 |
|
94 EXPORT_C void RMBufPacketBase::FreeInfo() |
|
95 /** |
|
96 Free info header only |
|
97 */ |
|
98 { |
|
99 if (iInfo) |
|
100 { |
|
101 iInfo->MBuf()->Free(); |
|
102 iInfo = NULL; |
|
103 } |
|
104 } |
|
105 |
|
106 EXPORT_C void RMBufPacketBase::Free() |
|
107 /** |
|
108 Delete info and data |
|
109 */ |
|
110 { |
|
111 FreeInfo(); |
|
112 RMBufChain::Free(); |
|
113 } |
|
114 |
|
115 |
|
116 EXPORT_C RMBufPktInfo* RMBufPacketBase::Info() |
|
117 /** |
|
118 Returns pointer to info header |
|
119 @return the info header |
|
120 */ |
|
121 { |
|
122 __ASSERT_ALWAYS(iInfo!=NULL, MBufExtPanic(EMbExtPanic_PacketHeader)); |
|
123 return (RMBufPktInfo*)iInfo; |
|
124 } |
|
125 |
|
126 EXPORT_C RMBufPktInfo* RMBufPacketBase::CreateL(RMBufQ& aPacket, TInt aLength, TUint aMBufHdrSize) |
|
127 /** |
|
128 Create an MBuf chain from an received MBuf Queue |
|
129 - used by Interfaces |
|
130 - queue in emptied. |
|
131 @param aPacket the MBuf Queue |
|
132 @param aLength the chain length |
|
133 @param aMBufHdrSize the MBuf header size |
|
134 @return the info header |
|
135 */ |
|
136 { |
|
137 iInfo = new (ELeave, aMBufHdrSize-sizeof(RMBufPktInfo)) RMBufPktInfo; |
|
138 Assign(aPacket); |
|
139 iInfo->iLength = aLength==0 ? Length() : aLength; |
|
140 return (RMBufPktInfo*)iInfo; |
|
141 } |
|
142 |
|
143 EXPORT_C RMBufPktInfo* RMBufPacketBase::CreateL(TInt aLength, TUint aMBufHdrSize) |
|
144 /** |
|
145 Create an empty MBuf chain of required length and header size |
|
146 - used by Interfaces |
|
147 - refer RMBufChain::AllocL notes regarding the deliberate decision not to provide an overloaded min/max mbuf size variant |
|
148 @param aLength the chain length |
|
149 @param aMBufHdrSize the header size |
|
150 @return the info header |
|
151 */ |
|
152 { |
|
153 RMBufChain::AllocL(aLength); |
|
154 CleanupStack::PushL(*this); |
|
155 iInfo = new (ELeave, aMBufHdrSize-sizeof(RMBufPktInfo)) RMBufPktInfo; |
|
156 CleanupStack::Pop(); |
|
157 iInfo->iLength = aLength; |
|
158 return (RMBufPktInfo*)iInfo; |
|
159 } |
|
160 |
|
161 EXPORT_C RMBufPktInfo* RMBufPacketBase::CreateL(const TDesC8 &aDesc, TInt aHdrSize, TUint aMBufHdrSize) |
|
162 /** |
|
163 Create a MBuf chain and header for receiving from a descriptor |
|
164 - used by SAPs |
|
165 @param aDesc the buffer which contains the header info |
|
166 @param aHdrSize the header size |
|
167 @param aMBufHdrSize the MBuf header size |
|
168 @return the info header |
|
169 */ |
|
170 { |
|
171 RMBufChain::CreateL(aDesc, aHdrSize); |
|
172 CleanupStack::PushL(*this); |
|
173 iInfo = new (ELeave, aMBufHdrSize-sizeof(RMBufPktInfo)) RMBufPktInfo; |
|
174 CleanupStack::Pop(); |
|
175 iInfo->iLength = aDesc.Length()+aHdrSize; |
|
176 return (RMBufPktInfo*)iInfo; |
|
177 } |
|
178 |
|
179 EXPORT_C RMBufPktInfo* RMBufPacketBase::CreateCopyL(const RMBufQ& aPacket, TInt aOffset, TInt aLength, TInt aHdrSize, TUint aMBufHdrSize) |
|
180 /** |
|
181 Create a MBuf chain from an received MBuf Queue |
|
182 - used by Interfaces |
|
183 @param aPacket the MBuf Queue |
|
184 @param aOffset the offset |
|
185 @param aLength the length of the data to be copied |
|
186 @param aHdrSize the header size |
|
187 @param aMBufHdrSize the MBuf Header Size |
|
188 @return the info header |
|
189 */ |
|
190 { |
|
191 iInfo = new (ELeave, aMBufHdrSize-sizeof(RMBufPktInfo)) RMBufPktInfo; |
|
192 iInfo->iLength = (aLength==0 ? Length() : aLength) + aHdrSize; |
|
193 ((RMBufChain&)aPacket).CopyL(*this, aOffset, aLength); |
|
194 PrependL(aHdrSize); |
|
195 return (RMBufPktInfo*)iInfo; |
|
196 } |
|
197 |
|
198 EXPORT_C RMBufPktInfo* RMBufPacketBase::CreateCopyL(RMBufStreamQ& aStream, TInt aOffset, TInt aLength, TInt aHdrSize, TUint aMBufHdrSize) |
|
199 /** |
|
200 Create a MBuf chain by copying data from a stream queue (basically an RMBufQ) |
|
201 aOffset and aLength specify location in stream queue. |
|
202 @param aStream the stream queue |
|
203 @param aOffset the offset |
|
204 @param aLength the data length |
|
205 @param aHdrSize the header size |
|
206 @param aMBufHdrSize the MBuf Header size |
|
207 @return the info header |
|
208 */ |
|
209 { |
|
210 iInfo = new (ELeave, aMBufHdrSize-sizeof(RMBufPktInfo)) RMBufPktInfo; |
|
211 iInfo->iLength = (aLength==0 ? Length() : aLength) + aHdrSize; |
|
212 aStream.CopySegmentL(*this, aOffset, aLength); |
|
213 PrependL(aHdrSize); |
|
214 return (RMBufPktInfo*)iInfo; |
|
215 } |
|
216 |
|
217 |
|
218 EXPORT_C RMBufPktInfo* RMBufPacketBase::CreateCopyL(const RMBufPktQ& aList, TInt aHdrSize, TUint aMBufHdrSize) |
|
219 /** |
|
220 Build a MBuf chain by copying a packet queue list, leaving space on the front |
|
221 for a header. (Very heavily used in PPP option processing). |
|
222 This is specially coded rather than using combination of RMBufChain::CopyL |
|
223 and RMBufChain::AppendL to ensure that the resulting packet is stored efficiently. |
|
224 - refer RMBufChain::AllocL notes regarding the deliberate decision not to provide an overloaded min/max mbuf size variant |
|
225 @param aList the packet queue |
|
226 @param aHdrSize the header size |
|
227 @param aMBufHdrSize the MBuf Header size |
|
228 @return the info header |
|
229 */ |
|
230 { |
|
231 // min K_MBufSmallSize sized mbuf is a valid assumption, because all headers are assumed to derive from a cell, which in turn is size K_MBufSmallSize |
|
232 __ASSERT_ALWAYS(aHdrSize<KMBufSmallSize, MBufExtPanic(EMbExtPanic_HeaderTooBig)); |
|
233 |
|
234 iInfo = new (ELeave, aMBufHdrSize-sizeof(RMBufPktInfo)) RMBufPktInfo; |
|
235 |
|
236 RMBufChain i; |
|
237 |
|
238 // Get total length of chain needed |
|
239 TInt len = 0; |
|
240 i = aList.First(); |
|
241 while (!i.IsEmpty()) |
|
242 { |
|
243 len += i.Length(); |
|
244 i = i.Next(); |
|
245 } |
|
246 |
|
247 // Allocate the chain |
|
248 iInfo->iLength = len+aHdrSize; |
|
249 AllocL(iInfo->iLength); |
|
250 |
|
251 // Do the copy |
|
252 TInt n, n1, n2; |
|
253 TUint8* p1, * p2; |
|
254 RMBuf* m1, * m2; |
|
255 |
|
256 i = aList.First(); |
|
257 m1 = i.First(); |
|
258 p1 = m1->Ptr(); |
|
259 n1 = m1->Length(); |
|
260 |
|
261 m2 = First(); |
|
262 p2 = m2->Ptr(); |
|
263 n2 = m2->Length(); |
|
264 |
|
265 if (aHdrSize>0) |
|
266 { |
|
267 if (aHdrSize==KMBufSmallSize) // min K_MBufSmallSize sized mbuf is a valid assumption, because all headers are assumed to derive from a cell, which in turn is size K_MBufSmallSize |
|
268 { |
|
269 m2 = m2->Next(); |
|
270 p2 = m2->Ptr(); |
|
271 n2 = m2->Length(); |
|
272 } |
|
273 else |
|
274 { |
|
275 p2 += aHdrSize; |
|
276 n2 -= aHdrSize; |
|
277 } |
|
278 } |
|
279 |
|
280 while (len>0) |
|
281 { |
|
282 n = n1<n2 ? n1 : n2; |
|
283 Mem::Copy(p2, p1, n); |
|
284 if (n1 -= n, n1==0) |
|
285 { |
|
286 if (m1 = m1->Next(), m1==NULL) |
|
287 { |
|
288 i = i.Next(); |
|
289 m1 = i.First(); |
|
290 } |
|
291 p1 = m1->Ptr(); |
|
292 n1 = m1->Length(); |
|
293 } |
|
294 else |
|
295 p1 += n; |
|
296 if (n2 -= n, n2==0) |
|
297 { |
|
298 m2 = m2->Next(); |
|
299 p2 = m2->Ptr(); |
|
300 n2 = m2->Length(); |
|
301 } |
|
302 else |
|
303 p2 += n; |
|
304 len -= n; |
|
305 } |
|
306 |
|
307 return (RMBufPktInfo*)iInfo; |
|
308 } |
|
309 |
|
310 |
|
311 EXPORT_C void RMBufPacketBase::TrimStart(TInt aOffset) |
|
312 /** |
|
313 As RMBufChain::TrimStart, but updates length in info header |
|
314 @param aOffset the offset |
|
315 */ |
|
316 { |
|
317 RMBufChain::TrimStart(aOffset); |
|
318 iInfo->iLength -= aOffset; |
|
319 } |
|
320 |
|
321 |
|
322 EXPORT_C void RMBufPacketBase::TrimEnd(TInt aOffset) |
|
323 /** |
|
324 As RMBufChain::TrimEnd, but updates length in info header |
|
325 @param aOffset the offset |
|
326 */ |
|
327 { |
|
328 // !BUG! Work around |
|
329 if (aOffset==0) |
|
330 RMBufChain::Free(); |
|
331 else |
|
332 // End work-around |
|
333 RMBufChain::TrimEnd(aOffset); |
|
334 iInfo->iLength = aOffset; |
|
335 } |
|
336 |
|
337 |
|
338 EXPORT_C RMBufPktInfo* RMBufPacketBase::NewInfoL(TUint aMBufHdrSize) |
|
339 /** |
|
340 Create an info header |
|
341 @param aMBufHdrSize the MBuf header size |
|
342 @return the info header |
|
343 */ |
|
344 { |
|
345 iInfo = new (ELeave, aMBufHdrSize-sizeof(RMBufPktInfo)) RMBufPktInfo; |
|
346 return (RMBufPktInfo*)iInfo; |
|
347 } |
|
348 |
|
349 EXPORT_C RMBufPktInfo* RMBufPacketBase::NewInfo(TUint aMBufHdrSize) |
|
350 /** |
|
351 Create an info header |
|
352 @param aMBufHdrSize the MBuf header size |
|
353 @return the info header |
|
354 */ |
|
355 { |
|
356 iInfo = new (aMBufHdrSize-sizeof(RMBufPktInfo)) RMBufPktInfo; |
|
357 return (RMBufPktInfo*)iInfo; |
|
358 } |
|
359 |
|
360 EXPORT_C void RMBufPacketBase::CopyPackedL(RMBufChain& aPacket) |
|
361 /** |
|
362 Copy an entire packed packet, complete with info header |
|
363 @param aPacket the packet |
|
364 */ |
|
365 { |
|
366 __ASSERT_DEBUG(iInfo==NULL, MBufExtPanic(EMbExtPanic_PacketHeader)); |
|
367 __ASSERT_ALWAYS(!aPacket.IsEmpty(), MBufExtPanic(EMbExtPanic_PacketHeaderEmpty)); |
|
368 __ASSERT_ALWAYS(aPacket.First()->Type()==EMBufHeader, MBufExtPanic(EMbExtPanic_PacketHeader)); |
|
369 RMBuf* m = aPacket.Remove(); |
|
370 // |
|
371 // The following assumes that aPacket.CopyL would actually leave before it makes any change |
|
372 // to aPacket at all. Inspection of CopyL reveals that this is the case. |
|
373 // |
|
374 TRAPD(err, aPacket.CopyL(*this)); |
|
375 // |
|
376 // In case CopyL failed, we'd need to restore aPacket, so we'd call Prepend. |
|
377 // In case it succedded, we'd still need to call Prepend so that the info block remains the same. |
|
378 // Hence we call aPacket.Prepend irrespective of aPacket.CopyL failure. |
|
379 // |
|
380 aPacket.Prepend(m); |
|
381 User::LeaveIfError(err); |
|
382 |
|
383 RMBufPktInfo* info = (RMBufPktInfo*)((RMBufPktInfo*)(m->Ptr()))->CopyL(); |
|
384 Prepend(info->MBuf()); |
|
385 } |
|
386 |
|
387 EXPORT_C RMBufPktInfo* RMBufPacketBase::PeekInfoInChain(RMBufChain& aChain) |
|
388 /** |
|
389 Allows the packet info header to be accessed while still on a packet queue |
|
390 @param aChain the chain to be accessed |
|
391 @return the info header |
|
392 */ |
|
393 { |
|
394 __ASSERT_ALWAYS(!aChain.IsEmpty(), MBufExtPanic(EMbExtPanic_PacketHeaderEmpty)); |
|
395 __ASSERT_ALWAYS(aChain.First()->Type()==EMBufHeader, MBufExtPanic(EMbExtPanic_PacketHeader)); |
|
396 return (RMBufPktInfo*)(aChain.First()->Ptr()); |
|
397 } |
|
398 |
|
399 void MBufExtPanic(TMBufExtPanic aPanic) |
|
400 /** |
|
401 extra panic function that causes panic |
|
402 @param panic code |
|
403 */ |
|
404 { |
|
405 _LIT(mBufExtString,"MBufExt"); |
|
406 User::Panic(mBufExtString, aPanic); |
|
407 } |
|
408 |