diff -r 000000000000 -r 7f656887cf89 plugins/networking/winsockprt/src/wsp_provider.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/networking/winsockprt/src/wsp_provider.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,570 @@ +// wsp_provider.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_provider.h" +#include "wsp_factory.h" +#include "wsp_socket.h" +#include "wsp_panic.h" +#include "wsp_log.h" + + +// +// Constants. +// + +const TInt KReceiveBufferSize = 4096; + + +// +// CWinSockProviderBase. +// + +CWinSockProviderBase::CWinSockProviderBase(RWin32Factory& aWin32Factory) + : iWin32Factory(aWin32Factory), iWinSockWriteBuffer(NULL, 0) + { + } + +CWinSockProviderBase::~CWinSockProviderBase() + { + delete iSendSocketWrapper; + delete iReceiveSocketWrapper; + delete iReceiveBuffer; + delete iSendBuffer; + iWin32Socket.Close(); + } + +void CWinSockProviderBase::ConstructL() + { + iSendSocketWrapper = CWin32SocketWrapper::NewL(*this, iWin32Socket); + iReceiveSocketWrapper = CWin32SocketWrapper::NewL(*this, iWin32Socket); + iReceiveBuffer = HBufC8::NewL(KReceiveBufferSize); + iWinSockWriteBuffer.Set(iReceiveBuffer->Des()); + } + +TInt CWinSockProviderBase::FillSendBuffer(const TDesC8& aDataToSend) + { + if (iSendBuffer) + { + if (iSendBuffer->Des().MaxLength() < aDataToSend.Length()) + { + iSendBuffer = iSendBuffer->ReAlloc(aDataToSend.Length()); + if (iSendBuffer == NULL) + { + return KErrNoMemory; + } + } + *iSendBuffer = aDataToSend; + } + else + { + iSendBuffer = aDataToSend.Alloc(); + if (iSendBuffer == NULL) + { + return KErrNoMemory; + } + } + return KErrNone; + } + +TInt CWinSockProviderBase::SetRemName(TSockAddr& anAddr) + { + WSP_LOG(WspLog::Write(_L("CWinSockProviderBase::SetRemName"))); + iRemoteAddr = anAddr; + return KErrNone; + } + +void CWinSockProviderBase::LocalName(TSockAddr& anAddr)const + { + WSP_LOG(WspLog::Write(_L("CWinSockProviderBase::LocalName"))); + iWin32Socket.GetSocketName(static_cast(anAddr)); // Throw away error code. + } + +TInt CWinSockProviderBase::SetLocalName(TSockAddr& anAddr) + { + WSP_LOG(WspLog::Write(_L("CWinSockProviderBase::SetLocalName"))); + return iWin32Socket.Bind(anAddr); + } + +void CWinSockProviderBase::AutoBind( void ) + { + WSP_LOG(WspLog::Write(_L("CWinSockProviderBase::AutoBind"))); + } + +TInt CWinSockProviderBase::GetOption(TUint /*aLevel*/, TUint /*aName*/, TDes8& /*anOption*/)const + { + return KErrNotSupported; + } + +TInt CWinSockProviderBase::SetOption(TUint /*aLevel*/, TUint /*aName*/, const TDesC8& /*anOption*/) + { + return KErrNotSupported; + } + +void CWinSockProviderBase::Ioctl(TUint /*aLevel*/, TUint /*aName*/, TDes8* /*anOption*/) + { + iSocket->Error(KErrNotSupported, MSocketNotify::EErrorIoctl); + } + +void CWinSockProviderBase::CancelIoctl(TUint /*aLevel*/, TUint /*aName*/) + { + } + +TInt CWinSockProviderBase::PassiveOpen(TUint /*aQue*/, const TDesC8& /*aConnectionData*/) + { + __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtUnexpectedActivePassiveOpenWithConnectionData)); + return 0; + } + +void CWinSockProviderBase::Shutdown(TCloseType /*option*/, const TDesC8& /*aDisconnectData*/) + { + __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtUnexpectedActiveShutdownWithConnectionData)); + } + +void CWinSockProviderBase::ActiveOpen(const TDesC8& /*aConnectionData*/) + { + __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtUnexpectedActiveOpenCallWithConnectionData)); + } + +void CWinSockProviderBase::Shutdown(TCloseType aType) + { + WSP_LOG(WspLog::Write(_L("CWinSockProviderBase::Shutdown"))); + if (aType != EImmediate) + { + iSocket->CanClose(); + } + } + + +// +// CWinSockTcpProvider. +// + +CWinSockTcpProvider* CWinSockTcpProvider::NewL(RWin32Factory& aWin32Factory) + { + CWinSockTcpProvider* self = new(ELeave) CWinSockTcpProvider(aWin32Factory); + CleanupStack::PushL(self); + self->ConstructL(RWin32Socket::ETcp); + CleanupStack::Pop(self); + return self; + } + +CWinSockTcpProvider* CWinSockTcpProvider::NewBlankLC(RWin32Factory& aWin32Factory) + { + CWinSockTcpProvider* self = new(ELeave) CWinSockTcpProvider(aWin32Factory); + CleanupStack::PushL(self); + self->ConstructL(RWin32Socket::EBlank); + return self; + } + +CWinSockTcpProvider::CWinSockTcpProvider(RWin32Factory& aWin32Factory) + : CWinSockProviderBase(aWin32Factory) + { + } + +void CWinSockTcpProvider::ConstructL(RWin32Socket::TType aType) + { + User::LeaveIfError(iWin32Socket.Open(iWin32Factory, aType)); + iConnectSocketWrapper = CWin32SocketWrapper::NewL(*this, iWin32Socket); + iAcceptSocketWrapper = CWin32SocketWrapper::NewL(*this, iWin32Socket); + CWinSockProviderBase::ConstructL(); + } + +CWinSockTcpProvider::~CWinSockTcpProvider() + { + delete iConnectSocketWrapper; + delete iAcceptSocketWrapper; + delete iAcceptSap; + } + +void CWinSockTcpProvider::RemName(TSockAddr& anAddr) const + { + WSP_LOG(WspLog::Write(_L("CWinSockTcpProvider::RemName"))); + iWin32Socket.GetPeerName(static_cast(anAddr)); // Throw away error code. + } + +TUint CWinSockTcpProvider::Write(const TDesC8& aDesc, TUint /*options*/, TSockAddr* /*anAddr*/) + { + WSP_LOG(WspLog::Printf(_L("CWinSockTcpProvider::Write: writing %d bytes"), aDesc.Length())); + WSP_RAW_LOG(WspLog::WriteRawOutbound(aDesc)); + if (iSendSocketWrapper->IsActive()) + { + return 0; + } + + TInt err = FillSendBuffer(aDesc); + if (err) + { + iSocket->Error(err, MSocketNotify::EErrorSend); + return 0; + } + iSendSocketWrapper->Send(*iSendBuffer); + return iSendBuffer->Length(); + } + +void CWinSockTcpProvider::GetData(TDes8& aDesc, TUint /*aOptions*/, TSockAddr* /*anAddr*/) + { + WSP_LOG(WspLog::Write(_L("CWinSockTcpProvider::GetData"))); + TInt esockBufferSize = aDesc.Length(); + if (esockBufferSize >= iEsockReadBuffer.Length()) + { + WSP_LOG(WspLog::Printf(_L("\tCopying all %d bytes up to ESock"), iEsockReadBuffer.Length())); + aDesc.Copy(iEsockReadBuffer); + StartReceive(); + } + else + { + WSP_LOG(WspLog::Printf(_L("\tESock buffer size: %d, available data: %d"), esockBufferSize, iEsockReadBuffer.Length())); + aDesc.Copy(iEsockReadBuffer.Left(esockBufferSize)); + iEsockReadBuffer.Set(iEsockReadBuffer.Right(iEsockReadBuffer.Length() - esockBufferSize)); + } + + WSP_RAW_LOG(WspLog::WriteRawInbound(aDesc)); + } + +void CWinSockTcpProvider::Start() + { + if (iListeningSap) + { + iListeningSap->HandleListeningSapStarted(); + iListeningSap = NULL; + } + } + +void CWinSockTcpProvider::ActiveOpen() + { + WSP_LOG(WspLog::Write(_L("CWinSockTcpProvider::ActiveOpen"))); + TInt err = iConnectSocketWrapper->Connect(iRemoteAddr); + if (err) + { + iSocket->Error(err, MSocketNotify::EErrorConnect); + } + } + +TInt CWinSockTcpProvider::PassiveOpen(TUint aQue) + { + WSP_LOG(WspLog::Write(_L("CWinSockTcpProvider::PassiveOpen"))); + TRAPD(err, DoPassiveOpenL(aQue)); + return err; + } + +TInt CWinSockTcpProvider::GetOption(TUint aLevel, TUint aName, TDes8& anOption) const + { + if (aLevel == KSolInetTcp) + { + switch (aName) + { + case KSoTcpNoDelay: + { + BOOL bOptVal = FALSE; + TInt length = sizeof(BOOL); + TInt err = iWin32Socket.GetOption(IPPROTO_TCP, TCP_NODELAY, (char*)&bOptVal, &length); + if (err == KErrNone) + { + TPckg intPackage(bOptVal); + anOption.Copy(intPackage); + } + return err; + } + } + } + + return CWinSockProviderBase::GetOption(aLevel, aName, anOption); + } + +TInt CWinSockTcpProvider::SetOption(TUint aLevel, TUint aName, const TDesC8& anOption) + { + if (aLevel == KSolInetTcp) + { + switch (aName) + { + case KSoTcpNoDelay: + { + TPckgC intPackage(0); + intPackage.Set(anOption); + BOOL bOptVal = intPackage(); + return iWin32Socket.SetOption(IPPROTO_TCP, TCP_NODELAY, (char*)&bOptVal, sizeof(BOOL)); + } + } + } + + return CWinSockProviderBase::SetOption(aLevel, aName, anOption); + } + +void CWinSockTcpProvider::HandleWin32SocketCompletion(TRequestType aRequestType, TInt aError) + { + switch (aRequestType) + { + case MWin32SocketObserver::EConnect: + { + WSP_LOG(WspLog::Printf(_L("CWinSockTcpProvider::HandleWin32SocketCompletion: EConnect, error: %d"), aError)); + if (aError) + { + iSocket->Error(aError, MSocketNotify::EErrorConnect); + } + else + { + StartReceive(); + if (iSocket) + { + iSocket->ConnectComplete(); + } + } + break; + } + case MWin32SocketObserver::ESend: + { + WSP_LOG(WspLog::Printf(_L("CWinSockTcpProvider::HandleWin32SocketCompletion: ESend, error: %d"), aError)); + if (iSocket) + { + if (aError) + { + iSocket->Error(aError, MSocketNotify::EErrorSend); + } + else + { + iSocket->CanSend(); + } + } + break; + } + case MWin32SocketObserver::EReceive: + { + WSP_LOG(WspLog::Printf(_L("CWinSockTcpProvider::HandleWin32SocketCompletion: EReceive, error: %d"), aError)); + if (aError) + { + if (iSocket) + { + iSocket->Error(aError, MSocketNotify::EErrorRecv); + } + } + else + { + iEsockReadBuffer.Set(iWinSockWriteBuffer); + TInt receivedBytes = iEsockReadBuffer.Length(); + WSP_LOG(WspLog::Printf(_L("\t %d bytes received"), receivedBytes)); + if (iSocket) + { + if (receivedBytes) + { + iSocket->NewData(receivedBytes); + } + else + { + iSocket->NewData(KNewDataEndofData); + } + } + } + break; + } + case MWin32SocketObserver::EAccept: + { + WSP_LOG(WspLog::Printf(_L("CWinSockTcpProvider::HandleWin32SocketCompletion: EAccept, error: %d"), aError)); + iAcceptSap->StartReceive(); + CWinSockProviderBase& acceptSap = *iAcceptSap; + iAcceptSap = NULL; // This pointer will be reused when our HandleListeningSapStarted gets, which may be as a result of the next CSocket::ConnectComplete call. + iSocket->ConnectComplete(acceptSap); + break; + } + case MWin32SocketObserver::ESendTo: + case MWin32SocketObserver::EReceiveFrom: + default: + { + __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtInvalidTcpSocketRequestType)); + } + } + } + +void CWinSockTcpProvider::DoPassiveOpenL(TUint aQue) + { + __ASSERT_DEBUG(iAcceptSap == NULL, Panic(EWinSockPrtCWinSockTcpProviderDoPassiveOpenLAcceptSapNotNull)); + CWinSockTcpProvider* acceptSap = CWinSockTcpProvider::NewBlankLC(iWin32Factory); + acceptSap->SetListeningSap(*this); + User::LeaveIfError(iWin32Socket.Listen(aQue)); + User::LeaveIfError(iAcceptSocketWrapper->Accept(acceptSap->iWin32Socket)); + CleanupStack::Pop(acceptSap); + iAcceptSap = acceptSap; + } + +void CWinSockTcpProvider::StartReceive() + { + iWinSockWriteBuffer.Zero(); + iReceiveSocketWrapper->Receive(iWinSockWriteBuffer); + } + +void CWinSockTcpProvider::SetListeningSap(CWinSockTcpProvider& aListeningSap) + { + __ASSERT_DEBUG(iListeningSap == NULL, Panic(EWinSockPrtCWinSockTcpProviderSetListeningSapAlreadySet)); + iListeningSap = &aListeningSap; + } + +void CWinSockTcpProvider::HandleListeningSapStarted() + { + __ASSERT_DEBUG(iAcceptSap == NULL, Panic(EWinSockPrtCWinSockTcpProviderStartAcceptSapNotNull)); + CWinSockTcpProvider* acceptSap = CWinSockTcpProvider::NewBlankLC(iWin32Factory); + acceptSap->SetListeningSap(*this); + User::LeaveIfError(iAcceptSocketWrapper->Accept(acceptSap->iWin32Socket)); + CleanupStack::Pop(acceptSap); + iAcceptSap = acceptSap; + } + + +// +// CWinSockUdpProvider. +// + +CWinSockUdpProvider* CWinSockUdpProvider::NewL(RWin32Factory& aWin32Factory) + { + CWinSockUdpProvider* self = new(ELeave) CWinSockUdpProvider(aWin32Factory); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +TInt CWinSockUdpProvider::SetLocalName(TSockAddr& anAddr) + { + TInt err = CWinSockProviderBase::SetLocalName(anAddr); + if (err == KErrNone) + { + iReceiveSocketWrapper->ReceiveFrom(iWinSockWriteBuffer, iReceiveFromAddress); + } + return err; + } + +void CWinSockUdpProvider::RemName(TSockAddr& anAddr) const + { + anAddr = iRemoteAddr; + } + +TUint CWinSockUdpProvider::Write(const TDesC8& aDesc, TUint /*options*/, TSockAddr* anAddr) + { + WSP_LOG(WspLog::Printf(_L("CWinSockUdpProvider::Write: writing %d bytes"), aDesc.Length())); + WSP_RAW_LOG(WspLog::WriteRawOutbound(aDesc)); + if (iSendSocketWrapper->IsActive()) + { + return 0; + } + TInt err = FillSendBuffer(aDesc); + if (err) + { + iSocket->Error(err, MSocketNotify::EErrorSend); + return 0; + } + if (anAddr) + { + iSendSocketWrapper->SendTo(*iSendBuffer, *anAddr); + } + else + { + iSendSocketWrapper->SendTo(*iSendBuffer, iRemoteAddr); + } + return iSendBuffer->Length(); + } + +void CWinSockUdpProvider::GetData(TDes8 &aDesc, TUint /*aOptions*/, TSockAddr* anAddr) + { + WSP_LOG(WspLog::Write(_L("CWinSockUdpProvider::GetData"))); + TInt esockBufferSize = aDesc.Length(); + if (esockBufferSize >= iEsockReadBuffer.Length()) + { + WSP_LOG(WspLog::Printf(_L("\tCopying all %d bytes up to ESock"), iEsockReadBuffer.Length())); + aDesc.Copy(iEsockReadBuffer); + } + else + { + WSP_LOG(WspLog::Printf(_L("\tESock buffer size: %d, available data: %d"), esockBufferSize, iEsockReadBuffer.Length())); + aDesc.Copy(iEsockReadBuffer.Left(esockBufferSize)); // Throw away remainder. + } + + WSP_RAW_LOG(WspLog::WriteRawInbound(aDesc)); + + if (anAddr) + { + anAddr->Copy(iReceiveFromAddress); + } + iWinSockWriteBuffer.Zero(); + iReceiveSocketWrapper->ReceiveFrom(iWinSockWriteBuffer, iReceiveFromAddress); + } + +void CWinSockUdpProvider::Start() + { + } + +void CWinSockUdpProvider::ActiveOpen(void) + { + __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtCWinSockUdpProviderActiveOpenUnexpectedCall)); + } + +TInt CWinSockUdpProvider::PassiveOpen(TUint /*aQue*/) + { + __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtCWinSockUdpProviderPassiveOpenUnexpectedCall)); + return 0; + } + +void CWinSockUdpProvider::HandleWin32SocketCompletion(TRequestType aRequestType, TInt aError) + { + switch (aRequestType) + { + case MWin32SocketObserver::ESendTo: + { + WSP_LOG(WspLog::Printf(_L("CWinSockUdpProvider::HandleWin32SocketCompletion: ESendTo, error: %d"), aError)); + if (aError) + { + iSocket->Error(aError, MSocketNotify::EErrorSend); + } + else + { + iSocket->CanSend(); + } + break; + } + case MWin32SocketObserver::EReceiveFrom: + { + WSP_LOG(WspLog::Printf(_L("CWinSockUdpProvider::HandleWin32SocketCompletion: EReceiveFrom, error: %d"), aError)); + if (aError) + { + iSocket->Error(aError, MSocketNotify::EErrorRecv); + } + else + { + iEsockReadBuffer.Set(iWinSockWriteBuffer); + WSP_LOG(WspLog::Printf(_L("\t %d bytes received"), iEsockReadBuffer.Length())); + iSocket->NewData(1); + } + break; + } + case MWin32SocketObserver::EConnect: + case MWin32SocketObserver::ESend: + case MWin32SocketObserver::EReceive: + case MWin32SocketObserver::EAccept: + default: + { + __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtInvalidUdpSocketRequestType)); + } + } + } + +CWinSockUdpProvider::~CWinSockUdpProvider() + { + } + +CWinSockUdpProvider::CWinSockUdpProvider(RWin32Factory& aWin32Factory) + : CWinSockProviderBase(aWin32Factory) + { + } + +void CWinSockUdpProvider::ConstructL() + { + User::LeaveIfError(iWin32Socket.Open(iWin32Factory, RWin32Socket::EUdp)); + CWinSockProviderBase::ConstructL(); + }