Poll gets it's own socket.

Moved send function back to non async handler.
This was needed to fix one part of GH5.
This commit is contained in:
Matthew Parlane 2013-02-02 22:42:27 +13:00
parent 6b8bb1b692
commit d05b029b0e
2 changed files with 357 additions and 291 deletions

View File

@ -603,6 +603,13 @@ CWII_IPC_HLE_Device_net_ip_top::CWII_IPC_HLE_Device_net_ip_top(u32 _DeviceID, co
int ret = WSAStartup(MAKEWORD(2,2), &InitData);
INFO_LOG(WII_IPC_NET, "WSAStartup: %d", ret);
#endif
u32 s = 0xDEADBEEF;
std::lock_guard<std::mutex> lk(socketMapMutex);
_tSocket* sock = new _tSocket();
socketMap[s] = sock;
sock->thread = new std::thread([this, s]{this->processSocket(s);});
}
CWII_IPC_HLE_Device_net_ip_top::~CWII_IPC_HLE_Device_net_ip_top()
@ -610,6 +617,27 @@ CWII_IPC_HLE_Device_net_ip_top::~CWII_IPC_HLE_Device_net_ip_top()
#ifdef _WIN32
WSACleanup();
#endif
std::lock_guard<std::mutex> lk(socketMapMutex);
auto i = socketMap.begin();
while(i != socketMap.end())
{
u32 s = i->first;
_tSocket * sock = i->second;
if(s != 0xDEADBEEF)
{
(void)shutdown(s, SHUT_RDWR);
#ifdef _WIN32
(void)closesocket(s);
#else
(void)close(s);
#endif
}
sock->StopAndJoin();
delete sock;
socketMap.erase(i++);
}
}
bool CWII_IPC_HLE_Device_net_ip_top::Open(u32 CommandAddress, u32 _Mode)
@ -711,7 +739,29 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 CommandAddress)
ReturnValue = -8; // EBADF
}
ERROR_LOG(WII_IPC_NET, "Failed to find socket %X", s);
ERROR_LOG(WII_IPC_NET, "Failed to find socket %d %08X", s, Command);
break;
}
case IOCTL_SO_POLL:
{
u32 s = 0xDEADBEEF;
_tSocket * sock = NULL;
{
std::lock_guard<std::mutex> lk(socketMapMutex);
if(socketMap.find(s) != socketMap.end())
sock = socketMap[s];
}
if(sock)
{
sock->addCommand(CommandAddress);
return false;
}
else
{
ReturnValue = -8; // EBADF
}
ERROR_LOG(WII_IPC_NET, "Failed to find socket %d %08X", s, Command);
break;
}
@ -732,7 +782,7 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 CommandAddress)
std::lock_guard<std::mutex> lk(socketMapMutex);
_tSocket* sock = new _tSocket();
socketMap[s] = sock;
sock->thread = new std::thread([this, s]{this->socketProcessor(s);});
sock->thread = new std::thread([this, s]{this->processSocket(s);});
}
break;
@ -763,14 +813,15 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 CommandAddress)
u32 s = Memory::Read_U32(BufferIn);
WARN_LOG(WII_IPC_NET, "IOCTL_SO_CLOSE (%08x)", s);
ReturnValue = shutdown(s, SHUT_RDWR);
#ifdef _WIN32
ReturnValue = closesocket(s);
ReturnValue = getNetErrorCode(ReturnValue, "IOCTL_SO_CLOSE", false);
#else
ReturnValue = close(s);
#endif
ReturnValue = getNetErrorCode(ReturnValue, "IOCTL_SO_CLOSE", false);
_tSocket * sock = NULL;
{
std::lock_guard<std::mutex> lk(socketMapMutex);
@ -785,6 +836,7 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 CommandAddress)
}
}
WARN_LOG(WII_IPC_NET, "IOCTL_SO_CLOSE finished (%08x) = ", s, ReturnValue);
break;
}
@ -797,6 +849,7 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 CommandAddress)
address.sin_family = addrPC.sin_family;
address.sin_addr.s_addr = addrPC.sin_addr.s_addr_;
address.sin_port = addrPC.sin_port;
ReturnValue = bind(Common::swap32(addr->socket), (sockaddr*)&address, sizeof(address));
WARN_LOG(WII_IPC_NET, "IOCTL_SO_BIND (%s:%d) = %d "
@ -1011,6 +1064,7 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 CommandAddress)
sa_len = sizeof(sa);
ReturnValue = getpeername(sock, &sa, &sa_len);
ReturnValue = getNetErrorCode(ReturnValue, "IOCTL_SO_GETPEERNAME", false);
Memory::Write_U8(BufferOutSize, BufferOut);
Memory::Write_U8(AF_INET, BufferOut + 1);
@ -1066,82 +1120,6 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 CommandAddress)
memcpy(Memory::GetPointer(BufferOut), ip_s, strlen(ip_s));
break;
}
case IOCTL_SO_POLL:
{
// Map Wii/native poll events types
unsigned int mapping[][2] = {
{ POLLIN, 0x0001 },
{ POLLOUT, 0x0008 },
{ POLLHUP, 0x0040 },
};
u32 unknown = Memory::Read_U32(BufferIn);
u32 timeout = Memory::Read_U32(BufferIn + 4);
int nfds = BufferOutSize / 0xc;
if (nfds == 0)
ERROR_LOG(WII_IPC_NET,"Hidden POLL");
pollfd_t* ufds = (pollfd_t *)malloc(sizeof(pollfd_t) * nfds);
if (ufds == NULL)
{
ReturnValue = -1;
break;
}
for (int i = 0; i < nfds; i++)
{
ufds[i].fd = Memory::Read_U32(BufferOut + 0xc*i); //fd
int events = Memory::Read_U32(BufferOut + 0xc*i + 4); //events
ufds[i].revents = Memory::Read_U32(BufferOut + 0xc*i + 8); //revents
// Translate Wii to native events
int unhandled_events = events;
ufds[i].events = 0;
for (unsigned int j = 0; j < sizeof (mapping) / sizeof (mapping[0]); ++j)
{
if (events & mapping[j][1])
ufds[i].events |= mapping[j][0];
unhandled_events &= ~mapping[j][1];
}
WARN_LOG(WII_IPC_NET, "IOCTL_SO_POLL(%d) "
"Sock: %08x, Unknown: %08x, Events: %08x, "
"NativeEvents: %08x",
i, ufds[i].fd, unknown, events, ufds[i].events
);
if (unhandled_events)
ERROR_LOG(WII_IPC_NET, "SO_POLL: unhandled Wii event types: %04x", unhandled_events);
}
ReturnValue = poll(ufds, nfds, timeout);
ReturnValue = getNetErrorCode(ReturnValue, "SO_POLL", false);
for (int i = 0; i<nfds; i++)
{
// Translate native to Wii events
int revents = 0;
for (unsigned int j = 0; j < sizeof (mapping) / sizeof (mapping[0]); ++j)
{
if (ufds[i].revents & mapping[j][0])
revents |= mapping[j][1];
}
// No need to change fd or events as they are input only.
// Memory::Write_U32(ufds[i].fd, BufferOut + 0xc*i); //fd
// Memory::Write_U32(events, BufferOut + 0xc*i + 4); //events
Memory::Write_U32(revents, BufferOut + 0xc*i + 8); //revents
WARN_LOG(WII_IPC_NET, "IOCTL_SO_POLL socket %d revents %08X events %08X", i, revents, ufds[i].events);
}
free(ufds);
break;
}
case IOCTL_SO_GETHOSTBYNAME:
{
hostent *remoteHost = gethostbyname((char*)Memory::GetPointer(BufferIn));
@ -1339,41 +1317,14 @@ int getNetErrorCode(int ret, std::string caller, bool isRW)
}
void CWII_IPC_HLE_Device_net_ip_top::socketProcessor(u32 socket)
s32 CWII_IPC_HLE_Device_net_ip_top::processSocketIoctl(u32 CommandAddress, u32 socket)
{
ERROR_LOG(WII_IPC_NET, "Socket %d has started a thread.... oh dear.", socket);
_tSocket* sock = NULL;
{
std::lock_guard<std::mutex> lk(socketMapMutex);
if(socketMap.find(socket) == socketMap.end())
{
ERROR_LOG(WII_IPC_NET, "Socket %d could not be found in the socket map.", socket);
return;
}
sock = socketMap[socket];
}
while((sock->WaitForEvent(), true) && sock->running)
{
u32 CommandAddress = 0;
while(sock->getCommand(CommandAddress))
{
using WII_IPC_HLE_Interface::ECommandType;
using WII_IPC_HLE_Interface::COMMAND_IOCTL;
using WII_IPC_HLE_Interface::COMMAND_IOCTLV;
s32 ReturnValue = 0;
ECommandType CommandType = static_cast<ECommandType>(Memory::Read_U32(CommandAddress));
if(CommandType == COMMAND_IOCTL)
{
u32 BufferIn = Memory::Read_U32(CommandAddress + 0x10);
u32 BufferInSize = Memory::Read_U32(CommandAddress + 0x14);
u32 BufferOut = Memory::Read_U32(CommandAddress + 0x18);
u32 BufferOutSize = Memory::Read_U32(CommandAddress + 0x1C);
u32 Command = Memory::Read_U32(CommandAddress + 0x0C);
WARN_LOG(WII_IPC_NET, "IOCTL command = %d", Command);
switch(Command)
{
case IOCTL_SO_ACCEPT:
@ -1420,6 +1371,80 @@ void CWII_IPC_HLE_Device_net_ip_top::socketProcessor(u32 socket)
socket, inet_ntoa(serverAddr.sin_addr), Common::swap16(serverAddr.sin_port));
break;
}
case IOCTL_SO_POLL:
{
// Map Wii/native poll events types
unsigned int mapping[][2] = {
{ POLLIN , 0x0001 },
{ POLLOUT, 0x0008 },
{ POLLHUP, 0x0040 },
};
u32 unknown = Memory::Read_U32(BufferIn);
u32 timeout = Memory::Read_U32(BufferIn + 4);
int nfds = BufferOutSize / 0xc;
if (nfds == 0)
ERROR_LOG(WII_IPC_NET,"Hidden POLL");
pollfd_t* ufds = (pollfd_t *)malloc(sizeof(pollfd_t) * nfds);
if (ufds == NULL)
{
ReturnValue = -1;
break;
}
for (int i = 0; i < nfds; i++)
{
ufds[i].fd = Memory::Read_U32(BufferOut + 0xc*i); //fd
int events = Memory::Read_U32(BufferOut + 0xc*i + 4); //events
ufds[i].revents = Memory::Read_U32(BufferOut + 0xc*i + 8); //revents
// Translate Wii to native events
int unhandled_events = events;
ufds[i].events = 0;
for (unsigned int j = 0; j < sizeof (mapping) / sizeof (mapping[0]); ++j)
{
if (events & mapping[j][1])
ufds[i].events |= mapping[j][0];
unhandled_events &= ~mapping[j][1];
}
WARN_LOG(WII_IPC_NET, "IOCTL_SO_POLL(%d) "
"Sock: %08x, Unknown: %08x, Events: %08x, "
"NativeEvents: %08x",
i, ufds[i].fd, unknown, events, ufds[i].events
);
if (unhandled_events)
ERROR_LOG(WII_IPC_NET, "SO_POLL: unhandled Wii event types: %04x", unhandled_events);
}
ReturnValue = poll(ufds, nfds, timeout);
ReturnValue = getNetErrorCode(ReturnValue, "SO_POLL", false);
for (int i = 0; i<nfds; i++)
{
// Translate native to Wii events
int revents = 0;
for (unsigned int j = 0; j < sizeof (mapping) / sizeof (mapping[0]); ++j)
{
if (ufds[i].revents & mapping[j][0])
revents |= mapping[j][1];
}
// No need to change fd or events as they are input only.
// Memory::Write_U32(ufds[i].fd, BufferOut + 0xc*i); //fd
// Memory::Write_U32(events, BufferOut + 0xc*i + 4); //events
Memory::Write_U32(revents, BufferOut + 0xc*i + 8); //revents
WARN_LOG(WII_IPC_NET, "IOCTL_SO_POLL socket %d revents %08X events %08X", i, revents, ufds[i].events);
}
free(ufds);
break;
}
default:
{
@ -1427,12 +1452,14 @@ void CWII_IPC_HLE_Device_net_ip_top::socketProcessor(u32 socket)
break;
}
}
}
else if (CommandType == COMMAND_IOCTLV)
{
return ReturnValue;
}
s32 CWII_IPC_HLE_Device_net_ip_top::processSocketIoctlv(u32 CommandAddress, u32 socket)
{
SIOCtlVBuffer CommandBuffer(CommandAddress);
s32 ReturnValue = 0;
u32 BufferIn = 0, BufferIn2 = 0, BufferIn3 = 0;
u32 BufferInSize = 0, BufferInSize2 = 0, BufferInSize3 = 0;
@ -1522,52 +1549,6 @@ void CWII_IPC_HLE_Device_net_ip_top::socketProcessor(u32 socket)
break;
}
case IOCTLV_SO_SENDTO:
{
struct sendto_params
{
u32 socket;
u32 flags;
u32 has_destaddr;
u8 destaddr[28];
} params;
char * data = (char*)Memory::GetPointer(BufferIn);
Memory::ReadBigEData((u8*)&params, BufferIn2, BufferInSize2);
if (params.has_destaddr)
{
struct sockaddr_in* addr = (struct sockaddr_in*)&params.destaddr;
u8 len = sizeof(sockaddr); //addr->sin_family & 0xFF;
addr->sin_family = addr->sin_family >> 8;
ReturnValue = sendto(socket, data,
BufferInSize, Common::swap32(params.flags), (struct sockaddr*)addr, len);
WARN_LOG(WII_IPC_NET,
"IOCTLV_SO_SENDTO = %d Socket: %08x, BufferIn: (%08x, %i), BufferIn2: (%08x, %i), %u.%u.%u.%u",
ReturnValue, socket, BufferIn, BufferInSize,
BufferIn2, BufferInSize2,
addr->sin_addr.s_addr & 0xFF,
(addr->sin_addr.s_addr >> 8) & 0xFF,
(addr->sin_addr.s_addr >> 16) & 0xFF,
(addr->sin_addr.s_addr >> 24) & 0xFF
);
ReturnValue = getNetErrorCode(ReturnValue, "SO_SENDTO", true);
}
else
{
ReturnValue = send(socket, data,
BufferInSize, Common::swap32(params.flags));
WARN_LOG(WII_IPC_NET, "IOCTLV_SO_SEND = %d Socket: %08x, BufferIn: (%08x, %i), BufferIn2: (%08x, %i)",
ReturnValue, socket, BufferIn, BufferInSize,
BufferIn2, BufferInSize2);
ReturnValue = getNetErrorCode(ReturnValue, "SO_SEND", true);
}
break;
}
default:
{
@ -1575,6 +1556,43 @@ void CWII_IPC_HLE_Device_net_ip_top::socketProcessor(u32 socket)
break;
}
}
return ReturnValue;
}
void CWII_IPC_HLE_Device_net_ip_top::processSocket(u32 socket)
{
//DEBUG_LOG(WII_IPC_NET, "Socket %08X has started a thread.... oh dear.", socket);
_tSocket* sock = NULL;
{
std::lock_guard<std::mutex> lk(socketMapMutex);
if(socketMap.find(socket) == socketMap.end())
{
ERROR_LOG(WII_IPC_NET, "Socket %d could not be found in the socket map.", socket);
return;
}
sock = socketMap[socket];
}
while((sock->WaitForEvent(), true) && sock->running)
{
u32 CommandAddress = 0;
while(sock->getCommand(CommandAddress))
{
using WII_IPC_HLE_Interface::ECommandType;
using WII_IPC_HLE_Interface::COMMAND_IOCTL;
using WII_IPC_HLE_Interface::COMMAND_IOCTLV;
s32 ReturnValue = 0;
ECommandType CommandType = static_cast<ECommandType>(Memory::Read_U32(CommandAddress));
if(CommandType == COMMAND_IOCTL)
{
ReturnValue = processSocketIoctl(CommandAddress, socket);
}
else if (CommandType == COMMAND_IOCTLV)
{
ReturnValue = processSocketIoctlv(CommandAddress, socket);
}
Memory::Write_U32(8, CommandAddress);
@ -1767,7 +1785,6 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 CommandAddress)
break;
}
case IOCTLV_SO_SENDTO:
case IOCTLV_SO_RECVFROM:
{
u32 s = 0;
@ -1777,6 +1794,7 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 CommandAddress)
} else {
s = Memory::Read_U32(BufferIn);
}
ERROR_LOG(WII_IPC_NET, "Adding sendto or recvfrom %08X %08X", s, CommandBuffer.Parameter);
_tSocket * sock = NULL;
{
@ -1794,10 +1812,56 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 CommandAddress)
ReturnValue = -8; // EBADF
}
ERROR_LOG(WII_IPC_NET, "Failed to find socket %d", s);
ERROR_LOG(WII_IPC_NET, "Failed to find socket %d %08X", s, CommandBuffer.Parameter);
break;
}
case IOCTLV_SO_SENDTO:
{
struct sendto_params
{
u32 socket;
u32 flags;
u32 has_destaddr;
u8 destaddr[28];
} params;
u32 socket = Memory::Read_U32(BufferIn2);
char * data = (char*)Memory::GetPointer(BufferIn);
Memory::ReadBigEData((u8*)&params, BufferIn2, BufferInSize2);
if (params.has_destaddr)
{
struct sockaddr_in* addr = (struct sockaddr_in*)&params.destaddr;
u8 len = sizeof(sockaddr_in); //addr->sin_family & 0xFF;
addr->sin_family = addr->sin_family >> 8;
ReturnValue = sendto(socket, data,
BufferInSize, Common::swap32(params.flags), (struct sockaddr*)addr, len);
WARN_LOG(WII_IPC_NET,
"IOCTLV_SO_SENDTO = %d Socket: %08x, BufferIn: (%08x, %i), BufferIn2: (%08x, %i), %u.%u.%u.%u",
ReturnValue, socket, BufferIn, BufferInSize,
BufferIn2, BufferInSize2,
addr->sin_addr.s_addr & 0xFF,
(addr->sin_addr.s_addr >> 8) & 0xFF,
(addr->sin_addr.s_addr >> 16) & 0xFF,
(addr->sin_addr.s_addr >> 24) & 0xFF
);
ReturnValue = getNetErrorCode(ReturnValue, "SO_SENDTO", true);
}
else
{
ReturnValue = send(socket, data,
BufferInSize, Common::swap32(params.flags));
WARN_LOG(WII_IPC_NET, "IOCTLV_SO_SEND = %d Socket: %08x, BufferIn: (%08x, %i), BufferIn2: (%08x, %i)",
ReturnValue, socket, BufferIn, BufferInSize,
BufferIn2, BufferInSize2);
ReturnValue = getNetErrorCode(ReturnValue, "SO_SEND", true);
}
break;
}
case IOCTLV_SO_GETADDRINFO:
{
struct addrinfo hints;

View File

@ -636,7 +636,9 @@ private:
#endif
std::map<u32, _tSocket*> socketMap;
std::mutex socketMapMutex;
void socketProcessor(u32 socket);
void processSocket(u32 socket);
s32 processSocketIoctl(u32 CommandAddress, u32 socket);
s32 processSocketIoctlv(u32 CommandAddress, u32 socket);
enum
{