authorisation/userpromptservice/server/source/upsserver/upssubsession.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 12 Oct 2009 10:17:04 +0300
changeset 15 da2ae96f639b
parent 8 35751d3474b7
permissions -rw-r--r--
Revision: 200941 Kit: 200941

/*
* 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: 
* Implements CUpsSession.	 See class and function definitions for
* more information.
*
*/


/**
 @file
*/

#include "upsserver.h"
#include "authoriser.h"
#include <ups/upserr.h>

namespace UserPromptService
{

CUpsSubsession* CUpsSubsession::NewL(CUpsSession &aSession, const RMessage2& aMessage)
/**
	Factory function allocates a new, initialized instance of CUpsSubsession.

	@param	aMessage		Standard server-side handle to message.
	@return					New, initialized instance of CUpsSubsession which
							is owned by the caller.
 */
	{
	CUpsSubsession* self = new(ELeave) CUpsSubsession(aSession);
	// Note that CUpsSubsession ulitmately derives from CObject and therefore it MUST NOT be deleted directly,
	// instead it should be closed if we leave. 
	// nb. CUpsSession does NOT derive from CObject...
	CleanupClosePushL(*self);
	self->ConstructL(aMessage);
	CleanupStack::Pop(self);
	return self;
	}

CUpsSubsession::CUpsSubsession(CUpsSession &aSession)
/**
	This private constructor prevents direct instantiation and provides
	a single point of definition from which to call the superclass c'tor.
 */
:	CScsSubsession(aSession)
	{
	// empty.
	//RDebug::Printf("0x%x CUpsSubsession(session %x)\n", this, &aSession);
	}

void CUpsSubsession::ConstructL(const RMessage2& aMessage)
/**
	Initialize this subsession object by opening a handle to the
	thread whose identifier has been sent.

	@param	aSession		Ref to session creating us
	@param	aMessage		Standard server-side handle to message.
 */
	{
	// ARGS: TThreadId, TProcessId

	TPckg<TThreadId> tidBuf(iClientTid);
	aMessage.ReadL(0, tidBuf);

	TPckg<TProcessId> pidBuf(iClientPid);
	aMessage.ReadL(1, pidBuf);
	}

CUpsSubsession::~CUpsSubsession()
/**
	Close this object's handle to the SS client thread.
 */
	{
	//RDebug::Printf("0x%x ~CUpsSubsession()\n", this);
	iDestination.Close();
	iOpaqueData.Close();
	}

TBool CUpsSubsession::DoServiceL(TInt aFunction, const RMessage2& aMessage)
/**
	Implement CScsSubsession by handling the supplied message.

	@param	aFunction		Function identifier without SCS code.
	@param	aMessage		Standard server-side handle to message.
	@return ETrue means complete client request now.
 */
	{
	UserPromptService::TSubsessionFunction f =
		static_cast<UserPromptService::TSubsessionFunction>(aFunction);
	//RDebug::Printf("0x%x CUpsSubsession::DoServiceL function %d\n", this, f);
	switch (f)
		{
	case UserPromptService::ESubsessPreparePrompt:
		PreparePromptL(aMessage);
		break;

	case UserPromptService::ESubsessExecutePrompt:
		ExecutePromptL(aMessage);
		return EFalse; // If ExecutePrompt returns, instead of leaving, it must have setup an async req
	BULLSEYE_OFF
	default:
		User::Leave(KErrNotSupported);
		break;
	BULLSEYE_RESTORE
		}
	return ETrue;
	}

void CUpsSubsession::PreparePromptL(const RMessage2& aMessage)
	/**
	   Save service, description, and opaque data for use in the
	   following execute prompt command.
	*/
	{
	// TIpcArgs is TServiceId aServiceId, const TDesC* aDestination, const TDesC8* aOpaqueData
	
	iServiceId.iUid = aMessage.Int0();

	// Get Description
	TInt destinationLength = aMessage.GetDesLengthL(1);
	iDestination.Close();
	iDestination.CreateL(destinationLength);
	aMessage.ReadL(1, iDestination);

	// Get Opaque Data
	TInt opaqueDataLength = aMessage.GetDesLengthL(2);
	iOpaqueData.Close();
	if(opaqueDataLength)
		{
		iOpaqueData.CreateL(opaqueDataLength);
		aMessage.ReadL(2, iOpaqueData);
		}
	}

void CUpsSubsession::ExecutePromptL(const RMessage2& aMessage)
	/**
	  Create and start the CAuthoriser to process the request.
	*/
	{
	// TIpcArgs is OUT:TUpsDecision& aDecision, IN:TBool aServerCheckOk

	// The authorizer object is derived from CAsyncRequest and its
	// lifecycle is automatically managed by the SCS framework
	//
	// iDestination and iOpaqueData are transfered to the CAuthoriser,
	// our handles will be closed.
	TBool serverCheckOk = aMessage.Int1();
	CUpsSession *session = static_cast<CUpsSession*>(&iSession);
	RPolicyCacheCountedHandle &cacheManager = session->UpsServer()->iPolicyCache;
	CleanupReleasePushL(cacheManager);
	if(!cacheManager.IsOpen())
		{
		cacheManager.OpenL();
		}
	CAuthoriser *authoriser = CAuthoriser::NewL(cacheManager,
												session, this, serverCheckOk,
												iClientTid, iClientPid,
												aMessage, iServiceId, iDestination, iOpaqueData);
	CleanupStack::Pop(&cacheManager); // transfered ownership to the new CAuthoriser
	CleanupStack::PushL(authoriser);
	authoriser->TransferToScsFrameworkL();
	CleanupStack::Pop(authoriser); // authoriser now owned by SCS framework

	/**
	   The authoriser is now responsible for completing the request,
	   so we must NOT leave.
	   
	   We could start the request processing off by calling an
	   authoriser function from within a TRAP handler, but for future
	   proofing we tell the authoriser to self complete so the
	   processing all happens within the active scheduler framework
	   and the authoriser state machine. This will make it much easier
	   to completly restart request processing (if we decide to when
	   policies are changed).
	*/
	authoriser->Wakeup();
	}


} // End of namespace UserPromptService
// End of file