cryptomgmtlibs/securitycommonutils/source/scsclient/scsclientbase.cpp
changeset 8 35751d3474b7
equal deleted inserted replaced
2:675a964f4eb5 8:35751d3474b7
       
     1 /*
       
     2 * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * Generic client-side code for client-server interaction.
       
    16 * Attempts to establish a connection to a session counting server,
       
    17 * starting the process if required.
       
    18 *
       
    19 */
       
    20 
       
    21 
       
    22 /**
       
    23  @file
       
    24 */
       
    25 
       
    26 #include <scs/scsclient.h>
       
    27 
       
    28 #include <scs/scscommon.h>
       
    29 
       
    30 using namespace ScsImpl;
       
    31 
       
    32 
       
    33 EXPORT_C RScsClientBase::RScsClientBase()
       
    34 /**
       
    35 	This constructor is protected to ensure this class is not
       
    36 	instantiated directly.
       
    37  */
       
    38 :	RSessionBase()
       
    39 	{
       
    40 	// empty.
       
    41 	}
       
    42 
       
    43 EXPORT_C void RScsClientBase::Close()
       
    44 /**
       
    45 	This method should be used in preference to RScsSessionBase::Close
       
    46 	because it sends a message to cancel any outstanding requests on the
       
    47 	session or its subsessions.
       
    48  */
       
    49 	{
       
    50 	if(iHandle)
       
    51 		{
       
    52 		RSessionBase::SendReceive(EPreCloseSession);
       
    53 		RSessionBase::Close();
       
    54 		}
       
    55 	}
       
    56 
       
    57 TInt RScsClientBase::StartServerProcess(const TDesC& aExeName, const TUidType& aFullExeUid)
       
    58 /**
       
    59 	This function is defined for the convenience of subclasses which need to start
       
    60 	a server process before they can connect to the server.
       
    61 
       
    62 	@param	aExeName		Executable which hosts the server.
       
    63 	@param	aFullExeUid		The server executable's full UID.  This is used to ensure the
       
    64 							intended executable is started, and not another executable
       
    65 							with the same name.
       
    66 	@return					Symbian OS error code.  KErrNone indicates success, and any other
       
    67 							value indicates failure.
       
    68 	@pre This function should only be called by Connect(const TVersion&) if the server is
       
    69 		not already running.
       
    70  */
       
    71 	{
       
    72 	RProcess pr;
       
    73 	TInt r = pr.Create(aExeName, /* aCommand */ KNullDesC, aFullExeUid);
       
    74 	if (r != KErrNone)
       
    75 		return r;
       
    76 
       
    77 	TRequestStatus rs;
       
    78 	pr.Rendezvous(rs);
       
    79 	if (rs != KRequestPending)
       
    80 		r = rs.Int();
       
    81 	else
       
    82 		{
       
    83 		pr.Resume();
       
    84 		User::WaitForRequest(rs);
       
    85 		if (rs.Int()==KErrAlreadyExists)
       
    86 			r=KErrAlreadyExists;
       
    87 		else
       
    88 			r = (pr.ExitType() == EExitPending) ? rs.Int() : KErrGeneral;
       
    89 		}
       
    90 
       
    91 	pr.Close();
       
    92 	return r;
       
    93 	}
       
    94 
       
    95 EXPORT_C TInt RScsClientBase::Connect(
       
    96 	const TDesC& aSvrName, const TVersion& aReqVer, const TDesC& aExeName, const TUidType& aFullExeUid)
       
    97 /**
       
    98 	Attempt to connect to the named server.  If the server is not available then attempt
       
    99 	to start its hosting process.
       
   100 
       
   101 	@param	aSvrName		Name of server to connect to.
       
   102 	@param	aReqVer			Required server version.
       
   103 	@param	aExeName		Executable which hosts the server.  This function will launch this
       
   104 							executable if the server is not running.
       
   105 	@param	aFullExeUid		The server executable's full UID.  This ensures the intended
       
   106 							executable is started, and not another executable with the same name.
       
   107 	@return					Symbian OS error code.  KErrNone indicates success,
       
   108 							and any other value indicates failure.
       
   109  */
       
   110 	{
       
   111 	TInt retries = 2;		// number of remaining retries
       
   112 
       
   113 	for (;;)
       
   114 		{
       
   115 		TInt r = CreateSession(aSvrName, aReqVer);
       
   116 		
       
   117 		// if connected then finished
       
   118 		if (r == KErrNone)
       
   119 			return r;
       
   120 
       
   121 		// if any reason other than server not available then abort
       
   122 		if (r != KErrNotFound && r != KErrServerTerminated)
       
   123 			return r;
       
   124 
       
   125 		if (--retries == 0)
       
   126 			return r;
       
   127 
       
   128 		r = StartServerProcess(aExeName, aFullExeUid);
       
   129 		if (r != KErrNone && r != KErrAlreadyExists)
       
   130 			return r;
       
   131 		}	// for (;;)
       
   132 	}
       
   133 
       
   134 // -------- server heap checking --------
       
   135 
       
   136 EXPORT_C TInt RScsClientBase::SetServerHeapFail(TInt aRate)
       
   137 /**
       
   138 	Start marking the server heap and set a deterministic
       
   139 	fail rate.  This should matched with a call to EndServerHeapFail.
       
   140 	
       
   141 	This function is empty in release builds.
       
   142 	
       
   143 	@param	aRate			Number of allocations after which allocation
       
   144 							should fail on the server heap.
       
   145 	@see EndServerHeapFail
       
   146 	@see __UHEAP_MARK
       
   147 	@see __UHEAP_SETFAIL
       
   148  */
       
   149 	{
       
   150 #ifndef _DEBUG
       
   151 	(void) aRate;
       
   152 	return KErrNone;
       
   153 #else
       
   154 	TIpcArgs ipc(aRate);
       
   155 	return RSessionBase::SendReceive(ScsImpl::EUHeapSetFail, ipc);
       
   156 #endif
       
   157 	}
       
   158 
       
   159 EXPORT_C TInt RScsClientBase::ResetServerHeapFail()
       
   160 /**
       
   161 	Finish marking the server heap and reset the failure rate.
       
   162 	This should match a previous call to SetServerHeapFail.
       
   163 
       
   164 	If there is a heap imbalance, then the server will be panicked.
       
   165 
       
   166 	This function is empty in release builds.
       
   167 	
       
   168 	@see SetServerHeapFail
       
   169 	@see __UHEAP_MARKEND
       
   170 	@see __UHEAP_RESET
       
   171  */
       
   172 	{
       
   173 #ifdef _DEBUG
       
   174 	return RSessionBase::SendReceive(ScsImpl::EUHeapResetFail);	
       
   175 #else
       
   176 	return KErrNone;
       
   177 #endif
       
   178 	}
       
   179 
       
   180 // -------- passing arguments to a server-side session --------
       
   181 
       
   182 EXPORT_C TInt RScsClientBase::ShutdownServer()
       
   183 /**
       
   184 DEBUG USE ONLY - Tells the server to shutdown down ASAP, and block
       
   185 until it has done so. This also closes the current session.
       
   186 
       
   187 If the server is not configured to use a inactivity shutdown timer,
       
   188 this will fail with KErrNotSupported.
       
   189 
       
   190 nb. You may still need to call the Close function of a derived class
       
   191 to ensure it gets to cleanup...
       
   192 
       
   193 	@return					Symbian OS error code where KErrNone indicates
       
   194 							success and any other value indicates failure.
       
   195  */
       
   196 	{
       
   197 	// Find servers PID
       
   198 	TPckgBuf<TProcessId> idBuf;
       
   199 	TIpcArgs args(&idBuf);
       
   200 	TInt r = RSessionBase::SendReceive(ScsImpl::EGetServerPid, args);
       
   201 	if(r != KErrNone) return r;
       
   202 
       
   203 	// Open a handle for the server thread
       
   204 	RProcess server;
       
   205 	r = server.Open(idBuf(), EOwnerThread);
       
   206 	if(r != KErrNone) return r;
       
   207 	
       
   208 	// Logon to the server process to spot when it exits
       
   209 	TRequestStatus rs;
       
   210 	server.Logon(rs);
       
   211 
       
   212 	// Ask the server to exit ASAP
       
   213 	r = RSessionBase::SendReceive(ScsImpl::EShutdownAsap);
       
   214 	if(r != KErrNone)
       
   215 		{
       
   216 		(void) server.LogonCancel(rs);
       
   217 		server.Close();
       
   218 		return r;
       
   219 		}
       
   220 
       
   221 	// Close our session
       
   222 	Close();
       
   223 
       
   224 	// Wait for the server to finish shutting down
       
   225 	User::WaitForRequest(rs); // nb. we do not care what code it shutdown with.
       
   226 
       
   227 	// Close our server process handle
       
   228 	server.Close();
       
   229 
       
   230 	return KErrNone;
       
   231 	}
       
   232 
       
   233 // -------- passing arguments to a server-side session --------
       
   234 
       
   235 EXPORT_C TInt RScsClientBase::CallSessionFunction(TInt aFunction) const
       
   236 /**
       
   237 	Send a command to the corresponding server-side session.  The
       
   238 	subclass uses this function instead of directly calling
       
   239 	RSubSessionBase::SendReceive because it adds the SCS code
       
   240 	which marks this as an ordinary session call.
       
   241 	
       
   242 	@param	aFunction		Function identifier.  Bits 31:24 must be zero,
       
   243 							because they are reserved for SCS commands.
       
   244 	@return					Error code with which the server completed the request.
       
   245  */
       
   246 	{
       
   247 	__ASSERT_DEBUG(! ScsFieldUsed(aFunction), ClientSidePanic(EScsClNoArgsSessUsedScs));
       
   248 	
       
   249 	TInt f = ECallSessionFunc | aFunction;
       
   250 	return RSessionBase::SendReceive(f);
       
   251 	}
       
   252 
       
   253 EXPORT_C TInt RScsClientBase::CallSessionFunction(TInt aFunction, const TIpcArgs& aArgs) const
       
   254 /**
       
   255 	Send a command to the corresponding server-side session.  The
       
   256 	subclass uses this function instead of directly calling
       
   257 	RSubSessionBase::SendReceive because it adds the SCS code which
       
   258 	marks this as an ordinary session call.
       
   259 
       
   260 	@param	aFunction		Session function identifier.  Bits 31:24 must be zero,
       
   261 							because they are reserved for SCS commands.
       
   262 	@param	aArgs			Standard IPC arguments.
       
   263 	@return					Error code with which the server completed the request.
       
   264  */
       
   265 	{
       
   266 	__ASSERT_DEBUG(! ScsFieldUsed(aFunction), ClientSidePanic(EScsClArgsSessUsedScs));
       
   267 	
       
   268 	TInt f = ECallSessionFunc | aFunction;
       
   269 	return RSessionBase::SendReceive(f, aArgs);
       
   270 	}
       
   271 
       
   272 EXPORT_C void RScsClientBase::CallSessionFunction(TInt aFunction, const TIpcArgs& aArgs, TRequestStatus& aStatus) const
       
   273 /**
       
   274 	Send the supplied function identifier and arguments to the server-side
       
   275 	session.  The subclass uses this function instead of directly calling
       
   276 	RSubSessionBase::SendReceive because it adds the SCS code which marks
       
   277 	this as an ordinary session call.
       
   278 
       
   279 	@param	aFunction		Session function identifier.  Bits 31:24 must be zero,
       
   280 							because they are reserved for SCS commands.
       
   281 	@param	aArgs			Standard IPC arguments.
       
   282 	@param	aStatus			This will be completed by the server when it has
       
   283 							finished handling the function.
       
   284  */
       
   285 	{
       
   286 	__ASSERT_DEBUG(! ScsFieldUsed(aFunction), ClientSidePanic(EScsClArgsSessAsyncUsedScs));
       
   287 	
       
   288 	TInt f = ECallSessionFunc | aFunction;
       
   289 	RSessionBase::SendReceive(f, aArgs, aStatus);
       
   290 	}
       
   291 
       
   292 EXPORT_C void RScsClientBase::CancelSessionFunction(TInt aFunction) const
       
   293 /**
       
   294 	Cancel an outstanding session request.  This has no effect if the
       
   295 	request is not outstanding.
       
   296 	
       
   297 	@param	aFunction		Implementation function.  This must be the
       
   298 							same value that was supplied to CallSessionFunction.
       
   299  */
       
   300 	{
       
   301 	__ASSERT_DEBUG(! ScsFieldUsed(aFunction), ClientSidePanic(EScsClCancelSessUsedScs));
       
   302 	
       
   303 	TInt f = ECancelSessionFunc | aFunction;
       
   304 	RSessionBase::SendReceive(f);
       
   305 	}
       
   306