summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorShawn Hoffman <godisgovernment@gmail.com>2012-02-17 00:41:31 -0800
committerShawn Hoffman <godisgovernment@gmail.com>2012-02-17 00:51:33 -0800
commit570a12dcd11710ffe00661f765fbb85ac03a457d (patch)
tree40c7a7ffc170130ee3e19e45599e7eaf02120a76 /Source/Core
parent2d5e80d36cfef064810b4effa3223bbe53417161 (diff)
Fix ICMP ping. Obey timeout.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Src/IPC_HLE/ICMP.h4
-rw-r--r--Source/Core/Core/Src/IPC_HLE/ICMPWin.cpp41
-rw-r--r--Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp68
3 files changed, 77 insertions, 36 deletions
diff --git a/Source/Core/Core/Src/IPC_HLE/ICMP.h b/Source/Core/Core/Src/IPC_HLE/ICMP.h
index abb99b9ded..c04e74ae0c 100644
--- a/Source/Core/Core/Src/IPC_HLE/ICMP.h
+++ b/Source/Core/Core/Src/IPC_HLE/ICMP.h
@@ -6,5 +6,5 @@
#include "Common.h"
-int icmp_echo_req(u32 s, sockaddr_in *addr, u8 *data, u32 data_length);
-int icmp_echo_rep(u32 s, sockaddr_in *addr, const u8 *data, u32 data_length);
+int icmp_echo_req(const u32 s, const sockaddr_in *addr, const u8 *data, const u32 data_length);
+int icmp_echo_rep(const u32 s, sockaddr_in *addr, const u32 timeout, const u32 data_length);
diff --git a/Source/Core/Core/Src/IPC_HLE/ICMPWin.cpp b/Source/Core/Core/Src/IPC_HLE/ICMPWin.cpp
index 8c90ce3ea3..a5d0cd240e 100644
--- a/Source/Core/Core/Src/IPC_HLE/ICMPWin.cpp
+++ b/Source/Core/Core/Src/IPC_HLE/ICMPWin.cpp
@@ -8,7 +8,6 @@ enum
enum
{
- // id/seq/data come from wii
ICMP_HDR_LEN = 4,
IP_HDR_LEN = 20
};
@@ -35,8 +34,8 @@ static u8 workspace[56];
* NOTE: to handle odd number of bytes, last (even) byte in
* buffer have a value of 0 (we assume that it does)
*/
-u16 cksum(u16 *buffer, int length)
-{
+u16 cksum(const u16 *buffer, int length)
+{
u32 sum = 0;
while (length > 0)
@@ -51,7 +50,7 @@ u16 cksum(u16 *buffer, int length)
return (u16)~sum;
}
-int icmp_echo_req(u32 s, sockaddr_in *addr, u8 *data, u32 data_length)
+int icmp_echo_req(const u32 s, const sockaddr_in *addr, const u8 *data, const u32 data_length)
{
memset(workspace, 0, sizeof(workspace));
icmp_hdr *header = (icmp_hdr *)workspace;
@@ -62,18 +61,38 @@ int icmp_echo_req(u32 s, sockaddr_in *addr, u8 *data, u32 data_length)
header->checksum = cksum((u16 *)header, ICMP_HDR_LEN + data_length);
- return sendto((SOCKET)s, (LPSTR)header, ICMP_HDR_LEN + data_length, 0,
+ int num_bytes = sendto((SOCKET)s, (LPSTR)header, ICMP_HDR_LEN + data_length, 0,
(sockaddr *)addr, sizeof(sockaddr));
+
+ if (num_bytes >= ICMP_HDR_LEN)
+ num_bytes -= ICMP_HDR_LEN;
+
+ return num_bytes;
}
-int icmp_echo_rep(u32 s, sockaddr_in *addr, const u8 *data, u32 data_length)
+int icmp_echo_rep(const u32 s, sockaddr_in *addr, const u32 timeout, const u32 data_length)
{
memset(workspace, 0, sizeof(workspace));
int addr_length = sizeof(sockaddr_in);
- int ret = recvfrom((SOCKET)s, (LPSTR)workspace,
- IP_HDR_LEN + ICMP_HDR_LEN + data_length,
- 0, (sockaddr *)addr, &addr_length);
+ int num_bytes = 0;
+
+ fd_set read_fds;
+ FD_ZERO(&read_fds);
+ FD_SET(s, &read_fds);
+
+ timeval t;
+ t.tv_sec = timeout / 1000;
+ if (select(0, &read_fds, NULL, NULL, &t) > 0)
+ {
+ num_bytes = recvfrom((SOCKET)s, (LPSTR)workspace,
+ IP_HDR_LEN + ICMP_HDR_LEN + data_length,
+ 0, (sockaddr *)addr, &addr_length);
+
+ // TODO do we need to memcmp the data?
+
+ if (num_bytes >= IP_HDR_LEN + ICMP_HDR_LEN)
+ num_bytes -= IP_HDR_LEN + ICMP_HDR_LEN;
+ }
- // TODO do we need to memcmp the data?
- return ret;
+ return num_bytes;
}
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 202ebc8191..1d2af7946a 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
@@ -154,6 +154,12 @@ bool CWII_IPC_HLE_Device_net_kd_request::IOCtl(u32 _CommandAddress)
WARN_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_UNLOCK_SOCKET - NI");
break;
+ case IOCTL_NWC24_REQUEST_REGISTER_USER_ID:
+ WARN_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_REQUEST_REGISTER_USER_ID");
+ Memory::Write_U32(0, BufferOut);
+ Memory::Write_U32(0, BufferOut+4);
+ break;
+
case IOCTL_NWC24_REQUEST_GENERATED_USER_ID: // (Input: none, Output: 32 bytes)
WARN_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_REQUEST_GENERATED_USER_ID");
//Memory::Write_U32(0xFFFFFFDC, BufferOut);
@@ -817,34 +823,35 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command,
"Socket: %08X, BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
sock, _BufferIn, BufferInSize, _BufferOut, BufferOutSize);
- struct sockaddr sa;
+ sockaddr sa;
socklen_t sa_len;
- sa_len = sizeof(sa);
+ 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);
+ Memory::Write_U8(sa.sa_family & 0xFF, _BufferOut + 1);
+ Memory::WriteBigEData((u8*)&sa.sa_data, _BufferOut + 2, BufferOutSize - 2);
return ret;
}
case IOCTL_SO_GETPEERNAME:
{
u32 sock = Memory::Read_U32(_BufferIn);
- WARN_LOG(WII_IPC_NET, "IOCTL_SO_GETPEERNAME "
- "Socket: %08X, BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
- sock, _BufferIn, BufferInSize, _BufferOut, BufferOutSize);
-
- struct sockaddr sa;
+ sockaddr sa;
socklen_t sa_len;
- sa_len = sizeof(sa);
+ sa_len = sizeof(sa);
+
int ret = getpeername(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);
+ Memory::Write_U8(AF_INET, _BufferOut + 1);
+ Memory::WriteBigEData((u8*)&sa.sa_data, _BufferOut + 2, BufferOutSize - 2);
+
+ WARN_LOG(WII_IPC_NET, "IOCTL_SO_GETPEERNAME(%x)", sock);
+
return ret;
}
+
case IOCTL_SO_GETHOSTID:
{
WARN_LOG(WII_IPC_NET, "IOCTL_SO_GETHOSTID "
@@ -993,7 +1000,7 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command,
// AF type?
u32 arg = Memory::Read_U32(_BufferIn);
u32 sock = (u32)socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
- ERROR_LOG(WII_IPC_NET, "IOCTL_SO_ICMPSOCKET(%x) %x", arg, sock);
+ DEBUG_LOG(WII_IPC_NET, "IOCTL_SO_ICMPSOCKET(%x) %x", arg, sock);
return getNetErrorCode(sock, "IOCTL_SO_ICMPSOCKET", false);
}
@@ -1005,7 +1012,7 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command,
{
u32 sock = Memory::Read_U32(_BufferIn);
u32 ret = closesocket(sock);
- ERROR_LOG(WII_IPC_NET, "IOCTL_SO_ICMPCLOSE(%x) %x", sock, ret);
+ DEBUG_LOG(WII_IPC_NET, "IOCTL_SO_ICMPCLOSE(%x) %x", sock, ret);
return getNetErrorCode(ret, "IOCTL_SO_ICMPCLOSE", false);
}
@@ -1396,7 +1403,7 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer
{
u8 length;
u8 addr_family;
- u16 port;
+ u16 icmp_id;
u32 ip;
} ip_info;
@@ -1411,14 +1418,14 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer
ip_info.length = Memory::Read_U8(_BufferIn + 16);
ip_info.addr_family = Memory::Read_U8(_BufferIn + 17);
- ip_info.port = Memory::Read_U16(_BufferIn + 18);
+ 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 || ip_info.port != 0)
+ 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 port %x",
- ip_info.length, ip_info.addr_family, ip_info.port);
+ "length %x addr_family %x",
+ ip_info.length, ip_info.addr_family);
}
DEBUG_LOG(WII_IPC_NET, "IOCTLV_SO_ICMPPING %x", ip_info.ip);
@@ -1427,13 +1434,28 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer
addr.sin_family = AF_INET;
addr.sin_addr.S_un.S_addr = Common::swap32(ip_info.ip);
memset(addr.sin_zero, 0, 8);
- u8 *data = Memory::GetPointer(_BufferIn2);
+
+ u8 data[0x20];
+ memset(data, 0, sizeof(data));
+ u32 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, BufferInSize2);
- if (ret >= 0)
+ int ret = icmp_echo_req(sock, &addr, data, icmp_length);
+ if (ret == icmp_length)
{
- //icmp_echo_rep(sock, &addr, data, BufferInSize2);
+ ret = icmp_echo_rep(sock, &addr, timeout, icmp_length);
}
+
// TODO proper error codes
return 0;
}