diff -r 9f5ae1728557 -r db3f5fa34ec7 messagingfw/msgtestfw/TestActions/Capabilities/src/SendProxyServer.cpp --- /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(const_cast(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 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 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<> 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<> 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(&ThreadFunction); + } + +TInt E32Dll(TDllReason) + { + return KErrNone; + } + +#endif