lbs/internal/lbstestserver/src/csecuresessionsubsessionbase.cpp
branchSymbian2
changeset 1 8758140453c0
child 6 c108117318cb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lbs/internal/lbstestserver/src/csecuresessionsubsessionbase.cpp	Thu Jan 21 12:53:44 2010 +0000
@@ -0,0 +1,319 @@
+// Copyright (c) 2006-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 "Symbian Foundation License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <e32debug.h>
+#include "csecuresessionsubsessionbase.h"
+#include "csubsessionbase.h"
+#include "lbsmessageenums.h"
+#include "messageutils.h"
+#include "lbsdevloggermacros.h"
+
+/** 
+constructor, call the CSecureSessionBase base class constructor
+
+@internalTechnology
+@released
+ */	
+CSecureSessionSubSessionBase::CSecureSessionSubSessionBase() : CSecureSessionBase()
+	{
+	LBSLOG(ELogP3, "CSecureSessionSubSessionBase::CSecureSessionSubSessionBase()");
+	}
+
+/** 
+destructor, release the subsession handler container
+
+@internalTechnology
+@released
+ */	
+CSecureSessionSubSessionBase::~CSecureSessionSubSessionBase()
+	{
+	LBSLOG(ELogP3, "->CSecureSessionSubSessionBase::~CSecureSessionSubSessionBase()");
+
+	if (iObjectIx)
+		{
+		TInt count = iObjectIx->Count();
+		for(TInt i=0; i<count; i++)
+			{
+			CObject* theObj = (*iObjectIx)[i];
+			if (theObj)
+				{
+				TInt handle = iObjectIx->At(theObj);
+				// if we reach here somethingbad has happened. The server class
+				// (i.e. the session object) is being closed by the client, BEFORE
+				// the client has closes all of the open subsessions.
+				// So the only reasonable thingto do here is:
+				// delete the subsession - without closing it first. 'Cos this is
+				// _exactly_ what the client side has asked for (for some reason).
+				// The may or may not be legal, or even a good idea depending on the type of server
+				// that is being developeds. But the server framework should NOT
+				// prevent this from happening. Generating a panic is a 
+				// server developers choice, not a framework developers choice.
+				// We delete by calling CObjectIdx::Remove(). This will call CObject::Close.
+				// This in turn calls MSubSessionImpl::MRelease::VirtualRelease
+				// which will destroy the sub session for us.
+				// CloseSubSession should not be called directly.
+				iObjectIx->Remove(handle);
+				
+				//
+				// If the array length has changed, then update count and move back one space,
+				// so that the same cell will be re-inspected during the next iteration of the
+				// loop  This is because we have removed the current cell and therefore the
+				// next cell is actually in iObjectIx[i] (i.e. the current one).
+				TInt newCount = iObjectIx->Count();
+				
+				if (newCount != count)
+					{
+					count = newCount;
+					i--;
+					}
+
+				}
+			}
+		delete iObjectIx;
+		}
+	if (iContainerIx)
+		{
+		iContainerIx->Remove(iObjectCon);
+		delete iContainerIx;
+		}
+	// session decrementing handled in the parent class
+	LBSLOG(ELogP3, "<-CSecureSessionSubSessionBase::~CSecureSessionSubSessionBase()");
+	}
+	
+/** 
+called as part of the CSession2 construction. 
+Create subsession handler container and call the session CreateL function to increase the session count
+
+@internalTechnology
+@released
+ */	
+void CSecureSessionSubSessionBase::CreateL()
+	{
+	LBSLOG(ELogP3, "->CSecureSessionSubSessionBase::CreateL");
+	iObjectIx = CObjectIx::NewL();
+	iContainerIx = CObjectConIx::NewL();
+	iObjectCon = iContainerIx->CreateL();
+	CSecureSessionBase::CreateL(); // call the parent class to inc the session count
+	iBaseCreateCalled = ETrue;
+	LBSLOG(ELogP3, "<-CSecureSessionSubSessionBase::CreateL");
+	}
+	
+/** 
+Do the real thing for subsession construction.
+Check whether the session constructL function is called or not first. If not, panic the server,
+Create a subsession and push it to stack, get the implementation of subsession and invoke the 
+real subsession creation implementation.
+
+Add the subsession handler to container and write the handler to client address space through message object
+Complete the creating message.
+
+@param aMessage A RMessage2 reference.
+@internalTechnology
+@released
+ */	
+void CSecureSessionSubSessionBase::CreateSubSessionL(const RMessage2& aMessage)
+	{
+	__ASSERT_ALWAYS(iBaseCreateCalled, Server()->PanicServer(CSecureServerBase::EBaseCreateNotCalled));
+	CSubSessionBase* subSession = new (ELeave) CSubSessionBase();
+	// Note: Use the CObject::Close() function instead of usual destructor
+	// because it is needed to correctly decrement the reference count.
+	// Close() will destruct subSession anyway if the ref count == 0.
+	CleanupClosePushL(*subSession);
+
+	MSubSessionImpl* impl = subSession->GetImplL(aMessage);
+	CleanupVirtualReleasePushL(*impl); // call Release() on destruction
+	//CleanupVirtualRelease::PushL(*impl);
+	subSession->SetImpl(impl); // will take ownership(!)
+	CleanupStack::Pop(impl);
+
+	// We need to pass a handle to the controllign server down to the subsession object.
+	// Since the subsession impl object is a CBase object (NOT a CSession2 object)
+	// we haev to do this outherwise the subsession will not be able to referene the
+	// server - which seems like a useful thing to do.
+	const CSecureServerBase* server = reinterpret_cast<const CSecureServerBase*>(Server()); 	
+	impl->CreateSubSessionL(aMessage, server);
+	
+	iObjectCon->AddL(subSession);
+	TInt handle = iObjectIx->AddL(subSession);
+	TPckgC<TInt> pH(handle);
+	MessageUtils::Write(aMessage, 3, pH);
+	aMessage.Complete(KErrNone);
+	CleanupStack::Pop(subSession);
+	}
+	
+/** 
+Do the real thing for subsession destruction.
+Check whether the session constructL function is called or not first. If not, panic the server,
+get a subsession handler from container and complete the message if subsession is already close, 
+if not, close subsession and remove it from container then complete the message.
+
+@param aMessage A RMessage2 reference.
+@internalTechnology
+@released
+ */	
+void CSecureSessionSubSessionBase::DestroySubSession(const RMessage2& aMessage)
+	{
+	__ASSERT_ALWAYS(iBaseCreateCalled, Server()->PanicServer(CSecureServerBase::EBaseCreateNotCalled));
+	CSubSessionBase* subSession = reinterpret_cast<CSubSessionBase*>(iObjectIx->At(aMessage.Int3()));
+	
+	if (subSession == NULL)
+		{
+		aMessage.Complete(KErrBadHandle);
+		}
+	else
+		{
+		// we have been asked to close a subsession by the client side so
+		// do just that :). c.f. CSecureSessionSubSessionBase::~CSecureSessionSubSessionBase() above.
+		// In this case we do need to call CloseSubSession before deleting
+		// the subsession object.
+		// We delete by calling CObjectIdx::Remove().This will call CObject::Close.
+		// This in turn calls MSubSessionImpl::MRelease::VirtualRelease
+		// which willdestroy the sub session for us.
+		CSubSessionBase* subSession = static_cast<CSubSessionBase*>(iObjectIx->At(aMessage.Int3()));
+		iObjectIx->Remove(aMessage.Int3());
+		aMessage.Complete(KErrNone);
+		}
+	}
+
+/** 
+Check whether the session constructL function is called or not first. If not, panic the server,
+
+Dispatch the message at session level, only two types of message are handled here:
+SubSession Open and Close.
+The other messages are fwd to subsession via DispatchMessage.
+
+@param aMessage A RMessage2 reference.
+@internalTechnology
+@released
+ */	
+void CSecureSessionSubSessionBase::DispatchL(const RMessage2& aMessage)
+	{
+	__ASSERT_ALWAYS(iBaseCreateCalled, Server()->PanicServer(CSecureServerBase::EBaseCreateNotCalled));
+	switch(aMessage.Function())
+		{
+		case ESecureSubSessionBaseOpen:
+			CreateSubSessionL(aMessage);
+			break;
+		case ESecureSubSessionBaseClose:
+			DestroySubSession(aMessage);
+			break;
+		default:
+			// the message could be EITHER a session operation - which we have to handle here, or an operation
+			// handled by the subsession which we have to forward
+			DispatchMessageL(aMessage);
+			break;
+		}
+		
+	}
+
+/** 
+Check whether the session constructL function is called or not first. If not, panic the server,
+
+Check whether the message are for session or subsession
+Dispatch the message at subsession level
+get the subsession handler from container and dispatch the message to subsession implementation!
+
+@param aMessage A RMessage2 reference.
+@internalTechnology
+@released
+ */	
+void CSecureSessionSubSessionBase::DispatchMessageL(const RMessage2& aMessage)
+	{
+	__ASSERT_ALWAYS(iBaseCreateCalled, Server()->PanicServer(CSecureServerBase::EBaseCreateNotCalled));
+	// NB the test is intened to ignore a function enum of ELastSessionMessageId - this is not a valid command
+	if(aMessage.Function()<ELastSessionMessageId)
+		{
+		// the message is for the session
+		ServiceMessageL(aMessage); // implmented in the DERIVED CSessionBase class.
+		}
+	else if(aMessage.Function()>ELastSessionMessageId)
+		{
+		// MUST be a message for the subsystem object - delegate
+		CSubSessionBase* subSession = static_cast<CSubSessionBase*>(iObjectIx->At(aMessage.Int3()));
+		subSession->Impl()->DispatchL(aMessage);
+		}
+	}
+
+/** 
+Return the server
+
+@return Pointer to server base
+@internalTechnology
+@released
+ */	
+const CSecureServerBase* CSecureSessionSubSessionBase::Server() const
+	{
+	return reinterpret_cast<const CSecureServerBase*>(CSession2::Server());
+	}
+
+/** 
+Check whether the session constructL function is called or not first. If not, panic the server,
+
+Dispatch the message at session level, only two types of message are handled here:
+SubSession Open and Close.
+If error happened when open subsession, destroy the subsession.
+
+otherwise, pop the error messages to session or fwd to subsession via DispatchError.
+
+@param aMessage A RMessage2 reference.
+@param aError Error code.
+@internalTechnology
+@released
+ */	
+void CSecureSessionSubSessionBase::DispatchError(const RMessage2& aMessage, TInt aError)
+	{
+	__ASSERT_ALWAYS(iBaseCreateCalled, Server()->PanicServer(CSecureServerBase::EBaseCreateNotCalled));
+	CSubSessionBase* subSession = NULL;
+	switch(aMessage.Function())
+		{
+		case ESecureSubSessionBaseOpen:
+			if(aError == KErrArgument)
+				{
+				// panic the client we have NO idea what sort
+				// of sub session class the user was tryign to create. 
+				// This is a client side failure!, so shoot the client
+				MessageUtils::PanicClient(aMessage, KServerFrameworkPanic, ESecureSubSessionBaseUnknownSubSessionType);
+				// NB there is NOTHING to clean up here, everything is deleted via
+				// the cleanup stack, and the subsession object was never added to the
+				// obejct containers.... See CreateSubSessionL above
+				}
+			else
+				{
+				// CreateSubSessionL() has caused a Leave, so there is 
+				// no sub session object to clear up - just complete the
+				// message with an error
+				aMessage.Complete(aError);
+				}
+			break;
+		case ESecureSubSessionBaseClose:
+			// Panic? Non-leaving function that just left?
+			break;
+		default:
+			// DisplatchMessageL above has left - this could be becuase ServiceMessageL left or the subsession DisplatchL
+			// NB the test is intened to ignore a function enum of ELastSessionMessageId - this is not a valid command
+			if(aMessage.Function()<ELastSessionMessageId)
+				{
+				// the message is for the session
+				ServiceMessageError(aMessage, aError); // implmented in the DERIVED CSessionBase class.
+				}
+			else if(aMessage.Function()>ELastSessionMessageId)
+				{
+				// MUST be a message for the subsystem object - delegate
+				subSession = static_cast<CSubSessionBase*>(iObjectIx->At(aMessage.Int3()));
+				subSession->Impl()->DispatchError(aMessage, aError);
+				}
+			break;
+		}
+	}