obex/obexprotocol/obextransport/src/obexinternalheader.cpp
changeset 0 d0791faffa3f
equal deleted inserted replaced
-1:000000000000 0:d0791faffa3f
       
     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 	}