bluetooth/btstack/eirman/eirmanserver.cpp
changeset 0 29b1cd4cb562
child 17 32ba20339036
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btstack/eirman/eirmanserver.cpp	Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,218 @@
+// Copyright (c) 2007-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:
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include "eirmanserver.h"
+#include <e32base.h>
+#include <bluetooth/logger.h>
+#include <bluetooth/logger/components.h>
+#include <bluetooth/eirmanshared.h>
+#include "eirmansession.h"
+#include "eirmanager.h"
+#include "eirmanserversecuritypolicy.h"
+#include "linkmgr.h"
+#include "eirmanpanics.h"
+
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_EIRMANAGER);
+#endif
+
+CEirManServer* CEirManServer::NewL(MHCICommandQueue& aCommandQueue, CLinkMgrProtocol& aLinkMgrProtocol)
+	{
+	LOG_STATIC_FUNC
+	
+	CEirManServer* self = new(ELeave) CEirManServer(aCommandQueue, aLinkMgrProtocol);
+	CleanupStack::PushL(self);
+	// StartL is where the kernel checks that there isn't already an instance 
+	// of the same server running, so do it before ConstructL.
+	self->StartL(KEirManServerName);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CEirManServer::~CEirManServer()
+	{
+	LOG_FUNC
+	delete iEirManager;
+	}
+
+CEirManServer::CEirManServer(MHCICommandQueue& aCommandQueue, CLinkMgrProtocol& aLinkMgrProtocol)
+	: CPolicyServer(CActive::EPriorityStandard, KEirManServerPolicy)
+	, iCommandQueue(aCommandQueue)
+	, iLinkMgrProtocol(aLinkMgrProtocol)
+	, iSessionCount(0)
+	, iIsFeaturesReady(EFalse)
+	, iIsEirSupported(EFalse)
+	{
+	LOG_FUNC
+	}
+
+void CEirManServer::ConstructL()
+	{
+	LOG_FUNC
+	}
+
+CSession2* CEirManServer::NewSessionL(const TVersion& aVersion, const RMessage2& /*aMessage*/) const
+	{
+	LOG_FUNC
+	// Server will refuse to create any more session if we have found out eir isn't supported.
+	if(iIsFeaturesReady && !iIsEirSupported)
+		{
+		User::Leave(KErrNotSupported);
+		}
+	
+	LOG3(_L("CEirManServer::NewSessionL aVersion = (%d,%d,%d)"), aVersion.iMajor, aVersion.iMinor, aVersion.iBuild);
+	
+	// Version number check...
+	TVersion v(KEirManSrvMajorVersionNumber,
+			   KEirManSrvMinorVersionNumber,
+			   KEirManSrvBuildVersionNumber);
+	
+	if ( !User::QueryVersionSupported(v, aVersion) )
+		{
+		LEAVEIFERRORL(KErrNotSupported);
+		}
+	
+	CEirManServer* ncThis = const_cast<CEirManServer*>(this);
+	
+	CEirManSession* sess = CEirManSession::NewL(*ncThis);
+	LOG1(_L("\tsess = 0x%08x"), sess);
+	return sess;
+	}
+
+void CEirManServer::AddSession()
+	{
+	LOG_FUNC
+	if(iSessionCount++ == 0)
+		{
+		// While we have clients we need to make sure that the protocol remains alive.
+		iLinkMgrProtocol.LocalOpen();
+		}
+	}
+
+void CEirManServer::DropSession()
+	{
+	LOG_FUNC
+	if(--iSessionCount == 0)
+		{
+		// There are no long 
+		iLinkMgrProtocol.LocalClose();
+		}
+	}
+
+void CEirManServer::NotifyFeaturesReady()
+	{
+	if(iIsFeaturesReady == EFalse)
+		{
+		__ASSERT_DEBUG(!iEirManager, EIR_SERVER_PANIC(EEirServerEirMangerAlreadyExists));
+		TRAPD(err, iEirManager = CEirManager::NewL(iCommandQueue, iLinkMgrProtocol));
+		iIsFeaturesReady = ETrue;
+		
+		iSessionIter.SetToFirst();
+		CSession2* sessionPtr;
+		if(iLinkMgrProtocol.IsExtendedInquiryResponseSupportedLocally() && err == KErrNone)
+			{
+			iIsEirSupported = ETrue;
+			}
+		else
+			{
+			err = ((err != KErrNone) ? KErrNoMemory : KErrNotSupported);
+			}
+		
+		while((sessionPtr = iSessionIter++) != NULL)
+			{
+			CEirManSession* eirSession = static_cast<CEirManSession*>(sessionPtr);
+			eirSession->NotifyEirFeatureState(err);
+			}
+		}
+	}
+
+TEirFeatureState CEirManServer::EirFeatureState()
+	{
+	TEirFeatureState ret = EEirFeaturePending;
+	if(iIsFeaturesReady && iIsEirSupported)
+		{
+		ret = EEirFeatureReady;
+		}
+	else if(iIsFeaturesReady && !iIsEirSupported)
+		{
+		ret = EEirFeatureNotSupported;
+		}
+	else
+		{
+		// ret will still be EEirFeaturePending
+		}
+	return ret;
+	}
+
+CPolicyServer::TCustomResult CEirManServer::CustomSecurityCheckL(const RMessage2& aMsg, TInt& /*aAction*/, TSecurityInfo& /*aMissing*/)
+	{
+	TEirManMessages function = static_cast<TEirManMessages>(aMsg.Function());
+	TEirTag tag;
+	TCustomResult result = EFail; //Fail everything by default
+	_LIT_SECURITY_POLICY_S0(KSDPSecurityPolicy, KSDPServerID);
+	_LIT_SECURITY_POLICY_S0(KStackSecurityPolicy, KStackID);
+	_LIT_SECURITY_POLICY_C1(KVendorSpecificDataSecurityPolicy, ECapabilityWriteDeviceData);
+	if(function == EEirManRegisterTag)
+		{
+		tag = static_cast<TEirTag>(aMsg.Int0());
+		switch(tag)
+			{
+			case EEirTagName:
+			case EEirTagTxPowerLevel:
+				/** These must have come from the stack **/
+				if(KStackSecurityPolicy.CheckPolicy(aMsg))
+					{
+					result = EPass;
+					}
+				break;
+			case EEirTagSdpUuid16:
+			case EEirTagSdpUuid32:
+			case EEirTagSdpUuid128:
+				/** These must have come from SDP server **/
+				if(KSDPSecurityPolicy.CheckPolicy(aMsg))
+					{
+					result = EPass;
+					}
+				break;
+			case EEirTagManufacturerSpecific:
+				/** To do this you must have write device data **/
+				if(KVendorSpecificDataSecurityPolicy.CheckPolicy(aMsg))
+					{
+					result = EPass;
+					}
+				break;
+			
+			case EEirTagFlags:
+				/** At present no implementation of Flags is supported. 
+				    So we are rejecting this until an implementation is provided. **/
+			default: //unknown or reserved tag, reject
+				//no need to do anything 
+				break;
+			}
+		}
+	//Anything not covered by the above is invalid so do nothing and let it fail
+	if(result == EFail)
+		{
+		LOG1(_L("CEirManServer::CustomSecurityCheckL failed. Function: %d"), function);
+		}
+	return result;
+	}