bluetooth/btsdp/database/SDPDatabase.cpp
changeset 0 29b1cd4cb562
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2000-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 <es_sock.h>
       
    17 #include <btsdp.h>
       
    18 #include <e32des8.h>
       
    19 #include <bluetooth/logger.h>
       
    20 
       
    21 #include "SDPDatabase.h"
       
    22 #include "DataEncoder.h"
       
    23 #include "EncoderVisitor.h"
       
    24 
       
    25 #ifdef __FLOG_ACTIVE
       
    26 _LIT8(KLogComponent, LOG_COMPONENT_SDPDATABASE);
       
    27 #endif
       
    28 
       
    29 void Panic(TSdpDatabasePanics aCode)
       
    30 	{
       
    31 	User::Panic(KSdpDatabasePanicName, aCode);
       
    32 	}
       
    33 
       
    34 // Class CSdpDatabase 
       
    35 
       
    36 EXPORT_C CSdpDatabase* CSdpDatabase::NewLC()
       
    37 /**
       
    38 Creates a CSdpDatabase object, but leaves on the cleanup stack.
       
    39 
       
    40 @return Pointer to the created CSdpDatabase object
       
    41 */
       
    42 	{
       
    43 	LOG_STATIC_FUNC
       
    44 	CSdpDatabase* self = new(ELeave) CSdpDatabase;
       
    45 	CleanupStack::PushL(self);
       
    46 	self->ConstructL();
       
    47 	return self;
       
    48 	}
       
    49 
       
    50 EXPORT_C CSdpDatabase* CSdpDatabase::NewL()
       
    51 /**
       
    52 Creates a CSdpDatabase object.(Does NOT leave it on the cleanup stack.)
       
    53 
       
    54 @return Pointer to the created CSdpDatabase object
       
    55 */
       
    56 	{
       
    57 	LOG_STATIC_FUNC
       
    58 	CSdpDatabase* self = CSdpDatabase::NewLC();
       
    59 	CleanupStack::Pop();
       
    60 	return self;
       
    61 	}
       
    62 
       
    63 CSdpDatabase::CSdpDatabase()
       
    64 : iCanAddRecord(ETrue), 
       
    65   iRecords(CSdpServRecord::LinkOffset()), 
       
    66   iNextFreeHandle(KSdpMinServRecordHandle)
       
    67 	{
       
    68 	CONNECT_LOGGER
       
    69 	}
       
    70 
       
    71 void CSdpDatabase::ConstructL()
       
    72 	{
       
    73 	LOG_FUNC
       
    74 	}
       
    75 
       
    76 EXPORT_C CSdpDatabase::~CSdpDatabase()
       
    77 /** Destructor
       
    78 */
       
    79 	{
       
    80 	LOG_FUNC
       
    81 	// Delete all records on the record list
       
    82 	iRecords.ResetAndDestroy();
       
    83 	CLOSE_LOGGER
       
    84 	}
       
    85 
       
    86 /** Adds a service record to this database.
       
    87 @param aRecord The record being added
       
    88 */
       
    89 EXPORT_C void CSdpDatabase::AddRecord(CSdpServRecord* aRecord)
       
    90 	{
       
    91 	LOG_FUNC
       
    92 	iRecords.AddInOrder(*aRecord); //Panics if aRecord's handle is already bagged.
       
    93 	//Must do this AFTER adding latest record...hence need for 'iCanAddRecord'
       
    94 	iCanAddRecord = ReviseNextFreeHandle();
       
    95 	}
       
    96 
       
    97 /** Creates a new record on this database
       
    98 @leave KErrSdpDatabaseFull implies no more spare handles
       
    99 */
       
   100 EXPORT_C CSdpServRecord* CSdpDatabase::NewRecordL()
       
   101 	{
       
   102 	LOG_FUNC
       
   103 	// Add a new record only if we have spare handles...
       
   104 	// ...there are 2^32 - 0x10000 to choose from!
       
   105 	if(!iCanAddRecord)
       
   106 		{
       
   107 		User::Leave(KErrSdpDatabaseFull);
       
   108 		}
       
   109 
       
   110 	CSdpServRecord* record = CSdpServRecord::NewL();
       
   111 	CleanupStack::PushL(record);
       
   112 
       
   113 	record
       
   114 		->BuildUintL(TSdpIntBuf<TUint16>(0))
       
   115 		->BuildUintL(TSdpIntBuf<TSdpServRecordHandle>(NextFreeHandle()));
       
   116 
       
   117 	AddRecord(record);
       
   118 	CleanupStack::Pop(); //record
       
   119 	return record;
       
   120 	}
       
   121 
       
   122 /** Encodes complete database. */
       
   123 EXPORT_C void CSdpDatabase::EncodeDbL()
       
   124 	{
       
   125 	LOG_FUNC
       
   126 	for(TServRecordIter recIter(RecordIter()); recIter; recIter++)
       
   127 		{// Iterate through records in Db
       
   128 		for (TServAttrIter attrIter((*recIter).AttributeIter()); attrIter; attrIter++)
       
   129 			{// iterate through attributes in record
       
   130 			CSdpAttr* theAttr = &(*attrIter);
       
   131 			CSdpAttrValue* theAttrValue = &(theAttr->Value());
       
   132 			TUint size = TElementEncoder::EncodedSize(theAttrValue->Type(), 
       
   133 													  theAttrValue->DataSize());
       
   134 
       
   135 			HBufC8* outbuf = HBufC8::NewLC(size);
       
   136 			TPtr8 writePtr = outbuf->Des();
       
   137 			TElementEncoder theEncoder(writePtr);
       
   138 			CAttrEncoderVisitor::EncodeAttributeL(theEncoder, (*attrIter).Value());
       
   139 			theAttr->BuildEncodedL(writePtr);
       
   140 			CleanupStack::PopAndDestroy(); //outbuf
       
   141 			}
       
   142 		}
       
   143 	}
       
   144 
       
   145 /** Dead function. Space filler for .def file (left in for BC)
       
   146 */
       
   147 EXPORT_C void CSdpDatabase::ParseDbL_Obscelete_DoesNothing()
       
   148 	{
       
   149 	LOG_FUNC
       
   150 	return;
       
   151 	}
       
   152 
       
   153 /** Returns the 'TSdpServRecordHandle' iNextFreeHandle.
       
   154 @return the next free handle 
       
   155 */
       
   156 EXPORT_C TSdpServRecordHandle CSdpDatabase::NextFreeHandle()
       
   157 	{
       
   158 	LOG_FUNC
       
   159 	return iNextFreeHandle;
       
   160 	}
       
   161 
       
   162 /**	Finds a handle not used by any record in database.
       
   163 	Starts at current next free handle value, and discovers if
       
   164 	it is used by a record in the database. If so cycles it on one in
       
   165 	in the allowed range, and checks again. This algorithm continues
       
   166 	until an unused handle is found (=>return ETrue) or all handles
       
   167 	have been checked and are found to be in use. (=>return EFalse)
       
   168 	NB. We start by looking for the next available handle going upwards
       
   169 	in value. Only if none are found do we return to the lower limit and
       
   170 	search for "holes" below the last claimed handle. This should
       
   171 	reduce processing time. We could have gone further and incremented
       
   172 	iNextFreeHandle value before doing anything else, because it is likely
       
   173 	that the current iNextFreeHandle will have just been used when this
       
   174 	function is called
       
   175 */
       
   176 TBool CSdpDatabase::ReviseNextFreeHandle()
       
   177 	{
       
   178 	LOG_FUNC
       
   179 	if(iNextFreeHandle>KSdpMaxServRecordHandle||
       
   180 		iNextFreeHandle<KSdpMinServRecordHandle)
       
   181 		{
       
   182 		iNextFreeHandle = KSdpMinServRecordHandle;
       
   183 		}
       
   184 
       
   185 	TSdpServRecordHandle origNextFreeHandle(iNextFreeHandle);
       
   186 	for(TServRecordIter recIter(RecordIter()); recIter; recIter++)
       
   187 		{// Iterate thru records in iDatabase
       
   188 		if((*recIter).Handle()==iNextFreeHandle)
       
   189 			{
       
   190 			if(++iNextFreeHandle>KSdpMaxServRecordHandle)
       
   191 				iNextFreeHandle = KSdpMinServRecordHandle;
       
   192 			//We've run out of handles
       
   193 			if(iNextFreeHandle==origNextFreeHandle)
       
   194 				return EFalse;
       
   195 			//Run through all records again to check for new incremented handle.
       
   196 			recIter.SetToFirst();
       
   197 			}
       
   198 		}
       
   199 	return ETrue;
       
   200 	}
       
   201 
       
   202 
       
   203 EXPORT_C CAttrUuidVisitor* CAttrUuidVisitor::NewL()
       
   204 	{
       
   205 	LOG_STATIC_FUNC
       
   206 	CAttrUuidVisitor* self = new(ELeave)CAttrUuidVisitor();
       
   207 	CleanupStack::PushL(self);
       
   208 	self->ConstructL();
       
   209 	CleanupStack::Pop();
       
   210 	return self;
       
   211 	}
       
   212 	
       
   213 EXPORT_C CAttrUuidVisitor::~CAttrUuidVisitor()
       
   214 	{
       
   215 	LOG_FUNC
       
   216 	iUuidContainer.Close();
       
   217 	}
       
   218 	
       
   219 EXPORT_C RUUIDContainer& CAttrUuidVisitor::GetUuids()
       
   220 	{
       
   221 	LOG_FUNC
       
   222 	return iUuidContainer;
       
   223 	}
       
   224 
       
   225 void CAttrUuidVisitor::EncodeAttributeL(CSdpAttrValue& /*aSrcAttr*/)
       
   226 	{
       
   227 	LOG_FUNC
       
   228 	__ASSERT_DEBUG(ETrue, User::Panic(_L("EncodeAttributeL() erroneously called"), KErrArgument));
       
   229 	}
       
   230 	
       
   231 CAttrUuidVisitor::CAttrUuidVisitor()
       
   232 	{
       
   233 	LOG_FUNC
       
   234 	iUuidContainer.Reset();
       
   235 	}
       
   236 	
       
   237 void CAttrUuidVisitor::ConstructL()
       
   238 	{
       
   239 	LOG_FUNC
       
   240 	}
       
   241 
       
   242 // Implementation of MAttributeVisitor interface
       
   243 void CAttrUuidVisitor::VisitAttributeL(CSdpAttr& /*aAttribute*/)
       
   244 	{
       
   245 	LOG_FUNC
       
   246 	__ASSERT_DEBUG(ETrue, Panic(ESdpDatabaseVisitAttributeLErroneouslyCalled));
       
   247 	}
       
   248 	
       
   249 void CAttrUuidVisitor::VisitAttributeValueL(CSdpAttrValue &aValue, TSdpElementType aType)
       
   250 	{
       
   251 	LOG_FUNC
       
   252 	switch (aType)
       
   253 		{
       
   254 		case ETypeUUID:
       
   255 			iUuidContainer.Add(aValue.UUID());
       
   256 			break;
       
   257 		case ETypeEncoded:
       
   258 			{
       
   259 			TPtrC8 ptr = aValue.Des();
       
   260 			if(ptr.Length() == KSdpElemHdrTypeShift + KSizeOf16BitUUID)
       
   261 				{
       
   262 				// 16-bit UUID
       
   263 				TUUID uuid = TUUID(BigEndian::Get16(&ptr[KSdpElemHdrTypeShift]));
       
   264 				iUuidContainer.Add(uuid);
       
   265 				}
       
   266 			else if(ptr.Length() == KSdpElemHdrTypeShift + KSizeOf32BitUUID)
       
   267 				{
       
   268 				// 32-bit UUID
       
   269 				TUUID uuid = TUUID(BigEndian::Get32(&ptr[KSdpElemHdrTypeShift]));
       
   270 				iUuidContainer.Add(uuid);
       
   271 				}
       
   272 			else if(ptr.Length() == KSdpElemHdrTypeShift + KSizeOf128BitUUID)
       
   273 				{
       
   274 				// 128-bit UUID
       
   275 				TUUID uuid = TUUID(BigEndian::Get32(&ptr[KSdpElemHdrTypeShift]),
       
   276 								   BigEndian::Get32(&ptr[KSdpElemHdrTypeShift+sizeof(TUint32)]),
       
   277 								   BigEndian::Get32(&ptr[KSdpElemHdrTypeShift+2*sizeof(TUint32)]),
       
   278 								   BigEndian::Get32(&ptr[KSdpElemHdrTypeShift+3*sizeof(TUint32)]));
       
   279 				iUuidContainer.Add(uuid);
       
   280 				}
       
   281 			else
       
   282 				{
       
   283 				// We don't support other UUIDs
       
   284 				}
       
   285 			}
       
   286 			break;
       
   287 		default:
       
   288 			__ASSERT_DEBUG(ETrue, Panic(ESdpDatabaseUnexpectedAttributeType));
       
   289 			break;
       
   290 		}
       
   291 	}
       
   292 
       
   293 void CAttrUuidVisitor::StartListL(CSdpAttrValueList& /*aList*/)
       
   294 	{
       
   295 	LOG_FUNC
       
   296 	}
       
   297 
       
   298 void CAttrUuidVisitor::EndListL()
       
   299 	{
       
   300 	LOG_FUNC
       
   301 	}
       
   302