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