From 124fe24f4c0f003370c1b08071627e0c2dbf1d39 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Thu, 22 Aug 2013 23:58:56 +1200 Subject: [PATCH] Make wii-network async. * accept still needs to be made async. --- Source/Core/Core/Core.vcxproj | 2 + Source/Core/Core/Core.vcxproj.filters | 6 + Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp | 11 +- .../Core/Src/IPC_HLE/WII_IPC_HLE_Device.h | 110 +- .../Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp | 1386 +++++++---------- .../Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.h | 262 ++-- .../IPC_HLE/WII_IPC_HLE_Device_net_ssl.cpp | 219 +-- .../Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.h | 105 +- Source/Core/Core/Src/IPC_HLE/WII_Socket.cpp | 615 ++++++++ Source/Core/Core/Src/IPC_HLE/WII_Socket.h | 214 +++ 10 files changed, 1716 insertions(+), 1214 deletions(-) create mode 100644 Source/Core/Core/Src/IPC_HLE/WII_Socket.cpp create mode 100644 Source/Core/Core/Src/IPC_HLE/WII_Socket.h diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index bc7fe296e4..c419f10115 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -335,6 +335,7 @@ + @@ -546,6 +547,7 @@ + diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index 8c1a65c0f5..65fc55bf04 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -574,6 +574,9 @@ IPC HLE %28IOS/Starlet%29\USB + + IPC HLE %28IOS/Starlet%29\Net + @@ -1069,6 +1072,9 @@ IPC HLE %28IOS/Starlet%29\USB + + IPC HLE %28IOS/Starlet%29\Net + 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 a18373af73..110023c14d 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp @@ -525,14 +525,15 @@ 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 commands 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.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device.h index 0495c5108e..2cd2aa1ff4 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device.h @@ -36,6 +36,61 @@ //#define FS_EFATAL (u32)-119 // Fatal error not used by IOS as fatal ERROR #define FS_EESEXHAUSTED (u32)-1016 // Max of 2 ES handles at a time +// A struct for IOS ioctlv calls +struct SIOCtlVBuffer +{ + SIOCtlVBuffer(u32 _Address) : m_Address(_Address) + { + // These are the Ioctlv parameters in the IOS communication. The BufferVector + // is a memory address offset at where the in and out buffer addresses are + // stored. + Parameter = Memory::Read_U32(m_Address + 0x0C); // command 3, arg0 + NumberInBuffer = Memory::Read_U32(m_Address + 0x10); // 4, arg1 + NumberPayloadBuffer = Memory::Read_U32(m_Address + 0x14); // 5, arg2 + BufferVector = Memory::Read_U32(m_Address + 0x18); // 6, arg3 + + // The start of the out buffer + u32 BufferVectorOffset = BufferVector; + + // Write the address and size for all in messages + for (u32 i = 0; i < NumberInBuffer; i++) + { + SBuffer Buffer; + Buffer.m_Address = Memory::Read_U32(BufferVectorOffset); + BufferVectorOffset += 4; + Buffer.m_Size = Memory::Read_U32(BufferVectorOffset); + BufferVectorOffset += 4; + InBuffer.push_back(Buffer); + DEBUG_LOG(WII_IPC_HLE, "SIOCtlVBuffer in%i: 0x%08x, 0x%x", + i, Buffer.m_Address, Buffer.m_Size); + } + + // Write the address and size for all out or in-out messages + for (u32 i = 0; i < NumberPayloadBuffer; i++) + { + SBuffer Buffer; + Buffer.m_Address = Memory::Read_U32(BufferVectorOffset); + BufferVectorOffset += 4; + Buffer.m_Size = Memory::Read_U32(BufferVectorOffset); + BufferVectorOffset += 4; + PayloadBuffer.push_back(Buffer); + DEBUG_LOG(WII_IPC_HLE, "SIOCtlVBuffer io%i: 0x%08x, 0x%x", + i, Buffer.m_Address, Buffer.m_Size); + } + } + + const u32 m_Address; + + u32 Parameter; + u32 NumberInBuffer; + u32 NumberPayloadBuffer; + u32 BufferVector; + + struct SBuffer { u32 m_Address, m_Size; }; + std::vector InBuffer; + std::vector PayloadBuffer; +}; + class IWII_IPC_HLE_Device { public: @@ -104,61 +159,6 @@ protected: bool m_Hardware; bool m_Active; - // A struct for IOS ioctlv calls - struct SIOCtlVBuffer - { - SIOCtlVBuffer(u32 _Address) : m_Address(_Address) - { - // These are the Ioctlv parameters in the IOS communication. The BufferVector - // is a memory address offset at where the in and out buffer addresses are - // stored. - Parameter = Memory::Read_U32(m_Address + 0x0C); // command 3, arg0 - NumberInBuffer = Memory::Read_U32(m_Address + 0x10); // 4, arg1 - NumberPayloadBuffer = Memory::Read_U32(m_Address + 0x14); // 5, arg2 - BufferVector = Memory::Read_U32(m_Address + 0x18); // 6, arg3 - - // The start of the out buffer - u32 BufferVectorOffset = BufferVector; - - // Write the address and size for all in messages - for (u32 i = 0; i < NumberInBuffer; i++) - { - SBuffer Buffer; - Buffer.m_Address = Memory::Read_U32(BufferVectorOffset); - BufferVectorOffset += 4; - Buffer.m_Size = Memory::Read_U32(BufferVectorOffset); - BufferVectorOffset += 4; - InBuffer.push_back(Buffer); - DEBUG_LOG(WII_IPC_HLE, "SIOCtlVBuffer in%i: 0x%08x, 0x%x", - i, Buffer.m_Address, Buffer.m_Size); - } - - // Write the address and size for all out or in-out messages - for (u32 i = 0; i < NumberPayloadBuffer; i++) - { - SBuffer Buffer; - Buffer.m_Address = Memory::Read_U32(BufferVectorOffset); - BufferVectorOffset += 4; - Buffer.m_Size = Memory::Read_U32(BufferVectorOffset); - BufferVectorOffset += 4; - PayloadBuffer.push_back(Buffer); - DEBUG_LOG(WII_IPC_HLE, "SIOCtlVBuffer io%i: 0x%08x, 0x%x", - i, Buffer.m_Address, Buffer.m_Size); - } - } - - const u32 m_Address; - - u32 Parameter; - u32 NumberInBuffer; - u32 NumberPayloadBuffer; - u32 BufferVector; - - struct SBuffer { u32 m_Address, m_Size; }; - std::vector InBuffer; - std::vector PayloadBuffer; - }; - // Write out the IPC struct from _CommandAddress to _NumberOfCommands numbers // of 4 byte commands. void DumpCommands(u32 _CommandAddress, size_t _NumberOfCommands = 8, 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 9bf7c89602..66ab28d1d9 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 @@ -38,7 +38,7 @@ it failed) #include "CommonPaths.h" #include "SettingsHandler.h" #include "ec_wii.h" - +#include "WII_Socket.h" #ifdef _WIN32 #include @@ -55,7 +55,6 @@ it failed) #include #include #include -#include #include #include #include @@ -66,7 +65,6 @@ typedef struct pollfd pollfd_t; #else #include #include -#include #include #include #endif @@ -333,6 +331,7 @@ s32 CWII_IPC_HLE_Device_net_kd_request::NWC24MakeUserID(u64* nwc24_id, u32 holly return WC24_OK; } + // ********************************************************************************** // Handle /dev/net/ncd/manage requests CWII_IPC_HLE_Device_net_ncd_manage::CWII_IPC_HLE_Device_net_ncd_manage(u32 _DeviceID, const std::string& _rDeviceName) @@ -517,7 +516,7 @@ bool CWII_IPC_HLE_Device_net_wd_command::IOCtlV(u32 CommandAddress) const char *ssid = "dolphin-emu"; strcpy((char *)bss->ssid, ssid); - bss->ssid_length = Common::swap16(strlen(ssid)); + bss->ssid_length = Common::swap16((u16)strlen(ssid)); bss->channel = Common::swap16(2); } @@ -610,130 +609,19 @@ bool CWII_IPC_HLE_Device_net_ip_top::Close(u32 _CommandAddress, bool _bForce) 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), (LPWSTR)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; + int saw_digit, octets; + char 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 (ch >= '0' && ch <= '9') { + unsigned int newt = (*tp * 10) + (ch - '0'); if (newt > 255) return (0); @@ -770,395 +658,307 @@ 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) +bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 _CommandAddress) +{ + u32 Command = Memory::Read_U32(_CommandAddress + 0x0C); + 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 (Command) { case IOCTL_SO_STARTUP: + { WARN_LOG(WII_IPC_NET, "IOCTL_SO_STARTUP " "BufferIn: (%08x, %i), BufferOut: (%08x, %i)", - _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + BufferIn, BufferInSize, BufferOut, BufferOutSize); 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) - 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_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); - int ret = shutdown(sock, how); - return getNetErrorCode(ret, "SO_SHUTDOWN", false); - break; - } - - case IOCTL_SO_CLOSE: - { - 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); - - 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)); - } - - - - return ret; - break; - } + { + u32 AF = Memory::Read_U32(BufferIn); + u32 TYPE = Memory::Read_U32(BufferIn + 0x04); + u32 PROT = Memory::Read_U32(BufferIn + 0x08); + WiiSockMan &sm = WiiSockMan::getInstance(); + ReturnValue = sm.newSocket(AF, TYPE, PROT); + WARN_LOG(WII_IPC_NET, "IOCTL_SO_SOCKET " + "Socket: %08x (%d,%d,%d), BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + ReturnValue, AF, TYPE, PROT, BufferIn, BufferInSize, BufferOut, BufferOutSize); + break; + } + case IOCTL_SO_CLOSE: + { + u32 sock = Memory::Read_U32(BufferIn); + + WiiSockMan &sm = WiiSockMan::getInstance(); + ReturnValue = sm.delSocket(sock); + + WARN_LOG(WII_IPC_NET, "IOCTL_SO_CLOSE (%08x)", ReturnValue); + break; + } + case IOCTL_SO_ICMPSOCKET: + { + u32 pf = Memory::Read_U32(BufferIn); + + WiiSockMan &sm = WiiSockMan::getInstance(); + ReturnValue = sm.newSocket(pf, SOCK_RAW, IPPROTO_ICMP); + WARN_LOG(WII_IPC_NET, "IOCTL_SO_ICMPSOCKET(%x) %d", pf, ReturnValue); + break; + } + case IOCTL_SO_ICMPCLOSE: + { + u32 sock = Memory::Read_U32(BufferIn); + WiiSockMan &sm = WiiSockMan::getInstance(); + ReturnValue = sm.delSocket(sock); + DEBUG_LOG(WII_IPC_NET, "IOCTL_SO_ICMPCLOSE(%x) %x", sock, ReturnValue); + break; + } + case IOCTL_SO_FCNTL: + { + u32 sock = Memory::Read_U32(BufferIn); + WiiSockMan &sm = WiiSockMan::getInstance(); + sm.doSock(sock, _CommandAddress, IOCTL_SO_FCNTL); + return false; + break; + } case IOCTL_SO_BIND: - { - 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)); - - 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); - break; - } - - 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); - break; - } + { + u32 sock = Memory::Read_U32(BufferIn); + WiiSockMan &sm = WiiSockMan::getInstance(); + sm.doSock(sock, _CommandAddress, IOCTL_SO_BIND); + return false; + break; + } + case IOCTL_SO_CONNECT: + { + u32 sock = Memory::Read_U32(BufferIn); + WiiSockMan &sm = WiiSockMan::getInstance(); + sm.doSock(sock, _CommandAddress, IOCTL_SO_CONNECT); + return false; + break; + } case IOCTL_SO_ACCEPT: - { - WARN_LOG(WII_IPC_NET, "IOCTL_SO_ACCEPT " - "BufferIn: (%08x, %i), BufferOut: (%08x, %i)", - _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + { + WARN_LOG(WII_IPC_NET, "IOCTL_SO_ACCEPT " + "BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + BufferIn, BufferInSize, BufferOut, BufferOutSize); + + u32 sock = Memory::Read_U32(BufferIn); + socklen_t addrlen; - 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); - } + struct sockaddr* addr = (struct sockaddr*) Memory::GetPointer(BufferOut); + int ret = (s32)accept(sock, addr, &addrlen); + ReturnValue = WiiSockMan::getNetErrorCode(ret, "SO_ACCEPT", false); + addr->sa_family = ((addr->sa_family&0xFF) << 8) | (u8)addrlen; + Memory::Write_U32(addrlen, BufferOut + 0x04); + break; + } + + ///////////////////////////////////////////////////////////// + // TODO: ALL BELOW // + ///////////////////////////////////////////////////////////// + + + 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); + int ret = shutdown(sock, how); + ReturnValue = WiiSockMan::getNetErrorCode(ret, "SO_SHUTDOWN", false); + break; + } + 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); + ReturnValue = WiiSockMan::getNetErrorCode(ret, "SO_LISTEN", false); + break; + } 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); + WARN_LOG(WII_IPC_NET,"IOCTL_SO_GETSOCKOPT(%08x, %08x, %08x)" + "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; + // 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_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]; + 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; + u8 optval[20]; + u32 optlen = 4; - int ret = getsockopt (sock, nat_level, nat_optname, (char *) &optval, (socklen_t*)&optlen); + int ret = getsockopt (sock, nat_level, nat_optname, (char *) &optval, (socklen_t*)&optlen); - ret = getNetErrorCode(ret, "SO_GETSOCKOPT", false); + ReturnValue = WiiSockMan::getNetErrorCode(ret, "SO_GETSOCKOPT", false); - Memory::Write_U32(optlen, _BufferOut + 0xC); - Memory::WriteBigEData((u8 *) optval, _BufferOut + 0x10, optlen); + Memory::Write_U32(optlen, BufferOut + 0xC); + Memory::WriteBigEData((u8 *) optval, BufferOut + 0x10, optlen); - if(optname == 0x1007){ - s32 errorcode = Memory::Read_U32(_BufferOut + 0x10); - WARN_LOG(WII_IPC_NET,"IOCTL_SO_GETSOCKOPT error code = %i", errorcode); - } - return ret; + if(optname == 0x1007){ + s32 errorcode = Memory::Read_U32(BufferOut + 0x10); + WARN_LOG(WII_IPC_NET,"IOCTL_SO_GETSOCKOPT error code = %i", errorcode); } + break; + } 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); + u8 optval[20]; + 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; + } + 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]); + + // 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) { - 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); + WARN_LOG(WII_IPC_NET, "SO_SETSOCKOPT: unknown level %d or optname %d", level, optname); - //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; - } - 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]); - - // 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; + // Default to the given level/optname. They match on Windows... + nat_level = level; + nat_optname = optname; } - case IOCTL_SO_FCNTL: - { - 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) - { - 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); - - 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 - } + int ret = setsockopt(S, nat_level, nat_optname, (char*)optval, optlen); + ReturnValue = WiiSockMan::getNetErrorCode(ret, "SO_SETSOCKOPT", false); + break; + } 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); + WARN_LOG(WII_IPC_NET, "IOCTL_SO_GETSOCKNAME " + "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); + 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; - } + Memory::Write_U8(BufferOutSize, BufferOut); + Memory::Write_U8(sa.sa_family & 0xFF, BufferOut + 1); + Memory::WriteBigEData((u8*)&sa.sa_data, BufferOut + 2, BufferOutSize - 2); + ReturnValue = ret; + break; + } 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); + sockaddr sa; + socklen_t sa_len; + sa_len = sizeof(sa); - int ret = getpeername(sock, &sa, &sa_len); + 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); + 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); + WARN_LOG(WII_IPC_NET, "IOCTL_SO_GETPEERNAME(%x)", sock); - return ret; - } + ReturnValue = ret; + break; + } 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; - } + { + 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; + } case IOCTL_SO_INETATON: - { - struct hostent *remoteHost = gethostbyname((char*)Memory::GetPointer(_BufferIn)); + { + 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; - } + 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; + } 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)); - break; - } + { + WARN_LOG(WII_IPC_NET, "IOCTL_SO_INETPTON " + "(Translating: %s)", Memory::GetPointer(BufferIn)); + ReturnValue = inet_pton((char*)Memory::GetPointer(BufferIn), Memory::GetPointer(BufferOut+4)); + break; + } 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); - 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) - ); - 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; - } + { + 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) + ); + 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_POLL: { @@ -1169,22 +969,25 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command, { 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"); + 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; @@ -1196,7 +999,7 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command, unhandled_events &= ~mapping[j][1]; } - WARN_LOG(WII_IPC_NET, "IOCTL_SO_POLL(%d) " + DEBUG_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 @@ -1208,7 +1011,7 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command, int ret = poll(ufds, nfds, timeout); - ret = getNetErrorCode(ret, "SO_POLL", false); + ret = WiiSockMan::getNetErrorCode(ret, "SO_POLL", false); for (int i = 0; ih_name) + 1; + u32 name_length = (u32)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); @@ -1276,11 +1080,11 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command, _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); + 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++; @@ -1300,68 +1104,53 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command, } //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: - { - // AF type? - 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); - } - 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 ret = closesocket(sock); -#else - u32 ret = close(sock); -#endif - DEBUG_LOG(WII_IPC_NET, "IOCTL_SO_ICMPCLOSE(%x) %x", sock, ret); - return getNetErrorCode(ret, "IOCTL_SO_ICMPCLOSE", false); - } - default: WARN_LOG(WII_IPC_NET,"0x%x " "BufferIn: (%08x, %i), BufferOut: (%08x, %i)", - _Command, _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + 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, "in addr %x size %x", BufferIn, BufferInSize); ERROR_LOG(WII_IPC_NET, "\n%s", - ArrayToString(Memory::GetPointer(_BufferIn), BufferInSize, 4).c_str() + ArrayToString(Memory::GetPointer(BufferIn), BufferInSize, 4).c_str() ); } if (BufferOutSize) { - ERROR_LOG(WII_IPC_NET, "out addr %x size %x", _BufferOut, BufferOutSize); + ERROR_LOG(WII_IPC_NET, "out addr %x size %x", BufferOut, BufferOutSize); } break; } - // We return a success for any potential unknown requests - return 0; + Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); + + return true; } -u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer) -{ + +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; @@ -1419,360 +1208,272 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer 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); + if (BufferOutSize >= 8) { - 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); - WARN_LOG(WII_IPC_NET,"IOCTLV_SO_GETINTERFACEOPT(%08X, %08X) " - "BufferIn: (%08x, %i), BufferIn2: (%08x, %i)", - param, param2, - _BufferIn, BufferInSize, _BufferIn2, BufferInSize2); - - switch (param2) - { - case 0xb003: // dns server table - { - u32 address = 0; - /*fd=socket(PF_INET,SOCK_STREAM,0); - strcpy(ifr.ifr_name,"name of interface"); - ioctl(fd,SIOCGIFADDR,&ifr); - saddr=*((struct sockaddr_in *)(&(ifr.ifr_addr))); - */ + switch (param2) + { + case 0xb003: // dns server table + { + u32 address = 0; + /*fd=socket(PF_INET,SOCK_STREAM,0); + strcpy(ifr.ifr_name,"name of interface"); + ioctl(fd,SIOCGIFADDR,&ifr); + saddr=*((struct sockaddr_in *)(&(ifr.ifr_addr))); + */ #ifdef _WIN32 - for (i = 0; i < 5; i++) + for (i = 0; i < 5; i++) + { + RetVal = GetAdaptersAddresses( + AF_INET, + 0, + NULL, + AdapterAddresses, + &OutBufferLength); + + if (RetVal != ERROR_BUFFER_OVERFLOW) { + break; + } + + if (AdapterAddresses != NULL) { + FREE(AdapterAddresses); + } + + AdapterAddresses = (PIP_ADAPTER_ADDRESSES)MALLOC(OutBufferLength); + if (AdapterAddresses == NULL) { + RetVal = GetLastError(); + break; + } + } + if (RetVal == NO_ERROR) + { + unsigned long dwBestIfIndex = 0; + IPAddr dwDestAddr = (IPAddr)0x08080808; + // If successful, output some information from the data we received + PIP_ADAPTER_ADDRESSES AdapterList = AdapterAddresses; + if (GetBestInterface(dwDestAddr,&dwBestIfIndex) == NO_ERROR) + { + while (AdapterList) { - RetVal = GetAdaptersAddresses( - AF_INET, - 0, - NULL, - AdapterAddresses, - &OutBufferLength); - - if (RetVal != ERROR_BUFFER_OVERFLOW) { - break; - } - - if (AdapterAddresses != NULL) { - FREE(AdapterAddresses); - } - - AdapterAddresses = (PIP_ADAPTER_ADDRESSES)MALLOC(OutBufferLength); - if (AdapterAddresses == NULL) { - RetVal = GetLastError(); - break; - } - } - if (RetVal == NO_ERROR) - { - unsigned long dwBestIfIndex = 0; - IPAddr dwDestAddr = (IPAddr)0x08080808; - // If successful, output some information from the data we received - PIP_ADAPTER_ADDRESSES AdapterList = AdapterAddresses; - if (GetBestInterface(dwDestAddr,&dwBestIfIndex) == NO_ERROR) + if (AdapterList->IfIndex == dwBestIfIndex && + AdapterList->FirstDnsServerAddress && + AdapterList->OperStatus == IfOperStatusUp) { - while (AdapterList) - { - if (AdapterList->IfIndex == dwBestIfIndex && - AdapterList->FirstDnsServerAddress && - AdapterList->OperStatus == IfOperStatusUp) - { - WARN_LOG(WII_IPC_NET, "Name of valid interface: %S", AdapterList->FriendlyName); - WARN_LOG(WII_IPC_NET, "DNS: %u.%u.%u.%u", - (unsigned char)AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[2], - (unsigned char)AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[3], - (unsigned char)AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[4], - (unsigned char)AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[5]); - address = Common::swap32(*(u32*)(&AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[2])); - break; - } - AdapterList = AdapterList->Next; - } + WARN_LOG(WII_IPC_NET, "Name of valid interface: %S", AdapterList->FriendlyName); + WARN_LOG(WII_IPC_NET, "DNS: %u.%u.%u.%u", + (unsigned char)AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[2], + (unsigned char)AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[3], + (unsigned char)AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[4], + (unsigned char)AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[5]); + address = Common::swap32(*(u32*)(&AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[2])); + break; } + AdapterList = AdapterList->Next; } - if (AdapterAddresses != NULL) { - FREE(AdapterAddresses); - } -#endif - if (address == 0) - address = 0x08080808; - - Memory::Write_U32(address, _BufferOut); - Memory::Write_U32(0x08080808, _BufferOut+4); - break; } - case 0x1003: // error - Memory::Write_U32(0, _BufferOut); - break; - case 0x1004: // mac address - Memory::WriteBigEData(default_address, _BufferOut, 6); - break; - case 0x1005: // link state - Memory::Write_U32(1, _BufferOut); - break; - case 0x4002: // ip addr number - Memory::Write_U32(1, _BufferOut); - break; - case 0x4003: // ip addr table - 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: - ERROR_LOG(WII_IPC_NET, "Unknown param2: %08X", param2); - break; } + if (AdapterAddresses != NULL) { + FREE(AdapterAddresses); + } +#endif + if (address == 0) + address = 0x08080808; - return 0; + Memory::Write_U32(address, _BufferOut); + Memory::Write_U32(0x08080808, _BufferOut+4); break; } - + case 0x1003: // error + Memory::Write_U32(0, _BufferOut); + break; + case 0x1004: // mac address + Memory::WriteBigEData(default_address, _BufferOut, 6); + break; + case 0x1005: // link state + Memory::Write_U32(1, _BufferOut); + break; + case 0x4002: // ip addr number + Memory::Write_U32(1, _BufferOut); + break; + case 0x4003: // ip addr table + 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: + ERROR_LOG(WII_IPC_NET, "Unknown param2: %08X", param2); + break; + } + 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; - - 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; - } - + { + u32 sock = Memory::Read_U32(_BufferIn2); + WiiSockMan &sm = WiiSockMan::getInstance(); + sm.doSock(sock, CommandAddress, IOCTLV_SO_SENDTO); + return false; + break; + } case IOCTLV_SO_RECVFROM: - { - 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; - } - + { + u32 sock = Memory::Read_U32(_BufferIn); + WiiSockMan &sm = WiiSockMan::getInstance(); + sm.doSock(sock, CommandAddress, IOCTLV_SO_RECVFROM); + return false; + break; + } case IOCTLV_SO_GETADDRINFO: + { + struct addrinfo hints; + struct addrinfo *result = NULL; + + if (BufferInSize3) { - struct addrinfo hints; - struct addrinfo *result = NULL; + 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); + } - if (BufferInSize3) + char* pNodeName = NULL; + if (BufferInSize > 0) + pNodeName = (char*)Memory::GetPointer(_BufferIn); + + char* pServiceName = NULL; + if (BufferInSize2 > 0) + pServiceName = (char*)Memory::GetPointer(_BufferIn2); + + int ret = getaddrinfo(pNodeName, pServiceName, BufferInSize3 ? &hints : NULL, &result); + u32 addr = _BufferOut; + u32 sockoffset = addr + 0x460; + if (ret >= 0) + { + while (result != NULL) { - 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); - } + Memory::Write_U32(result->ai_flags, addr); + Memory::Write_U32(result->ai_family, addr + 0x04); + Memory::Write_U32(result->ai_socktype, addr + 0x08); + Memory::Write_U32(result->ai_protocol, addr + 0x0C); + Memory::Write_U32((u32)result->ai_addrlen, addr + 0x10); + // what to do? where to put? the buffer of 0x834 doesn't allow space for this + Memory::Write_U32(/*result->ai_cannonname*/ 0, addr + 0x14); - char* pNodeName = NULL; - if (BufferInSize > 0) - pNodeName = (char*)Memory::GetPointer(_BufferIn); - - char* pServiceName = NULL; - if (BufferInSize2 > 0) - pServiceName = (char*)Memory::GetPointer(_BufferIn2); - - int ret = getaddrinfo(pNodeName, pServiceName, BufferInSize3 ? &hints : NULL, &result); - u32 addr = _BufferOut; - u32 sockoffset = addr + 0x460; - if (ret >= 0) - { - while (result != NULL) + if (result->ai_addr) { - Memory::Write_U32(result->ai_flags, addr); - Memory::Write_U32(result->ai_family, addr + 0x04); - Memory::Write_U32(result->ai_socktype, addr + 0x08); - Memory::Write_U32(result->ai_protocol, addr + 0x0C); - Memory::Write_U32(result->ai_addrlen, addr + 0x10); - // what to do? where to put? the buffer of 0x834 doesn't allow space for this - Memory::Write_U32(/*result->ai_cannonname*/ 0, addr + 0x14); - - if (result->ai_addr) - { - Memory::Write_U32(sockoffset, addr + 0x18); - Memory::Write_U16(((result->ai_addr->sa_family & 0xFF) << 8) | (result->ai_addrlen & 0xFF), sockoffset); - Memory::WriteBigEData((u8*)result->ai_addr->sa_data, sockoffset + 0x2, sizeof(result->ai_addr->sa_data)); - sockoffset += 0x1C; - } - else - { - Memory::Write_U32(0, addr + 0x18); - } - - if (result->ai_next) - { - Memory::Write_U32(addr + sizeof(addrinfo), addr + 0x1C); - } - else - { - Memory::Write_U32(0, addr + 0x1C); - } - - addr += sizeof(addrinfo); - result = result->ai_next; + Memory::Write_U32(sockoffset, addr + 0x18); + Memory::Write_U16(((result->ai_addr->sa_family & 0xFF) << 8) | (result->ai_addrlen & 0xFF), sockoffset); + Memory::WriteBigEData((u8*)result->ai_addr->sa_data, sockoffset + 0x2, sizeof(result->ai_addr->sa_data)); + sockoffset += 0x1C; + } + else + { + Memory::Write_U32(0, addr + 0x18); } - } - 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; + if (result->ai_next) + { + Memory::Write_U32(addr + sizeof(addrinfo), addr + 0x1C); + } + else + { + Memory::Write_U32(0, addr + 0x1C); + } + + addr += sizeof(addrinfo); + result = result->ai_next; + } } + 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)); + ReturnValue = ret; + break; + } case IOCTLV_SO_ICMPPING: + { + struct { - struct - { - u8 length; - u8 addr_family; - u16 icmp_id; - u32 ip; - } ip_info; + u8 length; + u8 addr_family; + u16 icmp_id; + 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); - - if (ip_info.length != 8 || ip_info.addr_family != AF_INET) - { - WARN_LOG(WII_IPC_NET, "IOCTLV_SO_ICMPPING strange IPInfo:\n" - "length %x addr_family %x", - ip_info.length, ip_info.addr_family); - } - - DEBUG_LOG(WII_IPC_NET, "IOCTLV_SO_ICMPPING %x", ip_info.ip); - - sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = Common::swap32(ip_info.ip); - memset(addr.sin_zero, 0, 8); - - u8 data[0x20]; - memset(data, 0, sizeof(data)); - s32 icmp_length = sizeof(data); - - if (BufferInSize2 == sizeof(data)) - memcpy(data, Memory::GetPointer(_BufferIn2), BufferInSize2); - else - { - // TODO sequence number is incremented either statically, by - // port, or by socket. Doesn't seem to matter, so we just leave - // it 0 - ((u16 *)data)[0] = Common::swap16(ip_info.icmp_id); - icmp_length = 22; - } - - int ret = icmp_echo_req(sock, &addr, data, icmp_length); - if (ret == icmp_length) - { - ret = icmp_echo_rep(sock, &addr, (u32)timeout, icmp_length); - } - - // TODO proper error codes - return 0; + 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); + + if (ip_info.length != 8 || ip_info.addr_family != AF_INET) + { + WARN_LOG(WII_IPC_NET, "IOCTLV_SO_ICMPPING strange IPInfo:\n" + "length %x addr_family %x", + ip_info.length, ip_info.addr_family); + } + + DEBUG_LOG(WII_IPC_NET, "IOCTLV_SO_ICMPPING %x", ip_info.ip); + + sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = Common::swap32(ip_info.ip); + memset(addr.sin_zero, 0, 8); + + u8 data[0x20]; + memset(data, 0, sizeof(data)); + s32 icmp_length = sizeof(data); + + if (BufferInSize2 == sizeof(data)) + memcpy(data, Memory::GetPointer(_BufferIn2), BufferInSize2); + else + { + // TODO sequence number is incremented either statically, by + // port, or by socket. Doesn't seem to matter, so we just leave + // it 0 + ((u16 *)data)[0] = Common::swap16(ip_info.icmp_id); + icmp_length = 22; + } + + int ret = icmp_echo_req(sock, &addr, data, icmp_length); + if (ret == icmp_length) + { + ret = icmp_echo_rep(sock, &addr, (u32)timeout, icmp_length); + } + + // TODO proper error codes + ReturnValue = 0; + break; + } default: WARN_LOG(WII_IPC_NET,"0x%x (BufferIn: (%08x, %i), BufferIn2: (%08x, %i)", CommandBuffer.Parameter, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2); - default_: for (u32 i = 0; i < CommandBuffer.NumberInBuffer; ++i) { ERROR_LOG(WII_IPC_NET, "in %i addr %x size %x", i, @@ -1791,14 +1492,11 @@ 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; } +u32 CWII_IPC_HLE_Device_net_ip_top::Update() +{ + WiiSockMan::getInstance().Update(); + return 0; +} 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 5a2a1f141c..506ba69911 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 @@ -135,7 +135,7 @@ struct nwc24_config_t NWC24_IDCS_GENERATED = 1, NWC24_IDCS_REGISTERED = 2 }; - + enum { URL_COUNT = 0x05, @@ -143,7 +143,7 @@ struct nwc24_config_t MAX_EMAIL_LENGTH = 0x40, MAX_PASSWORD_LENGTH = 0x20, }; - + u32 magic; /* 'WcCf' 0x57634366 */ u32 _unk_04; /* must be 8 */ u64 nwc24_id; @@ -167,21 +167,21 @@ class NWC24Config private: std::string path; nwc24_config_t config; - + public: NWC24Config() { path = File::GetUserPath(D_WIIWC24_IDX) + "nwc24msg.cfg"; ReadConfig(); } - + void ResetConfig() { int i; - + if (File::Exists(path)) File::Delete(path); - + const char* urls[5] = { "https://amw.wc24.wii.com/cgi-bin/account.cgi", "http://rcw.wc24.wii.com/cgi-bin/check.cgi", @@ -189,25 +189,25 @@ public: "http://mtw.wc24.wii.com/cgi-bin/delete.cgi", "http://mtw.wc24.wii.com/cgi-bin/send.cgi", }; - + memset(&config, 0, sizeof(config)); - + SetMagic(0x57634366); SetUnk(8); SetCreationStage(nwc24_config_t::NWC24_IDCS_INITIAL); SetEnableBooting(0); SetEmail("@wii.com"); - + for(i=0; i 0) @@ -173,26 +170,26 @@ u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer C 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; } - switch (_Parameter) + switch (CommandBuffer.Parameter) { case IOCTLV_NET_SSL_NEW: { - int verifyOption = Memory::Read_U32(_BufferOut); - const char * hostname = (const char*) Memory::GetPointer(_BufferOut2); + int verifyOption = Memory::Read_U32(BufferOut); + const char * hostname = (const char*) Memory::GetPointer(BufferOut2); int freeSSL = this->getSSLFreeID(); if (freeSSL) @@ -221,8 +218,8 @@ u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer C ssl_set_authmode(&_SSL[sslID].ctx, SSL_VERIFY_OPTIONAL); ssl_set_renegotiation(&_SSL[sslID].ctx, SSL_RENEGOTIATION_ENABLED); - memcpy(_SSL[sslID].hostname, hostname, min((int)BufferOutSize2, MAX_HOSTNAME_LEN)); - _SSL[sslID].hostname[MAX_HOSTNAME_LEN-1] = '\0'; + memcpy(_SSL[sslID].hostname, hostname, min((int)BufferOutSize2, NET_SSL_MAX_HOSTNAME_LEN)); + _SSL[sslID].hostname[NET_SSL_MAX_HOSTNAME_LEN-1] = '\0'; ssl_set_hostname(&_SSL[sslID].ctx, _SSL[sslID].hostname); _SSL[sslID].active = true; @@ -240,13 +237,13 @@ _SSL_NEW_ERROR: "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", verifyOption, hostname, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, - _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, - _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, + BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_SHUTDOWN: { - int sslID = Memory::Read_U32(_BufferOut) - 1; + int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { ssl_close_notify(&_SSL[sslID].ctx); @@ -259,7 +256,7 @@ _SSL_NEW_ERROR: memset(&_SSL[sslID].ctx, 0, sizeof(ssl_context)); memset(&_SSL[sslID].session, 0, sizeof(ssl_session)); memset(&_SSL[sslID].hs, 0, sizeof(havege_state)); - memset(_SSL[sslID].hostname, 0, MAX_HOSTNAME_LEN); + memset(_SSL[sslID].hostname, 0, NET_SSL_MAX_HOSTNAME_LEN); _SSL[sslID].active = false; @@ -274,8 +271,8 @@ _SSL_NEW_ERROR: "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, - _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, - _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, + BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_SETROOTCA: @@ -285,16 +282,16 @@ _SSL_NEW_ERROR: "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, - _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, - _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, + BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); - int sslID = Memory::Read_U32(_BufferOut) - 1; + int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { int ret = x509parse_crt_der( &_SSL[sslID].cacert, - Memory::GetPointer(_BufferOut2), + Memory::GetPointer(BufferOut2), BufferOutSize2); if (ret) @@ -322,10 +319,10 @@ _SSL_NEW_ERROR: "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, - _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, - _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, + BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); - int sslID = Memory::Read_U32(_BufferOut) - 1; + int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { std::string cert_base_path(File::GetUserPath(D_WIIUSER_IDX)); @@ -361,10 +358,10 @@ _SSL_NEW_ERROR: "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, - _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, - _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, + BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); - int sslID = Memory::Read_U32(_BufferOut) - 1; + int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { x509_free(&_SSL[sslID].clicert); @@ -384,7 +381,7 @@ _SSL_NEW_ERROR: } case IOCTLV_NET_SSL_SETBUILTINROOTCA: { - int sslID = Memory::Read_U32(_BufferOut) - 1; + int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { std::string cert_base_path(File::GetUserPath(D_WIIUSER_IDX)); @@ -411,16 +408,16 @@ _SSL_NEW_ERROR: "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, - _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, - _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, + BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_CONNECT: { - int sslID = Memory::Read_U32(_BufferOut) - 1; + int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { - _SSL[sslID].sockfd = Memory::Read_U32(_BufferOut2); + _SSL[sslID].sockfd = Memory::Read_U32(BufferOut2); WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_CONNECT socket = %d", _SSL[sslID].sockfd); ssl_set_bio(&_SSL[sslID].ctx, net_recv, &_SSL[sslID].sockfd, net_send, &_SSL[sslID].sockfd); Memory::Write_U32(SSL_OK, _BufferIn); @@ -434,77 +431,33 @@ _SSL_NEW_ERROR: "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, - _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, - _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, + BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_DOHANDSHAKE: { - int ret = 0; - int sslID = Memory::Read_U32(_BufferOut) - 1; + int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { - ret = ssl_handshake(&_SSL[sslID].ctx); - switch (ret) - { - case 0: - Memory::Write_U32(SSL_OK, _BufferIn); - break; - case POLARSSL_ERR_NET_WANT_READ: - Memory::Write_U32(SSL_ERR_RAGAIN, _BufferIn); - break; - case POLARSSL_ERR_NET_WANT_WRITE: - Memory::Write_U32(SSL_ERR_WAGAIN, _BufferIn); - break; - default: - Memory::Write_U32(SSL_ERR_FAILED, _BufferIn); - break; - } + WiiSockMan &sm = WiiSockMan::getInstance(); + sm.doSock(_SSL[sslID].sockfd, _CommandAddress, IOCTLV_NET_SSL_DOHANDSHAKE); + return false; } else { Memory::Write_U32(SSL_ERR_ID, _BufferIn); } - WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_DOHANDSHAKE = (%d) " - "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " - "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " - "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", - ret, - _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, - _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, - _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_WRITE: { - int sslID = Memory::Read_U32(_BufferOut) - 1; + int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { - int ret = ssl_write( &_SSL[sslID].ctx, Memory::GetPointer(_BufferOut2), BufferOutSize2); - -#ifdef DEBUG_SSL - File::IOFile("ssl_write.bin", "ab").WriteBytes(Memory::GetPointer(_BufferOut2), BufferOutSize2); -#endif - if (ret >= 0) - { - // Return bytes written or SSL_ERR_ZERO if none - Memory::Write_U32((ret == 0) ? SSL_ERR_ZERO : ret, _BufferIn); - } - else - { - switch (ret) - { - case POLARSSL_ERR_NET_WANT_READ: - Memory::Write_U32(SSL_ERR_RAGAIN, _BufferIn); - break; - case POLARSSL_ERR_NET_WANT_WRITE: - Memory::Write_U32(SSL_ERR_WAGAIN, _BufferIn); - break; - default: - Memory::Write_U32(SSL_ERR_FAILED, _BufferIn); - break; - } - } + WiiSockMan &sm = WiiSockMan::getInstance(); + sm.doSock(_SSL[sslID].sockfd, _CommandAddress, IOCTLV_NET_SSL_WRITE); + return false; } else { @@ -515,45 +468,21 @@ _SSL_NEW_ERROR: "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, - _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, - _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); - WARN_LOG(WII_IPC_SSL, "%s", Memory::GetPointer(_BufferOut2)); + _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, + BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); + WARN_LOG(WII_IPC_SSL, "%s", Memory::GetPointer(BufferOut2)); break; } case IOCTLV_NET_SSL_READ: { int ret = 0; - int sslID = Memory::Read_U32(_BufferOut) - 1; + int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { - ret = ssl_read( &_SSL[sslID].ctx, Memory::GetPointer(_BufferIn2), BufferInSize2); -#ifdef DEBUG_SSL - if (ret > 0) - { - File::IOFile("ssl_read.bin", "ab").WriteBytes(Memory::GetPointer(_BufferIn2), ret); - } -#endif - if (ret >= 0) - { - // Return bytes read or SSL_ERR_ZERO if none - Memory::Write_U32((ret == 0) ? SSL_ERR_ZERO : ret, _BufferIn); - } - else - { - switch (ret) - { - case POLARSSL_ERR_NET_WANT_READ: - Memory::Write_U32(SSL_ERR_RAGAIN, _BufferIn); - break; - case POLARSSL_ERR_NET_WANT_WRITE: - Memory::Write_U32(SSL_ERR_WAGAIN, _BufferIn); - break; - default: - Memory::Write_U32(SSL_ERR_FAILED, _BufferIn); - break; - } - } + WiiSockMan &sm = WiiSockMan::getInstance(); + sm.doSock(_SSL[sslID].sockfd, _CommandAddress, IOCTLV_NET_SSL_READ); + return false; } else { @@ -566,13 +495,13 @@ _SSL_NEW_ERROR: "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", ret, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, - _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, - _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, + BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_SETROOTCADEFAULT: { - int sslID = Memory::Read_U32(_BufferOut) - 1; + int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { Memory::Write_U32(SSL_OK, _BufferIn); @@ -586,8 +515,8 @@ _SSL_NEW_ERROR: "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, - _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, - _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, + BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } case IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT: @@ -597,13 +526,13 @@ _SSL_NEW_ERROR: "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, - _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, - _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, + BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); - int sslID = Memory::Read_U32(_BufferOut) - 1; + int sslID = Memory::Read_U32(BufferOut) - 1; if (SSLID_VALID(sslID)) { - Memory::Write_U32(SSL_OK, _BufferIn); + Memory::Write_U32(SSL_OK, _BufferIn); } else { @@ -616,22 +545,24 @@ _SSL_NEW_ERROR: "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", - _Parameter, + CommandBuffer.Parameter, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, - _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, - _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + _BufferIn3, BufferInSize3, BufferOut, BufferOutSize, + BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3); break; } - return returnValue; + + Memory::Write_U32(ReturnValue, _CommandAddress+4); + return true; } u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommand(u32 _Command, u32 _BufferIn, u32 BufferInSize, - u32 _BufferOut, u32 BufferOutSize) + u32 BufferOut, u32 BufferOutSize) { WARN_LOG(WII_IPC_SSL, "%s unknown %i " "(BufferIn: (%08x, %i), BufferOut: (%08x, %i)", GetDeviceName().c_str(), _Command, - _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + _BufferIn, BufferInSize, BufferOut, BufferOutSize); return 0; } diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.h index 426bef7562..7ace4beae0 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.h @@ -24,10 +24,60 @@ #include #include -#define MAX_HOSTNAME_LEN 256 +#define NET_SSL_MAX_HOSTNAME_LEN 256 #define NET_SSL_MAXINSTANCES 4 -#define SSLID_VALID(x) (x >= 0 && x < NET_SSL_MAXINSTANCES && _SSL[x].active) +#define SSLID_VALID(x) (x >= 0 && x < NET_SSL_MAXINSTANCES && CWII_IPC_HLE_Device_net_ssl::_SSL[x].active) + +enum ssl_err_t +{ + SSL_OK = 0, + SSL_ERR_FAILED = -1, + SSL_ERR_RAGAIN = -2, + SSL_ERR_WAGAIN = -3, + SSL_ERR_SYSCALL = -5, + SSL_ERR_ZERO = -6, // read or write returned 0 + SSL_ERR_CAGAIN = -7, // BIO not connected + SSL_ERR_ID = -8, // invalid SSL id + SSL_ERR_VCOMMONNAME = -9, // verify failed: common name + SSL_ERR_VROOTCA = -10, // verify failed: root ca + SSL_ERR_VCHAIN = -11, // verify failed: certificate chain + SSL_ERR_VDATE = -12, // verify failed: date invalid + SSL_ERR_SERVER_CERT = -13, // certificate cert invalid +}; + +enum SSL_IOCTL +{ + IOCTLV_NET_SSL_NEW = 0x01, + IOCTLV_NET_SSL_CONNECT = 0x02, + IOCTLV_NET_SSL_DOHANDSHAKE = 0x03, + IOCTLV_NET_SSL_READ = 0x04, + IOCTLV_NET_SSL_WRITE = 0x05, + IOCTLV_NET_SSL_SHUTDOWN = 0x06, + IOCTLV_NET_SSL_SETCLIENTCERT = 0x07, + IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT = 0x08, + IOCTLV_NET_SSL_REMOVECLIENTCERT = 0x09, + IOCTLV_NET_SSL_SETROOTCA = 0x0A, + IOCTLV_NET_SSL_SETROOTCADEFAULT = 0x0B, + IOCTLV_NET_SSL_DOHANDSHAKEEX = 0x0C, + IOCTLV_NET_SSL_SETBUILTINROOTCA = 0x0D, + IOCTLV_NET_SSL_SETBUILTINCLIENTCERT = 0x0E, + IOCTLV_NET_SSL_DISABLEVERIFYOPTIONFORDEBUG = 0x0F, + IOCTLV_NET_SSL_DEBUGGETVERSION = 0x14, + IOCTLV_NET_SSL_DEBUGGETTIME = 0x15, +}; + +typedef struct { + ssl_context ctx; + ssl_session session; + havege_state hs; + x509_cert cacert; + x509_cert clicert; + rsa_context rsa; + int sockfd; + char hostname[NET_SSL_MAX_HOSTNAME_LEN]; + bool active; +} WII_SSL; class CWII_IPC_HLE_Device_net_ssl : public IWII_IPC_HLE_Device { @@ -44,58 +94,11 @@ public: virtual bool IOCtl(u32 _CommandAddress); virtual bool IOCtlV(u32 _CommandAddress); int getSSLFreeID(); + + static WII_SSL _SSL[NET_SSL_MAXINSTANCES]; private: - struct _SSL{ - ssl_context ctx; - ssl_session session; - havege_state hs; - x509_cert cacert; - x509_cert clicert; - rsa_context rsa; - int sockfd; - char hostname[MAX_HOSTNAME_LEN]; - bool active; - } _SSL[NET_SSL_MAXINSTANCES]; - - enum - { - IOCTLV_NET_SSL_NEW = 0x01, - IOCTLV_NET_SSL_CONNECT = 0x02, - IOCTLV_NET_SSL_DOHANDSHAKE = 0x03, - IOCTLV_NET_SSL_READ = 0x04, - IOCTLV_NET_SSL_WRITE = 0x05, - IOCTLV_NET_SSL_SHUTDOWN = 0x06, - IOCTLV_NET_SSL_SETCLIENTCERT = 0x07, - IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT = 0x08, - IOCTLV_NET_SSL_REMOVECLIENTCERT = 0x09, - IOCTLV_NET_SSL_SETROOTCA = 0x0A, - IOCTLV_NET_SSL_SETROOTCADEFAULT = 0x0B, - IOCTLV_NET_SSL_DOHANDSHAKEEX = 0x0C, - IOCTLV_NET_SSL_SETBUILTINROOTCA = 0x0D, - IOCTLV_NET_SSL_SETBUILTINCLIENTCERT = 0x0E, - IOCTLV_NET_SSL_DISABLEVERIFYOPTIONFORDEBUG = 0x0F, - IOCTLV_NET_SSL_DEBUGGETVERSION = 0x14, - IOCTLV_NET_SSL_DEBUGGETTIME = 0x15, - }; - - enum ssl_err_t - { - SSL_OK = 0, - SSL_ERR_FAILED = -1, - SSL_ERR_RAGAIN = -2, - SSL_ERR_WAGAIN = -3, - SSL_ERR_SYSCALL = -5, - SSL_ERR_ZERO = -6, // read or write returned 0 - SSL_ERR_CAGAIN = -7, // BIO not connected - SSL_ERR_ID = -8, // invalid SSL id - SSL_ERR_VCOMMONNAME = -9, // verify failed: common name - SSL_ERR_VROOTCA = -10, // verify failed: root ca - SSL_ERR_VCHAIN = -11, // verify failed: certificate chain - SSL_ERR_VDATE = -12, // verify failed: date invalid - SSL_ERR_SERVER_CERT = -13, // certificate cert invalid - }; u32 ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _BufferInSize, u32 _BufferOut, u32 _BufferOutSize); u32 ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer CommandBuffer); diff --git a/Source/Core/Core/Src/IPC_HLE/WII_Socket.cpp b/Source/Core/Core/Src/IPC_HLE/WII_Socket.cpp new file mode 100644 index 0000000000..4bf5fd65d6 --- /dev/null +++ b/Source/Core/Core/Src/IPC_HLE/WII_Socket.cpp @@ -0,0 +1,615 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include "WII_Socket.h" +#include "WII_IPC_HLE.h" +#include "WII_IPC_HLE_Device.h" + +using WII_IPC_HLE_Interface::ECommandType; +using WII_IPC_HLE_Interface::COMMAND_IOCTL; +using WII_IPC_HLE_Interface::COMMAND_IOCTLV; + +#ifdef _WIN32 +#define ERRORCODE(name) WSA ## name +#define EITHER(win32, posix) win32 +#else +#define ERRORCODE(name) name +#define EITHER(win32, posix) posix +#endif + +char* WiiSockMan::DecodeError(s32 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), (LPWSTR)Message, 1024, NULL); + return Message; +#else + return strerror(ErrorCode); +#endif +} + + +s32 WiiSockMan::getNetErrorCode(s32 ret, std::string caller, bool isRW) +{ +#ifdef _WIN32 + s32 errorCode = WSAGetLastError(); +#else + s32 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); + + switch (errorCode) + { + case ERRORCODE(EMSGSIZE): + ERROR_LOG(WII_IPC_NET, "Find out why this happened, looks like PEEK failure?"); + return -1; // Should be -SO_EMSGSIZE + case EITHER(WSAENOTSOCK, EBADF): + return -SO_EBADF; + case ERRORCODE(EADDRINUSE): + return -SO_EADDRINUSE; + case ERRORCODE(ECONNRESET): + return -SO_ECONNRESET; + case ERRORCODE(EISCONN): + return -SO_EISCONN; + case ERRORCODE(ENOTCONN): + return -SO_EAGAIN; // After proper blocking SO_EAGAIN shouldn't be needed... + case ERRORCODE(EINPROGRESS): + return -SO_EINPROGRESS; + case ERRORCODE(EALREADY): + return -SO_EALREADY; + case ERRORCODE(EACCES): + return -SO_EACCES; + case EITHER(WSAEWOULDBLOCK, EAGAIN): + if(isRW){ + return -SO_EAGAIN; // EAGAIN + }else{ + return -SO_EINPROGRESS; // EINPROGRESS + } + // TODO: remove as this should no longer be a problem once blocking is supported. + case EITHER(WSA_INVALID_HANDLE, EBADF): + return -SO_EINPROGRESS; // EINPROGRESS + default: + return -1; + } + +} + +WiiSocket::~WiiSocket() +{ + if (fd >= 0) + { + (void)closeFd(); + } +} + +void WiiSocket::setFd(s32 s) +{ + if (fd >= 0) + (void)closeFd(); + + nonBlock = false; + fd = s; + +// TODO: Remove on completion of async +#ifdef _WIN32 + u_long iMode = 1; + int ioctlret = ioctlsocket(fd, FIONBIO, &iMode); + u32 millis = 3000; +#else + int flags; + if (-1 == (flags = fcntl(fd, F_GETFL, 0))) + flags = 0; + fcntl(fd, F_SETFL, flags | O_NONBLOCK); + + struct timeval millis; + millis.tv_sec = 3; + millis.tv_usec = 0; +#endif + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&millis,sizeof(millis)); +} + +s32 WiiSocket::closeFd() +{ + s32 ReturnValue = 0; + if (fd >= 0) + { +#ifdef _WIN32 + s32 ret = closesocket(fd); +#else + s32 ret = close(sock); +#endif + ReturnValue = WiiSockMan::getNetErrorCode(ret, "delSocket", false); + } + else + { + ReturnValue = WiiSockMan::getNetErrorCode(EITHER(WSAENOTSOCK, EBADF), "delSocket", false); + } + fd = -1; + return ReturnValue; +} + +s32 WiiSocket::_connect(sockaddr_in* name, s32 namelen) +{ + int ret = connect(fd, (sockaddr*)name, namelen); + ret = WiiSockMan::getNetErrorCode(ret, "SO_CONNECT", false); + + WARN_LOG(WII_IPC_NET,"IOCTL_SO_CONNECT (%08x, %s:%d)", + fd, inet_ntoa(name->sin_addr), Common::swap16(name->sin_port)); + + return ret; +} + +s32 WiiSocket::_bind(sockaddr_in* name, s32 namelen) +{ + int ret = bind(fd, (sockaddr*)name, namelen); + ret = WiiSockMan::getNetErrorCode(ret, "SO_BIND", false); + + WARN_LOG(WII_IPC_NET, "IOCTL_SO_BIND (%08X %s:%d) = %d ", fd, + inet_ntoa(name->sin_addr), Common::swap16(name->sin_port), ret); + + return ret; +} + +s32 WiiSocket::_fcntl(u32 cmd, u32 arg) +{ +#define F_GETFL 3 +#define F_SETFL 4 +#define F_NONBLOCK 4 + s32 ret = 0; + if (cmd == F_GETFL) + { + ret = nonBlock ? F_NONBLOCK : 0; + } + else if (cmd == F_SETFL) + { + nonBlock = (arg & F_NONBLOCK) == F_NONBLOCK; + } + else + { + ERROR_LOG(WII_IPC_NET, "SO_FCNTL unknown command"); + } + + WARN_LOG(WII_IPC_NET, "IOCTL_SO_FCNTL(%08x, %08X, %08X)", + fd, cmd, arg); + + return ret; +} + +void WiiSocket::update(bool read, bool write, bool except) +{ + auto it = pending_sockops.begin(); + while (it != pending_sockops.end()) + { + s32 ReturnValue = 0; + bool forceNonBlock = false; + ECommandType ct = static_cast(Memory::Read_U32(it->_CommandAddress)); + if (!it->is_ssl && ct == COMMAND_IOCTL) + { + u32 BufferIn = Memory::Read_U32(it->_CommandAddress + 0x10); + switch(it->net_type) + { + case IOCTL_SO_FCNTL: + { + u32 cmd = Memory::Read_U32(BufferIn + 4); + u32 arg = Memory::Read_U32(BufferIn + 8); + ReturnValue = _fcntl(cmd, arg); + break; + } + case IOCTL_SO_BIND: + { + //TODO: tidy + 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(&address, sizeof(address)); + break; + } + case IOCTL_SO_CONNECT: + { + + //struct sockaddr_in echoServAddr; + u32 has_addr = Memory::Read_U32(BufferIn + 0x04); + sockaddr_in serverAddr; + + u8 addr[28]; + Memory::ReadBigEData(addr, BufferIn + 0x08, sizeof(addr)); + + if (has_addr != 1) + { + ReturnValue = -1; + break; + } + + memset(&serverAddr, 0, sizeof(serverAddr)); + memcpy(&serverAddr, addr, addr[0]); + // GC/Wii sockets have a length param as well, we dont really care :) + serverAddr.sin_family = serverAddr.sin_family >> 8; + + ReturnValue = _connect(&serverAddr, sizeof(serverAddr)); + break; + } + default: + break; + } + + // Fix blocking error codes + if (!nonBlock) + { + if (it->net_type == IOCTL_SO_CONNECT + && ReturnValue == -SO_EISCONN) + { + ReturnValue = SO_SUCCESS; + } + } + } + else if (ct == COMMAND_IOCTLV) + { + SIOCtlVBuffer CommandBuffer(it->_CommandAddress); + u32 BufferIn = 0, BufferIn2 = 0; + u32 BufferInSize = 0, BufferInSize2 = 0; + u32 BufferOut = 0, BufferOut2 = 0; + u32 BufferOutSize = 0, BufferOutSize2 = 0; + + if (CommandBuffer.InBuffer.size() > 0) + { + BufferIn = CommandBuffer.InBuffer.at(0).m_Address; + BufferInSize = CommandBuffer.InBuffer.at(0).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.InBuffer.size() > 1) + { + BufferIn2 = CommandBuffer.InBuffer.at(1).m_Address; + BufferInSize2 = CommandBuffer.InBuffer.at(1).m_Size; + } + + if (it->is_ssl) + { + int sslID = Memory::Read_U32(BufferOut) - 1; + if (SSLID_VALID(sslID)) + { + switch(it->ssl_type) + { + case IOCTLV_NET_SSL_DOHANDSHAKE: + { + + int ret = ssl_handshake(&CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx); + switch (ret) + { + case 0: + Memory::Write_U32(SSL_OK, BufferIn); + break; + case POLARSSL_ERR_NET_WANT_READ: + Memory::Write_U32(SSL_ERR_RAGAIN, BufferIn); + if (!nonBlock) + ReturnValue = SSL_ERR_RAGAIN; + break; + case POLARSSL_ERR_NET_WANT_WRITE: + Memory::Write_U32(SSL_ERR_WAGAIN, BufferIn); + if (!nonBlock) + ReturnValue = SSL_ERR_WAGAIN; + break; + default: + Memory::Write_U32(SSL_ERR_FAILED, BufferIn); + break; + } + + WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_DOHANDSHAKE = (%d) " + "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " + "BufferOut: (%08x, %i), BufferOut2: (%08x, %i)", + ret, + BufferIn, BufferInSize, BufferIn2, BufferInSize2, + BufferOut, BufferOutSize, BufferOut2, BufferOutSize2); + break; + } + case IOCTLV_NET_SSL_WRITE: + { + int ret = ssl_write(&CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx, Memory::GetPointer(BufferOut2), BufferOutSize2); + +#ifdef DEBUG_SSL + File::IOFile("ssl_write.bin", "ab").WriteBytes(Memory::GetPointer(BufferOut2), BufferOutSize2); +#endif + if (ret >= 0) + { + // Return bytes written or SSL_ERR_ZERO if none + Memory::Write_U32((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn); + } + else + { + switch (ret) + { + case POLARSSL_ERR_NET_WANT_READ: + Memory::Write_U32(SSL_ERR_RAGAIN, BufferIn); + if (!nonBlock) + ReturnValue = SSL_ERR_RAGAIN; + break; + case POLARSSL_ERR_NET_WANT_WRITE: + Memory::Write_U32(SSL_ERR_WAGAIN, BufferIn); + if (!nonBlock) + ReturnValue = SSL_ERR_WAGAIN; + break; + default: + Memory::Write_U32(SSL_ERR_FAILED, BufferIn); + break; + } + } + break; + } + case IOCTLV_NET_SSL_READ: + { + int ret = ssl_read(&CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx, Memory::GetPointer(BufferIn2), BufferInSize2); +#ifdef DEBUG_SSL + if (ret > 0) + { + File::IOFile("ssl_read.bin", "ab").WriteBytes(Memory::GetPointer(_BufferIn2), ret); + } +#endif + if (ret >= 0) + { + // Return bytes read or SSL_ERR_ZERO if none + Memory::Write_U32((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn); + } + else + { + switch (ret) + { + case POLARSSL_ERR_NET_WANT_READ: + Memory::Write_U32(SSL_ERR_RAGAIN, BufferIn); + if (!nonBlock) + ReturnValue = SSL_ERR_RAGAIN; + break; + case POLARSSL_ERR_NET_WANT_WRITE: + Memory::Write_U32(SSL_ERR_WAGAIN, BufferIn); + if (!nonBlock) + ReturnValue = SSL_ERR_WAGAIN; + break; + default: + Memory::Write_U32(SSL_ERR_FAILED, BufferIn); + break; + } + } + break; + } + default: + break; + } + } + else + { + Memory::Write_U32(SSL_ERR_ID, BufferIn); + } + } + else + { + switch (it->net_type) + { + case IOCTLV_SO_SENDTO: + { + + char * data = (char*)Memory::GetPointer(BufferIn); + u32 flags = Common::swap32(BufferIn2 + 0x04); + u32 has_destaddr = Common::swap32(BufferIn2 + 0x08); + // Act as non blocking when SO_MSG_NONBLOCK is specified + forceNonBlock = ((flags & SO_MSG_NONBLOCK) == SO_MSG_NONBLOCK); + + // send/sendto only handles PEEK + flags &= SO_MSG_PEEK | SO_MSG_OOB; + + u8 destaddr[28]; + struct sockaddr_in* addr = (struct sockaddr_in*)&destaddr; + if (has_destaddr) + { + Memory::ReadBigEData((u8*)&destaddr, BufferIn2 + 0x0C, BufferInSize2 - 0x0C); + addr->sin_family = addr->sin_family >> 8; + } + + int ret = sendto(fd, data, BufferInSize, flags, + has_destaddr ? (struct sockaddr*)addr : NULL, + has_destaddr ? sizeof(sockaddr) : 0); + ReturnValue = WiiSockMan::getNetErrorCode(ret, "SO_SENDTO", true); + + WARN_LOG(WII_IPC_NET, + "%s = %d Socket: %08x, BufferIn: (%08x, %i), BufferIn2: (%08x, %i), %u.%u.%u.%u", + has_destaddr ? "IOCTLV_SO_SENDTO " : "IOCTLV_SO_SEND ", + ReturnValue, fd, 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 + ); + break; + } + case IOCTLV_SO_RECVFROM: + { + 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); + } + + // Act as non blocking when SO_MSG_NONBLOCK is specified + forceNonBlock = ((flags & SO_MSG_NONBLOCK) == SO_MSG_NONBLOCK); + + // recv/recvfrom only handles PEEK + flags &= SO_MSG_PEEK | SO_MSG_OOB; +#ifdef _WIN32 + if(flags & MSG_PEEK){ + unsigned long totallen = 0; + ioctlsocket(sock, FIONREAD, &totallen); + ReturnValue = totallen; + break; + } +#endif + int ret = recvfrom(sock, buf, len, flags, + fromlen ? (struct sockaddr*) &addr : NULL, + fromlen ? &fromlen : 0); + ReturnValue = WiiSockMan::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 ", + ReturnValue, 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); + } + break; + } + default: + break; + } + } + + } + + if ( nonBlock || forceNonBlock + || (!it->is_ssl && ReturnValue != -SO_EAGAIN && ReturnValue != -SO_EINPROGRESS && ReturnValue != -SO_EALREADY) + || (it->is_ssl && ReturnValue != SSL_ERR_WAGAIN && ReturnValue != SSL_ERR_RAGAIN)) + { + WARN_LOG(WII_IPC_NET, "IOCTL(V) Sock: %d ioctl/v: %d returned: %d nonBlock: %d forceNonBlock: %d", + fd, it->is_ssl ? it->ssl_type : it->net_type, ReturnValue, nonBlock, forceNonBlock); + WiiSockMan::EnqueueReply(it->_CommandAddress, ReturnValue); + it = pending_sockops.erase(it); + } + else + { + ++it; + } + } +} + +void WiiSocket::doSock(u32 _CommandAddress, NET_IOCTL type) +{ + sockop so = {_CommandAddress, false}; + so.net_type = type; + pending_sockops.push_back(so); +} + +void WiiSocket::doSock(u32 _CommandAddress, SSL_IOCTL type) +{ + sockop so = {_CommandAddress, true}; + so.ssl_type = type; + pending_sockops.push_back(so); +} + +s32 WiiSockMan::newSocket(s32 af, s32 type, s32 protocol) +{ + s32 s = (s32)socket(af, type, protocol); + s32 ret = getNetErrorCode(s, "newSocket", false); + if (ret >= 0) + { + WiiSocket& sock = WiiSockets[ret]; + sock.setFd(ret); + } + return ret; +} + +s32 WiiSockMan::delSocket(s32 s) +{ + s32 ReturnValue = WiiSockets[s].closeFd(); + WiiSockets.erase(s); + return ReturnValue; +} + +void WiiSockMan::Update() +{ + s32 nfds = 0; + fd_set read_fds, write_fds, except_fds; + struct timeval t = {0,0}; + FD_ZERO(&read_fds); + FD_ZERO(&write_fds); + FD_ZERO(&except_fds); + for (auto it = WiiSockets.begin(); it != WiiSockets.end(); ++it) + { + WiiSocket& sock = it->second; + if (sock.valid()) + { + FD_SET(sock.fd, &read_fds); + FD_SET(sock.fd, &write_fds); + FD_SET(sock.fd, &except_fds); + nfds = max(nfds, sock.fd+1); + } + else + { + // Good time to clean up invalid sockets. + WiiSockets.erase(sock.fd); + } + } + s32 ret = select(nfds, &read_fds, &write_fds, &except_fds, &t); + + if(ret >= 0) + { + for (auto it = WiiSockets.begin(); it != WiiSockets.end(); ++it) + { + WiiSocket& sock = it->second; + sock.update( + FD_ISSET(sock.fd, &read_fds) != 0, + FD_ISSET(sock.fd, &write_fds) != 0, + FD_ISSET(sock.fd, &except_fds) != 0 + ); + } + } + else + { + for (auto it = WiiSockets.begin(); it != WiiSockets.end(); ++it) + { + it->second.update(false, false, false); + } + } +} + +void WiiSockMan::EnqueueReply(u32 CommandAddress, s32 ReturnValue) +{ + Memory::Write_U32(8, CommandAddress); + // IOS seems to write back the command that was responded to + Memory::Write_U32(Memory::Read_U32(CommandAddress), CommandAddress + 8); + + // Return value + Memory::Write_U32(ReturnValue, CommandAddress + 4); + + WII_IPC_HLE_Interface::EnqReply(CommandAddress); +} + + +#undef ERRORCODE +#undef EITHER diff --git a/Source/Core/Core/Src/IPC_HLE/WII_Socket.h b/Source/Core/Core/Src/IPC_HLE/WII_Socket.h new file mode 100644 index 0000000000..c64c0dfd4d --- /dev/null +++ b/Source/Core/Core/Src/IPC_HLE/WII_Socket.h @@ -0,0 +1,214 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#ifndef _WII_SOCKET_H_ +#define _WII_SOCKET_H_ + + +#ifdef _WIN32 +#include +#include +#include + +#include "fakepoll.h" +#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) +#define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) + +#elif defined(__linux__) or defined(__APPLE__) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct pollfd pollfd_t; +#else +#include +#include +#include +#include +#include +#endif + +#include // std::for_each +#include +#include +#include +#include + +#include "FileUtil.h" +#include "WII_IPC_HLE.h" +#include "WII_IPC_HLE_Device_net.h" +#include "WII_IPC_HLE_Device_net_ssl.h" + +enum { + SO_MSG_OOB = 0x01, + SO_MSG_PEEK = 0x02, + SO_MSG_NONBLOCK = 0x04, +}; +enum { + SO_SUCCESS, + SO_E2BIG = 1, + SO_EACCES, + SO_EADDRINUSE, + SO_EADDRNOTAVAIL, + SO_EAFNOSUPPORT, + SO_EAGAIN, + SO_EALREADY, + SO_EBADF, + SO_EBADMSG, + SO_EBUSY, + SO_ECANCELED, + SO_ECHILD, + SO_ECONNABORTED, + SO_ECONNREFUSED, + SO_ECONNRESET, + SO_EDEADLK, + SO_EDESTADDRREQ, + SO_EDOM, + SO_EDQUOT, + SO_EEXIST, + SO_EFAULT, + SO_EFBIG, + SO_EHOSTUNREACH, + SO_EIDRM, + SO_EILSEQ, + SO_EINPROGRESS, + SO_EINTR, + SO_EINVAL, + SO_EIO, + SO_EISCONN, + SO_EISDIR, + SO_ELOOP, + SO_EMFILE, + SO_EMLINK, + SO_EMSGSIZE, + SO_EMULTIHOP, + SO_ENAMETOOLONG, + SO_ENETDOWN, + SO_ENETRESET, + SO_ENETUNREACH, + SO_ENFILE, + SO_ENOBUFS, + SO_ENODATA, + SO_ENODEV, + SO_ENOENT, + SO_ENOEXEC, + SO_ENOLCK, + SO_ENOLINK, + SO_ENOMEM, + SO_ENOMSG, + SO_ENOPROTOOPT, + SO_ENOSPC, + SO_ENOSR, + SO_ENOSTR, + SO_ENOSYS, + SO_ENOTCONN, + SO_ENOTDIR, + SO_ENOTEMPTY, + SO_ENOTSOCK, + SO_ENOTSUP, + SO_ENOTTY, + SO_ENXIO, + SO_EOPNOTSUPP, + SO_EOVERFLOW, + SO_EPERM, + SO_EPIPE, + SO_EPROTO, + SO_EPROTONOSUPPORT, + SO_EPROTOTYPE, + SO_ERANGE, + SO_EROFS, + SO_ESPIPE, + SO_ESRCH, + SO_ESTALE, + SO_ETIME, + SO_ETIMEDOUT, + SO_ETXTBSY, + SO_EXDEV +}; + +class WiiSocket +{ + struct sockop{ + u32 _CommandAddress; + bool is_ssl; + union + { + NET_IOCTL net_type; + SSL_IOCTL ssl_type; + }; + }; +private: + s32 fd; + bool nonBlock; + std::list pending_sockops; + + friend class WiiSockMan; + void setFd(s32 s); + s32 closeFd(); + s32 _fcntl(u32 cmd, u32 arg); + s32 _bind(sockaddr_in* name, s32 namelen); + s32 _connect(sockaddr_in* name, s32 namelen); + + void doSock(u32 _CommandAddress, NET_IOCTL type); + void doSock(u32 _CommandAddress, SSL_IOCTL type); + void update(bool read, bool write, bool except); + bool valid() {return fd >= 0;} +public: + WiiSocket() : fd(-1), nonBlock(false) {} + ~WiiSocket(); + void operator=(WiiSocket const&); // Don't implement + +}; + +class WiiSockMan +{ +public: + static s32 getNetErrorCode(s32 ret, std::string caller, bool isRW); + static char* DecodeError(s32 ErrorCode); + + static WiiSockMan& getInstance() + { + static WiiSockMan instance; // Guaranteed to be destroyed. + return instance; // Instantiated on first use. + } + void Update(); + static void EnqueueReply(u32 CommandAddress, s32 ReturnValue); + + // NON-BLOCKING FUNCTIONS + s32 newSocket(s32 af, s32 type, s32 protocol); + s32 delSocket(s32 s); + + template + void doSock(s32 sock, u32 CommandAddress, T type) + { + if (WiiSockets.find(sock) == WiiSockets.end()) + { + ERROR_LOG(WII_IPC_NET, + "doSock: Error, fd not found (%08x, %08X, %08X)", + sock, CommandAddress, type); + EnqueueReply(CommandAddress, -SO_EBADF); + } + else + { + WiiSockets[sock].doSock(CommandAddress, type); + } + } + +private: + WiiSockMan() {}; // Constructor? (the {} brackets) are needed here. + WiiSockMan(WiiSockMan const&); // Don't Implement + void operator=(WiiSockMan const&); // Don't implement + + std::unordered_map WiiSockets; +}; + +#endif