diff -r 000000000000 -r 7f656887cf89 plugins/networking/winsockprt/src/wsp_resolver.cpp --- /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 +// Prevent e32std.inl from failing to compile with "ambiguous access to overloaded function". +#define memmove _memmove +#define memset _memset +// +#include +#include +#include +#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(&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(&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 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(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(narrowHostNamePtr.PtrZ())); + delete narrowHostNameBuf; + if (hp) + { + TInetAddr& addr = reinterpret_cast(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(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); + }