diff -r 000000000000 -r 7f656887cf89 plugins/networking/winsockprt/src/wsp_socket.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/networking/winsockprt/src/wsp_socket.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,1072 @@ +// wsp_socket.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 +#include "wsp_socket.h" +#include "wsp_session.h" +#include "wsp_factory.h" +#include "wsp_panic.h" +#include "wsp_log.h" +#undef SetPort // Defined the Microsoft header "winspool.h". +#include + +// +// RWin32Socket. +// + +TInt RWin32Socket::Open(RWin32Factory& aFactory, TType aType) + { + WSP_LOG(WspLog::Printf(_L("RWin32Socket::Open: aType: %d, this: 0x%x"), aType, this)); + TPckgC typePckg(aType); + return CreateSubSession(aFactory, CWin32Factory::ENewSocket, typePckg); + } + +void RWin32Socket::Close() + { + WSP_LOG(WspLog::Printf(_L("RWin32Socket::Close: this: 0x%x"), this)); + RWin32SubSession::Close(); + } + +TInt RWin32Socket::Connect(const TInetAddr& aAddress, TRequestStatus& aStatus) + { + WSP_LOG(WspLog::Printf(_L("RWin32Socket::Connect: this: 0x%x"), this)); + iWin32Message.Set(CWin32Socket::EConnect, aAddress, aStatus); + return MakeRequest(iWin32Message); + } + +TInt RWin32Socket::Send(const TDesC8& aSendBuffer, TRequestStatus& aStatus) + { + WSP_LOG(WspLog::Printf(_L("RWin32Socket::Send: this: 0x%x, bytes to send: %d"), this, aSendBuffer.Length())); + iWin32Message.Set(CWin32Socket::ESend, aSendBuffer, aStatus); + return MakeRequest(iWin32Message); + } + +TInt RWin32Socket::SendTo(const TDesC8& aSendBuffer, const TInetAddr& aAddress, TRequestStatus& aStatus) + { + WSP_LOG(WspLog::Printf(_L("RWin32Socket::SendTo: this: 0x%x, bytes to send: %d"), this, aSendBuffer.Length())); + TPtr8 addressPtr(const_cast(aAddress.Ptr()), aAddress.Length(), aAddress.MaxLength()); // Slight hack - need to send two read buffers, but the framework doesn't support this, so send the address as a write buffer. + iWin32Message.Set(CWin32Socket::ESendTo, aSendBuffer, addressPtr, aStatus); + return MakeRequest(iWin32Message); + } + +TInt RWin32Socket::Receive(TDes8& aReceiveBuffer, TRequestStatus& aStatus) + { + WSP_LOG(WspLog::Printf(_L("RWin32Socket::Receive: this: 0x%x, bytes to receive: %d"), this, aReceiveBuffer.Length())); + iWin32Message.Set(CWin32Socket::EReceive, aReceiveBuffer, aStatus); + return MakeRequest(iWin32Message); + } + +TInt RWin32Socket::ReceiveFrom(TDes8& aReceiveBuffer, TInetAddr& aAddress, TRequestStatus& aStatus) + { + WSP_LOG(WspLog::Printf(_L("RWin32Socket::ReceiveFrom: this: 0x%x, bytes to receive: %d"), this, aReceiveBuffer.Length())); + TPtrC8 addressPtr((TUint8*)&aAddress, 0); // Slight hack - need to send two write buffers, but the framework doesn't support this, so send the address as a read buffer. + iWin32Message.Set(CWin32Socket::EReceiveFrom, addressPtr, aReceiveBuffer, aStatus); + return MakeRequest(iWin32Message); + } + +void RWin32Socket::CancelConnect() + { + TWin32Message cancelWin32Message; + cancelWin32Message.Set(CWin32Socket::ECancelConnect); + MakeRequest(cancelWin32Message); // Throw away return code - can't do anything useful with it. + } + +void RWin32Socket::CancelSend() + { + TWin32Message cancelWin32Message; + cancelWin32Message.Set(CWin32Socket::ECancelSend); + MakeRequest(cancelWin32Message); // Throw away return code - can't do anything useful with it. + } + +void RWin32Socket::CancelSendTo() + { + TWin32Message cancelWin32Message; + cancelWin32Message.Set(CWin32Socket::ECancelSendTo); + MakeRequest(cancelWin32Message); // Throw away return code - can't do anything useful with it. + } + +void RWin32Socket::CancelReceive() + { + TWin32Message cancelWin32Message; + cancelWin32Message.Set(CWin32Socket::ECancelReceive); + MakeRequest(cancelWin32Message); // Throw away return code - can't do anything useful with it. + } + +void RWin32Socket::CancelReceiveFrom() + { + TWin32Message cancelWin32Message; + cancelWin32Message.Set(CWin32Socket::ECancelReceiveFrom); + MakeRequest(cancelWin32Message); // Throw away return code - can't do anything useful with it. + } + +TInt RWin32Socket::GetSocketName(TInetAddr& aAddress) const + { + WSP_LOG(WspLog::Printf(_L("RWin32Socket::GetSocketName: this: 0x%x"), this)); + TRequestStatus status; + iWin32Message.Set(CWin32Socket::EGetSocketName, aAddress, status); + TInt err = MakeRequest(iWin32Message); + if (err) + { + return err; + } + else + { + User::WaitForRequest(status); + return status.Int(); + } + } + +TInt RWin32Socket::Bind(const TInetAddr& aAddress) + { + WSP_LOG(WspLog::Printf(_L("RWin32Socket::Bind: this: 0x%x"), this)); + TRequestStatus status; + iWin32Message.Set(CWin32Socket::EBind, aAddress, status); + TInt err = MakeRequest(iWin32Message); + if (err) + { + return err; + } + else + { + User::WaitForRequest(status); + return status.Int(); + } + } + +TInt RWin32Socket::GetPeerName(TInetAddr& aAddress) const + { + WSP_LOG(WspLog::Printf(_L("RWin32Socket::GetPeerName: this: 0x%x"), this)); + TRequestStatus status; + iWin32Message.Set(CWin32Socket::EGetPeerName, aAddress, status); + TInt err = MakeRequest(iWin32Message); + if (err) + { + return err; + } + else + { + User::WaitForRequest(status); + return status.Int(); + } + } + +TInt RWin32Socket::Listen(TUint aQueueSize) + { + WSP_LOG(WspLog::Printf(_L("RWin32Socket::Listen: this: 0x%x"), this)); + TPckgC queueSizePckg(aQueueSize); + TRequestStatus status; + iWin32Message.Set(CWin32Socket::EListen, queueSizePckg, status); + TInt err = MakeRequest(iWin32Message); + if (err) + { + return err; + } + else + { + User::WaitForRequest(status); + return status.Int(); + } + } + +TInt RWin32Socket::Accept(RWin32Socket& aNewSocket, TRequestStatus& aStatus) + { + WSP_LOG(WspLog::Printf(_L("RWin32Socket::Accept: this: 0x%x"), this)); + TPckgC newSocketHandlePckg(aNewSocket.iHandle); + iWin32Message.Set(CWin32Socket::EAccept, newSocketHandlePckg, aStatus); + return MakeRequest(iWin32Message); + } + +void RWin32Socket::CancelAccept() + { + TWin32Message cancelWin32Message; + cancelWin32Message.Set(CWin32Socket::ECancelAccept); + MakeRequest(cancelWin32Message); // Throw away return code - can't do anything useful with it. + } + +class TWin32SocketOptionsC + { +public: + TInt aLevel; + TInt aName; + const char* aValue; + TInt aLength; + }; + +class TWin32SocketOptions + { +public: + TInt aLevel; + TInt aName; + char* aValue; + TInt* aLength; + }; + +TInt RWin32Socket::GetOption(TInt aLevel, TInt aName, char* aValue, TInt* aLength) const + { + WSP_LOG(WspLog::Printf(_L("RWin32Socket::GetOption: this: 0x%x"), this)); + TWin32SocketOptions options = {aLevel, aName, aValue, aLength}; + TPckg optionsPckg(options); + TRequestStatus status; + iWin32Message.Set(CWin32Socket::EGetOption, optionsPckg, status); + TInt err = MakeRequest(iWin32Message); + if (err) + { + return err; + } + else + { + User::WaitForRequest(status); + return status.Int(); + } + } + +TInt RWin32Socket::SetOption(TInt aLevel, TInt aName, const char* aValue, TInt aLength) + { + WSP_LOG(WspLog::Printf(_L("RWin32Socket::SetOption: this: 0x%x"), this)); + TWin32SocketOptionsC options = {aLevel, aName, aValue, aLength}; + TPckgC optionsPckg(options); + TRequestStatus status; + iWin32Message.Set(CWin32Socket::ESetOption, optionsPckg, status); + TInt err = MakeRequest(iWin32Message); + if (err) + { + return err; + } + else + { + User::WaitForRequest(status); + return status.Int(); + } + } + +// +// CWin32Socket. +// + +CWin32Socket* CWin32Socket::NewL(CWin32Scheduler& aScheduler, RWin32Socket::TType aType) + { + CWin32Socket* self = new(ELeave) CWin32Socket(aScheduler, aType); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CWin32Socket::CWin32Socket(CWin32Scheduler& aScheduler, RWin32Socket::TType aType) + : CWin32SubSession(aScheduler), iType(aType) + { + } + +void CWin32Socket::ConstructL() + { + CWin32SubSession::ConstructL(); + + switch (iType) + { + case RWin32Socket::EBlank: + { + // Nothing to do. + break; + } + case RWin32Socket::ETcp: + { + __ASSERT_DEBUG(iSocket == 0, Panic(EWinSockPrtCWin32SocketCreateSocketUnexpectedValidSocket)); + Emulator::Lock(); + iSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, NULL, WSA_FLAG_OVERLAPPED); + Emulator::Unlock(); + if (iSocket == INVALID_SOCKET) + { + User::Leave(MapWinSockError(WSAGetLastError())); + } + break; + } + case RWin32Socket::EUdp: + { + __ASSERT_DEBUG(iSocket == 0, Panic(EWinSockPrtCWin32SocketCreateSocketUnexpectedValidSocket)); + Emulator::Lock(); + iSocket = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, NULL, WSA_FLAG_OVERLAPPED); + Emulator::Unlock(); + if (iSocket == INVALID_SOCKET) + { + User::Leave(MapWinSockError(WSAGetLastError())); + } + break; + } + default: + { + __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtCWin32SocketConstructLInvalidSocketType)); + } + } + } + +CWin32Socket::~CWin32Socket() + { + CloseSocket(); + } + +void CWin32Socket::ServiceL(TWin32Message& aMessage) + { + switch (aMessage.OppCode()) + { + case EConnect: + { + Connect(aMessage); + break; + } + case ECancelConnect: + { + if (iConnectMessage) + { + Complete(iConnectMessage, KErrCancel); + } + break; + } + case ESend: + { + Send(aMessage); + break; + } + case ECancelSend: + { + if (iSendMessage) + { + Complete(iSendMessage, KErrCancel); + } + break; + } + case ESendTo: + { + SendTo(aMessage); + break; + } + case ECancelSendTo: + { + if (iSendMessage) + { + Complete(iSendMessage, KErrCancel); + } + break; + } + case EReceive: + { + Receive(aMessage); + break; + } + case ECancelReceive: + { + if (iReceiveMessage) + { + Complete(iReceiveMessage, KErrCancel); + } + break; + } + case EReceiveFrom: + { + ReceiveFrom(aMessage); + break; + } + case ECancelReceiveFrom: + { + if (iReceiveMessage) + { + Complete(iReceiveMessage, KErrCancel); + } + break; + } + case EGetSocketName: + { + GetSocketName(aMessage); + break; + } + case EBind: + { + Bind(aMessage); + break; + } + case EGetPeerName: + { + GetPeerName(aMessage); + break; + } + case EListen: + { + Listen(aMessage); + break; + } + case EAccept: + { + Accept(aMessage); + break; + } + case ECancelAccept: + { + if (iAcceptMessage) + { + Complete(iAcceptMessage, KErrCancel); + } + break; + } + case EGetOption: + { + GetOption(aMessage); + break; + } + case ESetOption: + { + SetOption(aMessage); + break; + } + default: + { + __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtInvalidSocketOppCode)); + } + } + } + +void CWin32Socket::Connect(TWin32Message& aMessage) + { + __ASSERT_DEBUG(iConnectMessage == NULL, Panic(EWinSockPrtCWin32SocketMultipleConnectRequests)); + iConnectMessage = &aMessage; + WSP_LOG(WspLog::Printf(_L("CWin32Socket::Connect: this: 0x%x"), this)); + + if (WSAEventSelect(iSocket, iEvent, FD_CONNECT) == SOCKET_ERROR) + { + TInt err = MapWinSockError(WSAGetLastError()); + CloseSocket(); + Complete(iConnectMessage, err); + return; + } + + const TInetAddr& address = static_cast(iConnectMessage->ReadBuffer()); + SOCKADDR_IN winSockAddress; + ConvertAddress(address, winSockAddress); + + if (WSAConnect(iSocket, (LPSOCKADDR)&winSockAddress, sizeof(struct sockaddr_in), NULL, NULL, NULL, NULL) == SOCKET_ERROR) + { + TInt nError = WSAGetLastError(); + if (nError != WSAEWOULDBLOCK) + { + CloseSocket(); + Complete(iConnectMessage, MapWinSockError(nError)); + } + } + else + { + Complete(iConnectMessage, KErrNone); + } + } + +void CWin32Socket::Send(TWin32Message& aMessage) + { + __ASSERT_DEBUG((iSendMessage == NULL) && (iBytesSent == 0), Panic(EWinSockPrtCWin32SocketMultipleSendRequests)); + iSendMessage = &aMessage; + WSP_LOG(WspLog::Printf(_L("CWin32Socket::Send: this: 0x%x, bytes to send: %d"), this, iSendMessage->ReadBuffer().Length())); + DoSend(); + } + +void CWin32Socket::SendTo(TWin32Message& aMessage) + { + __ASSERT_DEBUG((iSendMessage == NULL) && (iBytesSent == 0), Panic(EWinSockPrtCWin32SocketMultipleSendToRequests)); + iSendMessage = &aMessage; + WSP_LOG(WspLog::Printf(_L("CWin32Socket::SendTo: this: 0x%x, bytes to send: %d"), this, iSendMessage->ReadBuffer().Length())); + TPtrC8 bufPtr(iSendMessage->ReadBuffer()); + iSendBuffer.buf = reinterpret_cast(const_cast(bufPtr.Ptr())); + iSendBuffer.len = bufPtr.Length(); + iSendOverlapped.hEvent = (void*) this; + TInetAddr address; + address.Copy(iSendMessage->WriteBuffer()); + SOCKADDR_IN winSockAddress; + ConvertAddress(address, winSockAddress); + DWORD numberOfBytesSent; + TInt ret = WSASendTo(iSocket, &iSendBuffer, 1, &numberOfBytesSent, 0, (LPSOCKADDR)&winSockAddress, sizeof(struct sockaddr_in), &iSendOverlapped, &SendToCompletion); + if (ret == SOCKET_ERROR) + { + TInt err = WSAGetLastError(); + if (err != WSA_IO_PENDING) + { + WSP_LOG(WspLog::Printf(_L("\tsocket error: %d"), err)); + Complete(iSendMessage, MapWinSockError(err)); + } + } + } + +void CWin32Socket::Receive(TWin32Message& aMessage) + { + __ASSERT_DEBUG(iReceiveMessage == NULL, Panic(EWinSockPrtCWin32SocketMultipleReceiveRequests)); + iReceiveMessage = &aMessage; + WSP_LOG(WspLog::Printf(_L("CWin32Socket::Receive: this: 0x%x, bytes to get: %d"), this, iReceiveMessage->WriteBuffer().MaxLength())); + iReceiveBuffer.buf = reinterpret_cast(const_cast(iReceiveMessage->WriteBuffer().Ptr())); + iReceiveBuffer.len = iReceiveMessage->WriteBuffer().MaxLength(); + iFlags = 0; + iReceiveOverlapped.hEvent = (void*) this; + DWORD numberOfBytesReceived; + TInt ret = WSARecv(iSocket, &iReceiveBuffer, 1, &numberOfBytesReceived, &iFlags, &iReceiveOverlapped, &ReceiveCompletion); + if (ret == SOCKET_ERROR) + { + TInt err = WSAGetLastError(); + if (err != WSA_IO_PENDING) + { + WSP_LOG(WspLog::Printf(_L("\tsocket error: %d"), err)); + Complete(iReceiveMessage, MapWinSockError(err)); + } + } + } + +void CWin32Socket::ReceiveFrom(TWin32Message& aMessage) + { + __ASSERT_DEBUG(iReceiveMessage == NULL, Panic(EWinSockPrtCWin32SocketMultipleReceiveFromRequests)); + iReceiveMessage = &aMessage; + WSP_LOG(WspLog::Printf(_L("CWin32Socket::ReceiveFrom: this: 0x%x, bytes to get: %d"), this, iReceiveMessage->WriteBuffer().MaxLength())); + iReceiveBuffer.buf = reinterpret_cast(const_cast(iReceiveMessage->WriteBuffer().Ptr())); + iReceiveBuffer.len = iReceiveMessage->WriteBuffer().MaxLength(); + iFlags = 0; + iReceiveOverlapped.hEvent = (void*) this; + iReceiveFromAddressLength = sizeof(struct sockaddr_in); + iReceiveFromClientAddress = (TInetAddr*)iReceiveMessage->ReadBuffer().Ptr(); + DWORD numberOfBytesReceived; + TInt ret = WSARecvFrom(iSocket, &iReceiveBuffer, 1, &numberOfBytesReceived, &iFlags, (LPSOCKADDR)&iReceiveFromAddress, &iReceiveFromAddressLength, &iReceiveOverlapped, &ReceiveFromCompletion); + if (ret == SOCKET_ERROR) + { + TInt err = WSAGetLastError(); + if (err != WSA_IO_PENDING) + { + WSP_LOG(WspLog::Printf(_L("\tsocket error: %d"), err)); + Complete(iReceiveMessage, MapWinSockError(err)); + } + } + } + +void CWin32Socket::GetSocketName(TWin32Message& aMessage) const + { + SOCKADDR_IN winSockAddress; + TInt length = sizeof(struct sockaddr_in); + if (getsockname(iSocket, (LPSOCKADDR)&winSockAddress, &length)) + { + aMessage.Complete(MapWinSockError(WSAGetLastError())); + } + else + { + __ASSERT_DEBUG(length == sizeof(struct sockaddr_in), Panic(EWinSockPrtCWin32SocketGetSocketNameInvalidSocketAddress)); + TInetAddr& address = static_cast(aMessage.WriteBuffer()); + ConvertAddress(winSockAddress, address); + aMessage.Complete(KErrNone); + } + } + +void CWin32Socket::Bind(TWin32Message& aMessage) + { + const TInetAddr& address = static_cast(aMessage.ReadBuffer()); + SOCKADDR_IN winSockAddress; + ConvertAddress(address, winSockAddress); + if (bind(iSocket, (LPSOCKADDR)&winSockAddress, sizeof(struct sockaddr_in))) + { + aMessage.Complete(MapWinSockError(WSAGetLastError())); + } + else + { + aMessage.Complete(KErrNone); + } + } + +void CWin32Socket::GetPeerName(TWin32Message& aMessage) const + { + SOCKADDR_IN winSockAddress; + TInt length = sizeof(struct sockaddr_in); + if (getpeername(iSocket, (LPSOCKADDR)&winSockAddress, &length)) + { + aMessage.Complete(MapWinSockError(WSAGetLastError())); + } + else + { + __ASSERT_DEBUG(length == sizeof(struct sockaddr_in), Panic(EWinSockPrtCWin32SocketGetPeerNameInvalidSocketAddress)); + TInetAddr& address = static_cast(aMessage.WriteBuffer()); + ConvertAddress(winSockAddress, address); + aMessage.Complete(KErrNone); + } + } + +void CWin32Socket::Listen(TWin32Message& aMessage) + { + TPckgBuf queueSizeBuf; + queueSizeBuf.Copy(aMessage.ReadBuffer()); + TUint& queueSize = queueSizeBuf(); + if (listen(iSocket, queueSize)) + { + aMessage.Complete(MapWinSockError(WSAGetLastError())); + } + else + { + aMessage.Complete(KErrNone); + } + } + +void CWin32Socket::Accept(TWin32Message& aMessage) + { + __ASSERT_DEBUG(iAcceptMessage == NULL, Panic(EWinSockPrtCWin32SocketMultipleAcceptRequests)); + __ASSERT_DEBUG(iBlankAcceptSocket == NULL, Panic(EWinSockPrtCWin32SocketAcceptBlankSocketNotNull)); + iAcceptMessage = &aMessage; + WSP_LOG(WspLog::Printf(_L("CWin32Socket::Accept: this: 0x%x"), this)); + if (WSAEventSelect(iSocket, iEvent, FD_ACCEPT) == SOCKET_ERROR) + { + Complete(iAcceptMessage, MapWinSockError(WSAGetLastError())); + } + TPckgBuf newSocketHandleBuf; + newSocketHandleBuf.Copy(iAcceptMessage->ReadBuffer()); + iBlankAcceptSocket = (CWin32Socket*)newSocketHandleBuf(); + } + +void CWin32Socket::GetOption(TWin32Message& aMessage) const + { + __ASSERT_DEBUG(aMessage.WriteBuffer().Length() == sizeof(TWin32SocketOptions), EWinSockPrtCWin32SocketGetOptionInvalidParameters); + TWin32SocketOptions* options = reinterpret_cast(const_cast(aMessage.WriteBuffer().Ptr())); + TInt err = getsockopt(iSocket, options->aLevel, options->aName, options->aValue, options->aLength); + TWin32Message* messagePrt = &aMessage; + if (err) + { + Complete(messagePrt, MapWinSockError(WSAGetLastError())); + } + else + { + Complete(messagePrt, KErrNone); + } + } + +void CWin32Socket::SetOption(TWin32Message& aMessage) + { + __ASSERT_DEBUG(aMessage.ReadBuffer().Length() == sizeof(TWin32SocketOptionsC), EWinSockPrtCWin32SocketSetOptionInvalidParameters); + const TWin32SocketOptionsC* options = reinterpret_cast(aMessage.ReadBuffer().Ptr()); + TInt err = setsockopt(iSocket, options->aLevel, options->aName, options->aValue, options->aLength); + TWin32Message* messagePrt = &aMessage; + if (err) + { + Complete(messagePrt, MapWinSockError(WSAGetLastError())); + } + else + { + Complete(messagePrt, KErrNone); + } + } + +void CWin32Socket::DoSend() + { + WSP_LOG(WspLog::Printf(_L("CWin32Socket::DoSend: this: 0x%x, bytes to send: %d"), this, iSendMessage->ReadBuffer().Length() - iBytesSent)); + TPtrC8 bufPtr(iSendMessage->ReadBuffer()); + iSendBuffer.buf = reinterpret_cast(const_cast(bufPtr.Ptr())) + iBytesSent; + iSendBuffer.len = bufPtr.Length() - iBytesSent; + iSendOverlapped.hEvent = (void*) this; + DWORD numberOfBytesSent; + Emulator::Lock(); + TInt ret = WSASend(iSocket, &iSendBuffer, 1, &numberOfBytesSent, 0, &iSendOverlapped, &SendCompletion); + Emulator::Unlock(); + if (ret == SOCKET_ERROR) + { + Emulator::Lock(); + TInt err = WSAGetLastError(); + Emulator::Unlock(); + if (err != WSA_IO_PENDING) + { + WSP_LOG(WspLog::Printf(_L("\tsocket error: %d"), err)); + Complete(iSendMessage, MapWinSockError(err)); + } + } + } + +void CWin32Socket::CloseSocket() + { + WSP_LOG(WspLog::Printf(_L("CWin32Socket::CloseSocket: this: 0x%x"), this)); + if (iSocket != INVALID_SOCKET) + { + closesocket(iSocket); + iSocket = INVALID_SOCKET; + } + } + +void CWin32Socket::Run() + { + WSP_LOG(WspLog::Printf(_L("CWin32Socket::Run: this: 0x%x"), this)); + WSANETWORKEVENTS eventStatus; + if (WSAEnumNetworkEvents(iSocket, iEvent, &eventStatus) == 0) + { + if (eventStatus.lNetworkEvents & FD_CONNECT) + { + HandleConnectionComplete(MapWinSockError(eventStatus.iErrorCode[FD_CONNECT_BIT])); + } + else if (eventStatus.lNetworkEvents & FD_ACCEPT) + { + HandleAcceptReady(MapWinSockError(eventStatus.iErrorCode[FD_ACCEPT_BIT])); + } + else + { + __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtUnexpectedWSANetworkEvent)); + } + } + else + { + __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtUnexpectedWSAEnumNetworkEventsError)); + } + } + +void CWin32Socket::HandleConnectionComplete(TInt aError) + { + ReleaseEventHandle(); // No longer needed because all further asynchronous I/O is done using overlapped buffer callbacks. + if (iConnectMessage) // May have been cancelled. + { + Complete(iConnectMessage, aError); + } + } + +void CWin32Socket::HandleAcceptReady(TInt aError) + { + if (aError) + { + Complete(iAcceptMessage, aError); + } + else + { + if (iAcceptMessage) // May have been cancelled. + { + iBlankAcceptSocket->iSocket = WSAAccept(iSocket, NULL, NULL, NULL, 0); + if (iBlankAcceptSocket->iSocket == INVALID_SOCKET) + { + Complete(iAcceptMessage, MapWinSockError(WSAGetLastError())); + } + else + { + Complete(iAcceptMessage, KErrNone); + } + } + + iBlankAcceptSocket = NULL; + if (WSAEventSelect(iSocket, iEvent, 0) == SOCKET_ERROR) + { + __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtCWin32SocketHandleAcceptReadyUnexpectedEventSelectError)); + } + } + } + +void CALLBACK CWin32Socket::SendCompletion(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD /*dwFlags*/) + { + Emulator::Reenter(); // This is a win32 callback so we're outside of the emulator at this point + WSP_LOG(WspLog::Printf(_L("CWin32Socket::SendCompletion: error: %d, object: 0x%x"), dwError, lpOverlapped->hEvent)); + switch (dwError) + { + case 0: + { + CWin32Socket* socket = reinterpret_cast(lpOverlapped->hEvent); + if (socket && socket->iSendMessage) // May have been cancelled. + { + socket->iBytesSent += cbTransferred; + if (socket->iBytesSent < socket->iSendMessage->ReadBuffer().Length()) + { + socket->DoSend(); + } + else + { + socket->Complete(socket->iSendMessage, KErrNone); + socket->iBytesSent = 0; + } + } + break; + } + case WSAEINVAL: + { + // Ignore - probably a completion on a closed socket due to cancellation. + break; + } + case WSAECONNRESET: + { + // Ignore - remote host has terminated the connection. + } + default: + { + __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtUnexpectedWSASendCompletionError)); + } + } + Emulator::Escape(); // And return to how we were + } + +void CALLBACK CWin32Socket::SendToCompletion(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD /*dwFlags*/) + { + Emulator::Reenter(); // This is a win32 callback so we're outside of the emulator at this point + WSP_LOG(WspLog::Printf(_L("CWin32Socket::SendToCompletion: error: %d, object: 0x%x"), dwError, lpOverlapped->hEvent)); + switch (dwError) + { + case 0: + { + CWin32Socket* socket = reinterpret_cast(lpOverlapped->hEvent); + if (socket->iSendMessage) // May have been cancelled. + { + __ASSERT_DEBUG(cbTransferred == (TUint)socket->iSendMessage->ReadBuffer().Length(), Panic(EWinSockPrtCWin32SocketSendToCompletionAllDataNotSent)); + socket->Complete(socket->iSendMessage, KErrNone); + } + break; + } + case WSAEINVAL: + { + // Ignore - probably a completion on a closed socket due to cancellation. + break; + } + default: + { + __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtUnexpectedWSASendToCompletionError)); + } + } + Emulator::Escape(); // And return to how we were + } + +void CALLBACK CWin32Socket::ReceiveCompletion(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD /*dwFlags*/) + { + if (dwError == WSAEINVAL) + { + // Ignore - probably a completion on a closed socket due to cancellation. + // Also, might not be a valid context from which to call Emulator::Reenter(). + return; + } + + Emulator::Reenter(); // This is a win32 callback so we're outside of the emulator at this point + WSP_LOG(WspLog::Printf(_L("CWin32Socket::ReceiveCompletion: error: %d, object: 0x%x"), dwError, lpOverlapped->hEvent)); + switch (dwError) + { + case 0: + { + CWin32Socket* socket = reinterpret_cast(lpOverlapped->hEvent); + if (socket && socket->iReceiveMessage) // May have been cancelled. + { + socket->iReceiveMessage->WriteBuffer().SetLength(cbTransferred); + socket->Complete(socket->iReceiveMessage, KErrNone); + } + break; + } + case WSAECONNRESET: + { + // Remote host has reset the connection. + // Ignore - seen these after Opera gets asked to receive a cookie. + break; + } + default: + { + __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtUnexpectedWSAReceiveCompletionError)); + } + } + Emulator::Escape(); // And return to how we were + } + +void CALLBACK CWin32Socket::ReceiveFromCompletion(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD /*dwFlags*/) + { + Emulator::Reenter(); // This is a win32 callback so we're outside of the emulator at this point + WSP_LOG(WspLog::Printf(_L("CWin32Socket::ReceiveFromCompletion: error: %d, object: 0x%x"), dwError, lpOverlapped->hEvent)); + switch (dwError) + { + case 0: + { + CWin32Socket* socket = reinterpret_cast(lpOverlapped->hEvent); + if (socket && socket->iReceiveMessage) // May have been cancelled. + { + socket->iReceiveMessage->WriteBuffer().SetLength(cbTransferred); + __ASSERT_DEBUG(socket->iReceiveFromAddressLength == sizeof(struct sockaddr_in), Panic(EWinSockPrtCWin32SocketReceiveFromCompletionInvalidAddressLength)); + TInetAddr address; + socket->ConvertAddress(socket->iReceiveFromAddress, address); + socket->iReceiveFromClientAddress->Copy(address); + socket->iReceiveFromClientAddress = NULL; + socket->Complete(socket->iReceiveMessage, KErrNone); + } + break; + } + case WSAEINVAL: + { + // Ignore - probably a completion on a closed socket due to cancellation. + break; + } + case WSAECONNRESET: + { + // Remote host has reset the connection. + // Ignore - seen these after Opera gets asked to receive a cookie. + break; + } + default: + { + __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtUnexpectedWSAReceiveCompletionError)); + } + } + Emulator::Escape(); // And return to how we were + } + +void CWin32Socket::ConvertAddress(const TInetAddr& aESockAddress, SOCKADDR_IN& aWinSockAddress) const + { + aWinSockAddress.sin_family = AF_INET; + aWinSockAddress.sin_addr.s_addr = htonl(aESockAddress.Address()); + aWinSockAddress.sin_port = htons(static_cast(aESockAddress.Port())); + } + +void CWin32Socket::ConvertAddress(const SOCKADDR_IN& aWinSockAddress, TInetAddr& aESockAddress) const + { + aESockAddress.SetAddress(htonl(aWinSockAddress.sin_addr.s_addr)); + aESockAddress.SetPort(htons(aWinSockAddress.sin_port)); + } + + + +// +// CWin32SocketWrapper. +// + +CWin32SocketWrapper* CWin32SocketWrapper::NewL(MWin32SocketObserver& aObserver, RWin32Socket& aWin32Socket) + { + CWin32SocketWrapper* self = new(ELeave) CWin32SocketWrapper(aObserver, aWin32Socket); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CWin32SocketWrapper::~CWin32SocketWrapper() + { + Cancel(); + } + +CWin32SocketWrapper::CWin32SocketWrapper(MWin32SocketObserver& aObserver, RWin32Socket& aWin32Socket) + : CActive(CActive::EPriorityStandard), iObserver(aObserver), iWin32Socket(aWin32Socket) + { + } + +void CWin32SocketWrapper::ConstructL() + { + CActiveScheduler::Add(this); + } + +TInt CWin32SocketWrapper::Connect(const TInetAddr& aAddress) + { + __ASSERT_DEBUG(!IsActive(), Panic(EWinSockPrtSocketWrapperConnectWhilstActive)); + iRequestType = MWin32SocketObserver::EConnect; + TInt err = iWin32Socket.Connect(aAddress, iStatus); + if (err == KErrNone) + { + SetActive(); + } + return err; + } + +TInt CWin32SocketWrapper::Send(const TDesC8& aSendBuffer) + { + __ASSERT_DEBUG(!IsActive(), Panic(EWinSockPrtSocketWrapperSendWhilstActive)); + iRequestType = MWin32SocketObserver::ESend; + TInt err = iWin32Socket.Send(aSendBuffer, iStatus); + if (err == KErrNone) + { + SetActive(); + } + return err; + } + +TInt CWin32SocketWrapper::SendTo(const TDesC8& aSendBuffer, const TInetAddr& aAddress) + { + __ASSERT_DEBUG(!IsActive(), Panic(EWinSockPrtSocketWrapperSendToWhilstActive)); + iRequestType = MWin32SocketObserver::ESendTo; + TInt err = iWin32Socket.SendTo(aSendBuffer, aAddress, iStatus); + if (err == KErrNone) + { + SetActive(); + } + return err; + } + +TInt CWin32SocketWrapper::Receive(TDes8& aReceiveBuffer) + { + __ASSERT_DEBUG(!IsActive(), Panic(EWinSockPrtSocketWrapperReceiveWhilstActive)); + iRequestType = MWin32SocketObserver::EReceive; + TInt err = iWin32Socket.Receive(aReceiveBuffer, iStatus); + if (err == KErrNone) + { + SetActive(); + } + return err; + } + +TInt CWin32SocketWrapper::ReceiveFrom(TDes8& aReceiveBuffer, TInetAddr& aAddress) + { + __ASSERT_DEBUG(!IsActive(), Panic(EWinSockPrtSocketWrapperReceiveFromWhilstActive)); + iRequestType = MWin32SocketObserver::EReceiveFrom; + TInt err = iWin32Socket.ReceiveFrom(aReceiveBuffer, aAddress, iStatus); + if (err == KErrNone) + { + SetActive(); + } + return err; + } + +TInt CWin32SocketWrapper::Accept(RWin32Socket& aNewSocket) + { + __ASSERT_DEBUG(!IsActive(), Panic(EWinSockPrtSocketWrapperAcceptWhilstActive)); + iRequestType = MWin32SocketObserver::EAccept; + TInt err = iWin32Socket.Accept(aNewSocket, iStatus); + if (err == KErrNone) + { + SetActive(); + } + return err; + } + +void CWin32SocketWrapper::DoCancel() + { + switch (iRequestType) + { + case MWin32SocketObserver::EConnect: + { + iWin32Socket.CancelConnect(); + break; + } + case MWin32SocketObserver::ESend: + { + iWin32Socket.CancelSend(); + break; + } + case MWin32SocketObserver::ESendTo: + { + iWin32Socket.CancelSendTo(); + break; + } + case MWin32SocketObserver::EReceive: + { + iWin32Socket.CancelReceive(); + break; + } + case MWin32SocketObserver::EReceiveFrom: + { + iWin32Socket.CancelReceiveFrom(); + break; + } + case MWin32SocketObserver::EAccept: + { + iWin32Socket.CancelAccept(); + break; + } + case MWin32SocketObserver::ENone: + default: + { + __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtSocketWrapperInvalidSocketOppCode)); + break; + } + } + } + +void CWin32SocketWrapper::RunL() + { + MWin32SocketObserver::TRequestType requestType = iRequestType; + iRequestType = MWin32SocketObserver::ENone; + iObserver.HandleWin32SocketCompletion(requestType, iStatus.Int()); + } + +TInt CWin32SocketWrapper::RunError(TInt /*aError*/) + { + __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtSocketWrapperUnexpectedRunError)); + return 0; + }