diff -r 675a964f4eb5 -r 35751d3474b7 authorisation/userpromptservice/examples/integration/tmsgserver/tmsgserver.cpp --- /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 +#include + +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(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(const_cast(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; + } +