diff options
| author | skidau <skidau@gmail.com> | 2013-03-27 12:58:04 +1100 |
|---|---|---|
| committer | skidau <skidau@gmail.com> | 2013-03-27 12:58:04 +1100 |
| commit | d33c19b0cd2bae982c8d35e86a9d3551f9e5c72f (patch) | |
| tree | ae367138689d09a5c64136ea5f516eec9ecec448 /Source/Core | |
| parent | ebf79a88653fc2d1b049fc25007868063cd2e46a (diff) | |
Revert the threading of wii-network.
This rolls back to commit bca2cac640e4aff69a97b919411855d0e4b305da.
Diffstat (limited to 'Source/Core')
| -rw-r--r-- | Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp | 12 | ||||
| -rw-r--r-- | Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp | 1654 | ||||
| -rw-r--r-- | Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.h | 87 |
3 files changed, 733 insertions, 1020 deletions
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp index 9c1072f030..83e2fa9092 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp @@ -535,14 +535,14 @@ void ExecuteCommand(u32 _Address) } } + // It seems that the original hardware overwrites the command after it has been + // executed. We write 8 which is not any valid command, and what IOS does + Memory::Write_U32(8, _Address); + // IOS seems to write back the command that was responded to + Memory::Write_U32(Command, _Address + 8); + if (CmdSuccess) { - // It seems that the original hardware overwrites the command after it has been - // executed. We write 8 which is not any valid command, and what IOS does - Memory::Write_U32(8, _Address); - // IOS seems to write back the command that was responded to - Memory::Write_U32(Command, _Address + 8); - // Ensure replies happen in order, fairly ugly // Without this, tons of games fail now that DI commads have different reply delays int reply_delay = pDevice ? pDevice->GetCmdDelay(_Address) : 0; 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 e7a9896fae..fa4c98dac2 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,7 +55,6 @@ it failed) #include "ICMP.h" #include "CommonPaths.h" #include "SettingsHandler.h" -#include "WII_IPC_HLE.h" #include "ec_wii.h" @@ -90,10 +89,6 @@ typedef struct pollfd pollfd_t; #include <errno.h> #endif -#ifdef _WIN32 -#define SHUT_RDWR SD_BOTH -#endif - extern std::queue<std::pair<u32,std::string> > g_ReplyQueueLater; const u8 default_address[] = { 0x00, 0x17, 0xAB, 0x99, 0x99, 0x99 }; @@ -108,30 +103,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) @@ -250,8 +245,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; } @@ -367,30 +362,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) { @@ -476,7 +471,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; } @@ -607,13 +602,6 @@ CWII_IPC_HLE_Device_net_ip_top::CWII_IPC_HLE_Device_net_ip_top(u32 _DeviceID, co int ret = WSAStartup(MAKEWORD(2,2), &InitData); INFO_LOG(WII_IPC_NET, "WSAStartup: %d", ret); #endif - - u32 s = 0xDEADBEEF; - std::lock_guard<std::mutex> lk(socketMapMutex); - _tSocket* sock = new _tSocket(); - socketMap[s] = sock; - sock->thread = new std::thread([this, s]{this->processSocket(s);}); - } CWII_IPC_HLE_Device_net_ip_top::~CWII_IPC_HLE_Device_net_ip_top() @@ -621,61 +609,150 @@ CWII_IPC_HLE_Device_net_ip_top::~CWII_IPC_HLE_Device_net_ip_top() #ifdef _WIN32 WSACleanup(); #endif - - std::lock_guard<std::mutex> lk(socketMapMutex); - auto i = socketMap.begin(); - while(i != socketMap.end()) - { - u32 s = i->first; - _tSocket * sock = i->second; - if(s != 0xDEADBEEF) - { - (void)shutdown(s, SHUT_RDWR); - #ifdef _WIN32 - (void)closesocket(s); - #else - (void)close(s); - #endif - } - - sock->StopAndJoin(); - delete sock; - socketMap.erase(i++); - } } -bool CWII_IPC_HLE_Device_net_ip_top::Open(u32 CommandAddress, u32 _Mode) +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; @@ -711,467 +788,517 @@ static unsigned int opt_name_mapping[][2] = { { SO_ERROR, 0x1009 } }; - -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) +u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command, + u32 _BufferIn, u32 BufferInSize, + u32 _BufferOut, u32 BufferOutSize) +{ + switch (_Command) { - case IOCTL_SO_CONNECT: - case IOCTL_SO_ACCEPT: + 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: { - u32 s = Memory::Read_U32(BufferIn); - _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 + //struct sockaddr_in echoServAddr; + struct connect_params { - ReturnValue = -8; // EBADF - } - - ERROR_LOG(WII_IPC_NET, "Failed to find socket %d %08X", s, Command); + 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) + 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; break; } - case IOCTL_SO_POLL: + + case IOCTL_SO_SHUTDOWN: { - 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); + 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); break; } - - case IOCTL_SO_SOCKET: + + case IOCTL_SO_CLOSE: { - u32 AF = Memory::Read_U32(BufferIn); - u32 TYPE = Memory::Read_U32(BufferIn + 0x04); - u32 PROT = Memory::Read_U32(BufferIn + 0x08); + 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 + break; + } + + case IOCTL_SO_SOCKET: + { + 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); + "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::lock_guard<std::mutex> lk(socketMapMutex); - _tSocket* sock = new _tSocket(); - socketMap[s] = sock; - sock->thread = new std::thread([this, s]{this->processSocket(s);}); + 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)); } - break; - } - 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_SHUTDOWN: - { - 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); - ReturnValue = shutdown(s, SHUT_RDWR); - #ifdef _WIN32 - ReturnValue = closesocket(s); - #else - ReturnValue = close(s); - #endif - - ReturnValue = getNetErrorCode(ReturnValue, "IOCTL_SO_CLOSE", false); - - _tSocket * sock = NULL; - { - std::lock_guard<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); - } - } - WARN_LOG(WII_IPC_NET, "IOCTL_SO_CLOSE finished (%08x) = ", s, ReturnValue); - + 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; - - ReturnValue = bind(Common::swap32(addr->socket), (sockaddr*)&address, sizeof(address)); - + int ret = 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), ReturnValue, - Common::swap32(addr->socket), BufferIn, BufferInSize, BufferOut, BufferOutSize); - - ReturnValue = getNetErrorCode(ReturnValue, "SO_BIND", false); + "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); 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); - ReturnValue = listen(S, BACKLOG); - ReturnValue = getNetErrorCode(ReturnValue, "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); + u32 ret = listen(S, BACKLOG); + return getNetErrorCode(ret, "SO_LISTEN", false); break; } - - case IOCTL_SO_GETSOCKOPT: + + case IOCTL_SO_ACCEPT: { - 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_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: + { + 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; - - 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); - + + 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); + 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); } - break; + return ret; } - - 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)){ - ReturnValue = 0; - break; + return 0; } 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; } - - ReturnValue = setsockopt(S, nat_level, nat_optname, (char*)optval, optlen); - ReturnValue = getNetErrorCode(ReturnValue, "SO_SETSOCKOPT", false); - - break; + + int ret = setsockopt(S, nat_level, nat_optname, (char*)optval, optlen); + + ret = getNetErrorCode(ret, "SO_SETSOCKOPT", false); + + return ret; } - - 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; - 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) + "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) { - int posix_flags = 0; - - for (unsigned int i = 0; i < sizeof (mapping) / sizeof (mapping[0]); ++i) + if (arg & mapping[i][1]) { - if (arg & mapping[i][1]) - { - posix_flags |= mapping[i][0]; - 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); } - else - { - WARN_LOG(WII_IPC_NET, "SO_FCNTL unknown command"); - } - #endif - break; + + 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 } - - 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); - 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; + 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; } - 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); - - ReturnValue = getpeername(sock, &sa, &sa_len); - ReturnValue = getNetErrorCode(ReturnValue, "IOCTL_SO_GETPEERNAME", false); - - Memory::Write_U8(BufferOutSize, BufferOut); - Memory::Write_U8(AF_INET, BufferOut + 1); - Memory::WriteBigEData((u8*)&sa.sa_data, BufferOut + 2, BufferOutSize - 2); + + 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); WARN_LOG(WII_IPC_NET, "IOCTL_SO_GETPEERNAME(%x)", sock); - - break; + + return ret; } - 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); - ReturnValue = 192 << 24 | 168 << 16 | 1 << 8 | 150; - break; + "(BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + return 192 << 24 | 168 << 16 | 1 << 8 | 150; } - 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])); - ReturnValue = remoteHost->h_addr_list[0] == 0 ? 0 : 1; - break; + "%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; } - case IOCTL_SO_INETPTON: + + case IOCTL_SO_INETPTON: { WARN_LOG(WII_IPC_NET, "IOCTL_SO_INETPTON " - "(Translating: %s)", Memory::GetPointer(BufferIn)); - ReturnValue = inet_pton((char*)Memory::GetPointer(BufferIn), Memory::GetPointer(BufferOut+4)); + "(Translating: %s)", Memory::GetPointer(_BufferIn)); + return 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)); - break; - } - case IOCTL_SO_GETHOSTBYNAME: + memset(Memory::GetPointer(_BufferOut), 0, BufferOutSize); + memcpy(Memory::GetPointer(_BufferOut), ip_s, strlen(ip_s)); + return 0; + } + + case IOCTL_SO_POLL: { - hostent *remoteHost = gethostbyname((char*)Memory::GetPointer(BufferIn)); + // 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) + return -1; + + 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); + } + + int ret = poll(ufds, nfds, timeout); + + ret = getNetErrorCode(ret, "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); + return ret; + } + + case IOCTL_SO_GETHOSTBYNAME: + { + 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++; @@ -1189,499 +1316,142 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 CommandAddress) 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()); - ReturnValue = 0; + // ArrayToString(Memory::GetPointer(_BufferOut), BufferOutSize, 16).c_str()); + return 0; } else { - ReturnValue = -1; + return -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); - 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; + return getNetErrorCode(sock, "IOCTL_SO_ICMPSOCKET", false); } - - 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); - return true; -} - -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 - 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); + 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 -#define ERRORCODE(name) WSA ## name -#define EITHER(win32, posix) win32 + u32 ret = closesocket(sock); #else -#define ERRORCODE(name) name -#define EITHER(win32, posix) posix + u32 ret = close(sock); #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 + DEBUG_LOG(WII_IPC_NET, "IOCTL_SO_ICMPCLOSE(%x) %x", sock, ret); + return getNetErrorCode(ret, "IOCTL_SO_ICMPCLOSE", false); } - case EITHER(WSA_INVALID_HANDLE, EBADF): - return -26; // EINPROGRESS (should be -8) - default: - return -1; - } - -#undef ERRORCODE -#undef EITHER -} - -s32 CWII_IPC_HLE_Device_net_ip_top::processSocketIoctl(u32 CommandAddress, u32 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) " + default: + WARN_LOG(WII_IPC_NET,"0x%x " "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: + _Command, _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + default_: + if (BufferInSize) { - // 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 + 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 (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; - { - std::lock_guard<std::mutex> lk(socketMapMutex); - if(socketMap.find(socket) == socketMap.end()) + if (BufferOutSize) { - ERROR_LOG(WII_IPC_NET, "Socket %d could not be found in the socket map.", socket); - return; + ERROR_LOG(WII_IPC_NET, "out addr %x size %x", _BufferOut, BufferOutSize); } - sock = socketMap[socket]; - } - while((sock->WaitForEvent(), true) && sock->running) - { - u32 CommandAddress = 0; - while(sock->getCommand(CommandAddress)) - { - - using WII_IPC_HLE_Interface::ECommandType; - using WII_IPC_HLE_Interface::COMMAND_IOCTL; - using WII_IPC_HLE_Interface::COMMAND_IOCTLV; - - s32 ReturnValue = 0; - - ECommandType CommandType = static_cast<ECommandType>(Memory::Read_U32(CommandAddress)); - - if(CommandType == COMMAND_IOCTL) - { - ReturnValue = processSocketIoctl(CommandAddress, socket); - } - else if (CommandType == COMMAND_IOCTLV) - { - ReturnValue = processSocketIoctlv(CommandAddress, socket); - } - - Memory::Write_U32(8, CommandAddress); - // 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); - } - - //DEBUG_LOG(WII_IPC_NET, "Socket %d has processed all events.", socket); + break; } - //DEBUG_LOG(WII_IPC_NET, "Socket %d has died.", socket); -} + // We return a success for any potential unknown requests + return 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 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer) +{ + 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: - { - #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); + { + 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) { @@ -1751,32 +1521,32 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 CommandAddress) 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: @@ -1785,87 +1555,109 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 CommandAddress) } - ReturnValue = 0; + return 0; break; } - case IOCTLV_SO_RECVFROM: - { - u32 s = 0; - if (CommandBuffer.Parameter == IOCTLV_SO_SENDTO) - { - s = Memory::Read_U32(BufferIn2); - } else { - s = Memory::Read_U32(BufferIn); - } - ERROR_LOG(WII_IPC_NET, "Adding sendto or recvfrom %08X %08X", s, CommandBuffer.Parameter); - - _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, CommandBuffer.Parameter); - break; - } - case IOCTLV_SO_SENDTO: - { - struct sendto_params { - u32 socket; - u32 flags; - u32 has_destaddr; - u8 destaddr[28]; - } params; - u32 socket = Memory::Read_U32(BufferIn2); - char * data = (char*)Memory::GetPointer(BufferIn); - Memory::ReadBigEData((u8*)¶ms, BufferIn2, BufferInSize2); - - if (params.has_destaddr) + 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; + + 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; + } + + case IOCTLV_SO_RECVFROM: { - 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; + u32 sock = Memory::Read_U32(_BufferIn); + u32 flags = Memory::Read_U32(_BufferIn + 4); - ReturnValue = sendto(socket, data, - BufferInSize, Common::swap32(params.flags), (struct sockaddr*)addr, len); + char *buf = (char *)Memory::GetPointer(_BufferOut); + int len = BufferOutSize; + struct sockaddr_in addr; + memset(&addr, 0, sizeof(sockaddr_in)); + socklen_t fromlen = 0; - 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 - ); + if (BufferOutSize2 != 0) + { + fromlen = BufferOutSize2 >= sizeof(struct sockaddr) ? BufferOutSize2 : sizeof(struct sockaddr); + } - 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); + if (flags != 2) + flags = 0; + else + flags = MSG_PEEK; - ReturnValue = getNetErrorCode(ReturnValue, "SO_SEND", true); + 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; } - break; - } + case IOCTLV_SO_GETADDRINFO: { struct addrinfo hints; @@ -1873,28 +1665,28 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 CommandAddress) 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); - ReturnValue = getaddrinfo(pNodeName, pServiceName, BufferInSize3 ? &hints : NULL, &result); - u32 addr = BufferOut; + int ret = getaddrinfo(pNodeName, pServiceName, BufferInSize3 ? &hints : NULL, &result); + u32 addr = _BufferOut; u32 sockoffset = addr + 0x460; - if (ReturnValue >= 0) + if (ret >= 0) { while (result != NULL) { @@ -1934,9 +1726,9 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 CommandAddress) 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)); - break; + _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + WARN_LOG(WII_IPC_NET, "IOCTLV_SO_GETADDRINFO: %s", Memory::GetPointer(_BufferIn)); + return ret; } case IOCTLV_SO_ICMPPING: @@ -1949,19 +1741,19 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 CommandAddress) 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) { @@ -1982,7 +1774,7 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 CommandAddress) 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 @@ -1992,20 +1784,19 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 CommandAddress) icmp_length = 22; } - ReturnValue = icmp_echo_req(sock, &addr, data, icmp_length); - if (ReturnValue == icmp_length) + int ret = icmp_echo_req(sock, &addr, data, icmp_length); + if (ret == icmp_length) { - ReturnValue = icmp_echo_rep(sock, &addr, (u32)timeout, icmp_length); + ret = icmp_echo_rep(sock, &addr, (u32)timeout, icmp_length); } // TODO proper error codes - ReturnValue = 0; - break; + return 0; } 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) { @@ -2024,7 +1815,16 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 CommandAddress) } break; } - Memory::Write_U32(ReturnValue, CommandAddress + 4); + + 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); 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 209d7a240b..75ff25c6eb 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,7 +29,6 @@ #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) @@ -569,54 +568,6 @@ private: } }; -class _tSocket -{ -public: - bool running; - std::mutex m_mutex; - std::thread* thread; - - _tSocket() - { - running = true; - } - - bool getCommand(u32& commandAddress) - { - std::lock_guard<std::mutex> lk(m_mutex); - if (commands.empty()) - return false; - commandAddress = commands.front(); - commands.pop(); - return true; - } - - void addCommand(u32 commandAddress) - { - std::lock_guard<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 { @@ -634,11 +585,6 @@ private: #ifdef _WIN32 WSADATA InitData; #endif - std::map<u32, _tSocket*> socketMap; - std::mutex socketMapMutex; - void processSocket(u32 socket); - s32 processSocketIoctl(u32 CommandAddress, u32 socket); - s32 processSocketIoctlv(u32 CommandAddress, u32 socket); enum { @@ -683,39 +629,6 @@ 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 |
