Implemented RObjectIx-based memoryaccess APIs.
Upshot is that objinfo now works again on platforms that define FSHELL_NO_DOBJECTIX_SUPPORT.
// 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;
}