--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptomgmtlibs/securitycommonutils/source/scsclient/scsclientbase.cpp Thu Sep 10 14:01:51 2009 +0300
@@ -0,0 +1,306 @@
+/*
+* 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:
+* Generic client-side code for client-server interaction.
+* Attempts to establish a connection to a session counting server,
+* starting the process if required.
+*
+*/
+
+
+/**
+ @file
+*/
+
+#include <scs/scsclient.h>
+
+#include <scs/scscommon.h>
+
+using namespace ScsImpl;
+
+
+EXPORT_C RScsClientBase::RScsClientBase()
+/**
+ This constructor is protected to ensure this class is not
+ instantiated directly.
+ */
+: RSessionBase()
+ {
+ // empty.
+ }
+
+EXPORT_C void RScsClientBase::Close()
+/**
+ This method should be used in preference to RScsSessionBase::Close
+ because it sends a message to cancel any outstanding requests on the
+ session or its subsessions.
+ */
+ {
+ if(iHandle)
+ {
+ RSessionBase::SendReceive(EPreCloseSession);
+ RSessionBase::Close();
+ }
+ }
+
+TInt RScsClientBase::StartServerProcess(const TDesC& aExeName, const TUidType& aFullExeUid)
+/**
+ This function is defined for the convenience of subclasses which need to start
+ a server process before they can connect to the server.
+
+ @param aExeName Executable which hosts the server.
+ @param aFullExeUid The server executable's full UID. This is used to ensure the
+ intended executable is started, and not another executable
+ with the same name.
+ @return Symbian OS error code. KErrNone indicates success, and any other
+ value indicates failure.
+ @pre This function should only be called by Connect(const TVersion&) if the server is
+ not already running.
+ */
+ {
+ RProcess pr;
+ TInt r = pr.Create(aExeName, /* aCommand */ KNullDesC, aFullExeUid);
+ if (r != KErrNone)
+ return r;
+
+ TRequestStatus rs;
+ pr.Rendezvous(rs);
+ if (rs != KRequestPending)
+ r = rs.Int();
+ else
+ {
+ pr.Resume();
+ User::WaitForRequest(rs);
+ if (rs.Int()==KErrAlreadyExists)
+ r=KErrAlreadyExists;
+ else
+ r = (pr.ExitType() == EExitPending) ? rs.Int() : KErrGeneral;
+ }
+
+ pr.Close();
+ return r;
+ }
+
+EXPORT_C TInt RScsClientBase::Connect(
+ const TDesC& aSvrName, const TVersion& aReqVer, const TDesC& aExeName, const TUidType& aFullExeUid)
+/**
+ Attempt to connect to the named server. If the server is not available then attempt
+ to start its hosting process.
+
+ @param aSvrName Name of server to connect to.
+ @param aReqVer Required server version.
+ @param aExeName Executable which hosts the server. This function will launch this
+ executable if the server is not running.
+ @param aFullExeUid The server executable's full UID. This ensures the intended
+ executable is started, and not another executable with the same name.
+ @return Symbian OS error code. KErrNone indicates success,
+ and any other value indicates failure.
+ */
+ {
+ TInt retries = 2; // number of remaining retries
+
+ for (;;)
+ {
+ TInt r = CreateSession(aSvrName, aReqVer);
+
+ // if connected then finished
+ if (r == KErrNone)
+ return r;
+
+ // if any reason other than server not available then abort
+ if (r != KErrNotFound && r != KErrServerTerminated)
+ return r;
+
+ if (--retries == 0)
+ return r;
+
+ r = StartServerProcess(aExeName, aFullExeUid);
+ if (r != KErrNone && r != KErrAlreadyExists)
+ return r;
+ } // for (;;)
+ }
+
+// -------- server heap checking --------
+
+EXPORT_C TInt RScsClientBase::SetServerHeapFail(TInt aRate)
+/**
+ Start marking the server heap and set a deterministic
+ fail rate. This should matched with a call to EndServerHeapFail.
+
+ This function is empty in release builds.
+
+ @param aRate Number of allocations after which allocation
+ should fail on the server heap.
+ @see EndServerHeapFail
+ @see __UHEAP_MARK
+ @see __UHEAP_SETFAIL
+ */
+ {
+#ifndef _DEBUG
+ (void) aRate;
+ return KErrNone;
+#else
+ TIpcArgs ipc(aRate);
+ return RSessionBase::SendReceive(ScsImpl::EUHeapSetFail, ipc);
+#endif
+ }
+
+EXPORT_C TInt RScsClientBase::ResetServerHeapFail()
+/**
+ Finish marking the server heap and reset the failure rate.
+ This should match a previous call to SetServerHeapFail.
+
+ If there is a heap imbalance, then the server will be panicked.
+
+ This function is empty in release builds.
+
+ @see SetServerHeapFail
+ @see __UHEAP_MARKEND
+ @see __UHEAP_RESET
+ */
+ {
+#ifdef _DEBUG
+ return RSessionBase::SendReceive(ScsImpl::EUHeapResetFail);
+#else
+ return KErrNone;
+#endif
+ }
+
+// -------- passing arguments to a server-side session --------
+
+EXPORT_C TInt RScsClientBase::ShutdownServer()
+/**
+DEBUG USE ONLY - Tells the server to shutdown down ASAP, and block
+until it has done so. This also closes the current session.
+
+If the server is not configured to use a inactivity shutdown timer,
+this will fail with KErrNotSupported.
+
+nb. You may still need to call the Close function of a derived class
+to ensure it gets to cleanup...
+
+ @return Symbian OS error code where KErrNone indicates
+ success and any other value indicates failure.
+ */
+ {
+ // Find servers PID
+ TPckgBuf<TProcessId> idBuf;
+ TIpcArgs args(&idBuf);
+ TInt r = RSessionBase::SendReceive(ScsImpl::EGetServerPid, args);
+ if(r != KErrNone) return r;
+
+ // Open a handle for the server thread
+ RProcess server;
+ r = server.Open(idBuf(), EOwnerThread);
+ if(r != KErrNone) return r;
+
+ // Logon to the server process to spot when it exits
+ TRequestStatus rs;
+ server.Logon(rs);
+
+ // Ask the server to exit ASAP
+ r = RSessionBase::SendReceive(ScsImpl::EShutdownAsap);
+ if(r != KErrNone)
+ {
+ (void) server.LogonCancel(rs);
+ server.Close();
+ return r;
+ }
+
+ // Close our session
+ Close();
+
+ // Wait for the server to finish shutting down
+ User::WaitForRequest(rs); // nb. we do not care what code it shutdown with.
+
+ // Close our server process handle
+ server.Close();
+
+ return KErrNone;
+ }
+
+// -------- passing arguments to a server-side session --------
+
+EXPORT_C TInt RScsClientBase::CallSessionFunction(TInt aFunction) const
+/**
+ Send a command to the corresponding server-side session. The
+ subclass uses this function instead of directly calling
+ RSubSessionBase::SendReceive because it adds the SCS code
+ which marks this as an ordinary session call.
+
+ @param aFunction Function identifier. Bits 31:24 must be zero,
+ because they are reserved for SCS commands.
+ @return Error code with which the server completed the request.
+ */
+ {
+ __ASSERT_DEBUG(! ScsFieldUsed(aFunction), ClientSidePanic(EScsClNoArgsSessUsedScs));
+
+ TInt f = ECallSessionFunc | aFunction;
+ return RSessionBase::SendReceive(f);
+ }
+
+EXPORT_C TInt RScsClientBase::CallSessionFunction(TInt aFunction, const TIpcArgs& aArgs) const
+/**
+ Send a command to the corresponding server-side session. The
+ subclass uses this function instead of directly calling
+ RSubSessionBase::SendReceive because it adds the SCS code which
+ marks this as an ordinary session call.
+
+ @param aFunction Session function identifier. Bits 31:24 must be zero,
+ because they are reserved for SCS commands.
+ @param aArgs Standard IPC arguments.
+ @return Error code with which the server completed the request.
+ */
+ {
+ __ASSERT_DEBUG(! ScsFieldUsed(aFunction), ClientSidePanic(EScsClArgsSessUsedScs));
+
+ TInt f = ECallSessionFunc | aFunction;
+ return RSessionBase::SendReceive(f, aArgs);
+ }
+
+EXPORT_C void RScsClientBase::CallSessionFunction(TInt aFunction, const TIpcArgs& aArgs, TRequestStatus& aStatus) const
+/**
+ Send the supplied function identifier and arguments to the server-side
+ session. The subclass uses this function instead of directly calling
+ RSubSessionBase::SendReceive because it adds the SCS code which marks
+ this as an ordinary session call.
+
+ @param aFunction Session function identifier. Bits 31:24 must be zero,
+ because they are reserved for SCS commands.
+ @param aArgs Standard IPC arguments.
+ @param aStatus This will be completed by the server when it has
+ finished handling the function.
+ */
+ {
+ __ASSERT_DEBUG(! ScsFieldUsed(aFunction), ClientSidePanic(EScsClArgsSessAsyncUsedScs));
+
+ TInt f = ECallSessionFunc | aFunction;
+ RSessionBase::SendReceive(f, aArgs, aStatus);
+ }
+
+EXPORT_C void RScsClientBase::CancelSessionFunction(TInt aFunction) const
+/**
+ Cancel an outstanding session request. This has no effect if the
+ request is not outstanding.
+
+ @param aFunction Implementation function. This must be the
+ same value that was supplied to CallSessionFunction.
+ */
+ {
+ __ASSERT_DEBUG(! ScsFieldUsed(aFunction), ClientSidePanic(EScsClCancelSessUsedScs));
+
+ TInt f = ECancelSessionFunc | aFunction;
+ RSessionBase::SendReceive(f);
+ }
+