diff -r 000000000000 -r 29b1cd4cb562 bluetooth/btsdp/database/rsdpdatabase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btsdp/database/rsdpdatabase.cpp Fri Jan 15 08:13:17 2010 +0200 @@ -0,0 +1,600 @@ +// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include +#include +#include "ipcinternals.h" +#include "DataEncoder.h" +#include "EncoderVisitor.h" +#include +#include +#include + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, LOG_COMPONENT_SDPDATABASE); +#endif + +static TInt StartServer() +// +// Start the server process or thread +// + { + LOG_STATIC_FUNC + + const TUidType serverUid(KNullUid,KNullUid,KSdpServerUid3); + +#ifdef __SDPSERVER_NO_PROCESSES__ + // + // In EKA1 WINS the server is a DLL, the exported entrypoint returns a TInt + // which represents the real entry-point for the server thread + // + RLibrary lib; + TInt r=lib.Load(KSdpServerImg,serverUid); + if (r!=KErrNone) + return r; + TLibraryFunction ordinal1=lib.Lookup(1); + TThreadFunction serverFunc=reinterpret_cast(ordinal1()); + // + // To deal with the unique thread (+semaphore!) naming in EPOC, and that we may + // be trying to restart a server that has just exited we attempt to create a + // unique thread name for the server. + // This uses Math::Random() to generate a 32-bit random number for the name + // + TName name(KSdpServerName); + _LIT(KHexString, "0x"); + name.Append(KHexString()); + name.AppendNum(Math::Random(),EHex); + RThread server; + r=server.Create(name,serverFunc, + KSdpServerStackSize, + NULL,&lib,NULL, + KSdpServerInitHeapSize,KSdpServerMaxHeapSize,EOwnerProcess); + lib.Close(); // if successful, server thread has handle to library now +#else + // + // EPOC and EKA2 is easy, we just create a new server process. Simultaneous + // launching of two such processes should be detected when the second one + // attempts to create the server object, failing with KErrAlreadyExists. + // + RProcess server; + TInt r=server.Create(KSdpServerImg,KNullDesC,serverUid); +#endif + + LOG(KSdpServerImg); + LOG1(_L("c\tSdp Server created, code %d"), r); + if (r!=KErrNone) + return r; + + TRequestStatus status; + // this is a variant of RProcess::Logon which completes either when the process + // terminates or when the new process calls "RProcess::Rendezvous();" + server.Rendezvous(status); + if (status!=KRequestPending) + { + server.Kill(0); // abort startup + } + else + { + server.Resume(); // Rendezvous OK - start the server + LOG(_L("c\tSdp Server Resumed")); + } + User::WaitForRequest(status); // wait for start or death + LOG1(_L("c\tSdp Server started, code %d (0=>success)"), status.Int()); + server.Close(); + LOG(_L("c\tSdp Server Closed")); + return status.Int(); + } + + +//================================== +// RSdp +//================================== + +EXPORT_C RSdp::RSdp() +/** Default constructor. */ + { + LOG_FUNC + } + +EXPORT_C TInt RSdp::Connect() +/** Connects a client process to the database. + +The connection should be closed after use with RHandleBase::Close(). + +@return System-wide error code */ + { + LOG_FUNC + TInt retry=2; + for (;;) + { + TInt r=CreateSession(KSdpServerName,TVersion(0,0,0)); //gives MessageSlots of -1 + //this uses global pool rather + //than local pool + if (r!=KErrNotFound && r!=KErrServerTerminated) + return r; + if (--retry==0) + return r; + r=StartServer(); + if (r!=KErrNone && r!=KErrAlreadyExists) + return r; + } + } + +EXPORT_C TVersion RSdp::Version() const +/** Gets the version of the database server. + +@return Version information */ + { + LOG_FUNC + return TVersion(KSdpServerMajorVersionNumber, + KSdpServerMinorVersionNumber, + KSdpServerBuildVersionNumber); + } + +EXPORT_C void RSdp::ResourceCountMarkStart() +/** Starts the counter to keep track of open subsessions. + +This should be used by clients to do resource leakage debugging checks. */ + { + LOG_FUNC + SendReceive(ESdpResourceCountMarkStart, TIpcArgs(NULL)); //ss// + } + +EXPORT_C void RSdp::ResourceCountMarkEnd() +/** Stops the counter to keep track of open subsessions. + +This should be used by clients to do resource leakage debugging checks. */ + { + LOG_FUNC + SendReceive(ESdpResourceCountMarkEnd, TIpcArgs(NULL)); //ss// + } + +EXPORT_C TInt RSdp::ResourceCount() +/** Gets the number of open subsessions to the database. + +This should be used by clients to do resource leakage debugging checks. + +@return Number of open subsessions to the database */ + { + LOG_FUNC + TInt count = 0; + TPckgBuf pckg(count); + SendReceive(ESdpResourceCount, TIpcArgs(&pckg)); //ss// + return pckg(); + } + +/** +@internalTechnology +@released +*/ +EXPORT_C TInt RSdp::__DbgMarkHeap() + { + LOG_FUNC +#ifdef _DEBUG + return SendReceive(ESdpServerDbgMarkHeap); +#else + return KErrNone; +#endif + } + +/** +@internalTechnology +@released +*/ +EXPORT_C TInt RSdp::__DbgCheckHeap(TInt aCount) + { + LOG_FUNC +#ifdef _DEBUG + return SendReceive(ESdpServerDbgCheckHeap, TIpcArgs(aCount)); +#else + (void)aCount; + return KErrNone; +#endif + } + +/** +@internalTechnology +@released +*/ +EXPORT_C TInt RSdp::__DbgMarkEnd(TInt aCount) + { + LOG_FUNC +#ifdef _DEBUG + return SendReceive(ESdpServerDbgMarkEnd, TIpcArgs(aCount)); +#else + (void)aCount; + return KErrNone; +#endif + } + +/** +@internalTechnology +@released +*/ +EXPORT_C TInt RSdp::__DbgFailNext(TInt aCount) + { + LOG_FUNC +#ifdef _DEBUG + return SendReceive(ESdpServerDbgFailNext, TIpcArgs(aCount)); +#else + (void)aCount; + return KErrNone; +#endif + } + +//================================== +// RSdpDatabase +//================================== + +EXPORT_C TInt RSdpDatabase::Open(RSdp& aSession) +/** Opens a SDP database subsession. + +@param aSession SDP database session +@return System-wide error code +@capability LocalServices */ + { + LOG_FUNC + return CreateSubSession(aSession, ESdpCreateDatabaseSubSession/*, TIpcArgs(&p[0])*/); //ss// + } + +EXPORT_C RSdpDatabase::RSdpDatabase() : + iBuffer(0) +/** Default constructor. + +@capability LocalServices */ + { + LOG_FUNC + } + +EXPORT_C void RSdpDatabase::Close() +/** Closes the SDP database subsession. + +Any records that have been added during this session will be removed when the session is closed. +@capability LocalServices */ + { + LOG_FUNC + //delete resources + delete iBuffer; + iBuffer = NULL; + + RSubSessionBase::CloseSubSession(ESdpCloseSubSession); + } + + +EXPORT_C void RSdpDatabase::CreateServiceRecordL(const TUUID& aUUID, TSdpServRecordHandle& aHandle) +/** Creates a new service record, with a single service class, in the SDP database. + + +@param aUUID The service class UUID for the service record +@param aHandle On return, the service record handle of the new record +@capability LocalServices */ + { + LOG_FUNC + if (SubSessionHandle()) + { + CSdpAttrValueDES* list = CSdpAttrValueDES::NewDESL(NULL); + CleanupStack::PushL(list); + MSdpElementBuilder* bldr = list; + + bldr + ->StartListL() + ->BuildUUIDL(aUUID) + ->EndListL(); + CreateServiceRecordL(*list, aHandle); + CleanupStack::PopAndDestroy(); //list + } + else + { + //Client has a bad handle therefore panic + User::Panic(_L("SDP-Subsession"), KErrBadHandle); + } + } + +EXPORT_C void RSdpDatabase::CreateServiceRecordL(CSdpAttrValueDES& aUUIDList, + TSdpServRecordHandle& aHandle) +/** Creates a new service record, with multiple service classes, in the SDP database. + +@param aUUIDList The service class attribute of the new record. This should +consist of a list of UUIDs of the service classes to which the record belongs. +The UUIDs should be ordered from the most derived service class to the base +one. +@param aHandle On return, the service record handle of the new record +@capability LocalServices */ + { + LOG_FUNC + if (SubSessionHandle()) + { + delete iBuffer; + iBuffer = 0; + TUint size = TElementEncoder::EncodedSize(ETypeDES, aUUIDList.DataSize()); + iBuffer = HBufC8::NewL(size); + TPtr8 ptr = iBuffer->Des(); + + TElementEncoder ee(ptr); + CAttrEncoderVisitor::EncodeAttributeL(ee, aUUIDList); + + TSdpServRecordHandlePckgBuf pckg; + User::LeaveIfError(SendReceive(ESdpDatabaseCreateServiceRecord, TIpcArgs(iBuffer, &pckg))); //ss// + aHandle = pckg(); //return handle in handle reference + } + else + { + //Client has a bad handle therefore panic + User::Panic(_L("SDP-Subsession"), KErrBadHandle); + } + } + + +EXPORT_C void RSdpDatabase::UpdateAttributeL(TSdpServRecordHandle aHandle, + TSdpAttributeID aAttrID, + CSdpAttrValue& aAttrValue) +/** Updates a service record attribute (value encapsulated in a CSdpAttrValue). + +If the attribute does not exist, it is created. If it already exists, the +current definition is removed and the new value inserted. + +No check is made that the attribute value is suitable for the service class +to which the record belongs. It is up to the user to ensure that the semantics +of the attribute defined by the service class are respected. + +@param aHandle The service record handle to update +@param aAttrID The attribute ID to update +@param aAttrValue The attribute value +@capability LocalServices */ + { + LOG_FUNC + if (SubSessionHandle()) + { + TSdpAttributeIDPckgBuf idPckg; + TSdpServRecordHandlePckgBuf handlePckg; + handlePckg() = aHandle; //put record handle into package + idPckg() = aAttrID; //put attr ID into package + + delete iBuffer; + iBuffer = 0; + TUint size = TElementEncoder::EncodedSize(aAttrValue.Type(), aAttrValue.DataSize()); + iBuffer = HBufC8::NewL(size); + TPtr8 ptr = iBuffer->Des(); + + TElementEncoder ee(ptr); + CAttrEncoderVisitor::EncodeAttributeL(ee, aAttrValue); + + User::LeaveIfError(SendReceive(ESdpDatabaseUpdateAttribute, TIpcArgs(&handlePckg, &idPckg, iBuffer))); //ss// + } + else + { + //Client has a bad handle therefore panic + User::Panic(_L("SDP-Subsession"), KErrBadHandle); + } + } + +EXPORT_C void RSdpDatabase::UpdateAttributeL(TSdpServRecordHandle aHandle, + TSdpAttributeID aAttrID, + TUint aUintValue) +/** Updates a service record attribute (integer value). + +If the attribute does not exist, it is created. If it already exists, the +current definition is removed and the new value inserted. + +No check is made that the attribute value is suitable for the service class +to which the record belongs. It is up to the user to ensure that the semantics +of the attribute defined by the service class are respected. + +@param aHandle The service record handle to update +@param aAttrID The attribute ID to update +@param aUintValue The attribute value +@capability LocalServices */ + { + LOG_FUNC + if (SubSessionHandle()) + { + TBuf8<4> buf; + buf.SetLength(4); + BigEndian::Put32(&buf[0], aUintValue); + CSdpAttrValueUint* attrValueUint = CSdpAttrValueUint::NewUintL(buf); + CleanupStack::PushL(attrValueUint); + UpdateAttributeL(aHandle, aAttrID, *attrValueUint); + CleanupStack::PopAndDestroy(); //attrValueUint + } + else + { + //Client has a bad handle therefore panic + User::Panic(_L("SDP-Subsession"), KErrBadHandle); + } + } + +EXPORT_C void RSdpDatabase::UpdateAttributeL(TSdpServRecordHandle aHandle, + TSdpAttributeID aAttrID, + const TDesC16& aDesCValue) +/** Updates a service record attribute (wide descriptor value). + +If the attribute does not exist, it is created. If it already exists, the +current definition is removed and the new value inserted. + +No check is made that the attribute value is suitable for the service class +to which the record belongs. It is up to the user to ensure that the semantics +of the attribute defined by the service class are respected. + +@param aHandle The service record handle to update +@param aAttrID The attribute ID to update +@param aDesCValue The attribute value +@capability LocalServices */ +/** Updates a service record attribute (narrow descriptor value). + +If the attribute does not exist, it is created. If it already exists, the +current value is removed and the new value inserted. + +No check is made that the attribute value is suitable for the service class +to which the record belongs. It is up to the user to ensure that the semantics +of the attribute defined by the service class are respected. + +@param aHandle The service record handle to update +@param aAttrID The attribute ID to update +@param aDesCValue The attribute value +@capability LocalServices */ + { + LOG_FUNC + if (SubSessionHandle()) + { + //The '5' below is max ratio of number of UTF_8 chars to number of unicode chars . + HBufC8* buf = HBufC8::NewLC(5*aDesCValue.Length()); + TPtr8 ptr = buf->Des(); + CnvUtfConverter::ConvertFromUnicodeToUtf8(ptr, aDesCValue); + UpdateAttributeL(aHandle, aAttrID, ptr); + CleanupStack::PopAndDestroy(); //buf + } + else + { + //Client has a bad handle therefore panic + User::Panic(_L("SDP-Subsession"), KErrBadHandle); + } + } + +EXPORT_C void RSdpDatabase::UpdateAttributeL(TSdpServRecordHandle aHandle, + TSdpAttributeID aAttrID, + const TDesC8& aDesCValue) +/** Updates a service record attribute (wide descriptor value). + +If the attribute does not exist, it is created. If it already exists, the +current value is removed and the new value inserted. + +No check is made that the attribute value is suitable for the service class +to which the record belongs. It is up to the user to ensure that the semantics +of the attribute defined by the service class are respected. + +@param aHandle The service record handle to update +@param aAttrID The attribute ID to update +@param aDesCValue The attribute value +@capability LocalServices */ +/** Updates a service record attribute (narrow descriptor value). + +If the attribute does not exist, it is created. If it already exists, the +current definition is removed and the new value inserted. + +No check is made that the attribute value is suitable for the service class +to which the record belongs. It is up to the user to ensure that the semantics +of the attribute defined by the service class are respected. + +@param aHandle The service record handle to update +@param aAttrID The attribute ID to update +@param aDesCValue The attribute value +@capability LocalServices */ + { + LOG_FUNC + if (SubSessionHandle()) + { + CSdpAttrValueString* attrValueString = CSdpAttrValueString::NewStringL(aDesCValue); + CleanupStack::PushL(attrValueString); + UpdateAttributeL(aHandle, aAttrID, *attrValueString); + CleanupStack::PopAndDestroy(); //attrValueString + } + else + { + //Client has a bad handle therefore panic + User::Panic(_L("SDP-Subsession"), KErrBadHandle); + } + } + +/** Delete an attribute from a service record. + +@param aHandle The service record from which to delete the attribute +@param aAttrID The ID of the attribute +@capability LocalServices +@deprecated Use non-leaving version instead +@see RSdpDatabase::DeleteAttribute +*/ +EXPORT_C void RSdpDatabase::DeleteAttributeL(TSdpServRecordHandle aHandle, TSdpAttributeID aAttrID) + { + LOG_FUNC + if (SubSessionHandle()) + { + TPckg idPckg(aAttrID); + TPckg handlePckg(aHandle); + User::LeaveIfError(SendReceive(ESdpDatabaseDeleteAttribute, TIpcArgs(&handlePckg, &idPckg))); + } + else + { + //Client has a bad handle therefore panic + User::Panic(_L("SDP-Subsession"), KErrBadHandle); + } + } + +/** Delete an attribute from a service record. + +@param aHandle The service record from which to delete the attribute +@param aAttrID The ID of the attribute +@capability LocalServices +*/ +EXPORT_C void RSdpDatabase::DeleteAttribute(TSdpServRecordHandle aHandle, TSdpAttributeID aAttrID) + { + LOG_FUNC + if (SubSessionHandle()) + { + TPckg idPckg(aAttrID); + TPckg handlePckg(aHandle); + + SendReceive(ESdpDatabaseDeleteAttribute, TIpcArgs(&handlePckg, &idPckg)); + } + else + { + //Client has a bad handle therefore panic + User::Panic(_L("SDP-Subsession"), KErrBadHandle); + } + } + +/** Deletes a service record. + +@param aHandle Handle of the service record to delete +@capability LocalServices +@deprecated Use non-leaving version instead +@see RSdpDatabase::DeleteRecord +*/ +EXPORT_C void RSdpDatabase::DeleteRecordL(TSdpServRecordHandle aHandle) + { + LOG_FUNC + if (SubSessionHandle()) + { + TPckg handlePckg(aHandle); + + User::LeaveIfError(SendReceive(ESdpDatabaseDeleteServiceRecord, TIpcArgs(&handlePckg))); + } + else + { + //Client has a bad handle therefore panic + User::Panic(_L("SDP-Subsession"), KErrBadHandle); + } + } + +/** Deletes a service record. + +@param aHandle Handle of the service record to delete +@capability LocalServices +*/ +EXPORT_C void RSdpDatabase::DeleteRecord(TSdpServRecordHandle aHandle) + { + LOG_FUNC + if (SubSessionHandle()) + { + TPckg handlePckg(aHandle); + + SendReceive(ESdpDatabaseDeleteServiceRecord, TIpcArgs(&handlePckg)); + } + else + { + //Client has a bad handle therefore panic + User::Panic(_L("SDP-Subsession"), KErrBadHandle); + } + } +