authorisation/userpromptservice/examples/integration/tmsgserver/tmsgserver.cpp
changeset 8 35751d3474b7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/authorisation/userpromptservice/examples/integration/tmsgserver/tmsgserver.cpp	Thu Sep 10 14:01:51 2009 +0300
@@ -0,0 +1,370 @@
+/*
+* 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 the License "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: 
+* Example code
+*
+*/
+
+
+#include "tmsgcommon.h"
+#include "tmsgserver.h"
+#include <e32cmn.h>
+#include <e32debug.h>
+
+inline CShutdown::CShutdown() :CTimer(-1) {CActiveScheduler::Add(this);}
+inline void CShutdown::ConstructL() {CTimer::ConstructL();}
+inline void CShutdown::Start() {After(KMyShutdownDelay);}
+
+void CShutdown::RunL()
+	{
+	CActiveScheduler::Stop();
+	}
+
+
+// CMsgServer ****************************************************************
+inline UserPromptService::RUpsSession& CMsgServer::Ups() {return iUps;}
+
+const TInt CMsgServer::iRanges[KPolicyRanges] =
+	{
+	ESendMsg,			// network services requried
+	ECancelSendMsg,		// no capability needed to request
+	ESeperatorEndAll
+	};
+
+const TUint8 CMsgServer::iElementsIndex[KPolicyRanges] = 
+	{
+	0,								// capability check for networkservices
+	EAlwaysPass,					// no check needed to cancel a request
+	CPolicyServer::ENotSupported	
+	};
+
+static const TInt KMsgServerCustomFailureAction = -1;
+
+const CPolicyServer::TPolicyElement CMsgServer::iPolicyElements[KPolicyElements] =
+	{
+	{_INIT_SECURITY_POLICY_C1(ECapabilityNetworkServices), KMsgServerCustomFailureAction}
+	};
+
+const CPolicyServer::TPolicy CMsgServer::iPolicy =
+	{
+	CPolicyServer::EAlwaysPass, // so that any client can connect	
+	KPolicyRanges,									 
+	iRanges,
+	iElementsIndex,
+	iPolicyElements,
+	};
+
+
+CMsgServer::CMsgServer()
+	: CPolicyServer(EPriorityStandard, iPolicy, ESharableSessions)
+	{
+	}
+
+CMsgServer::~CMsgServer()
+	{
+	iUps.Close();
+	}
+
+CMsgServer* CMsgServer::NewLC()
+	{
+	CMsgServer* self = new(ELeave) CMsgServer();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+void CMsgServer::ConstructL() 
+	{
+	// Create the RUpsSession
+	// A sub-session is created for each client
+	User::LeaveIfError(iUps.Connect());
+
+	StartL(KMsgServerName);
+	iShutdown.ConstructL();
+	iShutdown.Start();	
+	}
+
+CPolicyServer::TCustomResult CMsgServer::CustomFailureActionL(const RMessage2& aMessage, TInt /*aAction*/, const TSecurityInfo& /*aMissing*/)
+/** This function is only invoked for requests that allow UPS authorisation. The 
+ * message may be rejected later if the user denies the request.
+ */
+	{
+	CSession2* s = aMessage.Session();
+	__ASSERT_ALWAYS(s != NULL, User::Invariant());
+	CMsgServerSession* session = static_cast<CMsgServerSession*>(s);
+	session->SetPlatsecResult(EFalse);	
+	return CPolicyServer::EPass;	// The request may be rejected later by the UPS
+	}
+
+CSession2* CMsgServer::NewSessionL(const TVersion& aVersion, const RMessage2& /*aMessage*/) const
+	{
+	TVersion v(KMsgServerVersionMajor, KMsgServerVersionMinor, KMsgServerVersionBuild);
+	if (!User::QueryVersionSupported(v,aVersion))
+		{
+		User::Leave(KErrNotSupported);		
+		}
+	return new(ELeave) CMsgServerSession();
+	}
+
+void CMsgServer::AddSession()
+	{
+	++iSessionCount;
+	iShutdown.Cancel();
+	}
+
+void CMsgServer::DropSession()
+	{
+	if (--iSessionCount==0)	iShutdown.Start();
+	}
+
+void PanicClient(const RMessagePtr2& aMessage,TMsgServerPanic aPanic)
+	{
+	aMessage.Panic(KMsgServerName,aPanic);
+	}
+
+// CMsgServerSession *********************************************************
+inline CMsgServer& CMsgServerSession::Server()
+{return *static_cast<CMsgServer*>(const_cast<CServer2*>(CSession2::Server()));}
+
+CMsgServerSession::CMsgServerSession()
+	: iPlatsecResult(ETrue)
+	{
+	}
+
+CMsgServerSession::~CMsgServerSession()
+	{
+	delete iProcessor;	
+	iAuth.Close();
+	Server().DropSession();
+	}
+
+void CMsgServerSession::CreateL()
+	{
+	Server().AddSession();
+	iProcessor = CMsgProcessor::NewL(iAuth);
+	}
+
+void CMsgServerSession::ServiceL(const RMessage2& aMessage)
+	{
+	if (! iAuthInitialised)
+		{
+		RThread client;
+		aMessage.ClientL(client);
+		CleanupClosePushL(client);
+		User::LeaveIfError(iAuth.Initialise(Server().Ups(), client));
+		CleanupStack::PopAndDestroy(&client);
+		iAuthInitialised = ETrue;
+		}	
+	
+	iProcessor->ProcessL(aMessage, iPlatsecResult);
+	// Reset to 'passed' for next message because SetPlatsecResult is only ever called
+	// when a check fails.
+	iPlatsecResult = ETrue;	
+	}
+
+void CMsgServerSession::SetPlatsecResult(TBool aResult)
+	{
+	iPlatsecResult = aResult;
+	}
+
+// CMsgProcessor *********************************************************((((
+CMsgProcessor* CMsgProcessor::NewL(UserPromptService::RUpsSubsession& aAuth)
+	{
+	CMsgProcessor* self = new(ELeave) CMsgProcessor(aAuth);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CMsgProcessor::CMsgProcessor(UserPromptService::RUpsSubsession& aAuth)
+	: CActive(EPriorityStandard), iState(EIdle), iAuth(aAuth)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CMsgProcessor::ConstructL()
+	{
+	User::LeaveIfError(iTimer.CreateLocal());
+	}
+
+CMsgProcessor::~CMsgProcessor()
+	{	
+	Deque();
+	Reset();
+	iTimer.Close();
+	}
+
+TInt CMsgProcessor::RunError(TInt aError)
+	{
+	if (iState != EIdle) iMessage.Complete(aError);
+
+	Reset();
+	return KErrNone;
+	}
+
+void CMsgProcessor::Reset() 
+/**
+ * Resets the processor for the next message.
+ */
+	{
+	iMsgTo.Close();
+	iMsgBody.Close();
+	iState = EIdle;
+	}
+
+void CMsgProcessor::RunL()
+	{
+	User::LeaveIfError(iStatus.Int());
+	switch (iState)
+		{
+		case EAuthorising:			
+			// Check whether the request was authorised before proceeding
+			if (iDecision == EUpsDecSessionNo || iDecision == EUpsDecNo)
+				{ // The user or UPS denied the client's request so fail with security error.				  
+				iMessage.Complete(KErrPermissionDenied);
+				Reset();
+				}
+			else
+				{ // Request authorised so carry on as normal
+				SendL();	
+				}
+			break;
+		case ESending:						
+			// Message send so complete request and return
+			iMessage.Complete(KErrNone);
+			Reset();
+			break;
+		default: // invalid state - should never happen
+			__ASSERT_ALWAYS(EFalse, User::Invariant()); 
+			break;
+		}
+	}
+
+void CMsgProcessor::DoCancel()
+	{
+	switch (iState)
+		{
+		case EIdle:
+			break; // nothing to do
+		case EAuthorising:
+			iAuth.CancelPrompt();			
+			break;
+		case ESending:
+			iTimer.Cancel();
+			break;
+		default: // invalid state - should never happen
+			__ASSERT_ALWAYS(EFalse, User::Invariant());
+		}
+	if (iState != EIdle) iMessage.Complete(KErrCancel);
+	Reset();
+	}
+
+void CMsgProcessor::GetParamsL(const RMessage2& aMessage)
+/**
+ * Reads the parameters for sending a message. This data is also needed for the authorisation prompt
+ */
+	{
+	TInt l = aMessage.GetDesLength(0);
+	if (l <= 0) User::Leave(KErrArgument);
+	iMsgTo.CreateL(l);
+	aMessage.ReadL(0, iMsgTo);
+	l = aMessage.GetDesLength(1);
+	if (l <= 0) User::Leave(KErrArgument);
+	iMsgBody.CreateL(l);
+	aMessage.ReadL(1, iMsgBody);
+	}
+
+void CMsgProcessor::AuthoriseL(const RMessage2& aMessage, TBool aPlatsecResult)
+/**
+ * Implementation of the new authorisation state
+ * @param	aMessage		The message handle containing the SendMsg parameters
+ * @param	aPlatsecResult	Whether the client has the correct capabilities etc
+ */
+	{
+	iState = EAuthorising;
+	iPlatsecResult = aPlatsecResult;
+	iMessage = aMessage;
+	GetParamsL(iMessage);	// message parameters are used to identify the request 
+	iAuth.Authorise(iPlatsecResult, TUid::Uid(KServiceId), iMsgTo, iDecision, iStatus);
+	SetActive();
+	}
+
+void CMsgProcessor::SendL() 
+/**
+ * Simulatate the sending of a message by displaying the body
+ * to the screen and waiting for three seconds.
+ * 
+ * No changes necessary to support user prompts.
+ */
+	{
+	iState = ESending;
+	HBufC* tmp = HBufC::NewMaxLC(iMsgTo.Length() + iMsgBody.Length() + 3);
+	tmp->Des().Format(_L("%S: %S"), &iMsgTo, &iMsgBody);
+	User::LeaveIfError(User::InfoPrint(*tmp));
+	CleanupStack::PopAndDestroy(tmp);
+	iTimer.After(iStatus, 3 * 1000 * 1000);
+	SetActive();
+	}
+
+void CMsgProcessor::ProcessL(const RMessage2& aMessage, TBool aPlatsecResult)
+	{
+	switch (aMessage.Function())
+		{
+		case ESendMsg:
+			if (iState == EIdle)
+				{ // The first state is now authorisation				
+				AuthoriseL(aMessage, aPlatsecResult);
+				}
+			else
+				{ // Concurrent requests not supported
+				aMessage.Complete(KErrInUse); 
+				}
+			break;
+		case ECancelSendMsg:
+			Cancel();
+			aMessage.Complete(KErrNone);
+			break;
+		default:
+			User::Leave(KErrNotSupported);
+		}
+	}
+
+static void RunServerL()
+	{
+	// normal server startup code
+	User::LeaveIfError(RThread::RenameMe(KMsgServerName));
+	CActiveScheduler* s=new(ELeave) CActiveScheduler;
+	CleanupStack::PushL(s);
+	CActiveScheduler::Install(s);	
+	CMsgServer::NewLC();
+	RProcess::Rendezvous(KErrNone);
+	CActiveScheduler::Start();
+	CleanupStack::PopAndDestroy(2, s); 
+	}
+
+TInt E32Main()
+	{
+	__UHEAP_MARK;
+	CTrapCleanup* cleanup=CTrapCleanup::New();
+	TInt r=KErrNoMemory;
+	if (cleanup)
+		{
+		TRAP(r,RunServerL());
+		delete cleanup;
+		}
+	__UHEAP_MARKEND;
+	return r;
+	}
+