// 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:// Implements the SDP Protocol object// //#include <bluetooth/logger.h>#include <bt_sock.h>#include <btsdp.h>#include "sdp.h"#include "sdpclient.h"#include "sdpnetdb.h"#include "sdpstackutil.h"#include "sdpconsts.h"#include "bt.h"#ifdef __FLOG_ACTIVE_LIT8(KLogComponent, LOG_COMPONENT_SDP);#endifCSdpProtocol::CSdpProtocol(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan) :CBluetoothProtocolBase(aSecMan, aControlPlane, aCodMan), iClients(_FOFF(CSdpClient, iLink))/** Protocol Constructor.**/ { LOG_FUNC }CSdpProtocol::~CSdpProtocol()/** Protocol Destructor. We only clean up the signallers as the NetDbProviders are owned by ESOCK and it is up to it to destroy them.**/ { LOG_FUNC while(!iClients.IsEmpty()) { CSdpClient* c = iClients.First(); c->iLink.Deque(); delete c; } if(iLowerProtocol) iLowerProtocol->Close(); // Matches the bind#ifdef __FLOG_ACTIVE CLOSE_LOGGER#endif }CSdpProtocol* CSdpProtocol::NewL(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan) {#ifdef __FLOG_ACTIVE CONNECT_LOGGER#endif LOG_STATIC_FUNC CSdpProtocol* i=new (ELeave) CSdpProtocol(aSecMan, aControlPlane, aCodMan); return i; }void CSdpProtocol::InitL(TDesC& /*aTag*/)/** Pre-binding initialise. Alloc any stuff we need. This will only ever be called once during the lifetime of this protocol.**/ { LOG_FUNC // ...nothing required! }void CSdpProtocol::StartL()/** Binding complete.**/ { LOG_FUNC // Should check that we're bound now. __ASSERT_ALWAYS(iLowerProtocol,Panic(ESdpNotBound)); }void CSdpProtocol::BindToL(CProtocolBase* aProtocol)/*** Request by Protocol Mgr to bind to the specified protocol. We can only be bound to one lower layer protocol, so the function panics if we are already bound. @param aProtocol The protocol we need to bind to.**/ { LOG_FUNC FTRACE(TBuf<255> tmp(aProtocol->Tag()); LOG1(_L("CSdpProtocol::BindToL binding to %S"), &tmp)); if(!iLowerProtocol) {#ifdef _DEBUG TServerProtocolDesc prtDesc; aProtocol->Identify(&prtDesc); if(prtDesc.iAddrFamily!=KBTAddrFamily || prtDesc.iProtocol!=KL2CAP) { User::Leave(KErrBtEskError); }#endif iLowerProtocol=static_cast<CBluetoothProtocolBase*>(aProtocol); iLowerProtocol->BindL(this, KSDPPSM); iLowerProtocol->Open(); } else { User::Leave(KErrSdpAlreadyBound); } }// Factory functionsCNetDBProvdBase* CSdpProtocol::NewNetDatabaseL()/** Create a new NetDbProvider. The NetDbProvider returned is owned by the caller -- this protocol will not clean it up. esock uses this function to create a new NetDbProvider, and esock will delete when it is finished with it.**/ { LOG_FUNC return CSdpNetDbProvider::NewL(*this); }// Query functionsvoid CSdpProtocol::Identify(TServerProtocolDesc *aDesc)const/** Identify request from SOCKET server**/ { LOG_FUNC ProtocolIdentity(aDesc); }void CSdpProtocol::ProtocolIdentity(TServerProtocolDesc* aDesc) { LOG_STATIC_FUNC _LIT(name,"SDP"); aDesc->iProtocol=KSDP; aDesc->iName=name; aDesc->iAddrFamily=KBTAddrFamily; aDesc->iSockType=1; // Bogus... but (debug) esock demands non-zero here. aDesc->iVersion=TVersion(KBTMajor,KBTMinor,KBTBuild); aDesc->iByteOrder=EBigEndian; aDesc->iServiceInfo=0; aDesc->iNamingServices=KNSInfoDatabase; aDesc->iSecurity=0; aDesc->iMessageSize=KSocketMessageSizeUndefined; aDesc->iServiceTypeInfo=ECantProcessMBufChains; aDesc->iNumSockets=1;// Bogus... but (debug) esock demands non-zero here. }void CSdpProtocol::CloseNow()/** Our reference is now zero, so start to close. When SDP server is in place, this'll be far more involved, as we'll want to hang around to service SDP queries, for some (???) length of time. In the mean time, we can just close, as there are now no netdbs left, so even if any SDP clients are still hanging around, they may as well die.**/ { LOG_FUNC iClosePending = ETrue; TryToClose(); }void CSdpProtocol::Open()/** Request to open the protocol. The protocol may be repeatedly opened and closed. The order of calls is InitL, [Open *n , Close * n, CloseNow] * m, CanClose(upcall) etc.**/ { LOG_FUNC iClosePending = EFalse; CProtocolBase::Open(); }void CSdpProtocol::Close()/** This is one session closing. Just call default, which decs the ref count. CloseNow will be called when this hits 0.**/ { LOG_FUNC CProtocolBase::Close(); }void CSdpProtocol::TryToClose() { LOG_FUNC if (iClosePending && iClients.IsEmpty()) CanClose(); // delete's us! }void CSdpProtocol::GetClient(CSdpNetDbProvider& aNetDbProvider)/** Find a Client for this NetDbProvider. When a Client is found, the NetDbProvider is notified via the ClientUp() call. Note that if there is no existing Client then it will be created here and the link brought up before the ClientUp() call is made. This implies that the ClientUp() call on the NetDbProvider can be synchronous or Asynchronous. @param aNetDbProvider The NetDbProvider that needs a Client.**/ { LOG_FUNC CSdpClient* client; TBool needsL2CAPChannel = EFalse; client=FindClient(aNetDbProvider.iRemoteDev); if(!client) {// Need to create one needsL2CAPChannel = ETrue; TRAPD(err, client=CSdpClient::NewL(*this, *iLowerProtocol)); if(err != KErrNone) { // Can't create a client, so error the NetDbProvider aNetDbProvider.Error(err); return; } // Add client to the Q iClients.AddFirst(*client); } // Take NetDb off the idle Q // and add it to the client aNetDbProvider.iClient=client; client->AddNetDbProvider(aNetDbProvider); // Bring up the client if needed if (needsL2CAPChannel) client->Open(aNetDbProvider.iRemoteDev); // Will call back through ClientUp() }CSdpClient* CSdpProtocol::FindClient(const TBTDevAddr& aAddr)/** Find the existing client for this address. @return Pointer to a client for this address, or NULL if it doesn't exist.**/ { LOG_FUNC TDblQueIter<CSdpClient> iter(iClients); CSdpClient* client; while(iter) { client=iter++; if(client->iRemoteAddr == aAddr) { // We have a client, so return it return client; } } // No client return 0; }void CSdpProtocol::ClientDown(CSdpClient& aClient) { LOG_FUNC aClient.iLink.Deque(); delete &aClient; TryToClose(); }TInt CSdpProtocol::BearerConnectComplete(const TBTDevAddr& /*aAddr*/, CServProviderBase* /*aSSP*/) { LOG_FUNC // SDP Protocol doesn't do incoming stuff! Panic(ESdpClientPassiveConnect); return KErrNotSupported; }