diff -r 000000000000 -r 7f656887cf89 plugins/networking/winsockprt/src/wsp_session.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/networking/winsockprt/src/wsp_session.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,223 @@ +// wsp_session.cpp +// +// Copyright (c) 2002 - 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 "wsp_session.h" +#include "wsp_factory.h" +#include "wsp_request.h" +#include "wsp_panic.h" +#include "wsp_log.h" + + +// +// Constants. +// + +_LIT(KWspThreadName, "WinSockPrtThread"); +_LIT(KWspThreadNameWhilstWaitingForDeath, "WinSockPrtThread_WaitingForDeath_%Ld"); +_LIT(KWspThreadStartSemaphoreName, "WinSockPrtThreadStartSemaphore"); +const TInt KWspThreadStackSize = KDefaultStackSize; +const TInt KWspThreadMinHeapSize = 0x4000; // 16 kb +const TInt KWspThreadMaxHeapSize = 0x40000; // 256 kb + + +// +// RWin32Session. +// + +TInt RWin32Session::Open() + { + return CreateThread(); + } + +void RWin32Session::Close() + { + if (iThread.Handle()) + { + iWin32Message.Set(CWin32Session::EClose); + iRequest.MakeRequest(iWin32Message); + iThread.Close(); + } + } + +TInt RWin32Session::MakeRequest(TWin32Message& aMessage) + { + return iRequest.MakeRequest(aMessage); + } + +TInt RWin32Session::CreateThread() + { + WSP_LOG(WspLog::Write(_L("RWin32Session::CreateThread"))); +#ifdef _DEBUG + TFindThread findThread(KWspThreadName); + TFullName name; + __ASSERT_DEBUG(findThread.Next(name)==KErrNotFound, Panic(EWinSockPrtThreadAlreadyExists)); +#endif + + RSemaphore threadStartSemaphore; + TInt err = threadStartSemaphore.CreateGlobal(KWspThreadStartSemaphoreName, 0, EOwnerThread); + if (err) + { + return err; + } + + err = iThread.Create(KWspThreadName, WinSockPrtThreadStart, KWspThreadStackSize, KWspThreadMinHeapSize, KWspThreadMaxHeapSize, &iRequest, EOwnerThread); + if (err == KErrNone) + { + err = iRequest.DuplicateParentThreadHandle(iThread); + if (err) + { + iThread.Close(); + threadStartSemaphore.Close(); + return err; + } + //iThread.SetPriority(EPriorityAbsoluteVeryLow); // Hack to prevent the thread from blocking all threads lower than the default priority. Should really be using a raw Win32 thread rather than a Symbian one. + iThread.Resume(); + threadStartSemaphore.Wait(); + threadStartSemaphore.Close(); + } + else + { + threadStartSemaphore.Close(); + } + return err; + } + + +// +// Thread start functions. +// + +GLDEF_C TInt WinSockPrtThreadStart(TAny* aPtr) + { + __UHEAP_MARK; + CTrapCleanup* trapCleanup = CTrapCleanup::New(); + if (trapCleanup == NULL) + { + return KErrNoMemory; + } + TRAPD(err, InitialiseAndRunThreadL(aPtr)); + WSP_LOG(WspLog::Close()); + delete trapCleanup; + __UHEAP_MARKEND; + return err; + } + +GLDEF_C void InitialiseAndRunThreadL(TAny* aPtr) + { + WSP_LOG(User::LeaveIfError(WspLog::Open())); + CWin32Scheduler* win32Scheduler = CWin32Scheduler::NewL(); + CleanupStack::PushL(win32Scheduler); + TWin32Request* request = static_cast(aPtr); + CWin32Factory* win32Factory = CWin32Factory::NewL(*request, *win32Scheduler); + CleanupStack::PushL(win32Factory); + + RSemaphore threadStartSemaphore; + User::LeaveIfError(threadStartSemaphore.OpenGlobal(KWspThreadStartSemaphoreName, EOwnerThread)); + threadStartSemaphore.Signal(); + threadStartSemaphore.Close(); + + win32Scheduler->Start(); + + CleanupStack::PopAndDestroy(2, win32Scheduler); + } + + +// +// CWin32Session. +// + +void CWin32Session::AddSubSessionL(CWin32SubSession* aSubSession) + { + TInt subSessionHandle = reinterpret_cast(aSubSession); + TPckg subSessionHandlePckg(subSessionHandle); + iRequest.Message().WriteBuffer().Copy(subSessionHandlePckg); + CleanupStack::PushL(aSubSession); + User::LeaveIfError(iSubSessions.Append(aSubSession)); + CleanupStack::Pop(aSubSession); + } + +CWin32Session::~CWin32Session() + { + __ASSERT_DEBUG(iSubSessions.Count() == 0, Panic(EWinSockPrtSubSessionListNotEmpty)); + iSubSessions.Close(); + } + +CWin32Session::CWin32Session(TWin32Request& aRequest, CWin32Scheduler& aScheduler) + : CWin32ActiveObject(aScheduler), iRequest(aRequest) + { + } + +void CWin32Session::ConstructL() + { + CWin32ActiveObject::ConstructL(); + iRequest.SetEventHandle(iEvent); + } + +void CWin32Session::Run() + { + TInt err = KErrNone; + + CWin32SubSession* subSession = reinterpret_cast(iRequest.SubSession()); + TWin32Message& message = iRequest.Message(); + if (subSession == NULL) + { + switch (message.OppCode()) + { + case EClose: + { + Close(); + break; + } + case ECloseSubSession: + { + CloseSubSession(); + break; + } + default: + { + // Pass on to sub-class. + TRAP(err, ServiceL(message)); + } + } + } + else + { + TRAP(err, subSession->ServiceL(message)); + } + + iRequest.Requested(err); + } + +void CWin32Session::Close() + { + // This thread could take a while to die, so give it a different name so that subsequent client attempt to create another one don't fail with KErrInUse. + TTime time; + time.UniversalTime(); + const TInt64& int64 = time.Int64(); + TBuf<64> newThreadName; + newThreadName.Format(KWspThreadNameWhilstWaitingForDeath(), int64); + User::RenameThread(newThreadName); // Throw away error code. + iScheduler.Stop(); + } + +void CWin32Session::CloseSubSession() + { + TInt handle; + TPckg handlePckg(handle); + handlePckg.Copy(iRequest.Message().ReadBuffer()); + CWin32SubSession* subSessionToClose = reinterpret_cast(handle); + TInt pos = iSubSessions.Find(subSessionToClose); + __ASSERT_DEBUG(pos >= 0, Panic(EWinSockPrtUnableToFindSubSession)); + delete subSessionToClose; + iSubSessions.Remove(pos); + }