From 13957a627c7128c5b24e76aa6d446ca3a1f469a5 Mon Sep 17 00:00:00 2001 From: Sepalani Date: Sun, 10 Jul 2022 11:42:58 +0400 Subject: [PATCH 1/9] Common/Network: Remove unused constructors --- Source/Core/Common/Network.cpp | 14 -------------- Source/Core/Common/Network.h | 2 -- 2 files changed, 16 deletions(-) diff --git a/Source/Core/Common/Network.cpp b/Source/Core/Common/Network.cpp index d03b537e25..59d0c9026e 100644 --- a/Source/Core/Common/Network.cpp +++ b/Source/Core/Common/Network.cpp @@ -337,13 +337,6 @@ std::vector ARPPacket::Build() const TCPPacket::TCPPacket() = default; -TCPPacket::TCPPacket(const MACAddress& destination, const MACAddress& source) -{ - eth_header.destination = destination; - eth_header.source = source; - eth_header.ethertype = htons(IPV4_ETHERTYPE); -} - TCPPacket::TCPPacket(const MACAddress& destination, const MACAddress& source, const sockaddr_in& from, const sockaddr_in& to, u32 seq, u32 ack, u16 flags) { @@ -406,13 +399,6 @@ u16 TCPPacket::Size() const UDPPacket::UDPPacket() = default; -UDPPacket::UDPPacket(const MACAddress& destination, const MACAddress& source) -{ - eth_header.destination = destination; - eth_header.source = source; - eth_header.ethertype = htons(IPV4_ETHERTYPE); -} - UDPPacket::UDPPacket(const MACAddress& destination, const MACAddress& source, const sockaddr_in& from, const sockaddr_in& to, const std::vector& payload) { diff --git a/Source/Core/Common/Network.h b/Source/Core/Common/Network.h index f9706c0328..57479a1f11 100644 --- a/Source/Core/Common/Network.h +++ b/Source/Core/Common/Network.h @@ -194,7 +194,6 @@ static_assert(sizeof(ARPPacket) == ARPPacket::SIZE); struct TCPPacket { TCPPacket(); - TCPPacket(const MACAddress& destination, const MACAddress& source); TCPPacket(const MACAddress& destination, const MACAddress& source, const sockaddr_in& from, const sockaddr_in& to, u32 seq, u32 ack, u16 flags); std::vector Build(); @@ -213,7 +212,6 @@ struct TCPPacket struct UDPPacket { UDPPacket(); - UDPPacket(const MACAddress& destination, const MACAddress& source); UDPPacket(const MACAddress& destination, const MACAddress& source, const sockaddr_in& from, const sockaddr_in& to, const std::vector& payload); std::vector Build(); From b7bd2a4001ad12f03636d21b75785a032f8a8bc0 Mon Sep 17 00:00:00 2001 From: Sepalani Date: Sun, 10 Jul 2022 12:31:59 +0400 Subject: [PATCH 2/9] Common/Network: Use member initializer list --- Source/Core/Common/Network.cpp | 28 ++++++++++++---------------- Source/Core/Common/Network.h | 1 + 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/Source/Core/Common/Network.cpp b/Source/Core/Common/Network.cpp index 59d0c9026e..5bc6469912 100644 --- a/Source/Core/Common/Network.cpp +++ b/Source/Core/Common/Network.cpp @@ -85,9 +85,13 @@ std::optional StringToMacAddress(std::string_view mac_string) EthernetHeader::EthernetHeader() = default; -EthernetHeader::EthernetHeader(u16 ether_type) +EthernetHeader::EthernetHeader(u16 ether_type) : ethertype(htons(ether_type)) +{ +} + +EthernetHeader::EthernetHeader(const MACAddress& dest, const MACAddress& src, u16 ether_type) + : destination(dest), source(src), ethertype(htons(ether_type)) { - ethertype = htons(ether_type); } u16 EthernetHeader::Size() const @@ -339,13 +343,10 @@ TCPPacket::TCPPacket() = default; TCPPacket::TCPPacket(const MACAddress& destination, const MACAddress& source, const sockaddr_in& from, const sockaddr_in& to, u32 seq, u32 ack, u16 flags) + : eth_header(destination, source, IPV4_ETHERTYPE), + ip_header(Common::TCPHeader::SIZE, IPPROTO_TCP, from, to), + tcp_header(from, to, seq, ack, flags) { - eth_header.destination = destination; - eth_header.source = source; - eth_header.ethertype = htons(IPV4_ETHERTYPE); - - ip_header = Common::IPv4Header(Common::TCPHeader::SIZE, IPPROTO_TCP, from, to); - tcp_header = Common::TCPHeader(from, to, seq, ack, flags); } std::vector TCPPacket::Build() @@ -401,15 +402,10 @@ UDPPacket::UDPPacket() = default; UDPPacket::UDPPacket(const MACAddress& destination, const MACAddress& source, const sockaddr_in& from, const sockaddr_in& to, const std::vector& payload) + : eth_header(destination, source, IPV4_ETHERTYPE), + ip_header(static_cast(payload.size() + Common::UDPHeader::SIZE), IPPROTO_UDP, from, to), + udp_header(from, to, static_cast(payload.size())), data(payload) { - eth_header.destination = destination; - eth_header.source = source; - eth_header.ethertype = htons(IPV4_ETHERTYPE); - - ip_header = Common::IPv4Header(static_cast(payload.size() + Common::UDPHeader::SIZE), - IPPROTO_UDP, from, to); - udp_header = Common::UDPHeader(from, to, static_cast(payload.size())); - data = payload; } std::vector UDPPacket::Build() diff --git a/Source/Core/Common/Network.h b/Source/Core/Common/Network.h index 57479a1f11..718a297f09 100644 --- a/Source/Core/Common/Network.h +++ b/Source/Core/Common/Network.h @@ -47,6 +47,7 @@ struct EthernetHeader { EthernetHeader(); explicit EthernetHeader(u16 ether_type); + EthernetHeader(const MACAddress& dest, const MACAddress& src, u16 ether_type); u16 Size() const; static constexpr std::size_t SIZE = 14; From 4efe1e7ca7ca4377b5f54e277e2d086a649c2cbd Mon Sep 17 00:00:00 2001 From: Sepalani Date: Sun, 10 Jul 2022 12:48:12 +0400 Subject: [PATCH 3/9] Common/Network: Ensure offsetof is valid --- Source/Core/Common/Network.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/Core/Common/Network.h b/Source/Core/Common/Network.h index 718a297f09..e3b319bc6b 100644 --- a/Source/Core/Common/Network.h +++ b/Source/Core/Common/Network.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "Common/CommonTypes.h" @@ -57,6 +58,7 @@ struct EthernetHeader u16 ethertype = 0; }; static_assert(sizeof(EthernetHeader) == EthernetHeader::SIZE); +static_assert(std::is_standard_layout_v); struct IPv4Header { @@ -79,6 +81,7 @@ struct IPv4Header IPAddress destination_addr{}; }; static_assert(sizeof(IPv4Header) == IPv4Header::SIZE); +static_assert(std::is_standard_layout_v); struct TCPHeader { @@ -101,6 +104,7 @@ struct TCPHeader u16 urgent_pointer = 0; }; static_assert(sizeof(TCPHeader) == TCPHeader::SIZE); +static_assert(std::is_standard_layout_v); struct UDPHeader { @@ -117,6 +121,7 @@ struct UDPHeader u16 checksum = 0; }; static_assert(sizeof(UDPHeader) == UDPHeader::SIZE); +static_assert(std::is_standard_layout_v); #pragma pack(push, 1) struct ARPHeader From 6238834c05d173e92cf5857bcecf9b9a59ebdf68 Mon Sep 17 00:00:00 2001 From: Sepalani Date: Sun, 10 Jul 2022 13:56:33 +0400 Subject: [PATCH 4/9] Common/Network: Add InsertObj helper --- Source/Core/Common/Network.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/Source/Core/Common/Network.cpp b/Source/Core/Common/Network.cpp index 5bc6469912..2f5ddd44df 100644 --- a/Source/Core/Common/Network.cpp +++ b/Source/Core/Common/Network.cpp @@ -314,6 +314,14 @@ u16 ComputeTCPNetworkChecksum(const IPAddress& from, const IPAddress& to, const return htons(static_cast(tcp_checksum)); } +template +static inline void InsertObj(Container* container, const T& obj) +{ + static_assert(std::is_trivially_copyable_v); + const u8* const ptr = reinterpret_cast(&obj); + container->insert(container->end(), ptr, ptr + sizeof(obj)); +} + ARPPacket::ARPPacket() = default; u16 ARPPacket::Size() const @@ -332,10 +340,8 @@ std::vector ARPPacket::Build() const { std::vector result; result.reserve(EthernetHeader::SIZE + ARPHeader::SIZE); - const u8* eth_ptr = reinterpret_cast(ð_header); - result.insert(result.end(), eth_ptr, eth_ptr + EthernetHeader::SIZE); - const u8* arp_ptr = reinterpret_cast(&arp_header); - result.insert(result.end(), arp_ptr, arp_ptr + ARPHeader::SIZE); + InsertObj(&result, eth_header); + InsertObj(&result, arp_header); return result; } @@ -359,10 +365,8 @@ std::vector TCPPacket::Build() TCPHeader::SIZE + tcp_options.size() + data.size())); // copy data - const u8* eth_ptr = reinterpret_cast(ð_header); - result.insert(result.end(), eth_ptr, eth_ptr + EthernetHeader::SIZE); - const u8* ip_ptr = reinterpret_cast(&ip_header); - result.insert(result.end(), ip_ptr, ip_ptr + IPv4Header::SIZE); + InsertObj(&result, eth_header); + InsertObj(&result, ip_header); std::size_t offset = EthernetHeader::SIZE + IPv4Header::SIZE; if (ipv4_options.size() > 0) { @@ -419,10 +423,8 @@ std::vector UDPPacket::Build() udp_header.length = htons(static_cast(UDPHeader::SIZE + data.size())); // copy data - const u8* eth_ptr = reinterpret_cast(ð_header); - result.insert(result.end(), eth_ptr, eth_ptr + EthernetHeader::SIZE); - const u8* ip_ptr = reinterpret_cast(&ip_header); - result.insert(result.end(), ip_ptr, ip_ptr + IPv4Header::SIZE); + InsertObj(&result, eth_header); + InsertObj(&result, ip_header); std::size_t offset = EthernetHeader::SIZE + IPv4Header::SIZE; if (ipv4_options.size() > 0) { From b206f98261e9c24b3eb79eb1df466719216cb178 Mon Sep 17 00:00:00 2001 From: Sepalani Date: Sun, 10 Jul 2022 14:04:03 +0400 Subject: [PATCH 5/9] Common/Network: Remove unnecessary size checks --- Source/Core/Common/Network.cpp | 36 ++++++++++++---------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/Source/Core/Common/Network.cpp b/Source/Core/Common/Network.cpp index 2f5ddd44df..f6aac99922 100644 --- a/Source/Core/Common/Network.cpp +++ b/Source/Core/Common/Network.cpp @@ -368,11 +368,9 @@ std::vector TCPPacket::Build() InsertObj(&result, eth_header); InsertObj(&result, ip_header); std::size_t offset = EthernetHeader::SIZE + IPv4Header::SIZE; - if (ipv4_options.size() > 0) - { - result.insert(result.end(), ipv4_options.begin(), ipv4_options.end()); - offset += ipv4_options.size(); - } + result.insert(result.end(), ipv4_options.begin(), ipv4_options.end()); + offset += ipv4_options.size(); + tcp_header.checksum = 0; const u16 props = (ntohs(tcp_header.properties) & 0xfff) | (static_cast((tcp_options.size() + TCPHeader::SIZE) & 0x3c) << 10); @@ -381,15 +379,11 @@ std::vector TCPPacket::Build() result.insert(result.end(), tcp_ptr, tcp_ptr + TCPHeader::SIZE); const std::size_t tcp_offset = offset; offset += TCPHeader::SIZE; - if (tcp_options.size() > 0) - { - result.insert(result.end(), tcp_options.begin(), tcp_options.end()); - offset += tcp_options.size(); - } - if (data.size() > 0) - { - result.insert(result.end(), data.begin(), data.end()); - } + result.insert(result.end(), tcp_options.begin(), tcp_options.end()); + offset += tcp_options.size(); + + result.insert(result.end(), data.begin(), data.end()); + tcp_header.checksum = ComputeTCPNetworkChecksum( ip_header.source_addr, ip_header.destination_addr, &result[tcp_offset], static_cast(result.size() - tcp_offset), IPPROTO_TCP); @@ -426,20 +420,16 @@ std::vector UDPPacket::Build() InsertObj(&result, eth_header); InsertObj(&result, ip_header); std::size_t offset = EthernetHeader::SIZE + IPv4Header::SIZE; - if (ipv4_options.size() > 0) - { - result.insert(result.end(), ipv4_options.begin(), ipv4_options.end()); - offset += ipv4_options.size(); - } + result.insert(result.end(), ipv4_options.begin(), ipv4_options.end()); + offset += ipv4_options.size(); + udp_header.checksum = 0; const u8* udp_ptr = reinterpret_cast(&udp_header); result.insert(result.end(), udp_ptr, udp_ptr + UDPHeader::SIZE); const std::size_t udp_offset = offset; offset += UDPHeader::SIZE; - if (data.size() > 0) - { - result.insert(result.end(), data.begin(), data.end()); - } + result.insert(result.end(), data.begin(), data.end()); + udp_header.checksum = ComputeTCPNetworkChecksum( ip_header.source_addr, ip_header.destination_addr, &result[udp_offset], static_cast(result.size() - udp_offset), IPPROTO_UDP); From d902b04ae09a7118b7551a7fbe8c31f43cbcf643 Mon Sep 17 00:00:00 2001 From: Sepalani Date: Sun, 10 Jul 2022 14:11:50 +0400 Subject: [PATCH 6/9] Common/Network: Remove unused offset variables --- Source/Core/Common/Network.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Source/Core/Common/Network.cpp b/Source/Core/Common/Network.cpp index f6aac99922..1ee5496fcc 100644 --- a/Source/Core/Common/Network.cpp +++ b/Source/Core/Common/Network.cpp @@ -367,9 +367,8 @@ std::vector TCPPacket::Build() // copy data InsertObj(&result, eth_header); InsertObj(&result, ip_header); - std::size_t offset = EthernetHeader::SIZE + IPv4Header::SIZE; result.insert(result.end(), ipv4_options.begin(), ipv4_options.end()); - offset += ipv4_options.size(); + const std::size_t tcp_offset = result.size(); tcp_header.checksum = 0; const u16 props = (ntohs(tcp_header.properties) & 0xfff) | @@ -377,11 +376,7 @@ std::vector TCPPacket::Build() tcp_header.properties = htons(props); const u8* tcp_ptr = reinterpret_cast(&tcp_header); result.insert(result.end(), tcp_ptr, tcp_ptr + TCPHeader::SIZE); - const std::size_t tcp_offset = offset; - offset += TCPHeader::SIZE; result.insert(result.end(), tcp_options.begin(), tcp_options.end()); - offset += tcp_options.size(); - result.insert(result.end(), data.begin(), data.end()); tcp_header.checksum = ComputeTCPNetworkChecksum( @@ -419,15 +414,12 @@ std::vector UDPPacket::Build() // copy data InsertObj(&result, eth_header); InsertObj(&result, ip_header); - std::size_t offset = EthernetHeader::SIZE + IPv4Header::SIZE; result.insert(result.end(), ipv4_options.begin(), ipv4_options.end()); - offset += ipv4_options.size(); + const std::size_t udp_offset = result.size(); udp_header.checksum = 0; const u8* udp_ptr = reinterpret_cast(&udp_header); result.insert(result.end(), udp_ptr, udp_ptr + UDPHeader::SIZE); - const std::size_t udp_offset = offset; - offset += UDPHeader::SIZE; result.insert(result.end(), data.begin(), data.end()); udp_header.checksum = ComputeTCPNetworkChecksum( From 5fdf255a2da7736a791a8a35f9652ea5ac14fe06 Mon Sep 17 00:00:00 2001 From: Sepalani Date: Sun, 10 Jul 2022 20:12:07 +0400 Subject: [PATCH 7/9] Common/Network: Make Build() methods const --- Source/Core/Common/Network.cpp | 74 +++++++++++++------------ Source/Core/Common/Network.h | 4 +- Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp | 12 ++-- 3 files changed, 46 insertions(+), 44 deletions(-) diff --git a/Source/Core/Common/Network.cpp b/Source/Core/Common/Network.cpp index 1ee5496fcc..f35308a5ab 100644 --- a/Source/Core/Common/Network.cpp +++ b/Source/Core/Common/Network.cpp @@ -355,34 +355,36 @@ TCPPacket::TCPPacket(const MACAddress& destination, const MACAddress& source, { } -std::vector TCPPacket::Build() +std::vector TCPPacket::Build() const { std::vector result; - result.reserve(Size()); + result.reserve(Size()); // Useful not to invalidate .data() pointers - // recalc size - ip_header.total_len = htons(static_cast(IPv4Header::SIZE + ipv4_options.size() + - TCPHeader::SIZE + tcp_options.size() + data.size())); - - // copy data + // Copy data InsertObj(&result, eth_header); + u8* const ip_ptr = result.data() + result.size(); InsertObj(&result, ip_header); result.insert(result.end(), ipv4_options.begin(), ipv4_options.end()); - const std::size_t tcp_offset = result.size(); - - tcp_header.checksum = 0; - const u16 props = (ntohs(tcp_header.properties) & 0xfff) | - (static_cast((tcp_options.size() + TCPHeader::SIZE) & 0x3c) << 10); - tcp_header.properties = htons(props); - const u8* tcp_ptr = reinterpret_cast(&tcp_header); - result.insert(result.end(), tcp_ptr, tcp_ptr + TCPHeader::SIZE); + u8* const tcp_ptr = result.data() + result.size(); + InsertObj(&result, tcp_header); result.insert(result.end(), tcp_options.begin(), tcp_options.end()); result.insert(result.end(), data.begin(), data.end()); - tcp_header.checksum = ComputeTCPNetworkChecksum( - ip_header.source_addr, ip_header.destination_addr, &result[tcp_offset], - static_cast(result.size() - tcp_offset), IPPROTO_TCP); - std::copy(tcp_ptr, tcp_ptr + TCPHeader::SIZE, result.begin() + tcp_offset); + // Adjust size and checksum fields + const u16 tcp_length = static_cast(TCPHeader::SIZE + tcp_options.size() + data.size()); + const u16 tcp_properties = + (ntohs(tcp_header.properties) & 0xfff) | + (static_cast((tcp_options.size() + TCPHeader::SIZE) & 0x3c) << 10); + Common::BitCastPtr(tcp_ptr + offsetof(TCPHeader, properties)) = htons(tcp_properties); + + const u16 ip_total_len = static_cast(IPv4Header::SIZE + ipv4_options.size() + tcp_length); + Common::BitCastPtr(ip_ptr + offsetof(IPv4Header, total_len)) = htons(ip_total_len); + + auto checksum_bitcast_ptr = Common::BitCastPtr(tcp_ptr + offsetof(TCPHeader, checksum)); + checksum_bitcast_ptr = u16(0); + checksum_bitcast_ptr = ComputeTCPNetworkChecksum( + ip_header.source_addr, ip_header.destination_addr, tcp_ptr, tcp_length, IPPROTO_TCP); + return result; } @@ -401,31 +403,31 @@ UDPPacket::UDPPacket(const MACAddress& destination, const MACAddress& source, { } -std::vector UDPPacket::Build() +std::vector UDPPacket::Build() const { std::vector result; - result.reserve(Size()); + result.reserve(Size()); // Useful not to invalidate .data() pointers - // recalc size - ip_header.total_len = htons( - static_cast(IPv4Header::SIZE + ipv4_options.size() + UDPHeader::SIZE + data.size())); - udp_header.length = htons(static_cast(UDPHeader::SIZE + data.size())); - - // copy data + // Copy data InsertObj(&result, eth_header); + u8* const ip_ptr = result.data() + result.size(); InsertObj(&result, ip_header); result.insert(result.end(), ipv4_options.begin(), ipv4_options.end()); - const std::size_t udp_offset = result.size(); - - udp_header.checksum = 0; - const u8* udp_ptr = reinterpret_cast(&udp_header); - result.insert(result.end(), udp_ptr, udp_ptr + UDPHeader::SIZE); + u8* const udp_ptr = result.data() + result.size(); + InsertObj(&result, udp_header); result.insert(result.end(), data.begin(), data.end()); - udp_header.checksum = ComputeTCPNetworkChecksum( - ip_header.source_addr, ip_header.destination_addr, &result[udp_offset], - static_cast(result.size() - udp_offset), IPPROTO_UDP); - std::copy(udp_ptr, udp_ptr + UDPHeader::SIZE, result.begin() + udp_offset); + // Adjust size and checksum fields + const u16 udp_length = static_cast(UDPHeader::SIZE + data.size()); + Common::BitCastPtr(udp_ptr + offsetof(UDPHeader, length)) = htons(udp_length); + + const u16 ip_total_len = static_cast(IPv4Header::SIZE + ipv4_options.size() + udp_length); + Common::BitCastPtr(ip_ptr + offsetof(IPv4Header, total_len)) = htons(ip_total_len); + + auto checksum_bitcast_ptr = Common::BitCastPtr(udp_ptr + offsetof(UDPHeader, checksum)); + checksum_bitcast_ptr = u16(0); + checksum_bitcast_ptr = ComputeTCPNetworkChecksum( + ip_header.source_addr, ip_header.destination_addr, udp_ptr, udp_length, IPPROTO_UDP); return result; } diff --git a/Source/Core/Common/Network.h b/Source/Core/Common/Network.h index e3b319bc6b..27eaad7c42 100644 --- a/Source/Core/Common/Network.h +++ b/Source/Core/Common/Network.h @@ -202,7 +202,7 @@ struct TCPPacket TCPPacket(); TCPPacket(const MACAddress& destination, const MACAddress& source, const sockaddr_in& from, const sockaddr_in& to, u32 seq, u32 ack, u16 flags); - std::vector Build(); + std::vector Build() const; u16 Size() const; EthernetHeader eth_header; @@ -220,7 +220,7 @@ struct UDPPacket UDPPacket(); UDPPacket(const MACAddress& destination, const MACAddress& source, const sockaddr_in& from, const sockaddr_in& to, const std::vector& payload); - std::vector Build(); + std::vector Build() const; u16 Size() const; EthernetHeader eth_header; diff --git a/Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp b/Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp index 8dfbf59764..78ba89bc78 100644 --- a/Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp +++ b/Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp @@ -142,7 +142,7 @@ void CEXIETHERNET::BuiltInBBAInterface::HandleDHCP(const Common::UDPPacket& pack reply.AddOption(3, ip_part); // router ip reply.AddOption(255, {}); // end - Common::UDPPacket response(bba_mac, m_fake_mac, from, to, reply.Build()); + const Common::UDPPacket response(bba_mac, m_fake_mac, from, to, reply.Build()); WriteToQueue(response.Build()); } @@ -179,8 +179,8 @@ StackRef* CEXIETHERNET::BuiltInBBAInterface::GetTCPSlot(u16 src_port, u16 dst_po std::vector BuildFINFrame(StackRef* ref) { - Common::TCPPacket result(ref->bba_mac, ref->my_mac, ref->from, ref->to, ref->seq_num, - ref->ack_num, TCP_FLAG_FIN | TCP_FLAG_ACK | TCP_FLAG_RST); + const Common::TCPPacket result(ref->bba_mac, ref->my_mac, ref->from, ref->to, ref->seq_num, + ref->ack_num, TCP_FLAG_FIN | TCP_FLAG_ACK | TCP_FLAG_RST); for (auto& tcp_buf : ref->tcp_buffers) tcp_buf.used = false; @@ -189,8 +189,8 @@ std::vector BuildFINFrame(StackRef* ref) std::vector BuildAckFrame(StackRef* ref) { - Common::TCPPacket result(ref->bba_mac, ref->my_mac, ref->from, ref->to, ref->seq_num, - ref->ack_num, TCP_FLAG_ACK); + const Common::TCPPacket result(ref->bba_mac, ref->my_mac, ref->from, ref->to, ref->seq_num, + ref->ack_num, TCP_FLAG_ACK); return result.Build(); } @@ -498,7 +498,7 @@ std::optional> TryGetDataFromSocket(StackRef* ref) ref->from.sin_port = htons(remote_port); ref->from.sin_addr.s_addr = htonl(ref->target.toInteger()); const std::vector udp_data(buffer.begin(), buffer.begin() + datasize); - Common::UDPPacket packet(ref->bba_mac, ref->my_mac, ref->from, ref->to, udp_data); + const Common::UDPPacket packet(ref->bba_mac, ref->my_mac, ref->from, ref->to, udp_data); return packet.Build(); } break; From b950d038b9074fb7cba61989f3214ecbe3163355 Mon Sep 17 00:00:00 2001 From: Sepalani Date: Sun, 10 Jul 2022 20:34:15 +0400 Subject: [PATCH 8/9] Common/Network: Update IP checksum since total_len might have changed --- Source/Core/Common/Network.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Source/Core/Common/Network.cpp b/Source/Core/Common/Network.cpp index f35308a5ab..2d532690c1 100644 --- a/Source/Core/Common/Network.cpp +++ b/Source/Core/Common/Network.cpp @@ -377,9 +377,15 @@ std::vector TCPPacket::Build() const (static_cast((tcp_options.size() + TCPHeader::SIZE) & 0x3c) << 10); Common::BitCastPtr(tcp_ptr + offsetof(TCPHeader, properties)) = htons(tcp_properties); - const u16 ip_total_len = static_cast(IPv4Header::SIZE + ipv4_options.size() + tcp_length); + const u16 ip_header_size = static_cast(IPv4Header::SIZE + ipv4_options.size()); + const u16 ip_total_len = ip_header_size + tcp_length; Common::BitCastPtr(ip_ptr + offsetof(IPv4Header, total_len)) = htons(ip_total_len); + auto ip_checksum_bitcast_ptr = + Common::BitCastPtr(ip_ptr + offsetof(IPv4Header, header_checksum)); + ip_checksum_bitcast_ptr = u16(0); + ip_checksum_bitcast_ptr = htons(Common::ComputeNetworkChecksum(ip_ptr, ip_header_size)); + auto checksum_bitcast_ptr = Common::BitCastPtr(tcp_ptr + offsetof(TCPHeader, checksum)); checksum_bitcast_ptr = u16(0); checksum_bitcast_ptr = ComputeTCPNetworkChecksum( @@ -421,9 +427,15 @@ std::vector UDPPacket::Build() const const u16 udp_length = static_cast(UDPHeader::SIZE + data.size()); Common::BitCastPtr(udp_ptr + offsetof(UDPHeader, length)) = htons(udp_length); - const u16 ip_total_len = static_cast(IPv4Header::SIZE + ipv4_options.size() + udp_length); + const u16 ip_header_size = static_cast(IPv4Header::SIZE + ipv4_options.size()); + const u16 ip_total_len = ip_header_size + udp_length; Common::BitCastPtr(ip_ptr + offsetof(IPv4Header, total_len)) = htons(ip_total_len); + auto ip_checksum_bitcast_ptr = + Common::BitCastPtr(ip_ptr + offsetof(IPv4Header, header_checksum)); + ip_checksum_bitcast_ptr = u16(0); + ip_checksum_bitcast_ptr = htons(Common::ComputeNetworkChecksum(ip_ptr, ip_header_size)); + auto checksum_bitcast_ptr = Common::BitCastPtr(udp_ptr + offsetof(UDPHeader, checksum)); checksum_bitcast_ptr = u16(0); checksum_bitcast_ptr = ComputeTCPNetworkChecksum( From be2ede61094deb79bbb655ffe2b527aea09733a3 Mon Sep 17 00:00:00 2001 From: Sepalani Date: Sun, 10 Jul 2022 20:57:35 +0400 Subject: [PATCH 9/9] BBA/BuiltIn: Move functions to anonymous namespace --- Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp | 219 ++++++++++++------------ 1 file changed, 111 insertions(+), 108 deletions(-) diff --git a/Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp b/Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp index 78ba89bc78..e3e4220196 100644 --- a/Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp +++ b/Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp @@ -12,12 +12,123 @@ namespace ExpansionInterface { +namespace +{ u64 GetTickCountStd() { using namespace std::chrono; return duration_cast(steady_clock::now().time_since_epoch()).count(); } +std::vector BuildFINFrame(StackRef* ref) +{ + const Common::TCPPacket result(ref->bba_mac, ref->my_mac, ref->from, ref->to, ref->seq_num, + ref->ack_num, TCP_FLAG_FIN | TCP_FLAG_ACK | TCP_FLAG_RST); + + for (auto& tcp_buf : ref->tcp_buffers) + tcp_buf.used = false; + return result.Build(); +} + +std::vector BuildAckFrame(StackRef* ref) +{ + const Common::TCPPacket result(ref->bba_mac, ref->my_mac, ref->from, ref->to, ref->seq_num, + ref->ack_num, TCP_FLAG_ACK); + return result.Build(); +} + +// Change the IP identification and recompute the checksum +void SetIPIdentification(u8* ptr, std::size_t size, u16 value) +{ + if (size < Common::EthernetHeader::SIZE + Common::IPv4Header::SIZE) + return; + + u8* const ip_ptr = ptr + Common::EthernetHeader::SIZE; + const u8 ip_header_size = (*ip_ptr & 0xf) * 4; + if (size < Common::EthernetHeader::SIZE + ip_header_size) + return; + + u8* const ip_id_ptr = ip_ptr + offsetof(Common::IPv4Header, identification); + Common::BitCastPtr(ip_id_ptr) = htons(value); + + u8* const ip_checksum_ptr = ip_ptr + offsetof(Common::IPv4Header, header_checksum); + auto checksum_bitcast_ptr = Common::BitCastPtr(ip_checksum_ptr); + checksum_bitcast_ptr = u16(0); + checksum_bitcast_ptr = htons(Common::ComputeNetworkChecksum(ip_ptr, ip_header_size)); +} + +std::optional> TryGetDataFromSocket(StackRef* ref) +{ + size_t datasize = 0; // Set by socket.receive using a non-const reference + unsigned short remote_port; + + switch (ref->type) + { + case IPPROTO_UDP: + { + std::array buffer; + ref->udp_socket.receive(buffer.data(), MAX_UDP_LENGTH, datasize, ref->target, remote_port); + if (datasize > 0) + { + ref->from.sin_port = htons(remote_port); + ref->from.sin_addr.s_addr = htonl(ref->target.toInteger()); + const std::vector udp_data(buffer.begin(), buffer.begin() + datasize); + const Common::UDPPacket packet(ref->bba_mac, ref->my_mac, ref->from, ref->to, udp_data); + return packet.Build(); + } + break; + } + + case IPPROTO_TCP: + sf::Socket::Status st = sf::Socket::Status::Done; + TcpBuffer* tcp_buffer = nullptr; + for (auto& tcp_buf : ref->tcp_buffers) + { + if (tcp_buf.used) + continue; + tcp_buffer = &tcp_buf; + break; + } + + // set default size to 0 to avoid issue + datasize = 0; + const bool can_go = (GetTickCountStd() - ref->poke_time > 100 || ref->window_size > 2000); + std::array buffer; + if (tcp_buffer != nullptr && ref->ready && can_go) + st = ref->tcp_socket.receive(buffer.data(), MAX_TCP_LENGTH, datasize); + + if (datasize > 0) + { + Common::TCPPacket packet(ref->bba_mac, ref->my_mac, ref->from, ref->to, ref->seq_num, + ref->ack_num, TCP_FLAG_ACK); + packet.data = std::vector(buffer.begin(), buffer.begin() + datasize); + + // build buffer + tcp_buffer->seq_id = ref->seq_num; + tcp_buffer->tick = GetTickCountStd(); + tcp_buffer->data = packet.Build(); + tcp_buffer->seq_id = ref->seq_num; + tcp_buffer->used = true; + ref->seq_num += static_cast(datasize); + ref->poke_time = GetTickCountStd(); + return tcp_buffer->data; + } + if (GetTickCountStd() - ref->delay > 3000) + { + if (st == sf::Socket::Disconnected || st == sf::Socket::Error) + { + ref->ip = 0; + ref->tcp_socket.disconnect(); + return BuildFINFrame(ref); + } + } + break; + } + + return std::nullopt; +} +} // namespace + bool CEXIETHERNET::BuiltInBBAInterface::Activate() { if (IsActivated()) @@ -177,23 +288,6 @@ StackRef* CEXIETHERNET::BuiltInBBAInterface::GetTCPSlot(u16 src_port, u16 dst_po return nullptr; } -std::vector BuildFINFrame(StackRef* ref) -{ - const Common::TCPPacket result(ref->bba_mac, ref->my_mac, ref->from, ref->to, ref->seq_num, - ref->ack_num, TCP_FLAG_FIN | TCP_FLAG_ACK | TCP_FLAG_RST); - - for (auto& tcp_buf : ref->tcp_buffers) - tcp_buf.used = false; - return result.Build(); -} - -std::vector BuildAckFrame(StackRef* ref) -{ - const Common::TCPPacket result(ref->bba_mac, ref->my_mac, ref->from, ref->to, ref->seq_num, - ref->ack_num, TCP_FLAG_ACK); - return result.Build(); -} - void CEXIETHERNET::BuiltInBBAInterface::HandleTCPFrame(const Common::TCPPacket& packet) { const auto& [hwdata, ip_header, tcp_header, ip_options, tcp_options, data] = packet; @@ -482,97 +576,6 @@ bool CEXIETHERNET::BuiltInBBAInterface::SendFrame(const u8* frame, u32 size) return true; } -std::optional> TryGetDataFromSocket(StackRef* ref) -{ - size_t datasize = 0; // Set by socket.receive using a non-const reference - unsigned short remote_port; - - switch (ref->type) - { - case IPPROTO_UDP: - { - std::array buffer; - ref->udp_socket.receive(buffer.data(), MAX_UDP_LENGTH, datasize, ref->target, remote_port); - if (datasize > 0) - { - ref->from.sin_port = htons(remote_port); - ref->from.sin_addr.s_addr = htonl(ref->target.toInteger()); - const std::vector udp_data(buffer.begin(), buffer.begin() + datasize); - const Common::UDPPacket packet(ref->bba_mac, ref->my_mac, ref->from, ref->to, udp_data); - return packet.Build(); - } - break; - } - - case IPPROTO_TCP: - sf::Socket::Status st = sf::Socket::Status::Done; - TcpBuffer* tcp_buffer = nullptr; - for (auto& tcp_buf : ref->tcp_buffers) - { - if (tcp_buf.used) - continue; - tcp_buffer = &tcp_buf; - break; - } - - // set default size to 0 to avoid issue - datasize = 0; - const bool can_go = (GetTickCountStd() - ref->poke_time > 100 || ref->window_size > 2000); - std::array buffer; - if (tcp_buffer != nullptr && ref->ready && can_go) - st = ref->tcp_socket.receive(buffer.data(), MAX_TCP_LENGTH, datasize); - - if (datasize > 0) - { - Common::TCPPacket packet(ref->bba_mac, ref->my_mac, ref->from, ref->to, ref->seq_num, - ref->ack_num, TCP_FLAG_ACK); - packet.data = std::vector(buffer.begin(), buffer.begin() + datasize); - - // build buffer - tcp_buffer->seq_id = ref->seq_num; - tcp_buffer->tick = GetTickCountStd(); - tcp_buffer->data = packet.Build(); - tcp_buffer->seq_id = ref->seq_num; - tcp_buffer->used = true; - ref->seq_num += static_cast(datasize); - ref->poke_time = GetTickCountStd(); - return tcp_buffer->data; - } - if (GetTickCountStd() - ref->delay > 3000) - { - if (st == sf::Socket::Disconnected || st == sf::Socket::Error) - { - ref->ip = 0; - ref->tcp_socket.disconnect(); - return BuildFINFrame(ref); - } - } - break; - } - - return std::nullopt; -} - -// Change the IP identification and recompute the checksum -static void SetIPIdentification(u8* ptr, std::size_t size, u16 value) -{ - if (size < Common::EthernetHeader::SIZE + Common::IPv4Header::SIZE) - return; - - u8* const ip_ptr = ptr + Common::EthernetHeader::SIZE; - const u8 ip_header_size = (*ip_ptr & 0xf) * 4; - if (size < Common::EthernetHeader::SIZE + ip_header_size) - return; - - u8* const ip_id_ptr = ip_ptr + offsetof(Common::IPv4Header, identification); - Common::BitCastPtr(ip_id_ptr) = htons(value); - - u8* const ip_checksum_ptr = ip_ptr + offsetof(Common::IPv4Header, header_checksum); - auto checksum_bitcast_ptr = Common::BitCastPtr(ip_checksum_ptr); - checksum_bitcast_ptr = u16(0); - checksum_bitcast_ptr = htons(Common::ComputeNetworkChecksum(ip_ptr, ip_header_size)); -} - void CEXIETHERNET::BuiltInBBAInterface::ReadThreadHandler(CEXIETHERNET::BuiltInBBAInterface* self) { while (!self->m_read_thread_shutdown.IsSet())