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