messagingappbase/obexmtms/obexmtm/obexutil/source/ObexSdpUtils.cpp
changeset 0 72b543305e3a
child 23 238255e8b033
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     1 // Copyright (c) 2001-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 //class include
       
    17 #include "ObexSdpUtils.h"
       
    18 //system includes
       
    19 #include <es_sock.h>
       
    20 
       
    21 
       
    22 //
       
    23 // Bluetooth Assigned Numbers
       
    24 // The following constants come from the Bluetooth Specification Version 1.0B
       
    25 //
       
    26 
       
    27 const TUint32 KObexProtocolUUIDValue = 0x0008;
       
    28 const TUint32 KObexObjectPushUUIDValue = 0x1105;
       
    29 const TUint32 K_L2CAP_UUID_Value = 0x0100;
       
    30 const TUint32 K_RFCOMM_UUID_Value = 0x0003;
       
    31 
       
    32 const TUint16 KServiceClassIdAttributeId = 0x0001;
       
    33 const TUint16 KProtocolDescriptorListAttributeId = 0x0004;
       
    34 const TUint16 KBluetoothProfileDescriptorListAttributeId = 0x0009;
       
    35 const TUint16 KSupportedFormatsListAttributeId = 0x0303;
       
    36 
       
    37 
       
    38 //
       
    39 // The following structures are used to validate the record we receive from a remote
       
    40 // device
       
    41 //
       
    42 
       
    43 const TInt KAttributes = 4;
       
    44 const TInt KMaxComponents = 8;
       
    45 const TInt KTAttributeComponentMembers = 3;
       
    46 
       
    47 const TUint16 KExpectedAttributes[KAttributes] =
       
    48 	{
       
    49 	KServiceClassIdAttributeId,
       
    50 	KProtocolDescriptorListAttributeId,
       
    51 	KBluetoothProfileDescriptorListAttributeId,
       
    52 	KSupportedFormatsListAttributeId
       
    53 	};
       
    54 
       
    55 const TUint32 KExpectedComponents[KAttributes][KMaxComponents][KTAttributeComponentMembers] = 
       
    56 	{
       
    57 		// KServiceClassIdAttributeId 
       
    58 		{
       
    59 			{CObexSdpUtils::EUint, ETrue, KServiceClassIdAttributeId},
       
    60 			{CObexSdpUtils::EAnythingUntilNextExpectedValue, EFalse, 0},
       
    61 			{CObexSdpUtils::EUUID, ETrue, KObexObjectPushUUIDValue},
       
    62 			{CObexSdpUtils::EAnythingUntilEnd, EFalse, 0}
       
    63 		},
       
    64 		// KProtocolDescriptorListAttributeId
       
    65 		{ 
       
    66 			{CObexSdpUtils::EUint, ETrue,  KProtocolDescriptorListAttributeId},
       
    67 			{CObexSdpUtils::EAnythingUntilNextExpectedValue, EFalse, 0},
       
    68 			{CObexSdpUtils::EUUID, ETrue,  K_L2CAP_UUID_Value},
       
    69 			{CObexSdpUtils::EUintPossible, ETrue,  K_RFCOMM_UUID_Value}, //NOT MANDATORY TO RECEIVE THIS UINT
       
    70 			{CObexSdpUtils::EUUID, ETrue,  K_RFCOMM_UUID_Value},
       
    71 			{CObexSdpUtils::EUint, EFalse, 0}, //REMOTE OBEX PORT NUMBER
       
    72 			{CObexSdpUtils::EUUID, ETrue,  KObexProtocolUUIDValue},
       
    73 			{CObexSdpUtils::EAnythingUntilEnd, EFalse, 0}
       
    74 		},
       
    75 		// KBluetoothProfileDescriptorListAttributeId - NOT MANDATORY ATTRIBUTE BUT IF PRESENT INDICATES THAT REMOTE DEVICE CONFORMS 100% TO OBEX OBJECT PUSH PROFILE
       
    76 		{
       
    77 			{CObexSdpUtils::EUint, ETrue,  KBluetoothProfileDescriptorListAttributeId},
       
    78 			{CObexSdpUtils::EAnythingUntilNextExpectedValue, EFalse, 0},
       
    79 			{CObexSdpUtils::EUUID, ETrue,  KObexObjectPushUUIDValue},
       
    80 			{CObexSdpUtils::EUint, EFalse, 0}, //VERSION OF OBEX OBJECT PUT SUPPORTED
       
    81 			{CObexSdpUtils::EAnythingUntilEnd, EFalse, 0}
       
    82 		},
       
    83 		// KSupportedFormatsListAttributeId
       
    84 		{
       
    85 			{CObexSdpUtils::EUint, ETrue,  KSupportedFormatsListAttributeId},
       
    86 			{CObexSdpUtils::EUintListUntilEnd, EFalse, 0}, // FORMATS SUPPORTED - LIST OF UINTS OF UNSPECIFIED LENGTH
       
    87 			{CObexSdpUtils::ENoComponent, EFalse, 0}
       
    88 		}
       
    89 	};
       
    90 
       
    91 
       
    92 //
       
    93 // CObexSdpUtils
       
    94 //
       
    95 
       
    96 
       
    97 EXPORT_C CObexSdpUtils* CObexSdpUtils::NewL(MObexSdpUtilsObserver& aObserver)
       
    98 /**
       
    99  * Leave safe constructor
       
   100  *
       
   101  * @param aObserver Used to indicate results of SDP query
       
   102  */
       
   103 	{
       
   104 	CObexSdpUtils* self = new(ELeave) CObexSdpUtils(aObserver);
       
   105 	CleanupStack::PushL(self);
       
   106 	self->ConstructL();
       
   107 	CleanupStack::Pop();
       
   108 	return self;
       
   109 	}
       
   110 
       
   111 EXPORT_C CObexSdpUtils* CObexSdpUtils::NewLC(MObexSdpUtilsObserver& aObserver)
       
   112 /**
       
   113  * Leave safe constructor (which adds the newly created object to the cleanup stack)
       
   114  * 
       
   115  * @param aObserver Used to indicate results of SDP query
       
   116  */
       
   117 	{
       
   118 	CObexSdpUtils* self = new(ELeave) CObexSdpUtils(aObserver);
       
   119 	CleanupStack::PushL(self);
       
   120 	self->ConstructL();
       
   121 	return self;
       
   122 	}
       
   123 
       
   124 void CObexSdpUtils::ConstructL()
       
   125 /**
       
   126  * Necessary initial construction - Creates various structures used to check 
       
   127  * results obtained through CSdpAgent
       
   128  */
       
   129 	{
       
   130 	// Set up structures containing expected components
       
   131 	iAttributeArray = new(ELeave) CArrayPtrFlat<CAttribute>(1); //granularity of 1
       
   132 
       
   133 	TInt attrCount;
       
   134 	for (attrCount=0; attrCount<KAttributes; attrCount++)
       
   135 		{
       
   136 		CObexSdpUtils::CAttribute* attr = new(ELeave) CAttribute;
       
   137 		CleanupStack::PushL(attr);
       
   138 		attr->iAttributeComponentArray = new(ELeave) CArrayFixFlat<TAttributeComponent>(1); //granularity of 1
       
   139 
       
   140 		TInt compCount = -1;
       
   141 		do
       
   142 			{
       
   143 			compCount++;
       
   144 			TAttributeComponent comp;
       
   145 			comp.iType = (TType)KExpectedComponents[attrCount][compCount][0];
       
   146 			comp.iSpecificValue = KExpectedComponents[attrCount][compCount][1];
       
   147 			comp.iValue = KExpectedComponents[attrCount][compCount][2];
       
   148 			attr->iAttributeComponentArray->AppendL(comp);
       
   149 			} while (KExpectedComponents[attrCount][compCount][0]!=ENoComponent);
       
   150 
       
   151 		attr->iAttributeId = KExpectedAttributes[attrCount];
       
   152 		iAttributeArray->AppendL(attr);
       
   153 		CleanupStack::Pop(attr);
       
   154 		}
       
   155 	}
       
   156 
       
   157 
       
   158 CObexSdpUtils::CObexSdpUtils(MObexSdpUtilsObserver& aObserver) : iObserver(aObserver), iIsActiveSDPQuery(EFalse)
       
   159 
       
   160 /**
       
   161  * Simple constructor
       
   162  *
       
   163  * @param aObserver Used to indicate results of SDP query
       
   164  */
       
   165 	{
       
   166 	}
       
   167 
       
   168 CObexSdpUtils::~CObexSdpUtils()
       
   169 /**
       
   170  * Destructor. This can be called before the SDP Query completes to safely cancel the 
       
   171  * query - N.B. this is the only way to cancel a pending query
       
   172  */
       
   173 	{
       
   174 	if (iIsActiveSDPQuery)
       
   175 		// if we are in the middle of a query
       
   176 		{
       
   177 			HaltQueryWithError(KErrAbort); 
       
   178 			//iObserver.RemoteBtObexQueryResult(KErrAbort,KErrNotFound,EFalse,KErrNotFound,iSupportedFormatsList);
       
   179 			//iSdpAgent->Cancel();
       
   180 		}
       
   181 
       
   182 		if(iSdpAgent)
       
   183 		// if we have started a SDP agent
       
   184    		{
       
   185 			delete iSdpAgent;	
       
   186 		
       
   187 		}
       
   188 
       
   189 	iAttributeArray->ResetAndDestroy();
       
   190 	delete iAttributeArray;
       
   191 	}
       
   192 
       
   193 
       
   194 EXPORT_C void CObexSdpUtils::RemoteBtObexQueryL(TBTDevAddr aBtDevAddr)
       
   195 /**
       
   196  * Perform SDP query on a remote bluetooth device. Result is returned through the MObexSdpUtilsObserver 
       
   197  * observer class. The query can be cancelled at any time by destroying this CObexSdpUtils 
       
   198  * object.
       
   199  *
       
   200  * @param aBtDevAddr The address of the bluetooth device
       
   201  */
       
   202 	{
       
   203 		if(iSdpAgent)
       
   204 		{
       
   205 			iSdpAgent->Cancel();
       
   206 		}
       
   207 		else
       
   208 		{
       
   209 			iSdpAgent = CSdpAgent::NewL(*this,aBtDevAddr);
       
   210 		}
       
   211 
       
   212 	// Set up search for SDP records containing the OBEX Object Push Service 
       
   213 	// UUID.
       
   214 	// We also specify that the record must contain L2CAP and RFCOMM UUIDS as
       
   215 	// these are mandatory according to the BT Spec
       
   216 	CSdpSearchPattern* searchPattern = CSdpSearchPattern::NewL();
       
   217 	CleanupStack::PushL(searchPattern);
       
   218 	searchPattern->AddL(TUUID(KObexObjectPushUUIDValue));
       
   219 	searchPattern->AddL(TUUID(K_L2CAP_UUID_Value));
       
   220 	searchPattern->AddL(TUUID(K_RFCOMM_UUID_Value));
       
   221 	iSdpAgent->SetRecordFilterL(*searchPattern); //makes COPY of searchPattern
       
   222 	CleanupStack::PopAndDestroy(searchPattern);
       
   223 
       
   224 	// Start the search
       
   225 	iSdpRecordCount=0;
       
   226 	iSdpAgent->NextRecordRequestL(); //Will result in call to NextRecordRequestComplete()
       
   227 	iIsActiveSDPQuery = ETrue; //Keep record of the fact that we are mid query
       
   228 	}
       
   229 
       
   230 void CObexSdpUtils::NextRecordRequestComplete(TInt aError, TSdpServRecordHandle aHandle, TInt aTotalRecordsCount)
       
   231 /** 
       
   232  * Got an SDP record from the remote device, so check for errors and then request the 
       
   233  * first attribute.
       
   234  *
       
   235  * @param aError Error code 
       
   236  * @param aHandle Handle to the service recorde
       
   237  * @param aTotalRecordsCount The total number of records
       
   238  */
       
   239 	{
       
   240 	iSdpRecordCount++;
       
   241 
       
   242 	if (aError)
       
   243 		{
       
   244 		// return the error that has prevented us from continuing with our query
       
   245 		HaltQueryWithError(aError);
       
   246 		return;
       
   247 		}
       
   248 
       
   249 	if(iSdpRecordCount>aTotalRecordsCount)
       
   250 		{
       
   251 		// return KErrEof because we have gone through all the records and 
       
   252 		// the port hasn't been found
       
   253 		HaltQueryWithError(KErrEof);
       
   254 		return;
       
   255 		}
       
   256 
       
   257 	// Got a record so let's request our first attribute
       
   258 	iNotThisSdpRecord = EFalse;
       
   259 	iRemoteObexPort = KErrNotFound;
       
   260 	iFullComplianceWithObexObjectPush = EFalse;
       
   261 	iObexObjectPushProfileVersion = KErrNotFound;
       
   262 	iSupportedFormatsList.SetLength(0);
       
   263 
       
   264 	iAttribute = -1; 
       
   265 	RequestNextAttribute(aHandle); //will increment iAttribute to 0
       
   266 	}
       
   267 
       
   268 void CObexSdpUtils::AttributeRequestResult(TSdpServRecordHandle /*aHandle*/, TSdpAttributeID /*aAttrID*/, CSdpAttrValue* /*aAttrValue*/)
       
   269 /**
       
   270  * The overload of AttributeRequestL() that we are using in NextRecordRequestComplete()
       
   271  * should NOT result in this function being called, if it does then halt the query with an 
       
   272  * error.
       
   273  *
       
   274  * @param aHandle The handle to the service record
       
   275  * @param aAttrID The SDP Attribute ID
       
   276  * @param aAttrValue The SDP Attribute Value
       
   277  */
       
   278 	{
       
   279 	// The overload of AttributeRequestL() that we are using in NextRecordRequestComplete
       
   280 	// should NOT result in this function being called
       
   281 	HaltQueryWithError(KErrUnknown);
       
   282 	}
       
   283 
       
   284 void CObexSdpUtils::AttributeRequestComplete(TSdpServRecordHandle aHandle, TInt aError)
       
   285 /**
       
   286  * Called after we have got all the attribute components for current attribute being 
       
   287  * processed. If everything is OK get the next attribute or record.
       
   288  * 
       
   289  * @param aHandle The handle to the service record
       
   290  * @param aError The error code
       
   291  */
       
   292 	{
       
   293 	if (!aError && !iNotThisSdpRecord && iAttribute>=iAttributeArray->Count()-1 && iExpectedType==EUintListUntilEnd)
       
   294 		{
       
   295 		// Query is complete - got all the attributes and we have finished in the middle
       
   296 		// of compiling the list of supported obex formats (we can not know in advance the 
       
   297 		// no. of formats a remote device supports)
       
   298 		iObserver.RemoteBtObexQueryResult(KErrNone,iRemoteObexPort,iFullComplianceWithObexObjectPush,iObexObjectPushProfileVersion,iSupportedFormatsList);
       
   299 		HaltQuery();
       
   300 		}
       
   301 	else
       
   302 		{
       
   303 		// See if we should continue looking at the attributes for this record
       
   304 		if (iNotThisSdpRecord //there was a problem with attribute UUIDs and Uints
       
   305 		    || (iExpectedType==EAnythingUntilNextExpectedValue) //we should have got whatever we expected next!
       
   306 		    || (iExpectedType==EUint) //we should always get the Uint we are looking for
       
   307 			|| (iExpectedType==EUUID) //we should always get the UUID we are looking for 
       
   308 			|| (aError)) //an error has occured, note that not finding an attribute does NOT result in KErrNotFound
       
   309 			{
       
   310 			// following is an exception to the rules above...
       
   311 			if (iCurrentAttributeId==KBluetoothProfileDescriptorListAttributeId) //it OK to not find what we expect in for attribute because attribute is not mandatory
       
   312 				{
       
   313 				// therefore everything is OK with the record so far - Request the next attribute
       
   314 				RequestNextAttribute(aHandle);
       
   315 				}
       
   316 			else
       
   317 				{
       
   318 				// this record didn't satisfy our query so try the next one
       
   319 				TRAPD(err,iSdpAgent->NextRecordRequestL()); //results in call to NextRecordRequestComplete()
       
   320 				if (err)
       
   321 					{
       
   322 					HaltQueryWithError(err);
       
   323 					}
       
   324 				}
       
   325 			}
       
   326 		else
       
   327 			{
       
   328 			// Everything is OK with the record so far - Request the next attribute
       
   329 			RequestNextAttribute(aHandle);
       
   330 			}
       
   331 		}
       
   332 	}
       
   333 
       
   334 MSdpElementBuilder* CObexSdpUtils::BuildUUIDL(const TUUID& aUUID)
       
   335 /**
       
   336  * Got a UUID attribute component. Check it is what we expected to receive. Get the next attribute component.
       
   337  *
       
   338  * @param aUUID The Bluetooth UUID of attribute
       
   339  */
       
   340 	{
       
   341 	if(iNotThisSdpRecord
       
   342 	   || iExpectedType==EAnythingUntilEnd) //don't care what we get for current attribute anymore!
       
   343 		{
       
   344 		// Not interested in this UUID
       
   345 		return this;
       
   346 		}
       
   347 
       
   348 	if (iExpectedType==EAnythingUntilNextExpectedValue)
       
   349 		{
       
   350 		if (iNextExpectedType==EUUID && aUUID==TUUID(iNextExpectedValue))
       
   351 			{
       
   352 			// Got the "next" value we are looking for so set current expected to "next"
       
   353 			// and carry on!
       
   354 			NextAttributeComponent();
       
   355 			}
       
   356 		else
       
   357 			{
       
   358 			// Not interested in this UUID
       
   359 			return this;
       
   360 			}
       
   361 		}
       
   362 
       
   363 	iCurrentUUID = aUUID;
       
   364 
       
   365 	if (iExpectedType!=EUUID)
       
   366 		{
       
   367 		if (iExpectedType==EUintPossible)
       
   368 			{
       
   369 			// It was possible to receive a Uint but we got a UUID instead, this is
       
   370 			// perfectly valid. Go the the next component and call this method
       
   371 			// recursively to ensure next component is processed with this UUID
       
   372 			NextAttributeComponent();
       
   373 			BuildUUIDL(aUUID);
       
   374 			return this; //to prevent us missing an attribute
       
   375 			}
       
   376 		else
       
   377 			{
       
   378 			// Shouldn't have received a UUID!
       
   379 			iNotThisSdpRecord = ETrue;
       
   380 			}
       
   381 		}
       
   382 	else if (iExpectingSpecific)
       
   383 		{
       
   384 		if (aUUID != TUUID(iExpectedValue))
       
   385 			{
       
   386 			// Havn't got what we expected!
       
   387 			iNotThisSdpRecord = ETrue;
       
   388 			}
       
   389 		else if (aUUID==TUUID(KObexObjectPushUUIDValue) && iCurrentAttributeId==KBluetoothProfileDescriptorListAttributeId)
       
   390 			{
       
   391 			// remote device complies fully with obex object push profile
       
   392 			iFullComplianceWithObexObjectPush = ETrue;;
       
   393 			}
       
   394 		}
       
   395 	else
       
   396 		{
       
   397 		// When dealing with UUIDs we are ALWAYS expecting a specific UUID.
       
   398 		// If we end up here then something has gone wrong
       
   399 		iNotThisSdpRecord = ETrue;
       
   400 		}
       
   401 
       
   402 	NextAttributeComponent();
       
   403 	return this;
       
   404 	}
       
   405 
       
   406 
       
   407 MSdpElementBuilder* CObexSdpUtils::BuildUintL(const TDesC8& aUint)
       
   408 /**
       
   409  * Got a Uint attribute componet. Check it is what we expected to receive. Get the next attribute component.
       
   410  *
       
   411  * @param aUint Attribute as Uint contained in a descriptor
       
   412  */
       
   413 	{
       
   414 	if(iNotThisSdpRecord
       
   415 	   || iExpectedType==EAnythingUntilEnd) //don't care what we get for current attribute anymore!
       
   416 		{
       
   417 		// Not interested in this Uint
       
   418 		return this;
       
   419 		}
       
   420 
       
   421 	TUint32 uint = UInt32(aUint);
       
   422 
       
   423 	if (iExpectedType==EAnythingUntilNextExpectedValue)
       
   424 		{
       
   425 		if (iNextExpectedType==EUint && uint==iNextExpectedValue)
       
   426 			{
       
   427 			// Got the "next" value we are looking for so set current expected to "next"
       
   428 			// and carry on!
       
   429 			NextAttributeComponent();
       
   430 			}
       
   431 		else
       
   432 			{
       
   433 			// Not interested in this Uint
       
   434 			return this;
       
   435 			}
       
   436 		}
       
   437 
       
   438 	if (iExpectedType==ENoComponent || iExpectedType==EUUID)
       
   439 		{
       
   440 		// We should have not found a Uint
       
   441 		iNotThisSdpRecord = ETrue;
       
   442 		}
       
   443 	else if (iExpectingSpecific)
       
   444 		{
       
   445 		if (uint != iExpectedValue)
       
   446 			{
       
   447 			// Havn't got what we expected!
       
   448 			iNotThisSdpRecord = ETrue;
       
   449 			}
       
   450 		}
       
   451 	else
       
   452 		{
       
   453 		// Not expecting a specific value so the value we've got is unknown so it's
       
   454 		// a piece of info we are trying to discover
       
   455 
       
   456 		if (iCurrentAttributeId==KProtocolDescriptorListAttributeId && iCurrentUUID==TUUID(K_RFCOMM_UUID_Value))
       
   457 			{
       
   458 			// Got the port number!
       
   459 			iRemoteObexPort = uint;
       
   460 			}
       
   461 		else if (iCurrentAttributeId==KBluetoothProfileDescriptorListAttributeId && iCurrentUUID==TUUID(KObexObjectPushUUIDValue))
       
   462 			{
       
   463 			// Got the Obex Object Push Profile Version
       
   464 			iObexObjectPushProfileVersion = uint;
       
   465 			}
       
   466 		else if (iCurrentAttributeId==KSupportedFormatsListAttributeId && iCurrentUUID==TUUID(NULL))
       
   467 			{
       
   468 			// Got an Obex format supported by the remote device
       
   469 			TInt length = iSupportedFormatsList.Length();
       
   470 			if (length<KMaxObexSupportedFormats)
       
   471 				{
       
   472 				iSupportedFormatsList.SetLength(length+1);
       
   473 				iSupportedFormatsList[length]=(TUint8)uint;
       
   474 				}
       
   475 			else
       
   476 				{
       
   477 				HaltQueryWithError(KErrTooBig);
       
   478 				}
       
   479 			return this; //don't go to next expected component because a list doesn't
       
   480 						 //have a defined length
       
   481 			}
       
   482 		}
       
   483 
       
   484 		NextAttributeComponent();
       
   485 		return this;
       
   486 	}
       
   487 
       
   488 MSdpElementBuilder* CObexSdpUtils::BuildUnknownL(TUint8 /*aType*/, TUint8 /*aSizeDesc*/, const TDesC8& /*aData*/)
       
   489 /**
       
   490  * Not required for our SDP query, so we provide an empty implementation.
       
   491  */
       
   492 	{
       
   493 	return this;
       
   494 	}
       
   495 
       
   496 MSdpElementBuilder* CObexSdpUtils::BuildNilL()
       
   497 /**
       
   498  * Not required for our SDP query, so we provide an empty implementation.
       
   499  */
       
   500 	{
       
   501 	return this;
       
   502 	}
       
   503 
       
   504 MSdpElementBuilder* CObexSdpUtils::BuildIntL(const TDesC8& /*aInt*/)
       
   505 /**
       
   506  * Not required for our SDP query, so we provide an empty implementation.
       
   507  */
       
   508 	{
       
   509 	return this;
       
   510 	}
       
   511 
       
   512 MSdpElementBuilder* CObexSdpUtils::BuildBooleanL(TBool /*aBool*/)
       
   513 /**
       
   514  * Not required for our SDP query, so we provide an empty implementation.
       
   515  */
       
   516 	{
       
   517 	return this;
       
   518 	}
       
   519 
       
   520 MSdpElementBuilder* CObexSdpUtils::BuildStringL(const TDesC8& /*aString*/)
       
   521 /**
       
   522  * Not required for our SDP query, so we provide an empty implementation.
       
   523  */
       
   524 	{
       
   525 	return this;
       
   526 	}
       
   527 
       
   528 MSdpElementBuilder* CObexSdpUtils::BuildDESL()
       
   529 /**
       
   530  * Not required for our SDP query, so we provide an empty implementation.
       
   531  */
       
   532 	{
       
   533 	return this;
       
   534 	}
       
   535 
       
   536 MSdpElementBuilder* CObexSdpUtils::BuildDEAL()
       
   537 /**
       
   538  * Not required for our SDP query, so we provide an empty implementation.
       
   539  */
       
   540 	{
       
   541 	return this;
       
   542 	}
       
   543 
       
   544 MSdpElementBuilder* CObexSdpUtils::StartListL()
       
   545 /**
       
   546  * Not required for our SDP query, so we provide an empty implementation.
       
   547  */
       
   548 	{
       
   549 	return this;
       
   550 	}
       
   551 
       
   552 MSdpElementBuilder* CObexSdpUtils::EndListL()
       
   553 /**
       
   554  * Not required for our SDP query, so we provide an empty implementation.
       
   555  */
       
   556 	{
       
   557 	return this;
       
   558 	}
       
   559 
       
   560 MSdpElementBuilder* CObexSdpUtils::BuildURLL(const TDesC8& /*aURL*/)
       
   561 /**
       
   562  * Not required for our SDP query, so we provide an empty implementation.
       
   563  */
       
   564 	{
       
   565 	return this;
       
   566 	}
       
   567 
       
   568 TUint32 CObexSdpUtils::UInt32(const TDesC8& aUint)
       
   569 /**
       
   570  * Convert descriptor containing Uint to a numeric Uint.
       
   571  *
       
   572  * The Uints can be 1, 2, 4, 8 or 16 bytes long in theory. It is doubtful 
       
   573  * that the 8 or 16 byte variety would actually be used in our Obex Object 
       
   574  * Push Service case. The attribute Id will always be a 2 byte Uint but it 
       
   575  * is unclear from the spec what size the the port number should be. It is 
       
   576  * implied that it should only be 1 byte but in the EPOC implementation, it 
       
   577  * is returned as whatever size is it registered as (there is no type/size 
       
   578  * checking carried out in the SDP server).
       
   579  *
       
   580  * @param aUint The Uint as a descriptor
       
   581  */
       
   582 	{
       
   583 	TUint32 uint=0;
       
   584 
       
   585 	switch(aUint.Length())
       
   586 		{
       
   587 	case 1:
       
   588 		uint = (TUint32)aUint[0];
       
   589 		break;
       
   590 	case 2:
       
   591 		uint = (TUint32)(BigEndian::Get16(aUint.Ptr()));
       
   592 		break;
       
   593 	case 4:
       
   594 	default: 
       
   595 		// for our query, if larger Uids are received they may be truncated
       
   596 		uint = BigEndian::Get32(aUint.Ptr());
       
   597 		break;
       
   598 		}
       
   599 
       
   600 	return uint;
       
   601 	}
       
   602 
       
   603 void CObexSdpUtils::HaltQuery()
       
   604 /**
       
   605  * Halt the current SDP query by destroying the CSdpAgent.
       
   606  */
       
   607 	{
       
   608 		iSdpAgent->Cancel();
       
   609 		iIsActiveSDPQuery = EFalse;
       
   610 	}
       
   611 
       
   612 void CObexSdpUtils::HaltQueryWithError(TInt aError)
       
   613 /**
       
   614  * Halt the current SDP query by destroying the CSdpAgent. Inform MObexSdpUtilsObserver 
       
   615  * observer that query has completed with an error.
       
   616  * 
       
   617  * @param aError The error code
       
   618  */
       
   619 	{
       
   620 	iObserver.RemoteBtObexQueryResult(aError,KErrNotFound,EFalse,KErrNotFound,iSupportedFormatsList);
       
   621 	HaltQuery();
       
   622 	}
       
   623 
       
   624 void CObexSdpUtils::RequestNextAttribute(TSdpServRecordHandle aHandle)
       
   625 /**
       
   626  * Get next attribute if we are expecting another attribute.
       
   627  * 
       
   628  * @param aHandle The handle to the service records
       
   629  */
       
   630 	{
       
   631 	iAttribute++;
       
   632 	if (iAttribute >= iAttributeArray->Count())
       
   633 		{
       
   634 		// Shouldn't be requesting another attribute as have no expectation
       
   635 		// for another attribute
       
   636 		HaltQueryWithError(KErrNotFound);
       
   637 		}
       
   638 	else
       
   639 		{
       
   640 		iCurrentUUID=TUUID(NULL);
       
   641 
       
   642 		iAttributeComponent=-1;
       
   643 		NextAttributeComponent(); //will increment iAttributeComponent
       
   644 
       
   645 		iCurrentAttributeId = (*iAttributeArray)[iAttribute]->iAttributeId;
       
   646 		TRAPD(err,iSdpAgent->AttributeRequestL(this,aHandle,TSdpAttributeID(iCurrentAttributeId))); //results in multiple calls to BuildUUIDL() & BuildUintL(), ending with 1 call to AttributeRequestComplete()
       
   647 		if (err)
       
   648 			{
       
   649 			HaltQueryWithError(err);
       
   650 			}
       
   651 		}
       
   652 	}
       
   653 
       
   654 void CObexSdpUtils::NextAttributeComponent()
       
   655 /**
       
   656  * Get next attribute component if we are expecting another attribute component. Set 
       
   657  * internal expectations for the next attribute component we receive.
       
   658  */
       
   659 	{
       
   660 	iAttributeComponent++;
       
   661 	if (iAttributeComponent >= (*iAttributeArray)[iAttribute]->iAttributeComponentArray->Count())
       
   662 		{
       
   663 		// Shouldn't be requesting another attribute component as we have no 
       
   664 		// expectation for another attribute component
       
   665 		iNotThisSdpRecord = ETrue;
       
   666 		return;
       
   667 		}
       
   668 
       
   669 	// Set expectations for the next attribute component we receive
       
   670 	iExpectedType = (*(*iAttributeArray)[iAttribute]->iAttributeComponentArray)[iAttributeComponent].iType;
       
   671 	iExpectingSpecific = (*(*iAttributeArray)[iAttribute]->iAttributeComponentArray)[iAttributeComponent].iSpecificValue;
       
   672 	iExpectedValue = (*(*iAttributeArray)[iAttribute]->iAttributeComponentArray)[iAttributeComponent].iValue;
       
   673 
       
   674 	if (iExpectedType==EAnythingUntilNextExpectedValue)
       
   675 		{
       
   676 		iNextExpectedType = (*(*iAttributeArray)[iAttribute]->iAttributeComponentArray)[iAttributeComponent+1].iType;
       
   677 		iNextExpectedValue = (*(*iAttributeArray)[iAttribute]->iAttributeComponentArray)[iAttributeComponent+1].iValue;
       
   678 		}
       
   679 	}
       
   680 
       
   681 
       
   682 CObexSdpUtils::CAttribute::CAttribute()
       
   683 /**
       
   684  * Simple constructor
       
   685  */
       
   686 	{
       
   687 	}
       
   688 
       
   689 CObexSdpUtils::CAttribute::~CAttribute()
       
   690 /**
       
   691  * Destructor deletes array of attributes
       
   692  */
       
   693 	{
       
   694 	delete iAttributeComponentArray;
       
   695 	}