diff -r 000000000000 -r 7f656887cf89 libraries/iosrv/server/server.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libraries/iosrv/server/server.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,636 @@ +// server.cpp +// +// Copyright (c) 2006 - 2010 Accenture. All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the "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: +// Accenture - Initial contribution +// + +#include "server.h" +#include "pipe.h" +#include "console.h" +#include "file.h" +#include "null.h" +#include "persistentconsole.h" +#include "readwrite.h" +#include "clientserver.h" +#include "session.h" + + +#ifndef EKA2 + +// +// TServerStart. +// + +TServerStart::TServerStart() + { + } + +void TServerStart::SignalL() + { + RThread starter; + User::LeaveIfError(starter.Open(iId)); + starter.RequestComplete(iStatus,KErrNone); + starter.Close(); + } + +#endif + + +// +// CShutdownTimer. +// + +CShutdownTimer::CShutdownTimer() + : CTimer(-1) + { + CActiveScheduler::Add(this); + } + +void CShutdownTimer::ConstructL() + { + CTimer::ConstructL(); + } + +void CShutdownTimer::Start() + { + After(KShutdownDelay); + } + +void CShutdownTimer::RunL() + { + CActiveScheduler::Stop(); + } + + +// +// CIoServer. +// + +CIoServer::CIoServer() +#ifdef EKA2 + : CServer2(0, ESharableSessions) +#else + : CServer(0, ESharableSessions) +#endif + { + + } + +#ifdef EKA2 +CServer2* CIoServer::NewLC() +#else +CServer* CIoServer::NewLC() +#endif + { + CIoServer* self=new(ELeave) CIoServer; + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +CIoServer::~CIoServer() + { + if (iIoObjectContainerIndex) + { + iIoObjectContainerIndex->Remove(iIoObjectContainer); + } + delete iIoObjectContainerIndex; +#ifdef IOSRV_LOGGING + delete iLog; +#endif + } + +void CIoServer::ConstructL() + { +#if defined (__WINS__) && !defined (EKA2) + RThread().SetPriority(EPriorityAbsoluteHigh); +#else + RProcess().SetPriority(::EPriorityHigh); +#endif + User::LeaveIfError(iFs.Connect()); +#ifdef IOSRV_LOGGING + iLog = CIoLog::NewL(iFs); +#endif + iConfig.Init(); // Ignore error (defaults will be used). + StartL(KIoServerName); + iIoObjectContainerIndex = CObjectConIx::NewL(); + iIoObjectContainer = iIoObjectContainerIndex->CreateL(); + iShutdownTimer.ConstructL(); + iShutdownTimer.Start(); + } + +#ifdef EKA2 + CSession2* CIoServer::NewSessionL(const TVersion&, const RMessage2&) const +#else + CSharableSession* CIoServer::NewSessionL(const TVersion&) const +#endif + { + CIoSession* session = new(ELeave) CIoSession(); + LOG(CIoLog::Printf(_L("CIoSession 0x%08x created\r\n"), session)); + return session; + } + +void CIoServer::AddSession() + { + ++iSessionCount; + iShutdownTimer.Cancel(); + } + +void CIoServer::DropSession() + { + if (--iSessionCount == 0) + { + iShutdownTimer.Start(); + } + } + +CIoPipe& CIoServer::CreatePipeLC() + { + CIoPipe* pipe = CIoPipe::NewLC(); + iIoObjectContainer->AddL(pipe); + return *pipe; + } + +CIoConsole& CIoServer::CreateConsoleLC(const TDesC& aImplementation, const TDesC& aTitle, TSize aSize, MIoWriteEndPoint* aUnderlyingConsole, TUint aOptions) + { + CIoConsole* underlying = NULL; + while (aUnderlyingConsole && aUnderlyingConsole->IoepIsType(RIoHandle::EPersistentConsole)) + { + aUnderlyingConsole = ((CIoPersistentConsole*)aUnderlyingConsole)->TransientWriter(); + } + if (aUnderlyingConsole && aUnderlyingConsole->IoepIsConsole()) + { + underlying = (CIoConsole*)aUnderlyingConsole; + } + + CIoConsole* console = CIoConsole::NewLC(aImplementation, aTitle, aSize, iConfig, underlying, aOptions); + iIoObjectContainer->AddL(console); + return *console; + } + +CIoFile& CIoServer::CreateFileLC(const TDesC& aName, RIoFile::TMode aMode) + { + CIoFile* file = CIoFile::NewLC(iFs, aName, aMode); + iIoObjectContainer->AddL(file); + return *file; + } + +CIoNull& CIoServer::CreateNullLC() + { + CIoNull* null = CIoNull::NewLC(); + iIoObjectContainer->AddL(null); + return *null; + } + +CIoPersistentConsole& CIoServer::CreatePersistentConsoleLC(const TDesC& aName, const TDesC& aTitle, const RMsg& aMessage) + { + CIoPersistentConsole* pcons = CIoPersistentConsole::NewLC(aName, aTitle, *this, aMessage); + iIoObjectContainer->AddL(pcons); + return *pcons; + } + + +CIoReadObject& CIoServer::CreateReadObjLC() + { + CIoReadObject* obj = CIoReadObject::NewLC(iNextReadObjId++); + iIoObjectContainer->AddL(obj); + return *obj; + } + +CIoWriteObject& CIoServer::CreateWriteObjLC() + { + CIoWriteObject* obj = CIoWriteObject::NewLC(iNextWriteObjId++); + iIoObjectContainer->AddL(obj); + return *obj; + } + +CIoReadObject* CIoServer::NextReadObj(TThreadId aOwningThread) const + { + return (CIoReadObject*)DoFindObj(RIoHandle::EReadObject, aOwningThread, ETrue); + } + +CIoReadWriteObject* CIoServer::DoFindObj(RIoHandle::TType aType, TThreadId aOwningThread, TBool aNext) const + { + CIoReadWriteObject* lastMatchingObj = NULL; + const TInt numObjs = iIoObjectContainer->Count(); + for (TInt i = 0; i < numObjs; ++i) + { + CIoObject* obj = (CIoObject*)(*iIoObjectContainer)[i]; + if (obj->IsType(aType)) + { + CIoReadWriteObject* readWriteObj = (CIoReadWriteObject*)obj; + if (aNext && readWriteObj->IsOwner(aOwningThread) && !readWriteObj->OpenedByOwner()) + { + // aNext==ETrue means we return the first matching object that isn't already opened by its owner + return readWriteObj; + } + else if (!aNext && readWriteObj->IsOwner(aOwningThread) && readWriteObj->OpenedByOwner()) + { + // aNext==EFalse means we return the last matching object that *is* opened + lastMatchingObj = readWriteObj; + } + } + } + return lastMatchingObj; + } + +CIoWriteObject* CIoServer::NextWriteObj(TThreadId aOwningThread) const + { + return (CIoWriteObject*)DoFindObj(RIoHandle::EWriteObject, aOwningThread, ETrue); + } + +CIoReadObject* CIoServer::LastOpenedReadObj(TThreadId aOwningThread) const + { + return (CIoReadObject*)DoFindObj(RIoHandle::EReadObject, aOwningThread, EFalse); + } + +CIoWriteObject* CIoServer::LastOpenedWriteObj(TThreadId aOwningThread) const + { + return (CIoWriteObject*)DoFindObj(RIoHandle::EWriteObject, aOwningThread, EFalse); + } + +CIoPersistentConsole& CIoServer::FindPersistentConsoleL(const TDesC& aName) + { + const TInt numObjs = iIoObjectContainer->Count(); + for (TInt i=0; iIsType(RIoHandle::EPersistentConsole)) + { + CIoPersistentConsole& pcons = (CIoPersistentConsole&)*obj; + if (pcons.Name().Compare(aName)==0) + { + return pcons; + } + } + } + User::Leave(KErrNotFound); + return *(CIoPersistentConsole*)1; // To keep the compiler happy. + } + +CIoObject* CIoServer::FindObjectByName(RIoHandle::TType aType, TInt& aFindHandle, const TDesC& aMatch, TName& aName) const + { + FOREVER + { + TInt err = iIoObjectContainer->FindByName(aFindHandle, aMatch, aName); + if (err == KErrNone) + { + CIoObject* obj = (CIoObject*)iIoObjectContainer->At(aFindHandle); + if (obj->IsType(aType)) + { + return obj; + } + } + else + { + break; + } + } + return NULL; + } + +CIoObject& CIoServer::OpenObjectLC(TInt aFindHandle) + { + CIoObject* obj = (CIoObject*)iIoObjectContainer->At(aFindHandle); + if (obj) + { + User::LeaveIfError(obj->Open()); + CleanupClosePushL(*obj); + return *obj; + } + User::Leave(KErrNotFound); + return *(CIoObject*)1; // To keep the compiler happy. + } + +const TIoConfig& CIoServer::Config() + { + return iConfig; + } + +void CIoServer::PersistentConsoleAddL(const TDesC16& aName, const CIoPersistentConsole& aCons) + { + if (iPersistentConsoleNames.Find(aName)!=NULL) + { + User::Leave(KErrAlreadyExists); + } + iPersistentConsoleNames.InsertL(&aName, &aCons); + } + +void CIoServer::PersistentConsoleRemove(const TDesC16& aName, const CIoPersistentConsole& aCons) + { + if (iPersistentConsoleNames.Find(aName) == &aCons) + { + iPersistentConsoleNames.Remove(&aName); + } + } + +TInt CIoServer::RunError(TInt aError) + { + if (aError == KErrBadDescriptor) + { + PanicClient(Message(), EPanicBadDescriptor); + } + else if (aError == KErrBadHandle) + { + PanicClient(Message(), EPanicBadHandle); + } + else + { + LOG(CIoLog::LogCompletion(Message(), aError)); + Complete(Message(), aError); + } + + ReStart(); + return KErrNone; + } + + +// +// Statics. +// + +void PanicClient(const RMsg& aMessage, TIoPanicReason aReason) + { + aMessage.Panic(KIoServerName, aReason); + } + +#ifdef EKA2 +static void RunServerL() +#else +static void RunServerL(TServerStart& aStart) +#endif + { + CActiveScheduler* scheduler = new(ELeave) CActiveScheduler; + CleanupStack::PushL(scheduler); + CActiveScheduler::Install(scheduler); + + CIoServer::NewLC(); +#ifdef EKA2 + User::RenameThread(KIoServerName); + RProcess::Rendezvous(KErrNone); +#else + User::LeaveIfError(RThread().Rename(KIoServerName)); + aStart.SignalL(); +#endif + CActiveScheduler::Start(); + CleanupStack::PopAndDestroy(2, scheduler); + } + +#ifdef EKA2 +static TInt RunServer() +#else +static TInt RunServer(TServerStart& aStart) +#endif + { + __UHEAP_MARK; + CTrapCleanup* cleanup=CTrapCleanup::New(); + TInt r = KErrNoMemory; + if (cleanup) + { +#ifdef EKA2 + TRAP(r, RunServerL()); +#else + TRAP(r, RunServerL(aStart)); +#endif + delete cleanup; + } + __UHEAP_MARKEND; + return r; + } + + +#if defined(__WINS__) && !defined(EKA2) + +static TInt ThreadFunction(TAny* aParms) + { + return RunServer(*static_cast(aParms)); + } + +IMPORT_C TInt WinsMain(); +EXPORT_C TInt WinsMain() + { + return reinterpret_cast(&ThreadFunction); + } + +TInt E32Dll(TDllReason) + { + return KErrNone; + } + +#else +#ifdef EKA2 + +TInt E32Main() + { + return RunServer(); + } + +#else + +TInt TServerStart::GetCommand() + { + RProcess p; + if (p.CommandLineLength() != (sizeof(TServerStart) / sizeof(TText))) + { + return KErrGeneral; + } + TPtr ptr(reinterpret_cast(this), 0, (sizeof(TServerStart) / sizeof(TText))); + p.CommandLine(ptr); + return KErrNone; + } + +TInt E32Main() + { + TServerStart start; + TInt r = start.GetCommand(); + if (r == KErrNone) + { + r = RunServer(start); + } + return r; + } + +#endif +#endif + +#ifndef EKA2 +const TAny* MessagePtr(const RMsg& aMessage, TInt aParam) + { + const TAny* ptr; + switch (aParam) + { + case 0: + { + ptr = aMessage.Ptr0(); + break; + } + case 1: + { + ptr = aMessage.Ptr1(); + break; + } + case 2: + { + ptr = aMessage.Ptr2(); + break; + } + case 3: + { + ptr = aMessage.Ptr3(); + break; + } + default: + { + ASSERT(EFalse); + ptr = NULL; + } + } + return ptr; + } +#endif + +TInt DesLengthL(const RMsg& aMessage, TInt aParam) + { +#ifdef EKA2 + return aMessage.GetDesLengthL(aParam); +#else + return aMessage.Client().GetDesLength(MessagePtr(aMessage, aParam)); +#endif + } + +TInt MaxDesLengthL(const RMsg& aMessage, TInt aParam) + { +#ifdef EKA2 + return aMessage.GetDesMaxLengthL(aParam); +#else + return aMessage.Client().GetDesMaxLength(MessagePtr(aMessage, aParam)); +#endif + } + +void MessageReadL(const RMsg& aMessage, TInt aParam, TDes8& aDes) + { +#ifdef EKA2 + aMessage.ReadL(aParam, aDes); +#else + aMessage.ReadL(MessagePtr(aMessage, aParam), aDes); +#endif + } + +void MessageReadL(const RMsg& aMessage, TInt aParam, TDes8& aDes, TInt aOffset) + { +#ifdef EKA2 + aMessage.ReadL(aParam, aDes, aOffset); +#else + aMessage.ReadL(MessagePtr(aMessage, aParam), aDes, aOffset); +#endif + } + +void MessageReadL(const RMsg& aMessage, TInt aParam, TDes16& aDes) + { +#ifdef EKA2 + aMessage.ReadL(aParam, aDes); +#else + aMessage.ReadL(MessagePtr(aMessage, aParam), aDes); +#endif + } + +void MessageReadL(const RMsg& aMessage, TInt aParam, TDes16& aDes, TInt aOffset) + { +#ifdef EKA2 + aMessage.ReadL(aParam, aDes, aOffset); +#else + aMessage.ReadL(MessagePtr(aMessage, aParam), aDes, aOffset); +#endif + } + +void MessageWriteL(const RMsg& aMessage, TInt aParam, const TDesC8& aDes) + { +#ifdef EKA2 + aMessage.WriteL(aParam, aDes); +#else + aMessage.WriteL(MessagePtr(aMessage, aParam), aDes); +#endif + } + +void MessageWriteL(const RMsg& aMessage, TInt aParam, const TDesC16& aDes) + { +#ifdef EKA2 + aMessage.WriteL(aParam, aDes); +#else + aMessage.WriteL(MessagePtr(aMessage, aParam), aDes); +#endif + } + +TInt MessageWrite(const RMsg& aMessage, TInt aParam, const TDesC8& aDes) + { +#ifdef EKA2 + return aMessage.Write(aParam, aDes); +#else + return aMessage.Write(MessagePtr(aMessage, aParam), aDes); +#endif + } + +TInt MessageWrite(const RMsg& aMessage, TInt aParam, const TDesC16& aDes) + { +#ifdef EKA2 + return aMessage.Write(aParam, aDes); +#else + return aMessage.Write(MessagePtr(aMessage, aParam), aDes); +#endif + } + +TBool MessagePending(const RMsg& aMessage) + { +#ifdef EKA2 + return !aMessage.IsNull(); +#else + return aMessage != RMessagePtr(); +#endif + } + +TThreadId ClientThreadIdL(const RMsg& aMessage) + { + TThreadId clientThreadId; +#ifdef EKA2 + RThread clientThread; + aMessage.ClientL(clientThread); + clientThreadId = clientThread.Id(); + clientThread.Close(); +#else + clientThreadId = aMessage.Client().Id(); +#endif + return clientThreadId; + } + +TFullName ClientNameL(const RMsg& aMessage) + { +#ifdef EKA2 + RThread clientThread; + aMessage.ClientL(clientThread); + TFullName clientName(clientThread.FullName()); + clientThread.Close(); + return clientName; +#else + return aMessage.Client().FullName(); +#endif + } + +void Complete(const RMsg& aMessage, TInt aError) + { + LOG(CIoLog::LogCompletion(aMessage, aError)); + aMessage.Complete(aError); + } + +void CompleteIfPending(const RMsg& aMessage, TInt aError) + { + if (MessagePending(aMessage)) + { + Complete(aMessage, aError); + } + }