diff -r 675a964f4eb5 -r 35751d3474b7 cryptomgmtlibs/securitycommonutils/source/scsclient/scsclientbase.cpp --- /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 + +#include + +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 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); + } +