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:
parent
6b8bb1b692
commit
d05b029b0e
|
@ -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);
|
int ret = WSAStartup(MAKEWORD(2,2), &InitData);
|
||||||
INFO_LOG(WII_IPC_NET, "WSAStartup: %d", ret);
|
INFO_LOG(WII_IPC_NET, "WSAStartup: %d", ret);
|
||||||
#endif
|
#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()
|
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
|
#ifdef _WIN32
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
#endif
|
#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)
|
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
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -732,7 +782,7 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 CommandAddress)
|
||||||
std::lock_guard<std::mutex> lk(socketMapMutex);
|
std::lock_guard<std::mutex> lk(socketMapMutex);
|
||||||
_tSocket* sock = new _tSocket();
|
_tSocket* sock = new _tSocket();
|
||||||
socketMap[s] = sock;
|
socketMap[s] = sock;
|
||||||
sock->thread = new std::thread([this, s]{this->socketProcessor(s);});
|
sock->thread = new std::thread([this, s]{this->processSocket(s);});
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -763,14 +813,15 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 CommandAddress)
|
||||||
u32 s = Memory::Read_U32(BufferIn);
|
u32 s = Memory::Read_U32(BufferIn);
|
||||||
WARN_LOG(WII_IPC_NET, "IOCTL_SO_CLOSE (%08x)", s);
|
WARN_LOG(WII_IPC_NET, "IOCTL_SO_CLOSE (%08x)", s);
|
||||||
|
|
||||||
|
ReturnValue = shutdown(s, SHUT_RDWR);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
ReturnValue = closesocket(s);
|
ReturnValue = closesocket(s);
|
||||||
|
|
||||||
ReturnValue = getNetErrorCode(ReturnValue, "IOCTL_SO_CLOSE", false);
|
|
||||||
#else
|
#else
|
||||||
ReturnValue = close(s);
|
ReturnValue = close(s);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ReturnValue = getNetErrorCode(ReturnValue, "IOCTL_SO_CLOSE", false);
|
||||||
|
|
||||||
_tSocket * sock = NULL;
|
_tSocket * sock = NULL;
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(socketMapMutex);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -797,6 +849,7 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 CommandAddress)
|
||||||
address.sin_family = addrPC.sin_family;
|
address.sin_family = addrPC.sin_family;
|
||||||
address.sin_addr.s_addr = addrPC.sin_addr.s_addr_;
|
address.sin_addr.s_addr = addrPC.sin_addr.s_addr_;
|
||||||
address.sin_port = addrPC.sin_port;
|
address.sin_port = addrPC.sin_port;
|
||||||
|
|
||||||
ReturnValue = bind(Common::swap32(addr->socket), (sockaddr*)&address, sizeof(address));
|
ReturnValue = bind(Common::swap32(addr->socket), (sockaddr*)&address, sizeof(address));
|
||||||
|
|
||||||
WARN_LOG(WII_IPC_NET, "IOCTL_SO_BIND (%s:%d) = %d "
|
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);
|
sa_len = sizeof(sa);
|
||||||
|
|
||||||
ReturnValue = getpeername(sock, &sa, &sa_len);
|
ReturnValue = getpeername(sock, &sa, &sa_len);
|
||||||
|
ReturnValue = getNetErrorCode(ReturnValue, "IOCTL_SO_GETPEERNAME", false);
|
||||||
|
|
||||||
Memory::Write_U8(BufferOutSize, BufferOut);
|
Memory::Write_U8(BufferOutSize, BufferOut);
|
||||||
Memory::Write_U8(AF_INET, BufferOut + 1);
|
Memory::Write_U8(AF_INET, BufferOut + 1);
|
||||||
|
@ -1065,83 +1119,7 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 CommandAddress)
|
||||||
memset(Memory::GetPointer(BufferOut), 0, BufferOutSize);
|
memset(Memory::GetPointer(BufferOut), 0, BufferOutSize);
|
||||||
memcpy(Memory::GetPointer(BufferOut), ip_s, strlen(ip_s));
|
memcpy(Memory::GetPointer(BufferOut), ip_s, strlen(ip_s));
|
||||||
break;
|
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:
|
case IOCTL_SO_GETHOSTBYNAME:
|
||||||
{
|
{
|
||||||
hostent *remoteHost = gethostbyname((char*)Memory::GetPointer(BufferIn));
|
hostent *remoteHost = gethostbyname((char*)Memory::GetPointer(BufferIn));
|
||||||
|
@ -1339,9 +1317,251 @@ 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);
|
s32 ReturnValue = 0;
|
||||||
|
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);
|
||||||
|
switch(Command)
|
||||||
|
{
|
||||||
|
case IOCTL_SO_ACCEPT:
|
||||||
|
{
|
||||||
|
WARN_LOG(WII_IPC_NET, "IOCTL_SO_ACCEPT(%d) "
|
||||||
|
"BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
|
||||||
|
socket, BufferIn, BufferInSize, BufferOut, BufferOutSize);
|
||||||
|
struct sockaddr* addr = (struct sockaddr*) Memory::GetPointer(BufferOut);
|
||||||
|
socklen_t* addrlen = (socklen_t*) Memory::GetPointer(BufferOutSize);
|
||||||
|
*addrlen = sizeof(struct sockaddr);
|
||||||
|
ReturnValue = accept(socket, addr, addrlen);
|
||||||
|
ReturnValue = getNetErrorCode(ReturnValue, "SO_ACCEPT", false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IOCTL_SO_CONNECT:
|
||||||
|
{
|
||||||
|
//struct sockaddr_in echoServAddr;
|
||||||
|
struct connect_params
|
||||||
|
{
|
||||||
|
u32 socket;
|
||||||
|
u32 has_addr;
|
||||||
|
u8 addr[28];
|
||||||
|
} params;
|
||||||
|
sockaddr_in serverAddr;
|
||||||
|
|
||||||
|
Memory::ReadBigEData((u8*)¶ms, BufferIn, sizeof(connect_params));
|
||||||
|
|
||||||
|
if (Common::swap32(params.has_addr) != 1)
|
||||||
|
{
|
||||||
|
WARN_LOG(WII_IPC_NET,"IOCTL_SO_CONNECT: failed");
|
||||||
|
ReturnValue = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&serverAddr, 0, sizeof(serverAddr));
|
||||||
|
memcpy(&serverAddr, params.addr, params.addr[0]);
|
||||||
|
|
||||||
|
// GC/Wii sockets have a length param as well, we dont really care :)
|
||||||
|
serverAddr.sin_family = serverAddr.sin_family >> 8;
|
||||||
|
|
||||||
|
ReturnValue = connect(socket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
|
||||||
|
ReturnValue = getNetErrorCode(ReturnValue, "SO_CONNECT", false);
|
||||||
|
WARN_LOG(WII_IPC_NET,"IOCTL_SO_CONNECT (%08x, %s:%d)",
|
||||||
|
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:
|
||||||
|
{
|
||||||
|
|
||||||
|
ERROR_LOG(WII_IPC_NET, "Socket %08x has received an unknown IOCTLV %d.", socket, Command);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
|
||||||
|
u32 BufferOut = 0, BufferOut2 = 0, BufferOut3 = 0;
|
||||||
|
u32 BufferOutSize = 0, BufferOutSize2 = 0, BufferOutSize3 = 0;
|
||||||
|
|
||||||
|
if (CommandBuffer.InBuffer.size() > 0)
|
||||||
|
{
|
||||||
|
BufferIn = CommandBuffer.InBuffer.at(0).m_Address;
|
||||||
|
BufferInSize = CommandBuffer.InBuffer.at(0).m_Size;
|
||||||
|
}
|
||||||
|
if (CommandBuffer.InBuffer.size() > 1)
|
||||||
|
{
|
||||||
|
BufferIn2 = CommandBuffer.InBuffer.at(1).m_Address;
|
||||||
|
BufferInSize2 = CommandBuffer.InBuffer.at(1).m_Size;
|
||||||
|
}
|
||||||
|
if (CommandBuffer.InBuffer.size() > 2)
|
||||||
|
{
|
||||||
|
BufferIn3 = CommandBuffer.InBuffer.at(2).m_Address;
|
||||||
|
BufferInSize3 = CommandBuffer.InBuffer.at(2).m_Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CommandBuffer.PayloadBuffer.size() > 0)
|
||||||
|
{
|
||||||
|
BufferOut = CommandBuffer.PayloadBuffer.at(0).m_Address;
|
||||||
|
BufferOutSize = CommandBuffer.PayloadBuffer.at(0).m_Size;
|
||||||
|
}
|
||||||
|
if (CommandBuffer.PayloadBuffer.size() > 1)
|
||||||
|
{
|
||||||
|
BufferOut2 = CommandBuffer.PayloadBuffer.at(1).m_Address;
|
||||||
|
BufferOutSize2 = CommandBuffer.PayloadBuffer.at(1).m_Size;
|
||||||
|
}
|
||||||
|
if (CommandBuffer.PayloadBuffer.size() > 2)
|
||||||
|
{
|
||||||
|
BufferOut3 = CommandBuffer.PayloadBuffer.at(2).m_Address;
|
||||||
|
BufferOutSize3 = CommandBuffer.PayloadBuffer.at(2).m_Size;
|
||||||
|
}
|
||||||
|
switch(CommandBuffer.Parameter)
|
||||||
|
{
|
||||||
|
case IOCTLV_SO_RECVFROM:
|
||||||
|
{
|
||||||
|
|
||||||
|
u32 flags = Memory::Read_U32(BufferIn + 4);
|
||||||
|
|
||||||
|
char *buf = (char *)Memory::GetPointer(BufferOut);
|
||||||
|
int len = BufferOutSize;
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
memset(&addr, 0, sizeof(sockaddr_in));
|
||||||
|
socklen_t fromlen = 0;
|
||||||
|
|
||||||
|
if (BufferOutSize2 != 0)
|
||||||
|
{
|
||||||
|
fromlen = BufferOutSize2 >= sizeof(struct sockaddr) ? BufferOutSize2 : sizeof(struct sockaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags != 2)
|
||||||
|
flags = 0;
|
||||||
|
else
|
||||||
|
flags = MSG_PEEK;
|
||||||
|
#ifdef _WIN32
|
||||||
|
if(flags & MSG_PEEK){
|
||||||
|
unsigned long totallen = 0;
|
||||||
|
ioctlsocket(socket, FIONREAD, &totallen);
|
||||||
|
ReturnValue = totallen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ReturnValue = recvfrom(socket, buf, len, flags,
|
||||||
|
fromlen ? (struct sockaddr*) &addr : NULL,
|
||||||
|
fromlen ? &fromlen : 0);
|
||||||
|
|
||||||
|
ReturnValue = getNetErrorCode(ReturnValue, fromlen ? "SO_RECVFROM" : "SO_RECV", true);
|
||||||
|
|
||||||
|
|
||||||
|
WARN_LOG(WII_IPC_NET, "%s(%d, %p) Socket: %08X, Flags: %08X, "
|
||||||
|
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
||||||
|
"BufferOut: (%08x, %i), BufferOut2: (%08x, %i)",fromlen ? "IOCTLV_SO_RECVFROM " : "IOCTLV_SO_RECV ",
|
||||||
|
ReturnValue, buf, socket, flags,
|
||||||
|
BufferIn, BufferInSize, BufferIn2, BufferInSize2,
|
||||||
|
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2);
|
||||||
|
|
||||||
|
if (BufferOutSize2 != 0)
|
||||||
|
{
|
||||||
|
addr.sin_family = (addr.sin_family << 8) | (BufferOutSize2&0xFF);
|
||||||
|
Memory::WriteBigEData((u8*)&addr, BufferOut2, BufferOutSize2);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
|
||||||
|
ERROR_LOG(WII_IPC_NET, "Socket %d has received an unknown IOCTLV %d.", socket, CommandBuffer.Parameter);
|
||||||
|
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;
|
_tSocket* sock = NULL;
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(socketMapMutex);
|
std::lock_guard<std::mutex> lk(socketMapMutex);
|
||||||
|
@ -1351,7 +1571,7 @@ void CWII_IPC_HLE_Device_net_ip_top::socketProcessor(u32 socket)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sock = socketMap[socket];
|
sock = socketMap[socket];
|
||||||
}
|
}
|
||||||
while((sock->WaitForEvent(), true) && sock->running)
|
while((sock->WaitForEvent(), true) && sock->running)
|
||||||
{
|
{
|
||||||
u32 CommandAddress = 0;
|
u32 CommandAddress = 0;
|
||||||
|
@ -1368,213 +1588,11 @@ void CWII_IPC_HLE_Device_net_ip_top::socketProcessor(u32 socket)
|
||||||
|
|
||||||
if(CommandType == COMMAND_IOCTL)
|
if(CommandType == COMMAND_IOCTL)
|
||||||
{
|
{
|
||||||
u32 BufferIn = Memory::Read_U32(CommandAddress + 0x10);
|
ReturnValue = processSocketIoctl(CommandAddress, socket);
|
||||||
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:
|
|
||||||
{
|
|
||||||
WARN_LOG(WII_IPC_NET, "IOCTL_SO_ACCEPT(%d) "
|
|
||||||
"BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
|
|
||||||
socket, BufferIn, BufferInSize, BufferOut, BufferOutSize);
|
|
||||||
struct sockaddr* addr = (struct sockaddr*) Memory::GetPointer(BufferOut);
|
|
||||||
socklen_t* addrlen = (socklen_t*) Memory::GetPointer(BufferOutSize);
|
|
||||||
*addrlen = sizeof(struct sockaddr);
|
|
||||||
ReturnValue = accept(socket, addr, addrlen);
|
|
||||||
ReturnValue = getNetErrorCode(ReturnValue, "SO_ACCEPT", false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IOCTL_SO_CONNECT:
|
|
||||||
{
|
|
||||||
//struct sockaddr_in echoServAddr;
|
|
||||||
struct connect_params
|
|
||||||
{
|
|
||||||
u32 socket;
|
|
||||||
u32 has_addr;
|
|
||||||
u8 addr[28];
|
|
||||||
} params;
|
|
||||||
sockaddr_in serverAddr;
|
|
||||||
|
|
||||||
Memory::ReadBigEData((u8*)¶ms, BufferIn, sizeof(connect_params));
|
|
||||||
|
|
||||||
if (Common::swap32(params.has_addr) != 1)
|
|
||||||
{
|
|
||||||
WARN_LOG(WII_IPC_NET,"IOCTL_SO_CONNECT: failed");
|
|
||||||
ReturnValue = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&serverAddr, 0, sizeof(serverAddr));
|
|
||||||
memcpy(&serverAddr, params.addr, params.addr[0]);
|
|
||||||
|
|
||||||
// GC/Wii sockets have a length param as well, we dont really care :)
|
|
||||||
serverAddr.sin_family = serverAddr.sin_family >> 8;
|
|
||||||
|
|
||||||
ReturnValue = connect(socket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
|
|
||||||
ReturnValue = getNetErrorCode(ReturnValue, "SO_CONNECT", false);
|
|
||||||
WARN_LOG(WII_IPC_NET,"IOCTL_SO_CONNECT (%08x, %s:%d)",
|
|
||||||
socket, inet_ntoa(serverAddr.sin_addr), Common::swap16(serverAddr.sin_port));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
|
|
||||||
ERROR_LOG(WII_IPC_NET, "Socket %08x has received an unknown IOCTLV %d.", socket, Command);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (CommandType == COMMAND_IOCTLV)
|
else if (CommandType == COMMAND_IOCTLV)
|
||||||
{
|
{
|
||||||
SIOCtlVBuffer CommandBuffer(CommandAddress);
|
ReturnValue = processSocketIoctlv(CommandAddress, socket);
|
||||||
|
|
||||||
u32 BufferIn = 0, BufferIn2 = 0, BufferIn3 = 0;
|
|
||||||
u32 BufferInSize = 0, BufferInSize2 = 0, BufferInSize3 = 0;
|
|
||||||
|
|
||||||
u32 BufferOut = 0, BufferOut2 = 0, BufferOut3 = 0;
|
|
||||||
u32 BufferOutSize = 0, BufferOutSize2 = 0, BufferOutSize3 = 0;
|
|
||||||
|
|
||||||
if (CommandBuffer.InBuffer.size() > 0)
|
|
||||||
{
|
|
||||||
BufferIn = CommandBuffer.InBuffer.at(0).m_Address;
|
|
||||||
BufferInSize = CommandBuffer.InBuffer.at(0).m_Size;
|
|
||||||
}
|
|
||||||
if (CommandBuffer.InBuffer.size() > 1)
|
|
||||||
{
|
|
||||||
BufferIn2 = CommandBuffer.InBuffer.at(1).m_Address;
|
|
||||||
BufferInSize2 = CommandBuffer.InBuffer.at(1).m_Size;
|
|
||||||
}
|
|
||||||
if (CommandBuffer.InBuffer.size() > 2)
|
|
||||||
{
|
|
||||||
BufferIn3 = CommandBuffer.InBuffer.at(2).m_Address;
|
|
||||||
BufferInSize3 = CommandBuffer.InBuffer.at(2).m_Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CommandBuffer.PayloadBuffer.size() > 0)
|
|
||||||
{
|
|
||||||
BufferOut = CommandBuffer.PayloadBuffer.at(0).m_Address;
|
|
||||||
BufferOutSize = CommandBuffer.PayloadBuffer.at(0).m_Size;
|
|
||||||
}
|
|
||||||
if (CommandBuffer.PayloadBuffer.size() > 1)
|
|
||||||
{
|
|
||||||
BufferOut2 = CommandBuffer.PayloadBuffer.at(1).m_Address;
|
|
||||||
BufferOutSize2 = CommandBuffer.PayloadBuffer.at(1).m_Size;
|
|
||||||
}
|
|
||||||
if (CommandBuffer.PayloadBuffer.size() > 2)
|
|
||||||
{
|
|
||||||
BufferOut3 = CommandBuffer.PayloadBuffer.at(2).m_Address;
|
|
||||||
BufferOutSize3 = CommandBuffer.PayloadBuffer.at(2).m_Size;
|
|
||||||
}
|
|
||||||
switch(CommandBuffer.Parameter)
|
|
||||||
{
|
|
||||||
case IOCTLV_SO_RECVFROM:
|
|
||||||
{
|
|
||||||
|
|
||||||
u32 flags = Memory::Read_U32(BufferIn + 4);
|
|
||||||
|
|
||||||
char *buf = (char *)Memory::GetPointer(BufferOut);
|
|
||||||
int len = BufferOutSize;
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
memset(&addr, 0, sizeof(sockaddr_in));
|
|
||||||
socklen_t fromlen = 0;
|
|
||||||
|
|
||||||
if (BufferOutSize2 != 0)
|
|
||||||
{
|
|
||||||
fromlen = BufferOutSize2 >= sizeof(struct sockaddr) ? BufferOutSize2 : sizeof(struct sockaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags != 2)
|
|
||||||
flags = 0;
|
|
||||||
else
|
|
||||||
flags = MSG_PEEK;
|
|
||||||
#ifdef _WIN32
|
|
||||||
if(flags & MSG_PEEK){
|
|
||||||
unsigned long totallen = 0;
|
|
||||||
ioctlsocket(socket, FIONREAD, &totallen);
|
|
||||||
ReturnValue = totallen;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
ReturnValue = recvfrom(socket, buf, len, flags,
|
|
||||||
fromlen ? (struct sockaddr*) &addr : NULL,
|
|
||||||
fromlen ? &fromlen : 0);
|
|
||||||
|
|
||||||
ReturnValue = getNetErrorCode(ReturnValue, fromlen ? "SO_RECVFROM" : "SO_RECV", true);
|
|
||||||
|
|
||||||
|
|
||||||
WARN_LOG(WII_IPC_NET, "%s(%d, %p) Socket: %08X, Flags: %08X, "
|
|
||||||
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
|
||||||
"BufferOut: (%08x, %i), BufferOut2: (%08x, %i)",fromlen ? "IOCTLV_SO_RECVFROM " : "IOCTLV_SO_RECV ",
|
|
||||||
ReturnValue, buf, socket, flags,
|
|
||||||
BufferIn, BufferInSize, BufferIn2, BufferInSize2,
|
|
||||||
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2);
|
|
||||||
|
|
||||||
if (BufferOutSize2 != 0)
|
|
||||||
{
|
|
||||||
addr.sin_family = (addr.sin_family << 8) | (BufferOutSize2&0xFF);
|
|
||||||
Memory::WriteBigEData((u8*)&addr, BufferOut2, BufferOutSize2);
|
|
||||||
}
|
|
||||||
|
|
||||||
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*)¶ms, BufferIn2, BufferInSize2);
|
|
||||||
|
|
||||||
if (params.has_destaddr)
|
|
||||||
{
|
|
||||||
struct sockaddr_in* addr = (struct sockaddr_in*)¶ms.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:
|
|
||||||
{
|
|
||||||
|
|
||||||
ERROR_LOG(WII_IPC_NET, "Socket %d has received an unknown IOCTLV %d.", socket, CommandBuffer.Parameter);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Write_U32(8, CommandAddress);
|
Memory::Write_U32(8, CommandAddress);
|
||||||
|
@ -1767,7 +1785,6 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 CommandAddress)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case IOCTLV_SO_SENDTO:
|
|
||||||
case IOCTLV_SO_RECVFROM:
|
case IOCTLV_SO_RECVFROM:
|
||||||
{
|
{
|
||||||
u32 s = 0;
|
u32 s = 0;
|
||||||
|
@ -1777,6 +1794,7 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 CommandAddress)
|
||||||
} else {
|
} else {
|
||||||
s = Memory::Read_U32(BufferIn);
|
s = Memory::Read_U32(BufferIn);
|
||||||
}
|
}
|
||||||
|
ERROR_LOG(WII_IPC_NET, "Adding sendto or recvfrom %08X %08X", s, CommandBuffer.Parameter);
|
||||||
|
|
||||||
_tSocket * sock = NULL;
|
_tSocket * sock = NULL;
|
||||||
{
|
{
|
||||||
|
@ -1794,10 +1812,56 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 CommandAddress)
|
||||||
ReturnValue = -8; // EBADF
|
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;
|
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*)¶ms, BufferIn2, BufferInSize2);
|
||||||
|
|
||||||
|
if (params.has_destaddr)
|
||||||
|
{
|
||||||
|
struct sockaddr_in* addr = (struct sockaddr_in*)¶ms.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:
|
case IOCTLV_SO_GETADDRINFO:
|
||||||
{
|
{
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
|
|
|
@ -636,7 +636,9 @@ private:
|
||||||
#endif
|
#endif
|
||||||
std::map<u32, _tSocket*> socketMap;
|
std::map<u32, _tSocket*> socketMap;
|
||||||
std::mutex socketMapMutex;
|
std::mutex socketMapMutex;
|
||||||
void socketProcessor(u32 socket);
|
void processSocket(u32 socket);
|
||||||
|
s32 processSocketIoctl(u32 CommandAddress, u32 socket);
|
||||||
|
s32 processSocketIoctlv(u32 CommandAddress, u32 socket);
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue