plugins/networking/winsockprt/src/wsp_resolver.cpp
changeset 0 7f656887cf89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/networking/winsockprt/src/wsp_resolver.cpp	Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,387 @@
+// wsp_resolver.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 <winsock2.h>
+// Prevent e32std.inl from failing to compile with "ambiguous access to overloaded function".
+#define memmove _memmove
+#define memset _memset
+//
+#include <e32math.h>
+#include <in_sock.h>
+#include <utf.h>
+#include "wsp_resolver.h"
+#include "wsp_session.h"
+#include "wsp_factory.h"
+#include "wsp_panic.h"
+#include "wsp_log.h"
+
+
+//
+// Constants.
+//
+
+_LIT(KWspResolverWorkerThreadNameFormat, "WinSockPrtResolverWorkerThread_%x_%d");
+const TInt  KWspResolverWorkerThreadNameLength =  64;
+const TInt KWspResolverWorkerThreadStackSize = KDefaultStackSize;
+
+
+//
+// RWin32Socket.
+//
+
+RWin32Resolver::RWin32Resolver()
+	: iNameRecordPckg(NULL, 0, 0)
+	{
+	}
+
+TInt RWin32Resolver::Open(RWin32Factory& aFactory)
+	{
+	WSP_LOG(WspLog::Printf(_L("RWin32Resolver::Open: this: 0x%x"), this));
+	return CreateSubSession(aFactory, CWin32Factory::ENewResolver);
+	}
+
+void RWin32Resolver::Close()
+	{
+	WSP_LOG(WspLog::Printf(_L("RWin32Resolver::Close: this: 0x%x"), this));
+	RWin32SubSession::Close();
+	}
+
+TInt RWin32Resolver::GetByName(TNameRecord& aName, TRequestStatus& aStatus)
+	{
+	WSP_LOG(WspLog::Printf(_L("RWin32Resolver::GetByName: this: 0x%x"), this));
+	iNameRecordPckg.Set(reinterpret_cast<TUint8*>(&aName), sizeof(TNameRecord),sizeof(TNameRecord));
+	iWin32Message.Set(CWin32Resolver::EGetByName, iNameRecordPckg, aStatus);
+	return MakeRequest(iWin32Message);
+	}
+
+TInt RWin32Resolver::GetByAddress(TNameRecord& aName, TRequestStatus& aStatus)
+	{
+	WSP_LOG(WspLog::Printf(_L("RWin32Resolver::GetByAddress: this: 0x%x"), this));
+	iNameRecordPckg.Set(reinterpret_cast<TUint8*>(&aName), sizeof(TNameRecord),sizeof(TNameRecord));
+	iWin32Message.Set(CWin32Resolver::EGetByAddress, iNameRecordPckg, aStatus);
+	return MakeRequest(iWin32Message);
+	}
+
+void RWin32Resolver::Cancel()
+	{
+	WSP_LOG(WspLog::Printf(_L("RWin32Resolver::Cancel: this: 0x%x"), this));
+	TWin32Message cancelWin32Message;
+	cancelWin32Message.Set(CWin32Resolver::ECancel);
+	MakeRequest(cancelWin32Message); // Throw away return code - can't do anything useful with it.
+	}
+
+
+//
+// CWin32Resolver.
+//
+
+CWin32Resolver* CWin32Resolver::NewL(CWin32Scheduler& aScheduler)
+	{
+	CWin32Resolver* self = new(ELeave) CWin32Resolver(aScheduler);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CWin32Resolver::CWin32Resolver(CWin32Scheduler& aScheduler)
+	: CWin32SubSession(aScheduler)
+	{
+	}
+
+void CWin32Resolver::ConstructL()
+	{
+	CWin32SubSession::ConstructL();
+	}
+
+CWin32Resolver::~CWin32Resolver()
+	{
+	}
+
+void CWin32Resolver::Run()
+	{
+	iMessage->Complete(iError);
+	iMessage = NULL;
+	iWorkerThread.Close();
+	}
+
+void CWin32Resolver::ServiceL(TWin32Message& aMessage)
+	{
+	switch (aMessage.OppCode())
+		{
+		case EGetByName:
+		case EGetByAddress:
+			{
+			__ASSERT_DEBUG(iMessage == NULL, Panic(EWinSockPrtCWin32ResolverMultipleRequests));
+			iMessage = &aMessage;
+			CreateWorkerThread();
+			break;
+			}
+		case ECancel:
+			{
+			Cancel();
+			break;
+			}
+		default:
+			{
+			__ASSERT_DEBUG(EFalse, Panic(EWinSockPrtInvalidResolverOppCode));
+			}
+		}
+	}
+
+void CWin32Resolver::Cancel()
+	{
+	if (iWorkerThread.Handle() && (iWorkerThread.ExitType() == EExitPending))
+		{
+		iWorkerThread.Kill(KErrCancel);
+		iMessage->Complete(KErrCancel);
+		iMessage = NULL;
+		iWorkerThread.Close();
+		}
+	}
+
+void CWin32Resolver::CreateWorkerThread()
+	{
+	TBuf<KWspResolverWorkerThreadNameLength> threadName;
+	threadName.Format(KWspResolverWorkerThreadNameFormat, this, Math::Rand(iRandSeed));
+	TInt err = iWorkerThread.Create(threadName, WorkerThreadStart, KWspResolverWorkerThreadStackSize, NULL, this, EOwnerThread);
+	if (err == KErrNone)
+		{
+		iWorkerThread.Resume();
+		}
+	else
+		{
+		iMessage->Complete(err);
+		}
+	}
+
+
+//
+// CWin32Resolver worker thread methods.
+//
+
+TInt CWin32Resolver::WorkerThreadStart(TAny* aPtr)
+	{
+	CWin32Resolver* self = reinterpret_cast<CWin32Resolver*>(aPtr);
+
+	switch (self->iMessage->OppCode())
+		{
+		case EGetByName:
+			{
+			self->GetByName();
+			break;
+			}
+		case EGetByAddress:
+			{
+			self->GetByAddress();
+			break;
+			}
+		case ECancel:
+		default:
+			{
+			__ASSERT_DEBUG(EFalse, Panic(EWinSockPrtResolverInvalidWorkerThreadRequest));
+			}
+		}
+
+	return KErrNone;
+	}
+
+void CWin32Resolver::GetByName()
+	{
+	TNameRecord& nameRecord = (TNameRecord&)*iMessage->WriteBuffer().Ptr();
+	struct hostent* hp;
+	HBufC8* narrowHostNameBuf = HBufC8::New(nameRecord.iName.MaxLength() + 1); // Note, this is one bigger than the size of THostName to allow for a null termination character.
+	if (narrowHostNameBuf == NULL)
+		{
+		iError = KErrNoMemory;
+		}
+	else
+		{
+		TPtr8 narrowHostNamePtr(narrowHostNameBuf->Des());
+		CnvUtfConverter::ConvertFromUnicodeToUtf8(narrowHostNamePtr, nameRecord.iName);
+		hp = gethostbyname(reinterpret_cast<const char*>(narrowHostNamePtr.PtrZ()));
+		delete narrowHostNameBuf;
+		if (hp)
+			{
+			TInetAddr& addr = reinterpret_cast<TInetAddr&>(nameRecord.iAddr);
+			__ASSERT_DEBUG(hp->h_addrtype == AF_INET, Panic(EWinSockPrtResolverInvalidFamily));
+			addr.SetFamily(KAfInet);
+			__ASSERT_DEBUG(hp->h_length == 4, Panic(EWinSockPrtResolverInvalidAddressLength));
+			TUint32* address = (TUint32*)hp->h_addr_list[0];
+			addr.SetAddress(htonl(*address));
+			iError = KErrNone;
+			}
+		else
+			{
+			iError = KErrNotFound;
+			}
+		}
+	
+	if (!SetEvent(iEvent))
+		{
+		__ASSERT_DEBUG(EFalse, Panic(EWinSockPrtResolverUnexpectedSetEventError));
+		}
+	}
+
+void CWin32Resolver::GetByAddress()
+	{
+	TNameRecord& nameRecord = (TNameRecord&)*iMessage->WriteBuffer().Ptr();
+	TInetAddr& addr = reinterpret_cast<TInetAddr&>(nameRecord.iAddr);
+	struct hostent* hp;
+	char addressBuf[4];
+	*((TUint32*)addressBuf) = htonl(addr.Address());
+	hp = gethostbyaddr(addressBuf, 4, AF_INET);
+	if (hp)
+		{
+		TPtrC8 narrowAddressPtr((TUint8*)hp->h_name, User::StringLength((TUint8*)hp->h_name));
+		CnvUtfConverter::ConvertToUnicodeFromUtf8(nameRecord.iName, narrowAddressPtr);
+		iError = KErrNone;
+		}
+	else
+		{
+		iError = KErrNotFound;
+		}
+	
+	if (!SetEvent(iEvent))
+		{
+		__ASSERT_DEBUG(EFalse, Panic(EWinSockPrtResolverUnexpectedSetEventError));
+		}
+	}
+
+
+//
+// CWin32ResolverWrapper.
+//
+
+CWin32ResolverWrapper* CWin32ResolverWrapper::NewL(MWin32ResolverObserver& aObserver, RWin32Factory& aWin32Factory)
+	{
+	CWin32ResolverWrapper* self = new(ELeave) CWin32ResolverWrapper(aObserver);
+	CleanupStack::PushL(self);
+	self->ConstructL(aWin32Factory);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CWin32ResolverWrapper::~CWin32ResolverWrapper()
+	{
+	Cancel();
+	iWin32Resolver.Close();
+	}
+
+CWin32ResolverWrapper::CWin32ResolverWrapper(MWin32ResolverObserver& aObserver)
+	: CActive(CActive::EPriorityStandard), iObserver(aObserver)
+	{
+	}
+
+void CWin32ResolverWrapper::ConstructL(RWin32Factory& aWin32Factory)
+	{
+	User::LeaveIfError(iWin32Resolver.Open(aWin32Factory));
+	CActiveScheduler::Add(this);
+	}
+
+TInt CWin32ResolverWrapper::GetByName(TNameRecord& aName)
+	{
+	__ASSERT_DEBUG(!IsActive(), Panic(EWinSockPrtResolverWrapperGetByNameWhilstActive));
+	TInt err = iWin32Resolver.GetByName(aName, iStatus);
+	if (err == KErrNone)
+		{
+		SetActive();
+		}
+	return err;
+	}
+
+TInt CWin32ResolverWrapper::GetByAddress(TNameRecord& aName)
+	{
+	__ASSERT_DEBUG(!IsActive(), Panic(EWinSockPrtResolverWrapperGetByAddressWhilstActive));
+	TInt err = iWin32Resolver.GetByAddress(aName, iStatus);
+	if (err == KErrNone)
+		{
+		SetActive();
+		}
+	return err;
+	}
+
+void CWin32ResolverWrapper::DoCancel()
+	{
+	iWin32Resolver.Cancel();
+	}
+
+void CWin32ResolverWrapper::RunL()
+	{
+	iObserver.HandleWin32ResolverCompletion(iStatus.Int());
+	}
+
+TInt CWin32ResolverWrapper::RunError(TInt /*aError*/)
+	{
+	__ASSERT_DEBUG(EFalse, Panic(EWinSockPrtResolverWrapperUnexpectedRunError));
+	return 0;
+	}
+
+
+//
+// CWinSockResolver.
+//
+
+CWinSockResolver* CWinSockResolver::NewL(RWin32Factory& aFactory)
+	{
+	CWinSockResolver* self = new(ELeave) CWinSockResolver();
+	CleanupStack::PushL(self);
+	self->ConstructL(aFactory);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CWinSockResolver::~CWinSockResolver()
+	{
+	delete iResolverWrapper;
+	}
+
+void CWinSockResolver::CancelCurrentOperation()
+	{
+	iResolverWrapper->Cancel();
+	}
+
+void CWinSockResolver::GetByName(TNameRecord& aName)
+	{
+	iResolverWrapper->GetByName(aName);
+	}
+
+void CWinSockResolver::GetByAddress(TNameRecord& aName)
+	{
+	iResolverWrapper->GetByAddress(aName);
+	}
+
+void CWinSockResolver::SetHostName(TDes& /*aNameBuf*/)
+	{
+	// TODO:
+	ASSERT(EFalse);
+	}
+
+void CWinSockResolver::GetHostName(TDes& /*aNameBuf*/)
+	{
+	// TODO:
+	ASSERT(EFalse);
+	}
+
+void CWinSockResolver::HandleWin32ResolverCompletion(TInt aError)
+	{
+	iNotify->QueryComplete(aError);
+	}
+
+CWinSockResolver::CWinSockResolver()
+	{
+	}
+
+void CWinSockResolver::ConstructL(RWin32Factory& aFactory)
+	{
+	iResolverWrapper = CWin32ResolverWrapper::NewL(*this, aFactory);
+	}