diff options
| author | Matthew Parlane <parlane@gmail.com> | 2013-02-01 01:32:14 +1300 |
|---|---|---|
| committer | Matthew Parlane <parlane@gmail.com> | 2013-02-01 01:32:14 +1300 |
| commit | a0a09ed07a28f661e93e94ee1a1f352dcb153ac4 (patch) | |
| tree | a2d7c56648efccc4f72cba6cccce52c9ca29be9f /Source/Core | |
| parent | bca2cac640e4aff69a97b919411855d0e4b305da (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.cpp | 1506 | ||||
| -rw-r--r-- | Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.h | 85 |
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*)¶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; + 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*)¶ms, BufferIn, sizeof(connect_params)); + + if (Common::swap32(params.has_addr) != 1) + { + WARN_LOG(WII_IPC_NET,"IOCTL_SO_CONNECT: failed"); + ReturnValue = -1; + break; + } + + memset(&serverAddr, 0, sizeof(serverAddr)); + memcpy(&serverAddr, params.addr, params.addr[0]); + + // GC/Wii sockets have a length param as well, we dont really care :) + serverAddr.sin_family = serverAddr.sin_family >> 8; + + ReturnValue = connect(socket, (struct sockaddr *) &serverAddr, sizeof(serverAddr)); + ReturnValue = getNetErrorCode(ReturnValue, "SO_CONNECT", false); + WARN_LOG(WII_IPC_NET,"IOCTL_SO_CONNECT (%08x, %s:%d)", + socket, inet_ntoa(serverAddr.sin_addr), Common::swap16(serverAddr.sin_port)); + break; + } + default: + { + + ERROR_LOG(WII_IPC_NET, "Socket %08x has received an unknown IOCTLV %d.", socket, Command); + break; + } + } + + } + else if (CommandType == COMMAND_IOCTLV) + { + 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*)¶ms, BufferIn2, BufferInSize2); + + if (params.has_destaddr) + { + struct sockaddr_in* addr = (struct sockaddr_in*)¶ms.destaddr; + u8 len = sizeof(sockaddr); //addr->sin_family & 0xFF; + addr->sin_family = addr->sin_family >> 8; + + ReturnValue = sendto(socket, data, + BufferInSize, Common::swap32(params.flags), (struct sockaddr*)addr, len); + + WARN_LOG(WII_IPC_NET, + "IOCTLV_SO_SENDTO = %d Socket: %08x, BufferIn: (%08x, %i), BufferIn2: (%08x, %i), %u.%u.%u.%u", + ReturnValue, socket, BufferIn, BufferInSize, + BufferIn2, BufferInSize2, + addr->sin_addr.s_addr & 0xFF, + (addr->sin_addr.s_addr >> 8) & 0xFF, + (addr->sin_addr.s_addr >> 16) & 0xFF, + (addr->sin_addr.s_addr >> 24) & 0xFF + ); + + ReturnValue = getNetErrorCode(ReturnValue, "SO_SENDTO", true); + } + else + { + ReturnValue = send(socket, data, + BufferInSize, Common::swap32(params.flags)); + WARN_LOG(WII_IPC_NET, "IOCTLV_SO_SEND = %d Socket: %08x, BufferIn: (%08x, %i), BufferIn2: (%08x, %i)", + ReturnValue, socket, BufferIn, BufferInSize, + BufferIn2, BufferInSize2); + + ReturnValue = getNetErrorCode(ReturnValue, "SO_SEND", true); + } + break; + } + default: + { + + ERROR_LOG(WII_IPC_NET, "Socket %d has received an unknown IOCTLV %d.", socket, CommandBuffer.Parameter); + break; + } + } + } + + Memory::Write_U32(8, CommandAddress); + // 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*)¶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; + 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 |
