--- /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 <in_sock.h>
+#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 <emulator.h>
+
+//
+// RWin32Socket.
+//
+
+TInt RWin32Socket::Open(RWin32Factory& aFactory, TType aType)
+ {
+ WSP_LOG(WspLog::Printf(_L("RWin32Socket::Open: aType: %d, this: 0x%x"), aType, this));
+ TPckgC<TType> 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<TUint8*>(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<TUint> 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<TInt> 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<TWin32SocketOptions> 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<TWin32SocketOptionsC> 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<const TInetAddr&>(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<char*>(const_cast<TUint8*>(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<char*>(const_cast<TUint8*>(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<char*>(const_cast<TUint8*>(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<TInetAddr&>(aMessage.WriteBuffer());
+ ConvertAddress(winSockAddress, address);
+ aMessage.Complete(KErrNone);
+ }
+ }
+
+void CWin32Socket::Bind(TWin32Message& aMessage)
+ {
+ const TInetAddr& address = static_cast<const TInetAddr&>(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<TInetAddr&>(aMessage.WriteBuffer());
+ ConvertAddress(winSockAddress, address);
+ aMessage.Complete(KErrNone);
+ }
+ }
+
+void CWin32Socket::Listen(TWin32Message& aMessage)
+ {
+ TPckgBuf<TUint> 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<TInt> 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<TWin32SocketOptions*>(const_cast<TUint8*>(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<const TWin32SocketOptionsC*>(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<char*>(const_cast<TUint8*>(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<CWin32Socket*>(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<CWin32Socket*>(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<CWin32Socket*>(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<CWin32Socket*>(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<TUint16>(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;
+ }