messagingfw/msgtestfw/TestActions/Capabilities/src/SendProxyServer.cpp
changeset 62 db3f5fa34ec7
parent 0 8e480a14352b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/msgtestfw/TestActions/Capabilities/src/SendProxyServer.cpp	Wed Nov 03 22:41:46 2010 +0530
@@ -0,0 +1,732 @@
+// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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:
+// server.cpp
+// Transient server example - server implementation
+// 
+//
+
+#include "SendProxyserver.h"
+#include "MSERVER.H"
+
+
+
+inline CShutdown::CShutdown()
+	:CTimer(-1)
+	{CActiveScheduler::Add(this);}
+	
+	
+inline void CShutdown::ConstructL()
+	{CTimer::ConstructL();}
+	
+	
+inline void CShutdown::Start()
+	{After(KSendProxyShutdownDelay);}
+
+
+inline CSendProxyServer::CSendProxyServer()
+	:CServer2(0,ESharableSessions)
+	{}
+
+
+
+EXPORT_C TInt RMessage2Derv::GetiArgs(TInt aPos) const
+{
+	return iArgs[aPos];
+}
+
+
+
+
+inline CSendProxyServerSession::CSendProxyServerSession() : iSessionCount(0), iCommand( ENoCommandPending )
+	{}
+		
+	
+inline CSendProxyServer& CSendProxyServerSession::Server()
+	{return *static_cast<CSendProxyServer*>(const_cast<CServer2*>(CSession2::Server()));}
+	
+	
+inline TBool CSendProxyServerSession::ReceivePending() const
+	{return !iReceiveMsg.IsNull();}
+
+
+
+TInt RMsvServerSessionTest::SendReceive( TInt aFunction,const TIpcArgs& aArgs ) const
+	{ 
+	return RMsvServerSession::SendReceive( aFunction,aArgs ); 
+	}
+	
+TInt RMsvServerSessionTest::SendReceive( TInt aFunction ) const
+	{ 
+	return RMsvServerSession::SendReceive( aFunction ); 
+	}
+	// All we want is to access. Since RSessionBase::SendReceive is protected so is RMsvServerSession::SendReceive
+	// So as long as we derive from RSessionBase base we should be get access to SendReceive.
+
+
+void RMsvServerSessionTest::SendReceive( TInt aFunction,const TIpcArgs& aArgs,TRequestStatus& aRequestStatus ) const
+	{ 
+	RMsvServerSession::SendReceive( aFunction,aArgs,aRequestStatus ); 		
+	}
+	
+void RMsvServerSessionTest::SendReceive( TInt aFunction,TRequestStatus& aRequestStatus) const
+	{ 
+	return RMsvServerSession::SendReceive( aFunction,aRequestStatus ); 
+	}
+
+
+void RMsvServerSessionTest::SendReceiveAsync( TInt aFunction,const TIpcArgs& aArgs,TRequestStatus& aRequestStatus ) const
+	{ 
+	RMsvServerSession::SendReceive( aFunction,aArgs,aRequestStatus ); 		
+	User::WaitForRequest(aRequestStatus);		
+		// Lets pretend sync for simplicity sake.
+	}
+	
+void RMsvServerSessionTest::SendReceiveAsync( TInt aFunction,TRequestStatus& aRequestStatus) const
+	{ 
+	RMsvServerSession::SendReceive( aFunction,aRequestStatus ); 
+	User::WaitForRequest(aRequestStatus);
+		// Lets pretend sync for simplicity sake.
+	}
+
+
+TInt RMsvServerSessionTest::CreateSession(const TDesC& aServer,const TVersion& aVersion,TInt aAsyncMessageSlots)
+	{
+	return RMsvServerSession::CreateSession(aServer, aVersion, aAsyncMessageSlots);
+	}
+
+
+
+//
+
+
+TInt StartMsvServer()
+{
+
+	TInt err =  KErrNone ;
+	// EKA2 is simple No path required 
+	TBuf<32> serverFile;
+	
+	serverFile.Copy(_L("!") );
+	serverFile.Copy( KMsvServerNameExe );
+	
+	_LIT(KExe,".exe");
+	serverFile.Append(KExe);
+	RProcess server;
+	err = server.Create(serverFile,_L(""));
+	if(err != KErrNone)
+		return err;
+		
+	// Synchronise with the server
+	TRequestStatus reqStatus;
+	server.Rendezvous(reqStatus);
+	server.Resume();
+	 //Server will call the reciprocal static synchronise call
+	User::WaitForRequest(reqStatus);
+	//server.Close();
+	if(reqStatus.Int() != KErrNone)
+	{
+		return reqStatus.Int();
+	}
+	
+	return err;
+}	
+
+
+void CSendProxyServerSession::CreateL()
+//
+// 2nd phase construct for sessions - called by the CServer framework
+//
+	{	
+	
+	// Start up the messaging server that all messages will be forwarded to. 
+	TInt error = iMsvServerSession.CreateSession( KMsvServerName, iMsvServerSession.Version(), 2);
+	if (error==KErrNone)
+		{ // Session has been started. Server was already running.
+		}
+	else
+		{
+		error=StartMsvServer();
+		
+		if (error!=KErrNone)
+			{ // Leave
+			User::LeaveIfError(error);
+			}
+		else
+			{
+			
+			TInt error = iMsvServerSession.CreateSession( KMsvServerName, iMsvServerSession.Version(), 2);
+			if (error!=KErrNone)
+				{ // Leave					
+				User::LeaveIfError(error);
+				}
+			}
+		}		
+
+	
+	Server().AddSession();
+	
+	}
+
+
+CSendProxyServerSession::~CSendProxyServerSession()
+	{	
+	iMsvServerSession.Close();
+	Server().DropSession();		
+	}
+
+
+
+void CSendProxyServerSession::ServiceL(const RMessage2& aMessage)
+//
+// Handle a client request.
+// Leaving is handled by CSendProxyServer::ServiceError() which reports
+// the error code to the client
+//
+	{
+	TInt messageFunction = aMessage.Function();
+	
+	if (messageFunction==ESendData)
+		{	// We are setting up buffers as next time we actually execute the command.
+			// _ASSERT( iCommand == ENoCommandPending );
+			// Make sure we do not have another command pending.
+		iCommand = (TSendProxyMessages) aMessage.Int0();  //???? fix casts  
+		iFlags = aMessage.Int1();
+		aMessage.Complete( KErrNone );		
+		}
+	else if (messageFunction==EGetServerSecureId)
+		{ // This must done for the proxy server. 
+		  // We are not passing the data on to the messaging server
+
+		TSecureId cServerSecureId;
+		TPckg<TSecureId> buf(cServerSecureId);
+		
+		aMessage.ReadL(0,buf);
+			
+		cServerSecureId = RProcess().SecureId();
+		aMessage.WriteL(0,buf); 
+								
+		aMessage.Complete( KErrNone );
+		}
+	else if (messageFunction==EGetServerCapabilities)
+		{ // return the capabilities for the proxy server. 
+		  // We are not passing the data on to the messaging server
+
+		TInt32 cServerCaps;
+		TPckg<TInt32> buf(cServerCaps);
+		
+		aMessage.ReadL(0,buf);
+		
+		ReadCapabilities(cServerCaps);
+
+		aMessage.WriteL(0,buf); 
+								
+		aMessage.Complete( KErrNone );
+		}
+	else if ( messageFunction==EReceive )
+		{ 
+		if (ReceivePending())
+			PanicClient(aMessage,EPanicAlreadyReceiving);
+		else
+			{
+			iReceiveMsg=aMessage;
+			iReceiveLen=aMessage.Int1();
+			}
+		}
+	else if ( messageFunction==ECancelReceive )
+		{				
+		if (ReceivePending())
+			iReceiveMsg.Complete(KErrCancel);
+		aMessage.Complete( KErrNone );
+		}
+	else
+		{  // We are expected to execute a command.
+		TInt complete = DoCommandL( (const RMessage2Derv&) aMessage );		
+
+		// Indicate that we succesfully executed a full command and can take another.			
+		iCommand = ENoCommandPending;
+		iFlags = 0;
+		aMessage.Complete( complete );
+		}	
+		
+	}
+
+
+void CSendProxyServerSession::ReadCapabilities(TInt32& aServerCaps)
+	{
+	aServerCaps=0;
+
+	if (RProcess().HasCapability(ECapabilityTCB))
+		aServerCaps |= (1<<ECapabilityTCB);
+	
+	if (RProcess().HasCapability(ECapabilityCommDD))
+		aServerCaps |= (1<<ECapabilityCommDD);
+	
+	if (RProcess().HasCapability(ECapabilityPowerMgmt))
+		aServerCaps |= (1<<ECapabilityPowerMgmt);
+	
+	if (RProcess().HasCapability(ECapabilityMultimediaDD))
+		aServerCaps |= (1<<ECapabilityMultimediaDD);
+
+	if (RProcess().HasCapability(ECapabilityReadDeviceData))
+		aServerCaps |= (1<<ECapabilityReadDeviceData);
+	
+	if (RProcess().HasCapability(ECapabilityWriteDeviceData))
+		aServerCaps |= (1<<ECapabilityWriteDeviceData);
+
+	if (RProcess().HasCapability(ECapabilityDRM))
+		aServerCaps |= (1<<ECapabilityDRM);
+	
+	if (RProcess().HasCapability(ECapabilityTrustedUI))
+		aServerCaps |= (1<<ECapabilityTrustedUI);
+
+	if (RProcess().HasCapability(ECapabilityProtServ))
+		aServerCaps |= (1<<ECapabilityProtServ);
+
+	if (RProcess().HasCapability(ECapabilityDiskAdmin))
+		aServerCaps |= (1<<ECapabilityDiskAdmin);
+
+	if (RProcess().HasCapability(ECapabilityNetworkControl))
+		aServerCaps |= (1<<ECapabilityNetworkControl);
+
+	if (RProcess().HasCapability(ECapabilityAllFiles))
+		aServerCaps |= (1<<ECapabilityAllFiles);
+
+	if (RProcess().HasCapability(ECapabilitySwEvent))
+		aServerCaps |= (1<<ECapabilitySwEvent);
+
+	if (RProcess().HasCapability(ECapabilityNetworkServices))
+		aServerCaps |= (1<<ECapabilityNetworkServices);
+
+	if (RProcess().HasCapability(ECapabilityLocalServices))
+		aServerCaps |= (1<<ECapabilityLocalServices);
+
+	if (RProcess().HasCapability(ECapabilityReadUserData))
+		aServerCaps |= (1<<ECapabilityReadUserData);
+
+	if (RProcess().HasCapability(ECapabilityWriteUserData))
+		aServerCaps |= (1<<ECapabilityWriteUserData);
+
+	if (RProcess().HasCapability(ECapabilityLocation))
+		aServerCaps |= (1<<ECapabilityLocation);
+
+	if (RProcess().HasCapability(ECapabilitySurroundingsDD))
+		aServerCaps |= (1<<ECapabilitySurroundingsDD);
+
+	if (RProcess().HasCapability(ECapabilityUserEnvironment))
+		aServerCaps |= (1<<ECapabilityUserEnvironment);
+
+		
+	}
+
+
+//*************
+
+
+void CSendProxyServerSession::SetupTIpcArgL(const RMessage2Derv& aMessage, TInt aPos, TIpcArgs& atipcArgs )
+	{		
+	const TInt mask = ( 1<<TIpcArgs::KBitsPerType )-1;
+	
+	const TInt bits_shift  = (aPos * TIpcArgs::KBitsPerType );
+	const TInt type_flags = ( iFlags >> bits_shift ) & mask ;
+	
+		
+	if ( type_flags == TIpcArgs::EUnspecified )
+		{ // Unspecified so must be TInt.		
+		TInt tmp = aMessage.GetiArgs(aPos);
+		atipcArgs.Set( aPos, (TAny*) tmp);
+		}
+	else if ( type_flags  == TIpcArgs::EDesC8 )
+		{ // We have a read only descriptor can not use GetDesMaxLength on it. 
+		
+		TInt maxLength1 = aMessage.GetDesLength(aPos);
+		HBufC8* buffer1 = HBufC8::NewL(maxLength1);
+		iBuffer8[aPos].Assign(buffer1);
+			// Owns the buffer.
+
+		TPtr8 ptrBuffer1= (buffer1->Des());						
+		
+		aMessage.ReadL( aPos, ptrBuffer1 );		
+		atipcArgs.Set( aPos, buffer1);
+			// buffer is considered constant so internal flags in atipcArgs will be okay.
+		}
+	else if ( type_flags == TIpcArgs::EDes8 )
+		{ // Just generate a descriptor and copy the contents into it.
+		  // We need GetDesMaxLength because it is read/write and somebody will right more than the current length.
+
+		TInt maxLength2 = aMessage.GetDesMaxLength(aPos);		
+		 
+		HBufC8* buffer2 = HBufC8::NewL(maxLength2);
+		iBuffer8[aPos].Assign(buffer2);
+			// we want the buffer to read/write which is why we use RBuf8.
+			// The RBuf8 takes ownership of the HBuf.
+		
+		iTPtr8[aPos] = new (ELeave) TPtr8(buffer2->Des());
+								
+		aMessage.ReadL( aPos, *(iTPtr8[aPos]) );			
+		atipcArgs.Set( aPos, iTPtr8[aPos] );		
+			
+		}
+	else if (  type_flags == TIpcArgs::EDesC16 )
+		{ // We have a read only descriptor can not use GetDesMaxLength on it. 
+		
+		TInt maxLength3 = aMessage.GetDesLength(aPos);
+		HBufC16* buffer3 = HBufC16::NewL(maxLength3);
+		iBuffer16[aPos].Assign(buffer3);
+			// Owns the buffer.
+
+		TPtr16 ptrBuffer3= (buffer3->Des());						
+		
+		aMessage.ReadL( aPos, ptrBuffer3 );		
+		atipcArgs.Set( aPos, buffer3);
+			// buffer is considered constant so internal flags in atipcArgs will be okay.
+		}
+	else if ( type_flags == TIpcArgs::EDes16 )
+		{ // Just generate a descriptor and copy the contents into it.
+		  // We need GetDesMaxLength because it is read/write and somebody will right more than the current length.
+
+		TInt maxLength4 = aMessage.GetDesMaxLength(aPos);		
+		 
+		HBufC16* buffer4 = HBufC16::NewL(maxLength4);
+		iBuffer16[aPos].Assign(buffer4);
+			// we want the buffer to read/write which is why we use RBuf16.
+			// The RBuf16 takes ownership of the HBuf.
+		
+		iTPtr16[aPos] = new (ELeave) TPtr16(buffer4->Des());
+								
+		aMessage.ReadL( aPos, *(iTPtr16[aPos]) );			
+		atipcArgs.Set( aPos, iTPtr16[aPos] );		
+			
+		}
+	else if ( type_flags == TIpcArgs::EHandle )
+		{		
+		TInt tmp = aMessage.GetiArgs(aPos);
+		atipcArgs.Set( aPos, tmp);
+		}		
+	else
+		{ // Unknown error.
+		User::LeaveIfError(KErrGeneral);
+		}
+	
+	}
+
+void CSendProxyServerSession::SetupTIpcArgsL(const RMessage2Derv& aMessage, TIpcArgs& atipcArgs)
+	{	
+	SetupTIpcArgL( aMessage, 0, atipcArgs );
+	SetupTIpcArgL( aMessage, 1, atipcArgs );		
+	SetupTIpcArgL( aMessage, 2, atipcArgs );		
+	SetupTIpcArgL( aMessage, 3, atipcArgs );			
+	}
+
+
+//*************
+
+void CSendProxyServerSession::SetupReturnTIpcArgL(const RMessage2Derv& aMessage, TInt aPos )
+	{		
+	const TInt mask = ( 1<<TIpcArgs::KBitsPerType )-1;
+	
+	const TInt bits_shift  = (aPos * TIpcArgs::KBitsPerType );
+	const TInt type_flags = ( iFlags >> bits_shift ) & mask ;
+		
+	if (type_flags == TIpcArgs::EUnspecified)
+		{ // Do nothing can not write back to the args of a message.
+		}
+	else if ( type_flags == TIpcArgs::EDesC8 )
+		{ // We have constant descriptor no action required as we can not change it.
+		}
+	else if ( type_flags == TIpcArgs::EDes8 )
+		{ // We have a read/write descriptor we need to copy back any changes.
+		aMessage.WriteL( aPos, *(iTPtr8[aPos]) );		
+		}
+	else if ( type_flags == TIpcArgs::EDesC16 )
+		{ // We have constant descriptor no action required as we can not change it.
+		}
+	else if ( type_flags  == TIpcArgs::EDes16 )
+		{ // We have a read/write descriptor we need to copy back any changes.
+		aMessage.WriteL( aPos, *(iTPtr16[aPos]) );		
+		}
+	else if ( type_flags == TIpcArgs::EHandle )
+		{ //Do nothing as handles should not change.
+		}
+	else
+		{ // may need to implement 16 bit descriptors etc.
+		User::LeaveIfError(KErrGeneral);
+		}
+	
+	}
+
+
+void CSendProxyServerSession::SetupReturnTIpcArgsL(const RMessage2Derv& aMessage)
+	{	
+	SetupReturnTIpcArgL( aMessage, 0 );
+	SetupReturnTIpcArgL( aMessage, 1 );		
+	SetupReturnTIpcArgL( aMessage, 2 );		
+	SetupReturnTIpcArgL( aMessage, 3 );			
+	}
+
+
+void CSendProxyServerSession::ClearBuffer(TInt aPos)
+	{
+	
+	iBuffer8[aPos].Close();
+	delete iTPtr8[aPos];
+	iTPtr8[aPos]=0;
+
+	iBuffer16[aPos].Close();
+	delete iTPtr16[aPos];
+	iTPtr16[aPos]=0;
+		
+	}
+
+
+
+void CSendProxyServerSession::ClearBuffers()
+	{	
+	
+	ClearBuffer( 0 );
+	ClearBuffer( 1 );		
+	ClearBuffer( 2 );		
+	ClearBuffer( 3 );		
+	
+	}
+
+
+TInt CSendProxyServerSession::DoCommandL(const RMessage2Derv& aMessage ) 
+	{
+	TInt complete=KErrNone;	
+			
+	switch (iCommand)
+		{
+		
+		case ESend:
+			{		
+			
+			TIpcArgs tipcArgs;
+			SetupTIpcArgsL( ( (const RMessage2Derv&) aMessage ), tipcArgs);			
+			complete = iMsvServerSession.SendReceive( aMessage.Function(), tipcArgs );			
+			SetupReturnTIpcArgsL( (const RMessage2Derv&) aMessage);
+			ClearBuffers();
+			break;
+			}
+						
+		case ESendAsyncWait:
+			{				
+
+			TIpcArgs tipcArgs1;
+			SetupTIpcArgsL( ( (const RMessage2Derv&) aMessage ), tipcArgs1);			
+			
+			TRequestStatus requestStatus=KRequestPending;
+			iMsvServerSession.SendReceive( aMessage.Function(), tipcArgs1 , requestStatus );
+			User::WaitForRequest(requestStatus);			
+			SetupReturnTIpcArgsL( (const RMessage2Derv&) aMessage);
+			ClearBuffers();
+			complete = requestStatus.Int();
+
+			break;
+			}
+		default:
+			{
+			complete=KErrGeneral;
+			PanicClient(aMessage,EPanicIllegalFunction);			
+			break;
+			}
+		}
+				
+	return complete;			
+	}
+
+void CSendProxyServerSession::ServiceError(const RMessage2& aMessage,TInt aError)
+//
+// Handle an error from CSendProxyServerSession::ServiceL()
+// A bad descriptor error implies a badly programmed client, so panic it;
+// otherwise use the default handling (report the error to the client)
+//
+	{
+	if (aError==KErrBadDescriptor)
+		PanicClient(aMessage,EPanicBadDescriptor);
+	CSession2::ServiceError(aMessage,aError);
+	}
+
+void CShutdown::RunL()
+//
+// Initiate server exit when the timer expires
+//
+	{
+	CActiveScheduler::Stop();
+	}
+
+CServer2* CSendProxyServer::NewLC()
+	{
+	CSendProxyServer* self=new(ELeave) CSendProxyServer;
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+
+//**********************************
+
+void CSendProxyServer::ConstructL()
+//
+// 2nd phase construction - ensure the timer and server objects are running
+//
+	{
+	StartL(KSendProxyServerName);
+			
+	iShutdown.ConstructL();
+		// ensure that the server still exits even if the 1st client fails to connect
+	iShutdown.Start();	
+	}
+
+
+CSession2* CSendProxyServer::NewSessionL(const TVersion&,const RMessage2&) const
+//
+// Cretae a new client session. This should really check the version number.
+//
+	{
+	return new(ELeave) CSendProxyServerSession();
+	}
+
+void CSendProxyServer::AddSession()
+//
+// A new session is being created
+// Cancel the shutdown timer if it was running
+//
+	{
+	++iSessionCount;
+	iShutdown.Cancel();
+	}
+
+void CSendProxyServer::DropSession()
+//
+// A session is being destroyed
+// Start the shutdown timer if it is the last session.
+//
+	{
+	if (--iSessionCount==0)
+		iShutdown.Start();
+	}
+
+
+
+void PanicClient(const RMessagePtr2& aMessage,TSendProxyServerPanic aPanic)
+//
+// RMessagePtr2::Panic() also completes the message. This is:
+// (a) important for efficient cleanup within the kernel
+// (b) a problem if the message is completed a second time
+//
+	{
+	_LIT(KPanic,"SendProxyServer");
+	aMessage.Panic(KPanic,aPanic);
+	}
+
+
+//******************************
+
+
+static void RunServerL()
+//
+// Perform all server initialisation, in particular creation of the
+// scheduler and server and then run the scheduler
+//
+	{
+		
+	// naming the server thread after the server helps to debug panics
+	User::LeaveIfError(User::RenameThread(KSendProxyServerName));
+	//
+	// create and install the active scheduler we need
+	CActiveScheduler* s=new(ELeave) CActiveScheduler;
+	CleanupStack::PushL(s);
+	CActiveScheduler::Install(s);
+	//
+	// create the server (leave it on the cleanup stack)
+	CSendProxyServer::NewLC();
+	//
+	// Initialisation complete, now signal the client
+#ifdef __SENDPROXYSERVER_NO_PROCESSES__
+	RThread::Rendezvous(KErrNone);
+#else
+	RProcess::Rendezvous(KErrNone);
+#endif
+	//
+	// Ready to run
+	CActiveScheduler::Start();
+	//
+	// Cleanup the server and scheduler
+	CleanupStack::PopAndDestroy(2);
+
+	}
+
+
+
+//****************************************
+
+
+TInt E32Main()
+//
+// Server process entry-point
+//
+	{
+	__UHEAP_MARK;
+	//
+	CTrapCleanup* cleanup=CTrapCleanup::New();
+	TInt r=KErrNoMemory;
+	if (cleanup)
+		{
+		TRAP(r,RunServerL());
+		delete cleanup;
+		}
+	//
+	__UHEAP_MARKEND;
+	return r;
+	}
+
+#ifdef __SENDPROXYSERVER_NO_PROCESSES__
+
+// The server binary is an "EPOCEXE" target type
+// Thus the server parameter passing and startup code for WINS and EPOC are
+// significantly different.
+//
+// In EKA1 WINS, the EPOCEXE target is a DLL with an entry point called WinsMain,
+// taking no parameters and returning TInt. This is not really valid as a thread
+// function which takes a TAny* parameter which we need.
+//
+// So the DLL entry-point WinsMain() is used to return a TInt representing the
+// real thread function within the DLL. This is good as long as
+// sizeof(TInt)>=sizeof(TThreadFunction).
+//
+
+static TInt ThreadFunction(TAny*)
+//
+// WINS thread entry-point function.
+//
+	{
+	return E32Main();
+	}
+
+IMPORT_C TInt WinsMain();
+EXPORT_C TInt WinsMain()
+//
+// WINS DLL entry-point. Just return the real thread function 
+// cast to TInt
+//
+	{
+	return reinterpret_cast<TInt>(&ThreadFunction);
+	}
+
+TInt E32Dll(TDllReason)
+	{
+	return KErrNone;
+	}
+
+#endif