|
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 // |
|
15 |
|
16 #include <obex/internal/obexinternalheader.h> |
|
17 #include <es_sock.h> |
|
18 #include "logger.h" |
|
19 #include "obextransportfaults.h" |
|
20 #ifdef __FLOG_ACTIVE |
|
21 _LIT8(KLogComponent, "OBEXCT"); |
|
22 #endif |
|
23 |
|
24 #ifdef _DEBUG |
|
25 _LIT(KPanicCat, "ObexIntHdr"); |
|
26 #endif |
|
27 |
|
28 /** @internalComponent */ |
|
29 const TUint8 KObexHeaderTypeMask = 0xc0; |
|
30 |
|
31 /** |
|
32 Constructor |
|
33 */ |
|
34 EXPORT_C TObexInternalHeader::TObexInternalHeader () |
|
35 { |
|
36 LOG_LINE |
|
37 LOG_FUNC |
|
38 |
|
39 iHVSize = 0; |
|
40 } |
|
41 |
|
42 /** |
|
43 Try to read a header from aSource, taking up to a maximum of aMaxSize bytes. |
|
44 Returns the number of bytes actually read out. |
|
45 */ |
|
46 TUint16 TObexInternalHeader::ParseIn (TUint8* aSource, const TUint16 aMaxSize) |
|
47 { |
|
48 iHVSize = 1; |
|
49 if (aMaxSize < KObexHeaderHIShortSize + 1) return (0); |
|
50 SetHI (STATIC_CAST(THeaderID, *aSource)); |
|
51 |
|
52 switch (HIType ()) |
|
53 { |
|
54 case EUnicode: |
|
55 case EByteSeq: |
|
56 if (aMaxSize < KObexHeaderHILongSize) return (0); |
|
57 { |
|
58 TInt hvsize = BigEndian::Get16 (&aSource[1]) - HISize (); |
|
59 if (hvsize < 0) return (0); |
|
60 iHVSize = STATIC_CAST(TUint16, hvsize); |
|
61 } |
|
62 iHV.iObex = &aSource[KObexHeaderHILongSize]; |
|
63 iHVRep = EHVObexDefault; |
|
64 break; |
|
65 case E4Byte: |
|
66 iHVSize = 4; //fallthrough to case E1Byte |
|
67 case E1Byte: |
|
68 iHV.iObex = &aSource[KObexHeaderHIShortSize]; |
|
69 iHVRep = EHVObexDefault; |
|
70 break; |
|
71 default: |
|
72 return (0); |
|
73 } |
|
74 if (aMaxSize < TotalSize ()) |
|
75 return (0); |
|
76 return (TotalSize ()); |
|
77 } |
|
78 |
|
79 /** |
|
80 Write this header out to aDest, writting up to a max of aMaxSize bytes. |
|
81 returns the number of bytes actually written. |
|
82 All complicated by the fact that the internal rep. of the data in the header |
|
83 might be in one of a number of forms, as well as having to convert to the |
|
84 correct OBEX form, all with heavy consideration for thick and thin builds. |
|
85 For unicode on the wire, we also need to to endian conversion too.... |
|
86 */ |
|
87 TUint16 TObexInternalHeader::WriteOut (TUint8* aDest, const TUint16 aMaxSize) const |
|
88 { |
|
89 TInt byteswritten = TotalSize (); |
|
90 if (aMaxSize < byteswritten) return (0); |
|
91 *aDest = iHI; |
|
92 |
|
93 switch (HIType ()) |
|
94 { |
|
95 case EUnicode: |
|
96 case EByteSeq: |
|
97 // The following is arranged in order of expected frequency of use. |
|
98 // The less common the conversion, the less effort is put to efficiency. |
|
99 if (iHVRep == EHVDefered) |
|
100 {// The data will actually be written after the header is inserted. |
|
101 byteswritten = iHVMaxSize + KObexHeaderHILongSize; |
|
102 if (byteswritten > aMaxSize) |
|
103 byteswritten = aMaxSize; |
|
104 iHV.iDefered->Set (&aDest[KObexHeaderHILongSize], 0, byteswritten - KObexHeaderHILongSize); |
|
105 } |
|
106 else if (iHVRep == EHVObexDefault) |
|
107 {// The easy case: just send the data directly |
|
108 Mem::Copy (&aDest[KObexHeaderHILongSize], iHV.iObex, iHVSize); |
|
109 } |
|
110 else |
|
111 {// Big time (Uniocde/Ascii) conversions necessary |
|
112 TBufC<40> numbuf; |
|
113 TPtr src (numbuf.Des ()); |
|
114 if (iHVRep == EHVInt) |
|
115 { |
|
116 if ( GetHVText(src) != KErrNone ) |
|
117 { |
|
118 return (0); |
|
119 } |
|
120 } |
|
121 else |
|
122 { |
|
123 src.Set (iHV.iMachine, iHVSize / sizeof (TText), iHVSize / sizeof (TText)); |
|
124 } |
|
125 TInt i; |
|
126 if (HIType () == EUnicode) |
|
127 {// Need to convert to Unicode, from internal machine rep |
|
128 byteswritten = KObexHeaderHILongSize; |
|
129 if(src.Length()) |
|
130 {// Only need null term if the length is non-zero |
|
131 byteswritten += (2 * (src.Length () + 1)); |
|
132 // 2 = Unicode word size, + 1 for null terminal |
|
133 if (aMaxSize < byteswritten) return (0); |
|
134 for (i = 0; i < src.Length (); ++i) |
|
135 BigEndian::Put16 (&aDest[KObexHeaderHILongSize + (i * 2)], src[i]); |
|
136 BigEndian::Put16 (&aDest[KObexHeaderHILongSize + (i * 2)], 0); // Null term |
|
137 } |
|
138 } |
|
139 else // HIType == ByteSeq |
|
140 {// Convert to obex "byte sequence", from internal machine rep. |
|
141 byteswritten = KObexHeaderHILongSize + src.Length (); |
|
142 if (aMaxSize < byteswritten) return (0); |
|
143 for (i = 0; i < src.Length (); ++i) |
|
144 aDest[KObexHeaderHILongSize + i] = STATIC_CAST(TUint8, src[i]); |
|
145 } |
|
146 } |
|
147 BigEndian::Put16 (&aDest[1], STATIC_CAST(TUint16, byteswritten)); |
|
148 break; |
|
149 case E1Byte: |
|
150 aDest[KObexHeaderHIShortSize] = STATIC_CAST(TUint8, HVInt ()); |
|
151 break; |
|
152 case E4Byte: |
|
153 BigEndian::Put32 (&aDest[KObexHeaderHIShortSize], HVInt ()); |
|
154 break; |
|
155 default: |
|
156 return (0); |
|
157 } |
|
158 return (STATIC_CAST(TUint16, byteswritten)); |
|
159 } |
|
160 |
|
161 /** |
|
162 Setter for the header id |
|
163 |
|
164 @param aHID Header id |
|
165 */ |
|
166 EXPORT_C void TObexInternalHeader::SetHI (THeaderID aHID) |
|
167 { |
|
168 LOG_LINE |
|
169 LOG_FUNC |
|
170 |
|
171 iHI = aHID; |
|
172 } |
|
173 |
|
174 /** |
|
175 Setter for the header id and header value |
|
176 |
|
177 @param aHID Header id |
|
178 @param aValue Value for the header |
|
179 @see SetHI |
|
180 */ |
|
181 EXPORT_C void TObexInternalHeader::Set (THeaderID aHID, TInt aValue) |
|
182 { |
|
183 LOG_LINE |
|
184 LOG_FUNC |
|
185 |
|
186 SetHI (aHID); |
|
187 iHV.iInt = aValue; |
|
188 iHVRep = EHVInt; |
|
189 } |
|
190 |
|
191 /** |
|
192 Setter for the header id, header value and size of the header value |
|
193 |
|
194 @param aHID Header id |
|
195 @param aHV Header value |
|
196 @param aHVSize Size of the header value |
|
197 @see SetHI |
|
198 */ |
|
199 EXPORT_C void TObexInternalHeader::Set (THeaderID aHID, TUint8* aHV, TInt aHVSize) |
|
200 { |
|
201 LOG_LINE |
|
202 LOG_FUNC |
|
203 |
|
204 __ASSERT_DEBUG (aHV, PANIC (KPanicCat, ETransportNullPointer)); |
|
205 __ASSERT_DEBUG (aHVSize >= 0, PANIC (KPanicCat, EInvalidHeaderSize)); |
|
206 __ASSERT_DEBUG (aHVSize < (TInt)(KMaxTUint16 - 3), PANIC (KPanicCat, EInvalidHeaderSize)); |
|
207 SetHI (aHID); |
|
208 iHV.iObex = aHV; |
|
209 iHVSize = STATIC_CAST(TUint16, aHVSize); |
|
210 iHVRep = EHVObexDefault; |
|
211 } |
|
212 |
|
213 /** |
|
214 Setter for the header id, header value and size of the header value |
|
215 |
|
216 @param aHID Header id |
|
217 @param aString Descriptor containing the header value and its size |
|
218 @see SetHI |
|
219 */ |
|
220 EXPORT_C void TObexInternalHeader::Set (THeaderID aHID, const TDesC& aString) |
|
221 { |
|
222 LOG_LINE |
|
223 LOG_FUNC |
|
224 |
|
225 __ASSERT_DEBUG (aString.Size () <= (TInt)(KMaxTUint16 - 3), PANIC(KPanicCat, EStringOverflow)); |
|
226 SetHI (aHID); |
|
227 iHV.iMachine = CONST_CAST(TText*, aString.Ptr ()); |
|
228 iHVSize = STATIC_CAST(TUint16, aString.Size ()); |
|
229 iHVRep = EHVMachineText; |
|
230 } |
|
231 |
|
232 /** |
|
233 Setter for the header id, the header value data inserter, min and max size |
|
234 |
|
235 @param aHID Header id |
|
236 @param aDataInserter Data inserter |
|
237 @param aMinSize Min size of header value |
|
238 @param aMaxSize Max size of header value |
|
239 @see SetHI |
|
240 */ |
|
241 EXPORT_C void TObexInternalHeader::SetDeferred (THeaderID aHID, TPtr8* aDataInserter, TInt aMinSize, TInt aMaxSize) |
|
242 { |
|
243 LOG_LINE |
|
244 LOG_FUNC |
|
245 |
|
246 __ASSERT_DEBUG (aMinSize > 0, PANIC(KPanicCat, EInvalidHeaderSize)); |
|
247 SetHI (aHID); |
|
248 iHV.iDefered = aDataInserter; |
|
249 iHVSize = STATIC_CAST (TUint16, aMinSize); |
|
250 if (aMaxSize > TInt(KMaxTUint16 - KObexHeaderHILongSize)) |
|
251 iHVMaxSize = TUint16(KMaxTUint16 - (TUint)(KObexHeaderHILongSize)); |
|
252 else |
|
253 iHVMaxSize = STATIC_CAST (TUint16, aMaxSize > aMinSize ? aMaxSize : aMinSize); |
|
254 iHVRep = EHVDefered; |
|
255 aDataInserter->Set (NULL, 0, 0); |
|
256 } |
|
257 |
|
258 /** |
|
259 Returns the internal header ID |
|
260 |
|
261 @return Internal header ID |
|
262 */ |
|
263 EXPORT_C TObexInternalHeader::THeaderID TObexInternalHeader::HI () const |
|
264 { |
|
265 LOG_LINE |
|
266 LOG_FUNC |
|
267 |
|
268 return (iHI); |
|
269 } |
|
270 |
|
271 /** |
|
272 Returns the internal header type |
|
273 |
|
274 @return Internal header type |
|
275 */ |
|
276 EXPORT_C TObexInternalHeader::THeaderType TObexInternalHeader::HIType () const |
|
277 { |
|
278 LOG_LINE |
|
279 LOG_FUNC |
|
280 |
|
281 return (STATIC_CAST(THeaderType, (HI () & KObexHeaderTypeMask))); |
|
282 } |
|
283 |
|
284 /** |
|
285 Returns the internal header value |
|
286 |
|
287 @return Internal header value |
|
288 */ |
|
289 EXPORT_C TInt TObexInternalHeader::HVInt () const |
|
290 { |
|
291 LOG_LINE |
|
292 LOG_FUNC |
|
293 |
|
294 if (iHVRep == EHVObexDefault) |
|
295 { |
|
296 if (HIType () == E4Byte) |
|
297 return (BigEndian::Get32 (iHV.iObex)); |
|
298 else |
|
299 return (*iHV.iObex); |
|
300 } |
|
301 if (iHVRep == EHVInt) |
|
302 return (iHV.iInt); |
|
303 // Don't bother converting machine strings to ints! |
|
304 return (0); |
|
305 } |
|
306 |
|
307 /** |
|
308 Returns a pointer to the internal header value byte sequence |
|
309 |
|
310 @return Pointer to the internal header value byte sequence |
|
311 */ |
|
312 EXPORT_C TUint8* TObexInternalHeader::HVByteSeq () const |
|
313 { |
|
314 LOG_LINE |
|
315 LOG_FUNC |
|
316 |
|
317 if (iHVRep == EHVObexDefault) |
|
318 return (iHV.iObex); |
|
319 // Could do alsorts of fancy stuff else. |
|
320 return (NULL); |
|
321 } |
|
322 |
|
323 /** |
|
324 Returns header value as text |
|
325 |
|
326 Take the HV and put "an appropriate" representation of it into aString. |
|
327 The stable mate of "WriteOut" in terms of nasty conversions, but again all |
|
328 necessary in order to support both thick & thin builds. |
|
329 |
|
330 @return Error code |
|
331 */ |
|
332 EXPORT_C TInt TObexInternalHeader::GetHVText (TDes& aString) const |
|
333 { |
|
334 LOG_LINE |
|
335 LOG_FUNC |
|
336 |
|
337 switch (iHVRep) |
|
338 { |
|
339 case EHVMachineText: |
|
340 FLOG(_L8("EHVMachineText")); |
|
341 if (aString.Length () < STATIC_CAST(TInt, TUint(iHVSize / sizeof(TText)))) |
|
342 { |
|
343 FLOG(_L8("Target descriptor too small")); |
|
344 return (KErrBadDescriptor); |
|
345 } |
|
346 |
|
347 aString.Copy (TPtr (iHV.iMachine, iHVSize / sizeof(TText), iHVSize / sizeof(TText))); |
|
348 return (KErrNone); |
|
349 |
|
350 case EHVObexDefault: |
|
351 FLOG(_L8("EHVObexDefault")); |
|
352 if (HIType () == EUnicode) |
|
353 { |
|
354 // Unicode: read big endian and shove into descriptor |
|
355 FLOG(_L8(" -Unicode")); |
|
356 if (aString.MaxLength () < iHVSize / 2) |
|
357 { |
|
358 FLOG(_L8("Target descriptor too small")); |
|
359 return (KErrBadDescriptor); |
|
360 } |
|
361 |
|
362 aString.SetLength (iHVSize / 2); |
|
363 TInt i; |
|
364 for (i = 0; i < iHVSize / 2; ++i) |
|
365 { |
|
366 aString[i] = STATIC_CAST (TText, BigEndian::Get16 (&iHV.iObex[i * 2])); |
|
367 } |
|
368 |
|
369 if (i > 0 && aString[--i] == 0) // Zero length headers have no null terminal! |
|
370 { |
|
371 // Make sure last char is null term, and chop it off |
|
372 aString.SetLength (i); |
|
373 } |
|
374 |
|
375 return (KErrNone); |
|
376 } |
|
377 |
|
378 if (HIType () == EByteSeq) |
|
379 { |
|
380 // Descriptors can actually do the conversion for us here. |
|
381 FLOG(_L8(" -ByteSeq")); |
|
382 if (aString.MaxLength () < iHVSize) |
|
383 { |
|
384 FLOG(_L8("Target descriptor too small")); |
|
385 return (KErrBadDescriptor); |
|
386 } |
|
387 |
|
388 aString.Copy (TPtrC8 (iHV.iObex, iHVSize)); |
|
389 return (KErrNone); |
|
390 } |
|
391 break; |
|
392 |
|
393 case EHVInt: |
|
394 FLOG(_L8("EHVInt")); |
|
395 aString.Num (HVInt ()); |
|
396 return (KErrNone); |
|
397 |
|
398 default: |
|
399 break; |
|
400 } |
|
401 |
|
402 FLOG(_L8("Unknown error...")); |
|
403 aString.SetLength (0); |
|
404 return (KErrGeneral); |
|
405 } |
|
406 |
|
407 TUint16 TObexInternalHeader::DoTotalSize () const |
|
408 { |
|
409 return (STATIC_CAST(TUint16, HISize () + HVSize ())); |
|
410 } |
|
411 |
|
412 /** |
|
413 Returns the size of the internal header |
|
414 |
|
415 @return Size of the internal header |
|
416 */ |
|
417 EXPORT_C TUint16 TObexInternalHeader::HISize () const |
|
418 { |
|
419 LOG_LINE |
|
420 LOG_FUNC |
|
421 |
|
422 switch (HIType ()) |
|
423 { |
|
424 case EUnicode: |
|
425 case EByteSeq: |
|
426 return (KObexHeaderHILongSize); |
|
427 case E1Byte: |
|
428 case E4Byte: |
|
429 return (KObexHeaderHIShortSize); |
|
430 default: |
|
431 return (0); |
|
432 } |
|
433 } |
|
434 |
|
435 /** |
|
436 Returns the size of the internal header value |
|
437 |
|
438 @return Size of the internal header value |
|
439 */ |
|
440 EXPORT_C TUint16 TObexInternalHeader::HVSize () const |
|
441 { |
|
442 LOG_LINE |
|
443 LOG_FUNC |
|
444 |
|
445 if (iHVRep == EHVObexDefault || iHVRep == EHVDefered) |
|
446 return (iHVSize); |
|
447 TInt fact = 1; |
|
448 switch (HIType ()) |
|
449 { |
|
450 case EUnicode: |
|
451 fact = 2; //fallthrough to case EByteSeq |
|
452 case EByteSeq: |
|
453 if (iHVRep == EHVMachineText) |
|
454 return (STATIC_CAST(TUint16, fact * iHVSize / sizeof (TText))); |
|
455 return (40); |
|
456 case E1Byte: |
|
457 return (1); |
|
458 case E4Byte: |
|
459 return (4); |
|
460 default: |
|
461 return (0); |
|
462 } |
|
463 } |