--- /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;
+ }
+ }