bluetooth/btstack/sdp/sdp.cpp
changeset 0 29b1cd4cb562
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btstack/sdp/sdp.cpp	Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,302 @@
+// 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);
+#endif
+
+CSdpProtocol::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 functions
+
+CNetDBProvdBase* 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 functions
+
+void 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;
+	}
+