summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorMatthew Parlane <parlane@gmail.com>2013-02-01 01:32:14 +1300
committerMatthew Parlane <parlane@gmail.com>2013-02-01 01:32:14 +1300
commita0a09ed07a28f661e93e94ee1a1f352dcb153ac4 (patch)
treea2d7c56648efccc4f72cba6cccce52c9ca29be9f /Source/Core
parentbca2cac640e4aff69a97b919411855d0e4b305da (diff)
Started threading of network. Good results so far.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp1506
-rw-r--r--Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.h85
2 files changed, 904 insertions, 687 deletions
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp
index fa4c98dac2..e534d28baf 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp
@@ -55,6 +55,7 @@ it failed)
#include "ICMP.h"
#include "CommonPaths.h"
#include "SettingsHandler.h"
+#include "WII_IPC_HLE.h"
#include "ec_wii.h"
@@ -103,30 +104,30 @@ CWII_IPC_HLE_Device_net_kd_request::~CWII_IPC_HLE_Device_net_kd_request()
{
}
-bool CWII_IPC_HLE_Device_net_kd_request::Open(u32 _CommandAddress, u32 _Mode)
+bool CWII_IPC_HLE_Device_net_kd_request::Open(u32 CommandAddress, u32 _Mode)
{
INFO_LOG(WII_IPC_WC24, "NET_KD_REQ: Open");
- Memory::Write_U32(GetDeviceID(), _CommandAddress + 4);
+ Memory::Write_U32(GetDeviceID(), CommandAddress + 4);
m_Active = true;
return true;
}
-bool CWII_IPC_HLE_Device_net_kd_request::Close(u32 _CommandAddress, bool _bForce)
+bool CWII_IPC_HLE_Device_net_kd_request::Close(u32 CommandAddress, bool _bForce)
{
INFO_LOG(WII_IPC_WC24, "NET_KD_REQ: Close");
if (!_bForce)
- Memory::Write_U32(0, _CommandAddress + 4);
+ Memory::Write_U32(0, CommandAddress + 4);
m_Active = false;
return true;
}
-bool CWII_IPC_HLE_Device_net_kd_request::IOCtl(u32 _CommandAddress)
+bool CWII_IPC_HLE_Device_net_kd_request::IOCtl(u32 CommandAddress)
{
- u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC);
- 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 Parameter = Memory::Read_U32(CommandAddress + 0xC);
+ 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 ReturnValue = 0;
switch (Parameter)
@@ -245,8 +246,8 @@ bool CWII_IPC_HLE_Device_net_kd_request::IOCtl(u32 _CommandAddress)
break;
}
- // g_ReplyQueueLater.push(std::pair<u32, std::string>(_CommandAddress, GetDeviceName()));
- Memory::Write_U32(ReturnValue, _CommandAddress + 4);
+ // g_ReplyQueueLater.push(std::pair<u32, std::string>(CommandAddress, GetDeviceName()));
+ Memory::Write_U32(ReturnValue, CommandAddress + 4);
return true;
}
@@ -362,30 +363,30 @@ CWII_IPC_HLE_Device_net_ncd_manage::~CWII_IPC_HLE_Device_net_ncd_manage()
{
}
-bool CWII_IPC_HLE_Device_net_ncd_manage::Open(u32 _CommandAddress, u32 _Mode)
+bool CWII_IPC_HLE_Device_net_ncd_manage::Open(u32 CommandAddress, u32 _Mode)
{
INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: Open");
- Memory::Write_U32(GetDeviceID(), _CommandAddress+4);
+ Memory::Write_U32(GetDeviceID(), CommandAddress+4);
m_Active = true;
return true;
}
-bool CWII_IPC_HLE_Device_net_ncd_manage::Close(u32 _CommandAddress, bool _bForce)
+bool CWII_IPC_HLE_Device_net_ncd_manage::Close(u32 CommandAddress, bool _bForce)
{
INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: Close");
if (!_bForce)
- Memory::Write_U32(0, _CommandAddress + 4);
+ Memory::Write_U32(0, CommandAddress + 4);
m_Active = false;
return true;
}
-bool CWII_IPC_HLE_Device_net_ncd_manage::IOCtlV(u32 _CommandAddress)
+bool CWII_IPC_HLE_Device_net_ncd_manage::IOCtlV(u32 CommandAddress)
{
u32 return_value = 0;
u32 common_result = 0;
u32 common_vector = 0;
- SIOCtlVBuffer CommandBuffer(_CommandAddress);
+ SIOCtlVBuffer CommandBuffer(CommandAddress);
switch (CommandBuffer.Parameter)
{
@@ -471,7 +472,7 @@ bool CWII_IPC_HLE_Device_net_ncd_manage::IOCtlV(u32 _CommandAddress)
Memory::Write_U32(common_result,
CommandBuffer.PayloadBuffer.at(common_vector).m_Address + 4);
}
- Memory::Write_U32(return_value, _CommandAddress + 4);
+ Memory::Write_U32(return_value, CommandAddress + 4);
return true;
}
@@ -611,148 +612,38 @@ CWII_IPC_HLE_Device_net_ip_top::~CWII_IPC_HLE_Device_net_ip_top()
#endif
}
-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)
{
INFO_LOG(WII_IPC_NET, "NET_IP_TOP: Open");
- Memory::Write_U32(GetDeviceID(), _CommandAddress+4);
+ Memory::Write_U32(GetDeviceID(), CommandAddress+4);
m_Active = true;
return true;
}
-bool CWII_IPC_HLE_Device_net_ip_top::Close(u32 _CommandAddress, bool _bForce)
+bool CWII_IPC_HLE_Device_net_ip_top::Close(u32 CommandAddress, bool _bForce)
{
INFO_LOG(WII_IPC_NET, "NET_IP_TOP: Close");
if (!_bForce)
- Memory::Write_U32(0, _CommandAddress + 4);
+ Memory::Write_U32(0, CommandAddress + 4);
m_Active = false;
return true;
}
-bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 _CommandAddress)
-{
- 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);
-
- u32 ReturnValue = ExecuteCommand(Command, BufferIn, BufferInSize, BufferOut, BufferOutSize);
- Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
-
- return true;
-}
-
-struct bind_params
-{
- u32 socket;
- u32 has_name;
- u8 name[28];
-};
-
-struct GC_sockaddr
-{
- u8 sa_len;
- u8 sa_family;
- s8 sa_data[14];
-};
-
-struct GC_in_addr
-{
- // this cannot be named s_addr under windows - collides with some crazy define.
- u32 s_addr_;
-};
-
-struct GC_sockaddr_in
-{
- u8 sin_len;
- u8 sin_family;
- u16 sin_port;
- struct GC_in_addr sin_addr;
- s8 sin_zero[8];
-};
-
-char* DecodeError(int ErrorCode)
-{
-
-#ifdef _WIN32
- static char Message[1024];
- // If this program was multi-threaded, we'd want to use FORMAT_MESSAGE_ALLOCATE_BUFFER
- // instead of a static buffer here.
- // (And of course, free the buffer when we were done with it)
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
- FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, ErrorCode,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)Message, 1024, NULL);
- return Message;
-#else
- return strerror(ErrorCode);
-#endif
-}
-
-static int getNetErrorCode(int ret, std::string caller, bool isRW)
-{
-#ifdef _WIN32
- int errorCode = WSAGetLastError();
-#else
- int errorCode = errno;
-#endif
-
- if (ret >= 0)
- return ret;
-
- WARN_LOG(WII_IPC_NET, "%s failed with error %d: %s, ret= %d",
- caller.c_str(), errorCode, DecodeError(errorCode), ret);
-
-#ifdef _WIN32
-#define ERRORCODE(name) WSA ## name
-#define EITHER(win32, posix) win32
-#else
-#define ERRORCODE(name) name
-#define EITHER(win32, posix) posix
-#endif
-
- switch (errorCode)
- {
- case ERRORCODE(EMSGSIZE):
- WARN_LOG(WII_IPC_NET, "Find out why this happened, looks like PEEK failure?");
- return -1;
- case ERRORCODE(ECONNRESET):
- return -15; // ECONNRESET
- case ERRORCODE(EISCONN):
- return -30; // EISCONN
- case ERRORCODE(ENOTCONN):
- return -6; // EAGAIN
- case EITHER(WSAEWOULDBLOCK, EAGAIN):
- case ERRORCODE(EINPROGRESS):
- if(isRW){
- return -6; // EAGAIN
- }else{
- return -26; // EINPROGRESS
- }
- case EITHER(WSA_INVALID_HANDLE, EBADF):
- return -26; // EINPROGRESS
- default:
- return -1;
- }
-
-#undef ERRORCODE
-#undef EITHER
-}
-
static int inet_pton(const char *src, unsigned char *dst)
{
static const char digits[] = "0123456789";
int saw_digit, octets, ch;
unsigned char tmp[4], *tp;
-
+
saw_digit = 0;
octets = 0;
*(tp = tmp) = 0;
while ((ch = *src++) != '\0') {
const char *pch;
-
+
if ((pch = strchr(digits, ch)) != NULL) {
unsigned int newt = *tp * 10 + (pch - digits);
-
+
if (newt > 255)
return (0);
*tp = newt;
@@ -788,397 +679,395 @@ static unsigned int opt_name_mapping[][2] = {
{ SO_ERROR, 0x1009 }
};
-u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command,
- u32 _BufferIn, u32 BufferInSize,
- u32 _BufferOut, u32 BufferOutSize)
-{
- switch (_Command)
- {
- case IOCTL_SO_STARTUP:
- WARN_LOG(WII_IPC_NET, "IOCTL_SO_STARTUP "
- "BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
- _BufferIn, BufferInSize, _BufferOut, BufferOutSize);
- break;
- case IOCTL_SO_CONNECT:
+bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 CommandAddress)
+{
+ 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);
+ s32 ReturnValue = 0;
+
+ switch (Command)
+ {
+ case IOCTL_SO_CONNECT:
+ case IOCTL_SO_ACCEPT:
{
- //struct sockaddr_in echoServAddr;
- struct connect_params
+ u32 s = Memory::Read_U32(BufferIn);
+ _tSocket * sock = NULL;
{
- u32 socket;
- u32 has_addr;
- u8 addr[28];
- } params;
- sockaddr_in serverAddr;
-
- Memory::ReadBigEData((u8*)&params, _BufferIn, sizeof(connect_params));
-
- if (Common::swap32(params.has_addr) != 1)
- return -1;
-
- 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;
-
- int ret = connect(Common::swap32(params.socket), (struct sockaddr *) &serverAddr, sizeof(serverAddr));
- ret = getNetErrorCode(ret, "SO_CONNECT", false);
- WARN_LOG(WII_IPC_NET,"IOCTL_SO_CONNECT (%08x, %s:%d)",
- Common::swap32(params.socket), inet_ntoa(serverAddr.sin_addr), Common::swap16(serverAddr.sin_port));
- return ret;
+ std::unique_lock<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 %X", s);
break;
}
-
- case IOCTL_SO_SHUTDOWN:
+
+ case IOCTL_SO_SOCKET:
{
- WARN_LOG(WII_IPC_NET, "IOCTL_SO_SHUTDOWN "
- "BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
- _BufferIn, BufferInSize, _BufferOut, BufferOutSize);
-
- u32 sock = Memory::Read_U32(_BufferIn);
- u32 how = Memory::Read_U32(_BufferIn+4);
- int ret = shutdown(sock, how);
- return getNetErrorCode(ret, "SO_SHUTDOWN", false);
+ u32 AF = Memory::Read_U32(BufferIn);
+ u32 TYPE = Memory::Read_U32(BufferIn + 0x04);
+ u32 PROT = Memory::Read_U32(BufferIn + 0x08);
+ u32 s = (u32)socket(AF, TYPE, PROT);
+ WARN_LOG(WII_IPC_NET, "IOCTL_SO_SOCKET "
+ "Socket: %08x (%d,%d,%d), BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
+ s, AF, TYPE, PROT, BufferIn, BufferInSize, BufferOut, BufferOutSize);
+
+ ReturnValue = getNetErrorCode(s, "SO_SOCKET", false);
+
+ if (ReturnValue > 0)
+ {
+ std::unique_lock<std::mutex> lk(socketMapMutex);
+ _tSocket* sock = new _tSocket();
+ socketMap[s] = sock;
+ sock->thread = new std::thread(&CWII_IPC_HLE_Device_net_ip_top::socketProcessor, this, s);
+ }
+
break;
}
-
- case IOCTL_SO_CLOSE:
+ case IOCTL_SO_STARTUP:
{
- u32 sock = Memory::Read_U32(_BufferIn);
- WARN_LOG(WII_IPC_NET, "IOCTL_SO_CLOSE (%08x)", sock);
-
-#ifdef _WIN32
- u32 ret = closesocket(sock);
-
- return getNetErrorCode(ret, "IOCTL_SO_CLOSE", false);
-#else
- return close(sock);
-#endif
+ WARN_LOG(WII_IPC_NET, "IOCTL_SO_STARTUP "
+ "BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
+ BufferIn, BufferInSize, BufferOut, BufferOutSize);
break;
}
-
- case IOCTL_SO_SOCKET:
+
+ case IOCTL_SO_SHUTDOWN:
{
- u32 AF = Memory::Read_U32(_BufferIn);
- u32 TYPE = Memory::Read_U32(_BufferIn + 0x04);
- u32 PROT = Memory::Read_U32(_BufferIn + 0x08);
- u32 s = (u32)socket(AF, TYPE, PROT);
- WARN_LOG(WII_IPC_NET, "IOCTL_SO_SOCKET "
- "Socket: %08x (%d,%d,%d), BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
- s, AF, TYPE, PROT, _BufferIn, BufferInSize, _BufferOut, BufferOutSize);
-
- int ret = getNetErrorCode(s, "SO_SOCKET", false);
- if(ret>=0){
-#ifdef _WIN32
- u32 millis = 3000;
-#else
- struct timeval millis;
- millis.tv_sec = 3;
- millis.tv_usec = 0;
-#endif
- setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char *)&millis,sizeof(millis));
- }
+ WARN_LOG(WII_IPC_NET, "IOCTL_SO_SHUTDOWN "
+ "BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
+ BufferIn, BufferInSize, BufferOut, BufferOutSize);
+ u32 sock = Memory::Read_U32(BufferIn);
+ u32 how = Memory::Read_U32(BufferIn+4);
+ ReturnValue = shutdown(sock, how);
+ ReturnValue = getNetErrorCode(ReturnValue, "SO_SHUTDOWN", false);
+ break;
+ }
+
+ case IOCTL_SO_CLOSE:
+ {
+ u32 s = Memory::Read_U32(BufferIn);
+ WARN_LOG(WII_IPC_NET, "IOCTL_SO_CLOSE (%08x)", s);
+ #ifdef _WIN32
+ ReturnValue = closesocket(s);
+
+ ReturnValue = getNetErrorCode(ReturnValue, "IOCTL_SO_CLOSE", false);
+ #else
+ ReturnValue = close(s);
+ #endif
+
+ _tSocket * sock = NULL;
+ {
+ std::unique_lock<std::mutex> lk(socketMapMutex);
+ if(socketMap.find(s) != socketMap.end())
+ sock = socketMap[s];
+ if(sock)
+ {
+ //cascading failures hopefully
+ sock->StopAndJoin();
+ delete sock;
+ socketMap.erase(s);
+ }
+ }
- return ret;
+
break;
}
-
- case IOCTL_SO_BIND:
+ case IOCTL_SO_BIND:
{
- bind_params *addr = (bind_params*)Memory::GetPointer(_BufferIn);
+ bind_params *addr = (bind_params*)Memory::GetPointer(BufferIn);
GC_sockaddr_in addrPC;
memcpy(&addrPC, addr->name, sizeof(GC_sockaddr_in));
sockaddr_in address;
address.sin_family = addrPC.sin_family;
address.sin_addr.s_addr = addrPC.sin_addr.s_addr_;
address.sin_port = addrPC.sin_port;
- int ret = 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 "
- "Socket: %08X, BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
- inet_ntoa(address.sin_addr), Common::swap16(address.sin_port), ret,
- Common::swap32(addr->socket), _BufferIn, BufferInSize, _BufferOut, BufferOutSize);
-
- return getNetErrorCode(ret, "SO_BIND", false);
+ "Socket: %08X, BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
+ inet_ntoa(address.sin_addr), Common::swap16(address.sin_port), ReturnValue,
+ Common::swap32(addr->socket), BufferIn, BufferInSize, BufferOut, BufferOutSize);
+
+ ReturnValue = getNetErrorCode(ReturnValue, "SO_BIND", false);
break;
}
-
- case IOCTL_SO_LISTEN:
+
+ case IOCTL_SO_LISTEN:
{
WARN_LOG(WII_IPC_NET, "IOCTL_SO_LISTEN "
- "BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
- _BufferIn, BufferInSize, _BufferOut, BufferOutSize);
-
- u32 S = Memory::Read_U32(_BufferIn);
- u32 BACKLOG = Memory::Read_U32(_BufferIn + 0x04);
- u32 ret = listen(S, BACKLOG);
- return getNetErrorCode(ret, "SO_LISTEN", false);
+ "BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
+ BufferIn, BufferInSize, BufferOut, BufferOutSize);
+
+ u32 S = Memory::Read_U32(BufferIn);
+ u32 BACKLOG = Memory::Read_U32(BufferIn + 0x04);
+ ReturnValue = listen(S, BACKLOG);
+ ReturnValue = getNetErrorCode(ReturnValue, "SO_LISTEN", false);
break;
}
-
- case IOCTL_SO_ACCEPT:
- {
- WARN_LOG(WII_IPC_NET, "IOCTL_SO_ACCEPT "
- "BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
- _BufferIn, BufferInSize, _BufferOut, BufferOutSize);
-
- u32 S = Memory::Read_U32(_BufferIn);
- struct sockaddr* addr = (struct sockaddr*) Memory::GetPointer(_BufferOut);
- socklen_t* addrlen = (socklen_t*) Memory::GetPointer(BufferOutSize);
- *addrlen = sizeof(struct sockaddr);
- int ret = accept(S, addr, addrlen);
- return getNetErrorCode(ret, "SO_ACCEPT", false);
- }
-
- case IOCTL_SO_GETSOCKOPT:
+
+ case IOCTL_SO_GETSOCKOPT:
{
- u32 sock = Memory::Read_U32(_BufferOut);
- u32 level = Memory::Read_U32(_BufferOut + 4);
- u32 optname = Memory::Read_U32(_BufferOut + 8);
-
+ u32 sock = Memory::Read_U32(BufferOut);
+ u32 level = Memory::Read_U32(BufferOut + 4);
+ u32 optname = Memory::Read_U32(BufferOut + 8);
+
WARN_LOG(WII_IPC_NET,"IOCTL_SO_GETSOCKOPT(%08x, %08x, %08x)"
- "BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
- sock, level, optname,
- _BufferIn, BufferInSize, _BufferOut, BufferOutSize);
-
+ "BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
+ sock, level, optname,
+ BufferIn, BufferInSize, BufferOut, BufferOutSize);
+
// Do the level/optname translation
int nat_level = -1, nat_optname = -1;
-
+
for (unsigned int i = 0; i < sizeof (opt_level_mapping) / sizeof (opt_level_mapping[0]); ++i)
if (level == opt_level_mapping[i][1])
nat_level = opt_level_mapping[i][0];
-
- for (unsigned int i = 0; i < sizeof (opt_name_mapping) / sizeof (opt_name_mapping[0]); ++i)
- if (optname == opt_name_mapping[i][1])
- nat_optname = opt_name_mapping[i][0];
-
- u8 optval[20];
- u32 optlen = 4;
-
- int ret = getsockopt (sock, nat_level, nat_optname, (char *) &optval, (socklen_t*)&optlen);
-
- ret = getNetErrorCode(ret, "SO_GETSOCKOPT", false);
-
-
- Memory::Write_U32(optlen, _BufferOut + 0xC);
- Memory::WriteBigEData((u8 *) optval, _BufferOut + 0x10, optlen);
-
+
+ for (unsigned int i = 0; i < sizeof (opt_name_mapping) / sizeof (opt_name_mapping[0]); ++i)
+ if (optname == opt_name_mapping[i][1])
+ nat_optname = opt_name_mapping[i][0];
+
+ u8 optval[20];
+ u32 optlen = 4;
+
+ ReturnValue = getsockopt (sock, nat_level, nat_optname, (char *) &optval, (socklen_t*)&optlen);
+
+ ReturnValue = getNetErrorCode(ReturnValue, "SO_GETSOCKOPT", false);
+
+
+ Memory::Write_U32(optlen, BufferOut + 0xC);
+ Memory::WriteBigEData((u8 *) optval, BufferOut + 0x10, optlen);
+
if(optname == 0x1007){
- s32 errorcode = Memory::Read_U32(_BufferOut + 0x10);
+ s32 errorcode = Memory::Read_U32(BufferOut + 0x10);
WARN_LOG(WII_IPC_NET,"IOCTL_SO_GETSOCKOPT error code = %i", errorcode);
}
- return ret;
+ break;
}
-
- case IOCTL_SO_SETSOCKOPT:
+
+ case IOCTL_SO_SETSOCKOPT:
{
- u32 S = Memory::Read_U32(_BufferIn);
- u32 level = Memory::Read_U32(_BufferIn + 4);
- u32 optname = Memory::Read_U32(_BufferIn + 8);
- u32 optlen = Memory::Read_U32(_BufferIn + 0xc);
+ u32 S = Memory::Read_U32(BufferIn);
+ u32 level = Memory::Read_U32(BufferIn + 4);
+ u32 optname = Memory::Read_U32(BufferIn + 8);
+ u32 optlen = Memory::Read_U32(BufferIn + 0xc);
u8 optval[20];
- Memory::ReadBigEData(optval, _BufferIn + 0x10, optlen);
-
+ Memory::ReadBigEData(optval, BufferIn + 0x10, optlen);
+
//TODO: bug booto about this, 0x2005 most likely timeout related, default value on wii is , 0x2001 is most likely tcpnodelay
if (level == 6 && (optname == 0x2005 || optname == 0x2001)){
- return 0;
+ ReturnValue = 0;
+ break;
}
WARN_LOG(WII_IPC_NET, "IOCTL_SO_SETSOCKOPT(%08x, %08x, %08x, %08x) "
"BufferIn: (%08x, %i), BufferOut: (%08x, %i)"
"%02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx",
- S, level, optname, optlen, _BufferIn, BufferInSize, _BufferOut, BufferOutSize, optval[0], optval[1], optval[2], optval[3], optval[4], optval[5], optval[6], optval[7], optval[8], optval[9], optval[10], optval[11], optval[12], optval[13], optval[14], optval[15], optval[16], optval[17], optval[18], optval[19]);
-
+ S, level, optname, optlen, BufferIn, BufferInSize, BufferOut, BufferOutSize,
+ optval[0], optval[1], optval[2], optval[3],
+ optval[4], optval[5], optval[6], optval[7],
+ optval[8], optval[9], optval[10], optval[11],
+ optval[12], optval[13], optval[14], optval[15],
+ optval[16], optval[17], optval[18], optval[19]);
+
// Do the level/optname translation
int nat_level = -1, nat_optname = -1;
-
+
for (unsigned int i = 0; i < sizeof (opt_level_mapping) / sizeof (opt_level_mapping[0]); ++i)
if (level == opt_level_mapping[i][1])
nat_level = opt_level_mapping[i][0];
-
+
for (unsigned int i = 0; i < sizeof (opt_name_mapping) / sizeof (opt_name_mapping[0]); ++i)
if (optname == opt_name_mapping[i][1])
nat_optname = opt_name_mapping[i][0];
-
+
if (nat_level == -1 || nat_optname == -1)
{
WARN_LOG(WII_IPC_NET, "SO_SETSOCKOPT: unknown level %d or optname %d", level, optname);
-
+
// Default to the given level/optname. They match on Windows...
nat_level = level;
nat_optname = optname;
}
-
- int ret = setsockopt(S, nat_level, nat_optname, (char*)optval, optlen);
-
- ret = getNetErrorCode(ret, "SO_SETSOCKOPT", false);
-
- return ret;
+
+ ReturnValue = setsockopt(S, nat_level, nat_optname, (char*)optval, optlen);
+ ReturnValue = getNetErrorCode(ReturnValue, "SO_SETSOCKOPT", false);
+
+ break;
}
-
- case IOCTL_SO_FCNTL:
+
+ case IOCTL_SO_FCNTL:
{
- u32 sock = Memory::Read_U32(_BufferIn);
- u32 cmd = Memory::Read_U32(_BufferIn + 4);
- u32 arg = Memory::Read_U32(_BufferIn + 8);
-
+ u32 sock = Memory::Read_U32(BufferIn);
+ u32 cmd = Memory::Read_U32(BufferIn + 4);
+ u32 arg = Memory::Read_U32(BufferIn + 8);
+
WARN_LOG(WII_IPC_NET, "IOCTL_SO_FCNTL(%08X, %08X) "
- "Socket: %08x, BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
- cmd, arg,
- sock, _BufferIn, BufferInSize, _BufferOut, BufferOutSize);
-#ifdef _WIN32
-#define F_GETFL 3
-#define F_SETFL 4
-#define F_NONBLOCK 4
- if (cmd == F_GETFL)
- {
- WARN_LOG(WII_IPC_NET, "F_GETFL WTF?");
- }
- else if (cmd == F_SETFL)
- {
- u_long iMode = 0;
- //if (arg & F_NONBLOCK)
- iMode = 1;
- int ioctlret = ioctlsocket(sock, FIONBIO, &iMode);
- return getNetErrorCode(ioctlret, "SO_FCNTL", false);
- }
- else
- {
- WARN_LOG(WII_IPC_NET, "SO_FCNTL unknown command");
- }
- return 0;
-#else
- // Map POSIX <-> Wii socket flags
- // First one is POSIX, second one is Wii
- static int mapping[][2] = {
- { O_NONBLOCK, 0x4 },
- };
-
- if (cmd == F_GETFL)
- {
- int flags = fcntl(sock, F_GETFL, 0);
- int ret = 0;
-
- for (unsigned int i = 0; i < sizeof (mapping) / sizeof (mapping[0]); ++i)
- if (flags & mapping[i][0])
- ret |= mapping[i][1];
- return ret;
- }
- else if (cmd == F_SETFL)
- {
- int posix_flags = O_NONBLOCK; //0;
-
- for (unsigned int i = 0; i < sizeof (mapping) / sizeof (mapping[0]); ++i)
+ "Socket: %08x, BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
+ cmd, arg,
+ sock, BufferIn, BufferInSize, BufferOut, BufferOutSize);
+ #ifdef _WIN32
+ #define F_GETFL 3
+ #define F_SETFL 4
+ #define F_NONBLOCK 4
+ if (cmd == F_GETFL)
{
- if (arg & mapping[i][1])
+ WARN_LOG(WII_IPC_NET, "F_GETFL WTF?");
+ }
+ else if (cmd == F_SETFL)
+ {
+ u_long iMode = 0;
+ if (arg & F_NONBLOCK)
+ iMode = 1;
+ ReturnValue = ioctlsocket(sock, FIONBIO, &iMode);
+ ReturnValue = getNetErrorCode(ReturnValue, "SO_FCNTL", false);
+ }
+ else
+ {
+ WARN_LOG(WII_IPC_NET, "SO_FCNTL unknown command");
+ }
+ #else
+ // Map POSIX <-> Wii socket flags
+ // First one is POSIX, second one is Wii
+ static int mapping[][2] = {
+ { O_NONBLOCK, 0x4 },
+ };
+
+ if (cmd == F_GETFL)
+ {
+ int flags = fcntl(sock, F_GETFL, 0);
+ ReturnValue = 0;
+
+ for (unsigned int i = 0; i < sizeof (mapping) / sizeof (mapping[0]); ++i)
+ if (flags & mapping[i][0])
+ ReturnValue |= mapping[i][1];
+ }
+ else if (cmd == F_SETFL)
+ {
+ int posix_flags = 0;
+
+ for (unsigned int i = 0; i < sizeof (mapping) / sizeof (mapping[0]); ++i)
{
- posix_flags |= mapping[i][0];
- arg &= ~mapping[i][1];
+ if (arg & mapping[i][1])
+ {
+ posix_flags |= mapping[i][0];
+ arg &= ~mapping[i][1];
+ }
}
+
+ if (arg)
+ WARN_LOG(WII_IPC_NET, "SO_FCNTL F_SETFL unhandled flags: %08x", arg);
+
+ ReturnValue = fcntl(sock, F_SETFL, posix_flags);
+ ReturnValue = getNetErrorCode(ReturnValue, "SO_FCNTL", false);
}
-
- if (arg)
- WARN_LOG(WII_IPC_NET, "SO_FCNTL F_SETFL unhandled flags: %08x", arg);
-
- int ret = fcntl(sock, F_SETFL, posix_flags);
- return getNetErrorCode(ret, "SO_FCNTL", false);
- }
- else
- {
- WARN_LOG(WII_IPC_NET, "SO_FCNTL unknown command");
- }
- return 0;
-#endif
+ else
+ {
+ WARN_LOG(WII_IPC_NET, "SO_FCNTL unknown command");
+ }
+ #endif
+ break;
}
-
- case IOCTL_SO_GETSOCKNAME:
+
+ case IOCTL_SO_GETSOCKNAME:
{
- u32 sock = Memory::Read_U32(_BufferIn);
-
+ u32 sock = Memory::Read_U32(BufferIn);
+
WARN_LOG(WII_IPC_NET, "IOCTL_SO_GETSOCKNAME "
- "Socket: %08X, BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
- sock, _BufferIn, BufferInSize, _BufferOut, BufferOutSize);
-
+ "Socket: %08X, BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
+ sock, BufferIn, BufferInSize, BufferOut, BufferOutSize);
+
sockaddr sa;
socklen_t sa_len;
sa_len = sizeof(sa);
- int ret = getsockname(sock, &sa, &sa_len);
-
- Memory::Write_U8(BufferOutSize, _BufferOut);
- Memory::Write_U8(sa.sa_family & 0xFF, _BufferOut + 1);
- Memory::WriteBigEData((u8*)&sa.sa_data, _BufferOut + 2, BufferOutSize - 2);
- return ret;
+ ReturnValue = getsockname(sock, &sa, &sa_len);
+
+ Memory::Write_U8(BufferOutSize, BufferOut);
+ Memory::Write_U8(sa.sa_family & 0xFF, BufferOut + 1);
+ Memory::WriteBigEData((u8*)&sa.sa_data, BufferOut + 2, BufferOutSize - 2);
+ break;
}
- case IOCTL_SO_GETPEERNAME:
+ case IOCTL_SO_GETPEERNAME:
{
- u32 sock = Memory::Read_U32(_BufferIn);
-
+ u32 sock = Memory::Read_U32(BufferIn);
+
sockaddr sa;
socklen_t sa_len;
sa_len = sizeof(sa);
-
- int ret = getpeername(sock, &sa, &sa_len);
-
- Memory::Write_U8(BufferOutSize, _BufferOut);
- Memory::Write_U8(AF_INET, _BufferOut + 1);
- Memory::WriteBigEData((u8*)&sa.sa_data, _BufferOut + 2, BufferOutSize - 2);
+
+ ReturnValue = getpeername(sock, &sa, &sa_len);
+
+ Memory::Write_U8(BufferOutSize, BufferOut);
+ Memory::Write_U8(AF_INET, BufferOut + 1);
+ Memory::WriteBigEData((u8*)&sa.sa_data, BufferOut + 2, BufferOutSize - 2);
WARN_LOG(WII_IPC_NET, "IOCTL_SO_GETPEERNAME(%x)", sock);
-
- return ret;
+
+ break;
}
-
- case IOCTL_SO_GETHOSTID:
+ case IOCTL_SO_GETHOSTID:
{
WARN_LOG(WII_IPC_NET, "IOCTL_SO_GETHOSTID "
- "(BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
- _BufferIn, BufferInSize, _BufferOut, BufferOutSize);
- return 192 << 24 | 168 << 16 | 1 << 8 | 150;
+ "(BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
+ BufferIn, BufferInSize, BufferOut, BufferOutSize);
+ ReturnValue = 192 << 24 | 168 << 16 | 1 << 8 | 150;
+ break;
}
-
- case IOCTL_SO_INETATON:
+ case IOCTL_SO_INETATON:
{
- struct hostent *remoteHost = gethostbyname((char*)Memory::GetPointer(_BufferIn));
-
- Memory::Write_U32(Common::swap32(*(u32 *)remoteHost->h_addr_list[0]), _BufferOut);
+ struct hostent *remoteHost = gethostbyname((char*)Memory::GetPointer(BufferIn));
+
+ Memory::Write_U32(Common::swap32(*(u32 *)remoteHost->h_addr_list[0]), BufferOut);
WARN_LOG(WII_IPC_NET, "IOCTL_SO_INETATON = %d "
- "%s, BufferIn: (%08x, %i), BufferOut: (%08x, %i), IP Found: %08X",remoteHost->h_addr_list[0] == 0 ? -1 : 0,
- (char*)Memory::GetPointer(_BufferIn), _BufferIn, BufferInSize, _BufferOut, BufferOutSize, Common::swap32(*(u32 *)remoteHost->h_addr_list[0]));
- return remoteHost->h_addr_list[0] == 0 ? 0 : 1;
+ "%s, BufferIn: (%08x, %i), BufferOut: (%08x, %i), IP Found: %08X",remoteHost->h_addr_list[0] == 0 ? -1 : 0,
+ (char*)Memory::GetPointer(BufferIn), BufferIn, BufferInSize, BufferOut, BufferOutSize, Common::swap32(*(u32 *)remoteHost->h_addr_list[0]));
+ ReturnValue = remoteHost->h_addr_list[0] == 0 ? 0 : 1;
+ break;
}
-
- case IOCTL_SO_INETPTON:
+ case IOCTL_SO_INETPTON:
{
WARN_LOG(WII_IPC_NET, "IOCTL_SO_INETPTON "
- "(Translating: %s)", Memory::GetPointer(_BufferIn));
- return inet_pton((char*)Memory::GetPointer(_BufferIn), Memory::GetPointer(_BufferOut+4));
+ "(Translating: %s)", Memory::GetPointer(BufferIn));
+ ReturnValue = inet_pton((char*)Memory::GetPointer(BufferIn), Memory::GetPointer(BufferOut+4));
break;
}
-
- case IOCTL_SO_INETNTOP:
+ case IOCTL_SO_INETNTOP:
{
- u32 af = Memory::Read_U32(_BufferIn);
- //u32 af = Memory::Read_U32(_BufferIn + 4);
- u32 src = Memory::Read_U32(_BufferIn + 8);
- //u32 af = Memory::Read_U32(_BufferIn + 12);
- //u32 af = Memory::Read_U32(_BufferIn + 16);
- //u32 af = Memory::Read_U32(_BufferIn + 20);
+ u32 af = Memory::Read_U32(BufferIn);
+ //u32 af = Memory::Read_U32(BufferIn + 4);
+ u32 src = Memory::Read_U32(BufferIn + 8);
+ //u32 af = Memory::Read_U32(BufferIn + 12);
+ //u32 af = Memory::Read_U32(BufferIn + 16);
+ //u32 af = Memory::Read_U32(BufferIn + 20);
char ip_s[16];
sprintf(ip_s, "%i.%i.%i.%i",
- Memory::Read_U8(_BufferIn + 8),
- Memory::Read_U8(_BufferIn + 8 + 1),
- Memory::Read_U8(_BufferIn + 8 + 2),
- Memory::Read_U8(_BufferIn + 8 + 3)
- );
+ Memory::Read_U8(BufferIn + 8),
+ Memory::Read_U8(BufferIn + 8 + 1),
+ Memory::Read_U8(BufferIn + 8 + 2),
+ Memory::Read_U8(BufferIn + 8 + 3)
+ );
WARN_LOG(WII_IPC_NET, "IOCTL_SO_INETNTOP %s", ip_s);
- memset(Memory::GetPointer(_BufferOut), 0, BufferOutSize);
- memcpy(Memory::GetPointer(_BufferOut), ip_s, strlen(ip_s));
- return 0;
+ memset(Memory::GetPointer(BufferOut), 0, BufferOutSize);
+ memcpy(Memory::GetPointer(BufferOut), ip_s, strlen(ip_s));
+ break;
}
-
- case IOCTL_SO_POLL:
+
+ case IOCTL_SO_POLL:
{
// Map Wii/native poll events types
unsigned int mapping[][2] = {
@@ -1186,24 +1075,27 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command,
{ POLLOUT, 0x0008 },
{ POLLHUP, 0x0040 },
};
-
- u32 unknown = Memory::Read_U32(_BufferIn);
- u32 timeout = Memory::Read_U32(_BufferIn + 4);
-
+
+ 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)
- return -1;
-
+ {
+ 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
-
+ 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;
@@ -1213,21 +1105,20 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command,
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
+ "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);
}
-
- int ret = poll(ufds, nfds, timeout);
-
- ret = getNetErrorCode(ret, "SO_POLL", false);
-
+
+ ReturnValue = poll(ufds, nfds, timeout);
+ ReturnValue = getNetErrorCode(ReturnValue, "SO_POLL", false);
+
for (int i = 0; i<nfds; i++)
{
@@ -1240,65 +1131,65 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command,
}
// 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
+ // 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);
- return ret;
+ break;
}
-
- case IOCTL_SO_GETHOSTBYNAME:
+
+ case IOCTL_SO_GETHOSTBYNAME:
{
- hostent *remoteHost = gethostbyname((char*)Memory::GetPointer(_BufferIn));
-
+ hostent *remoteHost = gethostbyname((char*)Memory::GetPointer(BufferIn));
+
WARN_LOG(WII_IPC_NET, "IOCTL_SO_GETHOSTBYNAME "
- "Address: %s, BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
- (char*)Memory::GetPointer(_BufferIn), _BufferIn, BufferInSize, _BufferOut, BufferOutSize);
-
+ "Address: %s, BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
+ (char*)Memory::GetPointer(BufferIn), BufferIn, BufferInSize, BufferOut, BufferOutSize);
+
if (remoteHost)
{
for (int i = 0; remoteHost->h_aliases[i]; ++i)
{
WARN_LOG(WII_IPC_NET, "alias%i:%s", i, remoteHost->h_aliases[i]);
}
-
+
for (int i = 0; remoteHost->h_addr_list[i]; ++i)
{
u32 ip = Common::swap32(*(u32*)(remoteHost->h_addr_list[i]));
char ip_s[16];
sprintf(ip_s, "%i.%i.%i.%i",
- ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
+ ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
DEBUG_LOG(WII_IPC_NET, "addr%i:%s", i, ip_s);
}
-
- Memory::Memset(_BufferOut, 0, BufferOutSize);
- u32 wii_addr = _BufferOut + 4 * 3 + 2 * 2;
-
+
+ Memory::Memset(BufferOut, 0, BufferOutSize);
+ u32 wii_addr = BufferOut + 4 * 3 + 2 * 2;
+
u32 name_length = strlen(remoteHost->h_name) + 1;
Memory::WriteBigEData((const u8 *)remoteHost->h_name, wii_addr, name_length);
- Memory::Write_U32(wii_addr, _BufferOut);
+ Memory::Write_U32(wii_addr, BufferOut);
wii_addr += (name_length + 4) & ~3;
-
+
// aliases - empty
- Memory::Write_U32(wii_addr, _BufferOut + 4);
+ Memory::Write_U32(wii_addr, BufferOut + 4);
Memory::Write_U32(wii_addr + sizeof(u32), wii_addr);
wii_addr += sizeof(u32);
Memory::Write_U32((u32)NULL, wii_addr);
wii_addr += sizeof(u32);
-
+
// hardcode to ipv4
_dbg_assert_msg_(WII_IPC_NET,
- remoteHost->h_addrtype == AF_INET && remoteHost->h_length == sizeof(u32),
- "returned host info is not IPv4");
- Memory::Write_U16(AF_INET, _BufferOut + 8);
- Memory::Write_U16(sizeof(u32), _BufferOut + 10);
-
+ remoteHost->h_addrtype == AF_INET && remoteHost->h_length == sizeof(u32),
+ "returned host info is not IPv4");
+ Memory::Write_U16(AF_INET, BufferOut + 8);
+ Memory::Write_U16(sizeof(u32), BufferOut + 10);
+
// addrlist - probably only really need to return 1 anyways...
- Memory::Write_U32(wii_addr, _BufferOut + 12);
+ Memory::Write_U32(wii_addr, BufferOut + 12);
u32 num_addr = 0;
while (remoteHost->h_addr_list[num_addr])
num_addr++;
@@ -1316,142 +1207,459 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command,
Memory::Write_U32_Swap(*(u32*)(remoteHost->h_addr_list[i]), wii_addr);
wii_addr += sizeof(u32);
}
-
+
//ERROR_LOG(WII_IPC_NET, "\n%s",
- // ArrayToString(Memory::GetPointer(_BufferOut), BufferOutSize, 16).c_str());
- return 0;
+ // ArrayToString(Memory::GetPointer(BufferOut), BufferOutSize, 16).c_str());
+ ReturnValue = 0;
}
else
{
- return -1;
+ ReturnValue = -1;
}
-
+
break;
}
-
- case IOCTL_SO_ICMPSOCKET:
+
+ case IOCTL_SO_ICMPSOCKET:
{
// AF type?
- u32 arg = Memory::Read_U32(_BufferIn);
+ u32 arg = Memory::Read_U32(BufferIn);
u32 sock = (u32)socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
DEBUG_LOG(WII_IPC_NET, "IOCTL_SO_ICMPSOCKET(%x) %x", arg, sock);
- return getNetErrorCode(sock, "IOCTL_SO_ICMPSOCKET", false);
+ ReturnValue = getNetErrorCode(sock, "IOCTL_SO_ICMPSOCKET", false);
+ break;
}
+
+ case IOCTL_SO_ICMPCANCEL:
+ ERROR_LOG(WII_IPC_NET, "IOCTL_SO_ICMPCANCEL");
+ goto default_;
+
+ case IOCTL_SO_ICMPCLOSE:
+ {
+ u32 sock = Memory::Read_U32(BufferIn);
+ #ifdef _WIN32
+ u32 ReturnValue = closesocket(sock);
+ #else
+ u32 ReturnValue = close(sock);
+ #endif
+ DEBUG_LOG(WII_IPC_NET, "IOCTL_SO_ICMPCLOSE(%x) %x", sock, ReturnValue);
+ ReturnValue = getNetErrorCode(ReturnValue, "IOCTL_SO_ICMPCLOSE", false);
+ break;
+ }
+
+ default:
+ {
+ WARN_LOG(WII_IPC_NET,"0x%x "
+ "BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
+ Command, BufferIn, BufferInSize, BufferOut, BufferOutSize);
+default_:
+ if (BufferInSize)
+ {
+ ERROR_LOG(WII_IPC_NET, "in addr %x size %x", BufferIn, BufferInSize);
+ ERROR_LOG(WII_IPC_NET, "\n%s",
+ ArrayToString(Memory::GetPointer(BufferIn), BufferInSize, 4).c_str()
+ );
+ }
+
+ if (BufferOutSize)
+ {
+ ERROR_LOG(WII_IPC_NET, "out addr %x size %x", BufferOut, BufferOutSize);
+ }
+ break;
+ }
+ }
+
+ Memory::Write_U32(ReturnValue, CommandAddress + 0x4);
- case IOCTL_SO_ICMPCANCEL:
- ERROR_LOG(WII_IPC_NET, "IOCTL_SO_ICMPCANCEL");
- goto default_;
+ return true;
+}
- case IOCTL_SO_ICMPCLOSE:
- {
- u32 sock = Memory::Read_U32(_BufferIn);
+char* DecodeError(int ErrorCode)
+{
+
+#ifdef _WIN32
+ char Message[1024];
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, ErrorCode,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)Message, 1024, NULL);
+ return Message;
+#else
+ return strerror(ErrorCode);
+#endif
+}
+
+int getNetErrorCode(int ret, std::string caller, bool isRW)
+{
#ifdef _WIN32
- u32 ret = closesocket(sock);
+ int errorCode = WSAGetLastError();
#else
- u32 ret = close(sock);
+ int errorCode = errno;
#endif
- DEBUG_LOG(WII_IPC_NET, "IOCTL_SO_ICMPCLOSE(%x) %x", sock, ret);
- return getNetErrorCode(ret, "IOCTL_SO_ICMPCLOSE", false);
- }
+ if (ret >= 0)
+ return ret;
+
+ WARN_LOG(WII_IPC_NET, "%s failed with error %d: %s, ret= %d",
+ caller.c_str(), errorCode, DecodeError(errorCode), ret);
+
+#ifdef _WIN32
+#define ERRORCODE(name) WSA ## name
+#define EITHER(win32, posix) win32
+#else
+#define ERRORCODE(name) name
+#define EITHER(win32, posix) posix
+#endif
+
+ switch (errorCode)
+ {
+ case ERRORCODE(EMSGSIZE):
+ WARN_LOG(WII_IPC_NET, "Find out why this happened, looks like PEEK failure?");
+ return -1;
+ case ERRORCODE(ECONNRESET):
+ return -15; // ECONNRESET
+ case ERRORCODE(EISCONN):
+ return -30; // EISCONN
+ case ERRORCODE(ENOTCONN):
+ return -6; // EAGAIN
+ case EITHER(WSAEWOULDBLOCK, EAGAIN):
+ case ERRORCODE(EINPROGRESS):
+ if(isRW){
+ return -6; // EAGAIN
+ }else{
+ return -26; // EINPROGRESS
+ }
+ case EITHER(WSA_INVALID_HANDLE, EBADF):
+ return -26; // EINPROGRESS (should be -8)
default:
- WARN_LOG(WII_IPC_NET,"0x%x "
- "BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
- _Command, _BufferIn, BufferInSize, _BufferOut, BufferOutSize);
- default_:
- if (BufferInSize)
+ return -1;
+ }
+
+#undef ERRORCODE
+#undef EITHER
+}
+
+
+void CWII_IPC_HLE_Device_net_ip_top::socketProcessor(u32 socket)
+{
+ ERROR_LOG(WII_IPC_NET, "Socket %d has started a thread.... oh dear.", socket);
+ _tSocket* sock = NULL;
+ {
+ std::unique_lock<std::mutex> lk(socketMapMutex);
+ if(socketMap.find(socket) == socketMap.end())
{
- ERROR_LOG(WII_IPC_NET, "in addr %x size %x", _BufferIn, BufferInSize);
- ERROR_LOG(WII_IPC_NET, "\n%s",
- ArrayToString(Memory::GetPointer(_BufferIn), BufferInSize, 4).c_str()
- );
+ ERROR_LOG(WII_IPC_NET, "Socket %d could not be found in the socket map.", socket);
+ return;
}
-
- if (BufferOutSize)
+ sock = socketMap[socket];
+ }
+ while((sock->WaitForEvent(), true) && sock->running)
+ {
+ u32 CommandAddress = 0;
+ while(sock->getCommand(CommandAddress))
{
- ERROR_LOG(WII_IPC_NET, "out addr %x size %x", _BufferOut, BufferOutSize);
+
+ 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:
+ {
+ 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*)&params, 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)
+ {
+ SIOCtlVBuffer CommandBuffer(CommandAddress);
+
+ 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*)&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:
+ {
+
+ ERROR_LOG(WII_IPC_NET, "Socket %d has received an unknown IOCTLV %d.", socket, CommandBuffer.Parameter);
+ break;
+ }
+ }
+ }
+
+ Memory::Write_U32(8, CommandAddress);
+ // IOS seems to write back the command that was responded to
+ Memory::Write_U32(CommandType, CommandAddress + 8);
+ // Return value
+ Memory::Write_U32(ReturnValue, CommandAddress + 4);
+ WII_IPC_HLE_Interface::EnqReply(CommandAddress);
}
- break;
+
+ //DEBUG_LOG(WII_IPC_NET, "Socket %d has processed all events.", socket);
}
-
- // We return a success for any potential unknown requests
- return 0;
+ //DEBUG_LOG(WII_IPC_NET, "Socket %d has died.", socket);
}
-u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer)
-{
- u32 _BufferIn = 0, _BufferIn2 = 0, _BufferIn3 = 0;
+
+bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 CommandAddress)
+{
+ 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 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ BufferOut3 = CommandBuffer.PayloadBuffer.at(2).m_Address;
BufferOutSize3 = CommandBuffer.PayloadBuffer.at(2).m_Size;
}
- //struct ifreq { /* BUGBUG: reduced form of ifreq just for this hack */
- // char ifr_name[16];
- // struct sockaddr ifr_addr;
- //};
-
- //struct ifreq ifr; struct sockaddr_in saddr;
- //int fd;
-
-#ifdef _WIN32
- PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL;
- ULONG OutBufferLength = 0;
- ULONG RetVal = 0, i;
-#endif
-
- u32 param = 0, param2 = 0, param3, param4, param5 = 0;
-
switch (CommandBuffer.Parameter)
{
case IOCTLV_SO_GETINTERFACEOPT:
- {
- param = Memory::Read_U32(_BufferIn);
- param2 = Memory::Read_U32(_BufferIn+4);
- param3 = Memory::Read_U32(_BufferOut);
- param4 = Memory::Read_U32(_BufferOut2);
+ {
+ #ifdef _WIN32
+ PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL;
+ ULONG OutBufferLength = 0;
+ ULONG RetVal = 0, i;
+ #endif
+
+ u32 param = 0, param2 = 0, param3, param4, param5 = 0;
+ param = Memory::Read_U32(BufferIn);
+ param2 = Memory::Read_U32(BufferIn+4);
+ param3 = Memory::Read_U32(BufferOut);
+ param4 = Memory::Read_U32(BufferOut2);
if (BufferOutSize >= 8)
{
- param5 = Memory::Read_U32(_BufferOut+4);
+ param5 = Memory::Read_U32(BufferOut+4);
}
WARN_LOG(WII_IPC_NET,"IOCTLV_SO_GETINTERFACEOPT(%08X, %08X) "
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i)",
param, param2,
- _BufferIn, BufferInSize, _BufferIn2, BufferInSize2);
+ BufferIn, BufferInSize, BufferIn2, BufferInSize2);
switch (param2)
{
@@ -1521,32 +1729,32 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer
if (address == 0)
address = 0x08080808;
- Memory::Write_U32(address, _BufferOut);
- Memory::Write_U32(0x08080808, _BufferOut+4);
+ Memory::Write_U32(address, BufferOut);
+ Memory::Write_U32(0x08080808, BufferOut+4);
break;
}
case 0x1003:
- Memory::Write_U32(0, _BufferOut);
+ Memory::Write_U32(0, BufferOut);
break;
case 0x1004:
- Memory::WriteBigEData(default_address, _BufferOut, 6);
+ Memory::WriteBigEData(default_address, BufferOut, 6);
break;
case 0x1005:
- Memory::Write_U32(1, _BufferOut);
- Memory::Write_U32(4, _BufferOut2);
+ Memory::Write_U32(1, BufferOut);
+ Memory::Write_U32(4, BufferOut2);
break;
case 0x4002:
- Memory::Write_U32(2, _BufferOut);
+ Memory::Write_U32(2, BufferOut);
break;
case 0x4003:
- Memory::Write_U32(0xC, _BufferOut2);
- Memory::Write_U32(10 << 24 | 1 << 8 | 30, _BufferOut);
- Memory::Write_U32(255 << 24 | 255 << 16 | 255 << 8 | 0, _BufferOut+4);
- Memory::Write_U32(10 << 24 | 0 << 16 | 255 << 8 | 255, _BufferOut+8);
+ Memory::Write_U32(0xC, BufferOut2);
+ Memory::Write_U32(10 << 24 | 1 << 8 | 30, BufferOut);
+ Memory::Write_U32(255 << 24 | 255 << 16 | 255 << 8 | 0, BufferOut+4);
+ Memory::Write_U32(10 << 24 | 0 << 16 | 255 << 8 | 255, BufferOut+8);
break;
default:
@@ -1555,109 +1763,41 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer
}
- return 0;
+ ReturnValue = 0;
break;
}
case IOCTLV_SO_SENDTO:
+ case IOCTLV_SO_RECVFROM:
+ {
+ u32 s = 0;
+ if (CommandBuffer.Parameter == 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;
-
- int ret = sendto(Common::swap32(params.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",
- ret, Common::swap32(params.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
- );
-
- return getNetErrorCode(ret, "SO_SENDTO", true);
- }
- else
- {
- int ret = send(Common::swap32(params.socket), data,
- BufferInSize, Common::swap32(params.flags));
- WARN_LOG(WII_IPC_NET, "IOCTLV_SO_SEND = %d Socket: %08x, BufferIn: (%08x, %i), BufferIn2: (%08x, %i)",
- ret, Common::swap32(params.socket), _BufferIn, BufferInSize,
- _BufferIn2, BufferInSize2);
-
- return getNetErrorCode(ret, "SO_SEND", true);
- }
- break;
+ s = Memory::Read_U32(BufferIn2);
+ } else {
+ s = Memory::Read_U32(BufferIn);
}
-
- case IOCTLV_SO_RECVFROM:
+
+ _tSocket * sock = NULL;
{
- u32 sock = Memory::Read_U32(_BufferIn);
- 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;
-
- static int ret;
-#ifdef _WIN32
- if(flags & MSG_PEEK){
- unsigned long totallen = 0;
- ioctlsocket(sock, FIONREAD, &totallen);
- return totallen;
- }
-#endif
- ret = recvfrom(sock, buf, len, flags,
- fromlen ? (struct sockaddr*) &addr : NULL,
- fromlen ? &fromlen : 0);
-
- int err = getNetErrorCode(ret, 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 ",
- err, buf, sock, 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);
- }
-
- return err;
+ std::unique_lock<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", s);
+ break;
+ }
+
case IOCTLV_SO_GETADDRINFO:
{
struct addrinfo hints;
@@ -1665,28 +1805,28 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer
if (BufferInSize3)
{
- hints.ai_flags = Memory::Read_U32(_BufferIn3);
- hints.ai_family = Memory::Read_U32(_BufferIn3 + 0x4);
- hints.ai_socktype = Memory::Read_U32(_BufferIn3 + 0x8);
- hints.ai_protocol = Memory::Read_U32(_BufferIn3 + 0xC);
- hints.ai_addrlen = Memory::Read_U32(_BufferIn3 + 0x10);
- hints.ai_canonname = (char*)Memory::Read_U32(_BufferIn3 + 0x14);
- hints.ai_addr = (sockaddr *)Memory::Read_U32(_BufferIn3 + 0x18);
- hints.ai_next = (addrinfo *)Memory::Read_U32(_BufferIn3 + 0x1C);
+ hints.ai_flags = Memory::Read_U32(BufferIn3);
+ hints.ai_family = Memory::Read_U32(BufferIn3 + 0x4);
+ hints.ai_socktype = Memory::Read_U32(BufferIn3 + 0x8);
+ hints.ai_protocol = Memory::Read_U32(BufferIn3 + 0xC);
+ hints.ai_addrlen = Memory::Read_U32(BufferIn3 + 0x10);
+ hints.ai_canonname = (char*)Memory::Read_U32(BufferIn3 + 0x14);
+ hints.ai_addr = (sockaddr *)Memory::Read_U32(BufferIn3 + 0x18);
+ hints.ai_next = (addrinfo *)Memory::Read_U32(BufferIn3 + 0x1C);
}
char* pNodeName = NULL;
if (BufferInSize > 0)
- pNodeName = (char*)Memory::GetPointer(_BufferIn);
+ pNodeName = (char*)Memory::GetPointer(BufferIn);
char* pServiceName = NULL;
if (BufferInSize2 > 0)
- pServiceName = (char*)Memory::GetPointer(_BufferIn2);
+ pServiceName = (char*)Memory::GetPointer(BufferIn2);
- int ret = getaddrinfo(pNodeName, pServiceName, BufferInSize3 ? &hints : NULL, &result);
- u32 addr = _BufferOut;
+ ReturnValue = getaddrinfo(pNodeName, pServiceName, BufferInSize3 ? &hints : NULL, &result);
+ u32 addr = BufferOut;
u32 sockoffset = addr + 0x460;
- if (ret >= 0)
+ if (ReturnValue >= 0)
{
while (result != NULL)
{
@@ -1726,9 +1866,9 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer
WARN_LOG(WII_IPC_NET, "IOCTLV_SO_GETADDRINFO "
"(BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
- _BufferIn, BufferInSize, _BufferOut, BufferOutSize);
- WARN_LOG(WII_IPC_NET, "IOCTLV_SO_GETADDRINFO: %s", Memory::GetPointer(_BufferIn));
- return ret;
+ BufferIn, BufferInSize, BufferOut, BufferOutSize);
+ WARN_LOG(WII_IPC_NET, "IOCTLV_SO_GETADDRINFO: %s", Memory::GetPointer(BufferIn));
+ break;
}
case IOCTLV_SO_ICMPPING:
@@ -1741,19 +1881,19 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer
u32 ip;
} ip_info;
- u32 sock = Memory::Read_U32(_BufferIn);
- u32 num_ip = Memory::Read_U32(_BufferIn + 4);
- u64 timeout = Memory::Read_U64(_BufferIn + 8);
+ u32 sock = Memory::Read_U32(BufferIn);
+ u32 num_ip = Memory::Read_U32(BufferIn + 4);
+ u64 timeout = Memory::Read_U64(BufferIn + 8);
if (num_ip != 1)
{
WARN_LOG(WII_IPC_NET, "IOCTLV_SO_ICMPPING %i IPs", num_ip);
}
- ip_info.length = Memory::Read_U8(_BufferIn + 16);
- ip_info.addr_family = Memory::Read_U8(_BufferIn + 17);
- ip_info.icmp_id = Memory::Read_U16(_BufferIn + 18);
- ip_info.ip = Memory::Read_U32(_BufferIn + 20);
+ ip_info.length = Memory::Read_U8(BufferIn + 16);
+ ip_info.addr_family = Memory::Read_U8(BufferIn + 17);
+ ip_info.icmp_id = Memory::Read_U16(BufferIn + 18);
+ ip_info.ip = Memory::Read_U32(BufferIn + 20);
if (ip_info.length != 8 || ip_info.addr_family != AF_INET)
{
@@ -1774,7 +1914,7 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer
s32 icmp_length = sizeof(data);
if (BufferInSize2 == sizeof(data))
- memcpy(data, Memory::GetPointer(_BufferIn2), BufferInSize2);
+ memcpy(data, Memory::GetPointer(BufferIn2), BufferInSize2);
else
{
// TODO sequence number is incremented either statically, by
@@ -1784,19 +1924,20 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer
icmp_length = 22;
}
- int ret = icmp_echo_req(sock, &addr, data, icmp_length);
- if (ret == icmp_length)
+ ReturnValue = icmp_echo_req(sock, &addr, data, icmp_length);
+ if (ReturnValue == icmp_length)
{
- ret = icmp_echo_rep(sock, &addr, (u32)timeout, icmp_length);
+ ReturnValue = icmp_echo_rep(sock, &addr, (u32)timeout, icmp_length);
}
// TODO proper error codes
- return 0;
+ ReturnValue = 0;
+ break;
}
default:
WARN_LOG(WII_IPC_NET,"0x%x (BufferIn: (%08x, %i), BufferIn2: (%08x, %i)",
- CommandBuffer.Parameter, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2);
+ CommandBuffer.Parameter, BufferIn, BufferInSize, BufferIn2, BufferInSize2);
default_:
for (u32 i = 0; i < CommandBuffer.NumberInBuffer; ++i)
{
@@ -1815,16 +1956,7 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer
}
break;
}
-
- return 0;
-}
-
-bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 CommandAddress)
-{
- SIOCtlVBuffer buf(CommandAddress);
-
- u32 return_value = ExecuteCommandV(buf);
- Memory::Write_U32(return_value, CommandAddress + 4);
+ Memory::Write_U32(ReturnValue, CommandAddress + 4);
return true;
}
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.h
index 75ff25c6eb..6b98564ca7 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.h
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.h
@@ -29,6 +29,7 @@
#include <ws2tcpip.h>
#endif
#include "Timer.h"
+#include "Thread.h"
#include "FileUtil.h"
// data layout of the network configuration file (/shared2/sys/net/02/config.dat)
@@ -568,6 +569,54 @@ private:
}
};
+class _tSocket
+{
+public:
+ bool running;
+ std::mutex m_mutex;
+ std::thread* thread;
+
+ _tSocket()
+ {
+ running = true;
+ }
+
+ bool getCommand(u32& commandAddress)
+ {
+ std::unique_lock<std::mutex> lk(m_mutex);
+ if (commands.empty())
+ return false;
+ commandAddress = commands.front();
+ commands.pop();
+ return true;
+ }
+
+ void addCommand(u32 commandAddress)
+ {
+ std::unique_lock<std::mutex> lk(m_mutex);
+ commands.push(commandAddress);
+ event.Set();
+ }
+
+ void StopAndJoin()
+ {
+ running = false;
+ event.Set();
+ thread->join();
+ delete thread;
+ thread = NULL;
+ }
+
+ void WaitForEvent()
+ {
+ event.Wait();
+ }
+private:
+ Common::Event event;
+ std::queue<u32> commands;
+
+};
+
//////////////////////////////////////////////////////////////////////////
class CWII_IPC_HLE_Device_net_ip_top : public IWII_IPC_HLE_Device
{
@@ -585,6 +634,9 @@ private:
#ifdef _WIN32
WSADATA InitData;
#endif
+ std::map<u32, _tSocket*> socketMap;
+ std::mutex socketMapMutex;
+ void socketProcessor(u32 socket);
enum
{
@@ -629,6 +681,39 @@ private:
u32 ExecuteCommandV(SIOCtlVBuffer& CommandBuffer);
};
+static int getNetErrorCode(int ret, std::string caller, bool isRW);
+
+
+struct bind_params
+{
+ u32 socket;
+ u32 has_name;
+ u8 name[28];
+};
+
+struct GC_sockaddr
+{
+ u8 sa_len;
+ u8 sa_family;
+ s8 sa_data[14];
+};
+
+struct GC_in_addr
+{
+ // this cannot be named s_addr under windows - collides with some crazy define.
+ u32 s_addr_;
+};
+
+struct GC_sockaddr_in
+{
+ u8 sin_len;
+ u8 sin_family;
+ u16 sin_port;
+ struct GC_in_addr sin_addr;
+ s8 sin_zero[8];
+};
+
+
// **********************************************************************************
// Interface for reading and changing network configuration (probably some other stuff as well)
class CWII_IPC_HLE_Device_net_ncd_manage : public IWII_IPC_HLE_Device