os/security/cryptomgmtlibs/securitycommonutils/source/scsclient/scsclientbase.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/cryptomgmtlibs/securitycommonutils/source/scsclient/scsclientbase.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,306 @@
1.4 +/*
1.5 +* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +* Generic client-side code for client-server interaction.
1.19 +* Attempts to establish a connection to a session counting server,
1.20 +* starting the process if required.
1.21 +*
1.22 +*/
1.23 +
1.24 +
1.25 +/**
1.26 + @file
1.27 +*/
1.28 +
1.29 +#include <scs/scsclient.h>
1.30 +
1.31 +#include <scs/scscommon.h>
1.32 +
1.33 +using namespace ScsImpl;
1.34 +
1.35 +
1.36 +EXPORT_C RScsClientBase::RScsClientBase()
1.37 +/**
1.38 + This constructor is protected to ensure this class is not
1.39 + instantiated directly.
1.40 + */
1.41 +: RSessionBase()
1.42 + {
1.43 + // empty.
1.44 + }
1.45 +
1.46 +EXPORT_C void RScsClientBase::Close()
1.47 +/**
1.48 + This method should be used in preference to RScsSessionBase::Close
1.49 + because it sends a message to cancel any outstanding requests on the
1.50 + session or its subsessions.
1.51 + */
1.52 + {
1.53 + if(iHandle)
1.54 + {
1.55 + RSessionBase::SendReceive(EPreCloseSession);
1.56 + RSessionBase::Close();
1.57 + }
1.58 + }
1.59 +
1.60 +TInt RScsClientBase::StartServerProcess(const TDesC& aExeName, const TUidType& aFullExeUid)
1.61 +/**
1.62 + This function is defined for the convenience of subclasses which need to start
1.63 + a server process before they can connect to the server.
1.64 +
1.65 + @param aExeName Executable which hosts the server.
1.66 + @param aFullExeUid The server executable's full UID. This is used to ensure the
1.67 + intended executable is started, and not another executable
1.68 + with the same name.
1.69 + @return Symbian OS error code. KErrNone indicates success, and any other
1.70 + value indicates failure.
1.71 + @pre This function should only be called by Connect(const TVersion&) if the server is
1.72 + not already running.
1.73 + */
1.74 + {
1.75 + RProcess pr;
1.76 + TInt r = pr.Create(aExeName, /* aCommand */ KNullDesC, aFullExeUid);
1.77 + if (r != KErrNone)
1.78 + return r;
1.79 +
1.80 + TRequestStatus rs;
1.81 + pr.Rendezvous(rs);
1.82 + if (rs != KRequestPending)
1.83 + r = rs.Int();
1.84 + else
1.85 + {
1.86 + pr.Resume();
1.87 + User::WaitForRequest(rs);
1.88 + if (rs.Int()==KErrAlreadyExists)
1.89 + r=KErrAlreadyExists;
1.90 + else
1.91 + r = (pr.ExitType() == EExitPending) ? rs.Int() : KErrGeneral;
1.92 + }
1.93 +
1.94 + pr.Close();
1.95 + return r;
1.96 + }
1.97 +
1.98 +EXPORT_C TInt RScsClientBase::Connect(
1.99 + const TDesC& aSvrName, const TVersion& aReqVer, const TDesC& aExeName, const TUidType& aFullExeUid)
1.100 +/**
1.101 + Attempt to connect to the named server. If the server is not available then attempt
1.102 + to start its hosting process.
1.103 +
1.104 + @param aSvrName Name of server to connect to.
1.105 + @param aReqVer Required server version.
1.106 + @param aExeName Executable which hosts the server. This function will launch this
1.107 + executable if the server is not running.
1.108 + @param aFullExeUid The server executable's full UID. This ensures the intended
1.109 + executable is started, and not another executable with the same name.
1.110 + @return Symbian OS error code. KErrNone indicates success,
1.111 + and any other value indicates failure.
1.112 + */
1.113 + {
1.114 + TInt retries = 2; // number of remaining retries
1.115 +
1.116 + for (;;)
1.117 + {
1.118 + TInt r = CreateSession(aSvrName, aReqVer);
1.119 +
1.120 + // if connected then finished
1.121 + if (r == KErrNone)
1.122 + return r;
1.123 +
1.124 + // if any reason other than server not available then abort
1.125 + if (r != KErrNotFound && r != KErrServerTerminated)
1.126 + return r;
1.127 +
1.128 + if (--retries == 0)
1.129 + return r;
1.130 +
1.131 + r = StartServerProcess(aExeName, aFullExeUid);
1.132 + if (r != KErrNone && r != KErrAlreadyExists)
1.133 + return r;
1.134 + } // for (;;)
1.135 + }
1.136 +
1.137 +// -------- server heap checking --------
1.138 +
1.139 +EXPORT_C TInt RScsClientBase::SetServerHeapFail(TInt aRate)
1.140 +/**
1.141 + Start marking the server heap and set a deterministic
1.142 + fail rate. This should matched with a call to EndServerHeapFail.
1.143 +
1.144 + This function is empty in release builds.
1.145 +
1.146 + @param aRate Number of allocations after which allocation
1.147 + should fail on the server heap.
1.148 + @see EndServerHeapFail
1.149 + @see __UHEAP_MARK
1.150 + @see __UHEAP_SETFAIL
1.151 + */
1.152 + {
1.153 +#ifndef _DEBUG
1.154 + (void) aRate;
1.155 + return KErrNone;
1.156 +#else
1.157 + TIpcArgs ipc(aRate);
1.158 + return RSessionBase::SendReceive(ScsImpl::EUHeapSetFail, ipc);
1.159 +#endif
1.160 + }
1.161 +
1.162 +EXPORT_C TInt RScsClientBase::ResetServerHeapFail()
1.163 +/**
1.164 + Finish marking the server heap and reset the failure rate.
1.165 + This should match a previous call to SetServerHeapFail.
1.166 +
1.167 + If there is a heap imbalance, then the server will be panicked.
1.168 +
1.169 + This function is empty in release builds.
1.170 +
1.171 + @see SetServerHeapFail
1.172 + @see __UHEAP_MARKEND
1.173 + @see __UHEAP_RESET
1.174 + */
1.175 + {
1.176 +#ifdef _DEBUG
1.177 + return RSessionBase::SendReceive(ScsImpl::EUHeapResetFail);
1.178 +#else
1.179 + return KErrNone;
1.180 +#endif
1.181 + }
1.182 +
1.183 +// -------- passing arguments to a server-side session --------
1.184 +
1.185 +EXPORT_C TInt RScsClientBase::ShutdownServer()
1.186 +/**
1.187 +DEBUG USE ONLY - Tells the server to shutdown down ASAP, and block
1.188 +until it has done so. This also closes the current session.
1.189 +
1.190 +If the server is not configured to use a inactivity shutdown timer,
1.191 +this will fail with KErrNotSupported.
1.192 +
1.193 +nb. You may still need to call the Close function of a derived class
1.194 +to ensure it gets to cleanup...
1.195 +
1.196 + @return Symbian OS error code where KErrNone indicates
1.197 + success and any other value indicates failure.
1.198 + */
1.199 + {
1.200 + // Find servers PID
1.201 + TPckgBuf<TProcessId> idBuf;
1.202 + TIpcArgs args(&idBuf);
1.203 + TInt r = RSessionBase::SendReceive(ScsImpl::EGetServerPid, args);
1.204 + if(r != KErrNone) return r;
1.205 +
1.206 + // Open a handle for the server thread
1.207 + RProcess server;
1.208 + r = server.Open(idBuf(), EOwnerThread);
1.209 + if(r != KErrNone) return r;
1.210 +
1.211 + // Logon to the server process to spot when it exits
1.212 + TRequestStatus rs;
1.213 + server.Logon(rs);
1.214 +
1.215 + // Ask the server to exit ASAP
1.216 + r = RSessionBase::SendReceive(ScsImpl::EShutdownAsap);
1.217 + if(r != KErrNone)
1.218 + {
1.219 + (void) server.LogonCancel(rs);
1.220 + server.Close();
1.221 + return r;
1.222 + }
1.223 +
1.224 + // Close our session
1.225 + Close();
1.226 +
1.227 + // Wait for the server to finish shutting down
1.228 + User::WaitForRequest(rs); // nb. we do not care what code it shutdown with.
1.229 +
1.230 + // Close our server process handle
1.231 + server.Close();
1.232 +
1.233 + return KErrNone;
1.234 + }
1.235 +
1.236 +// -------- passing arguments to a server-side session --------
1.237 +
1.238 +EXPORT_C TInt RScsClientBase::CallSessionFunction(TInt aFunction) const
1.239 +/**
1.240 + Send a command to the corresponding server-side session. The
1.241 + subclass uses this function instead of directly calling
1.242 + RSubSessionBase::SendReceive because it adds the SCS code
1.243 + which marks this as an ordinary session call.
1.244 +
1.245 + @param aFunction Function identifier. Bits 31:24 must be zero,
1.246 + because they are reserved for SCS commands.
1.247 + @return Error code with which the server completed the request.
1.248 + */
1.249 + {
1.250 + __ASSERT_DEBUG(! ScsFieldUsed(aFunction), ClientSidePanic(EScsClNoArgsSessUsedScs));
1.251 +
1.252 + TInt f = ECallSessionFunc | aFunction;
1.253 + return RSessionBase::SendReceive(f);
1.254 + }
1.255 +
1.256 +EXPORT_C TInt RScsClientBase::CallSessionFunction(TInt aFunction, const TIpcArgs& aArgs) const
1.257 +/**
1.258 + Send a command to the corresponding server-side session. The
1.259 + subclass uses this function instead of directly calling
1.260 + RSubSessionBase::SendReceive because it adds the SCS code which
1.261 + marks this as an ordinary session call.
1.262 +
1.263 + @param aFunction Session function identifier. Bits 31:24 must be zero,
1.264 + because they are reserved for SCS commands.
1.265 + @param aArgs Standard IPC arguments.
1.266 + @return Error code with which the server completed the request.
1.267 + */
1.268 + {
1.269 + __ASSERT_DEBUG(! ScsFieldUsed(aFunction), ClientSidePanic(EScsClArgsSessUsedScs));
1.270 +
1.271 + TInt f = ECallSessionFunc | aFunction;
1.272 + return RSessionBase::SendReceive(f, aArgs);
1.273 + }
1.274 +
1.275 +EXPORT_C void RScsClientBase::CallSessionFunction(TInt aFunction, const TIpcArgs& aArgs, TRequestStatus& aStatus) const
1.276 +/**
1.277 + Send the supplied function identifier and arguments to the server-side
1.278 + session. The subclass uses this function instead of directly calling
1.279 + RSubSessionBase::SendReceive because it adds the SCS code which marks
1.280 + this as an ordinary session call.
1.281 +
1.282 + @param aFunction Session function identifier. Bits 31:24 must be zero,
1.283 + because they are reserved for SCS commands.
1.284 + @param aArgs Standard IPC arguments.
1.285 + @param aStatus This will be completed by the server when it has
1.286 + finished handling the function.
1.287 + */
1.288 + {
1.289 + __ASSERT_DEBUG(! ScsFieldUsed(aFunction), ClientSidePanic(EScsClArgsSessAsyncUsedScs));
1.290 +
1.291 + TInt f = ECallSessionFunc | aFunction;
1.292 + RSessionBase::SendReceive(f, aArgs, aStatus);
1.293 + }
1.294 +
1.295 +EXPORT_C void RScsClientBase::CancelSessionFunction(TInt aFunction) const
1.296 +/**
1.297 + Cancel an outstanding session request. This has no effect if the
1.298 + request is not outstanding.
1.299 +
1.300 + @param aFunction Implementation function. This must be the
1.301 + same value that was supplied to CallSessionFunction.
1.302 + */
1.303 + {
1.304 + __ASSERT_DEBUG(! ScsFieldUsed(aFunction), ClientSidePanic(EScsClCancelSessUsedScs));
1.305 +
1.306 + TInt f = ECancelSessionFunc | aFunction;
1.307 + RSessionBase::SendReceive(f);
1.308 + }
1.309 +