plugins/networking/winsockprt/src/wsp_session.cpp
changeset 0 7f656887cf89
--- /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<TWin32Request*>(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<TInt>(aSubSession);
+	TPckg<TInt> 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<CWin32SubSession*>(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<TInt> handlePckg(handle);
+	handlePckg.Copy(iRequest.Message().ReadBuffer());
+	CWin32SubSession* subSessionToClose = reinterpret_cast<CWin32SubSession*>(handle);
+	TInt pos = iSubSessions.Find(subSessionToClose);
+	__ASSERT_DEBUG(pos >= 0, Panic(EWinSockPrtUnableToFindSubSession));
+	delete subSessionToClose;
+	iSubSessions.Remove(pos);
+	}