sl@0: /*
sl@0: * Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: * All rights reserved.
sl@0: * This component and the accompanying materials are made available
sl@0: * under the terms of the License "Eclipse Public License v1.0"
sl@0: * which accompanies this distribution, and is available
sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: *
sl@0: * Initial Contributors:
sl@0: * Nokia Corporation - initial contribution.
sl@0: *
sl@0: * Contributors:
sl@0: *
sl@0: * Description: 
sl@0: * fstokenserver.cpp
sl@0: *
sl@0: */
sl@0: 
sl@0: 
sl@0: #include "fsserver.h"
sl@0: #include "fstokenutil.h"
sl@0: #include "cfskeystoreserver.h"
sl@0: #include "CKeyStoreSession.h"
sl@0: #include "filecertstore.h"
sl@0: #include "CCertStoreSession.h"
sl@0: #include "CFSCertAppsServer.h"
sl@0: #include "CCertAppsSession.h"
sl@0: #include "FSResources.h"
sl@0: #include "FSDialog.h"
sl@0: #include "tokenserverdebug.h"
sl@0: #include "fstokenservername.h"
sl@0: 
sl@0: // CTokenServerSession /////////////////////////////////////////////////////////
sl@0: 
sl@0: CTokenServerSession::CTokenServerSession()
sl@0: 	{
sl@0: 	}
sl@0: 
sl@0: inline CTokenServer& CTokenServerSession::Server()
sl@0: 	{
sl@0: 	return static_cast<CTokenServer&>(const_cast<CServer2&>(*CSession2::Server()));
sl@0: 	}
sl@0: 
sl@0: void CTokenServerSession::CreateL()
sl@0: 	{
sl@0: 	Server().AddSession();
sl@0: 	}
sl@0: 
sl@0: CTokenServerSession::~CTokenServerSession()
sl@0: 	{
sl@0: 	Server().DropSession();
sl@0: 	}
sl@0: 
sl@0: /**
sl@0:  * Handle a client request.  Leaving is handled by
sl@0:  * CTokenServerSession::ServiceError() which reports the error code to the
sl@0:  * client.
sl@0:  */
sl@0: void CTokenServerSession::ServiceL(const RMessage2& aMessage)
sl@0: 	{
sl@0: #ifdef _DEBUG
sl@0: 	// OOM testing
sl@0: 	switch (aMessage.Function())
sl@0: 		{
sl@0: 		case EStartOOMTest:
sl@0: 			TokenServerDebug::StartOOMTest();
sl@0: 			aMessage.Complete(KErrNone);
sl@0: 			return;
sl@0: 			
sl@0: 		case EIncHeapFailPoint:
sl@0: 			TokenServerDebug::IncHeapFailPoint();
sl@0: 			aMessage.Complete(KErrNone);
sl@0: 			return;
sl@0: 			
sl@0: 		case EResetHeapFail:
sl@0: 			TokenServerDebug::ResetHeapFail();
sl@0: 			aMessage.Complete(KErrNone);
sl@0: 			return;
sl@0: 
sl@0: 		case EAllocCount:
sl@0: 			aMessage.Complete(User::CountAllocCells());
sl@0: 			return;
sl@0: 		}	
sl@0: #endif
sl@0: 	
sl@0: 	DoServiceL(aMessage);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0:  * Handle an error from ServiceL() A bad descriptor error implies a badly
sl@0:  * programmed client, so panic it - otherwise report the error to the client.
sl@0:  */
sl@0: void CTokenServerSession::ServiceError(const RMessage2& aMessage, TInt aError)
sl@0: 	{
sl@0: 	if (aError==KErrBadDescriptor)
sl@0: 		{
sl@0: 		PanicClient(aMessage, EPanicBadDescriptor);
sl@0: 		}
sl@0: 	
sl@0: 	CSession2::ServiceError(aMessage, aError);
sl@0: 	}
sl@0: 
sl@0: // CTokenServer ////////////////////////////////////////////////////////////////
sl@0: 
sl@0: inline CTokenServer::CTokenServer() :
sl@0: 	CServer2(0, ESharableSessions)
sl@0: 	{
sl@0: 	}
sl@0: 
sl@0: CServer2* CTokenServer::NewLC()
sl@0: 	{
sl@0: 	CTokenServer* self=new(ELeave) CTokenServer;
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->ConstructL();
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: CTokenServer::~CTokenServer()
sl@0: 	{
sl@0: 	FSResources::Cleanup();
sl@0: 	FSDialog::Cleanup();
sl@0: 
sl@0: 	delete iKeyStoreServer;
sl@0: 	delete iCertStoreServer;
sl@0: 	delete iCertAppsServer;
sl@0: 	}
sl@0: 
sl@0: /**	2nd phase construction - ensure the timer and server objects are running. */
sl@0: void CTokenServer::ConstructL()
sl@0: 	{
sl@0: 	FSResources::InitialiseL();
sl@0: 	FSDialog::InitialiseL();
sl@0: 	
sl@0: 	TPtrC serverName(KFSTokenServerName());
sl@0: 		// Naming the server thread after the server helps to debug panics
sl@0: #ifdef __WINS__
sl@0: #ifdef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
sl@0: 	serverName.Set(KFSNewTokenServerName());
sl@0: #endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
sl@0: #endif // __WINS__
sl@0: 		
sl@0: 	StartL(serverName);
sl@0: 	
sl@0: 	// Ensure that the server still exits even if the 1st client fails to connect
sl@0: 	iShutdown.ConstructL();
sl@0: 	iShutdown.Start();
sl@0: 	}
sl@0: 
sl@0: /** A new session is being created - cancel the shutdown timer if it was running. */
sl@0: void CTokenServer::AddSession()
sl@0: 	{
sl@0: 	++iSessionCount;
sl@0: 	iShutdown.Cancel();
sl@0: 	}
sl@0: 
sl@0: /** A session is being destroyed - start the shutdown timer if it is the last session. */
sl@0: void CTokenServer::DropSession()
sl@0: 	{
sl@0: 	if (--iSessionCount==0)
sl@0: 		{
sl@0: 		iShutdown.Start();
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /** Lazily create key store server object. */
sl@0: CFSKeyStoreServer& CTokenServer::KeyStoreServerL() const
sl@0: 	{
sl@0: 	if (!iKeyStoreServer)
sl@0: 		{
sl@0: 		iKeyStoreServer = CFSKeyStoreServer::NewL();
sl@0: 		}
sl@0: 	
sl@0: 	return *iKeyStoreServer;
sl@0: 	}
sl@0: 
sl@0: /** Lazily create cert store server object. */
sl@0: CFSCertStoreServer& CTokenServer::CertStoreServerL() const
sl@0: 	{
sl@0: 	if (!iCertStoreServer)
sl@0: 		{
sl@0: 		iCertStoreServer = CFSCertStoreServer::NewL();
sl@0: 		}
sl@0: 	
sl@0: 	return *iCertStoreServer;
sl@0: 	}
sl@0: 
sl@0: /** Lazily create cert apps server object. */
sl@0: CFSCertAppsServer& CTokenServer::CertAppsServerL() const
sl@0: 	{
sl@0: 	if (!iCertAppsServer)
sl@0: 		{
sl@0: 		iCertAppsServer = CFSCertAppsServer::NewL();
sl@0: 		}
sl@0: 	
sl@0: 	return *iCertAppsServer;
sl@0: 	}
sl@0: 
sl@0: /** Create a new client session. */
sl@0: CSession2* CTokenServer::NewSessionL(const TVersion& aVersion, const RMessage2& /*aMessage*/) const
sl@0: 	{
sl@0: 	// The token the client wants to talk to is encoded in the major version number
sl@0: 	ETokenEnum token = static_cast<ETokenEnum>(aVersion.iMajor);	
sl@0: 
sl@0: 	// The minor version number represents the version of the protocol
sl@0: 	if (aVersion.iMinor != KFSProtolVersion)
sl@0: 		{
sl@0: 		User::Leave(KErrNotSupported);
sl@0: 		}
sl@0: 
sl@0: 	CTokenServerSession* result = NULL;
sl@0: 	
sl@0: 	switch (token)
sl@0: 		{
sl@0: 		case EFileKeyStore:
sl@0: 			result = KeyStoreServerL().CreateSessionL();
sl@0: 			break;
sl@0: 
sl@0: 		case EFileCertStore:
sl@0: 			result = CertStoreServerL().CreateSessionL();
sl@0: 			break;
sl@0: 			
sl@0: 		case EFileCertApps:
sl@0: 			result = CertAppsServerL().CreateSessionL();
sl@0: 			break;
sl@0: 			
sl@0: 		default:
sl@0: 			User::Leave(KErrNotSupported);
sl@0: 			break;
sl@0: 		}
sl@0: 
sl@0: 	return result;
sl@0: 	}
sl@0: 
sl@0: // CShutdown ///////////////////////////////////////////////////////////////////
sl@0: 
sl@0: inline CShutdown::CShutdown() :
sl@0: 	CTimer(-1)
sl@0: 	{
sl@0: 	CActiveScheduler::Add(this);
sl@0: 	}
sl@0: 
sl@0: inline void CShutdown::ConstructL()
sl@0: 	{
sl@0: 	CTimer::ConstructL();
sl@0: 	}
sl@0: 
sl@0: inline void CShutdown::Start()
sl@0: 	{
sl@0: 	After(KServerShutdownDelay);
sl@0: 	}
sl@0: 
sl@0: /** Initiate server exit when the timer expires. */
sl@0: void CShutdown::RunL()
sl@0: 	{
sl@0: 	CActiveScheduler::Stop();
sl@0: 	}
sl@0: 
sl@0: // Server startup //////////////////////////////////////////////////////////////
sl@0: 
sl@0: /**
sl@0:  * Perform all server initialisation, in particular creation of the scheduler
sl@0:  * and server and then run the scheduler.
sl@0:  */
sl@0: static void RunServerL()
sl@0: 	{
sl@0: 	TPtrC serverName(KFSTokenServerName());
sl@0: 	// Naming the server thread after the server helps to debug panics
sl@0: #ifdef __WINS__
sl@0: #ifdef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
sl@0: 	serverName.Set(KFSNewTokenServerName());
sl@0: #endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
sl@0: #endif // __WINS__
sl@0: 	
sl@0: 	User::LeaveIfError(User::RenameThread(serverName));
sl@0: 	
sl@0: 	// Create and install the active scheduler we need
sl@0: 	CActiveScheduler* s=new(ELeave) CActiveScheduler;
sl@0: 	CleanupStack::PushL(s);
sl@0: 	CActiveScheduler::Install(s);
sl@0: 	
sl@0: 	// Create the server and leave it on the cleanup stack
sl@0: 	CTokenServer::NewLC();
sl@0: 	
sl@0: 	// Before starting the server, notify client that initialisation is
sl@0: 	// complete.
sl@0: 	// (note that WINS on EKA1 uses threads since it lacks process emulation)
sl@0: 	RProcess::Rendezvous(KErrNone);
sl@0: 
sl@0: 	// Ready to run
sl@0: 	CActiveScheduler::Start();
sl@0: 	
sl@0: 	// Cleanup the server and scheduler
sl@0: 	CleanupStack::PopAndDestroy(2);
sl@0: 	}
sl@0: 
sl@0: /** Server process entry point. */
sl@0: TInt E32Main()
sl@0: 	{
sl@0: #ifdef _DEBUG
sl@0: 	TokenServerDebug::HeapCheckStart();
sl@0: #endif
sl@0: 
sl@0: 	CTrapCleanup* cleanup=CTrapCleanup::New();
sl@0: 	TInt r=KErrNoMemory;
sl@0: 	if (cleanup)
sl@0: 		{
sl@0: 		TRAP(r,RunServerL());
sl@0: 		delete cleanup;
sl@0: 		}
sl@0: 
sl@0: #ifdef _DEBUG
sl@0: 	TokenServerDebug::HeapCheckEnd();
sl@0: #endif
sl@0: 	return r;
sl@0: 	}
sl@0: 
sl@0: // Only for wins on EKA1 - WINS loads a DLL and starts a new thread
sl@0: // by calling WinsMain which does the "server" startup