mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-31 00:32:53 +00:00
Merge pull request #10831 from sepalani/BBA-cleanup
Common/Network+BBA/Builtin: Cleanup
This commit is contained in:
commit
20059776d9
@ -85,9 +85,13 @@ std::optional<MACAddress> StringToMacAddress(std::string_view mac_string)
|
|||||||
|
|
||||||
EthernetHeader::EthernetHeader() = default;
|
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
|
u16 EthernetHeader::Size() const
|
||||||
@ -310,6 +314,14 @@ u16 ComputeTCPNetworkChecksum(const IPAddress& from, const IPAddress& to, const
|
|||||||
return htons(static_cast<u16>(tcp_checksum));
|
return htons(static_cast<u16>(tcp_checksum));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Container, typename T>
|
||||||
|
static inline void InsertObj(Container* container, const T& obj)
|
||||||
|
{
|
||||||
|
static_assert(std::is_trivially_copyable_v<T>);
|
||||||
|
const u8* const ptr = reinterpret_cast<const u8*>(&obj);
|
||||||
|
container->insert(container->end(), ptr, ptr + sizeof(obj));
|
||||||
|
}
|
||||||
|
|
||||||
ARPPacket::ARPPacket() = default;
|
ARPPacket::ARPPacket() = default;
|
||||||
|
|
||||||
u16 ARPPacket::Size() const
|
u16 ARPPacket::Size() const
|
||||||
@ -328,74 +340,57 @@ std::vector<u8> ARPPacket::Build() const
|
|||||||
{
|
{
|
||||||
std::vector<u8> result;
|
std::vector<u8> result;
|
||||||
result.reserve(EthernetHeader::SIZE + ARPHeader::SIZE);
|
result.reserve(EthernetHeader::SIZE + ARPHeader::SIZE);
|
||||||
const u8* eth_ptr = reinterpret_cast<const u8*>(ð_header);
|
InsertObj(&result, eth_header);
|
||||||
result.insert(result.end(), eth_ptr, eth_ptr + EthernetHeader::SIZE);
|
InsertObj(&result, arp_header);
|
||||||
const u8* arp_ptr = reinterpret_cast<const u8*>(&arp_header);
|
|
||||||
result.insert(result.end(), arp_ptr, arp_ptr + ARPHeader::SIZE);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
TCPPacket::TCPPacket() = default;
|
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,
|
TCPPacket::TCPPacket(const MACAddress& destination, const MACAddress& source,
|
||||||
const sockaddr_in& from, const sockaddr_in& to, u32 seq, u32 ack, u16 flags)
|
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<u8> TCPPacket::Build()
|
std::vector<u8> TCPPacket::Build() const
|
||||||
{
|
{
|
||||||
std::vector<u8> result;
|
std::vector<u8> result;
|
||||||
result.reserve(Size());
|
result.reserve(Size()); // Useful not to invalidate .data() pointers
|
||||||
|
|
||||||
// recalc size
|
// Copy data
|
||||||
ip_header.total_len = htons(static_cast<u16>(IPv4Header::SIZE + ipv4_options.size() +
|
InsertObj(&result, eth_header);
|
||||||
TCPHeader::SIZE + tcp_options.size() + data.size()));
|
u8* const ip_ptr = result.data() + result.size();
|
||||||
|
InsertObj(&result, ip_header);
|
||||||
|
result.insert(result.end(), ipv4_options.begin(), ipv4_options.end());
|
||||||
|
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());
|
||||||
|
|
||||||
|
// Adjust size and checksum fields
|
||||||
|
const u16 tcp_length = static_cast<u16>(TCPHeader::SIZE + tcp_options.size() + data.size());
|
||||||
|
const u16 tcp_properties =
|
||||||
|
(ntohs(tcp_header.properties) & 0xfff) |
|
||||||
|
(static_cast<u16>((tcp_options.size() + TCPHeader::SIZE) & 0x3c) << 10);
|
||||||
|
Common::BitCastPtr<u16>(tcp_ptr + offsetof(TCPHeader, properties)) = htons(tcp_properties);
|
||||||
|
|
||||||
|
const u16 ip_header_size = static_cast<u16>(IPv4Header::SIZE + ipv4_options.size());
|
||||||
|
const u16 ip_total_len = ip_header_size + tcp_length;
|
||||||
|
Common::BitCastPtr<u16>(ip_ptr + offsetof(IPv4Header, total_len)) = htons(ip_total_len);
|
||||||
|
|
||||||
|
auto ip_checksum_bitcast_ptr =
|
||||||
|
Common::BitCastPtr<u16>(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<u16>(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);
|
||||||
|
|
||||||
// copy data
|
|
||||||
const u8* eth_ptr = reinterpret_cast<const u8*>(ð_header);
|
|
||||||
result.insert(result.end(), eth_ptr, eth_ptr + EthernetHeader::SIZE);
|
|
||||||
const u8* ip_ptr = reinterpret_cast<const u8*>(&ip_header);
|
|
||||||
result.insert(result.end(), ip_ptr, ip_ptr + IPv4Header::SIZE);
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
tcp_header.checksum = 0;
|
|
||||||
const u16 props = (ntohs(tcp_header.properties) & 0xfff) |
|
|
||||||
(static_cast<u16>((tcp_options.size() + TCPHeader::SIZE) & 0x3c) << 10);
|
|
||||||
tcp_header.properties = htons(props);
|
|
||||||
const u8* tcp_ptr = reinterpret_cast<const u8*>(&tcp_header);
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
tcp_header.checksum = ComputeTCPNetworkChecksum(
|
|
||||||
ip_header.source_addr, ip_header.destination_addr, &result[tcp_offset],
|
|
||||||
static_cast<u16>(result.size() - tcp_offset), IPPROTO_TCP);
|
|
||||||
std::copy(tcp_ptr, tcp_ptr + TCPHeader::SIZE, result.begin() + tcp_offset);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,60 +401,45 @@ u16 TCPPacket::Size() const
|
|||||||
|
|
||||||
UDPPacket::UDPPacket() = default;
|
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,
|
UDPPacket::UDPPacket(const MACAddress& destination, const MACAddress& source,
|
||||||
const sockaddr_in& from, const sockaddr_in& to, const std::vector<u8>& payload)
|
const sockaddr_in& from, const sockaddr_in& to, const std::vector<u8>& payload)
|
||||||
|
: eth_header(destination, source, IPV4_ETHERTYPE),
|
||||||
|
ip_header(static_cast<u16>(payload.size() + Common::UDPHeader::SIZE), IPPROTO_UDP, from, to),
|
||||||
|
udp_header(from, to, static_cast<u16>(payload.size())), data(payload)
|
||||||
{
|
{
|
||||||
eth_header.destination = destination;
|
|
||||||
eth_header.source = source;
|
|
||||||
eth_header.ethertype = htons(IPV4_ETHERTYPE);
|
|
||||||
|
|
||||||
ip_header = Common::IPv4Header(static_cast<u16>(payload.size() + Common::UDPHeader::SIZE),
|
|
||||||
IPPROTO_UDP, from, to);
|
|
||||||
udp_header = Common::UDPHeader(from, to, static_cast<u16>(payload.size()));
|
|
||||||
data = payload;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> UDPPacket::Build()
|
std::vector<u8> UDPPacket::Build() const
|
||||||
{
|
{
|
||||||
std::vector<u8> result;
|
std::vector<u8> result;
|
||||||
result.reserve(Size());
|
result.reserve(Size()); // Useful not to invalidate .data() pointers
|
||||||
|
|
||||||
// recalc size
|
// Copy data
|
||||||
ip_header.total_len = htons(
|
InsertObj(&result, eth_header);
|
||||||
static_cast<u16>(IPv4Header::SIZE + ipv4_options.size() + UDPHeader::SIZE + data.size()));
|
u8* const ip_ptr = result.data() + result.size();
|
||||||
udp_header.length = htons(static_cast<u16>(UDPHeader::SIZE + data.size()));
|
InsertObj(&result, ip_header);
|
||||||
|
result.insert(result.end(), ipv4_options.begin(), ipv4_options.end());
|
||||||
|
u8* const udp_ptr = result.data() + result.size();
|
||||||
|
InsertObj(&result, udp_header);
|
||||||
|
result.insert(result.end(), data.begin(), data.end());
|
||||||
|
|
||||||
// copy data
|
// Adjust size and checksum fields
|
||||||
const u8* eth_ptr = reinterpret_cast<const u8*>(ð_header);
|
const u16 udp_length = static_cast<u16>(UDPHeader::SIZE + data.size());
|
||||||
result.insert(result.end(), eth_ptr, eth_ptr + EthernetHeader::SIZE);
|
Common::BitCastPtr<u16>(udp_ptr + offsetof(UDPHeader, length)) = htons(udp_length);
|
||||||
const u8* ip_ptr = reinterpret_cast<const u8*>(&ip_header);
|
|
||||||
result.insert(result.end(), ip_ptr, ip_ptr + IPv4Header::SIZE);
|
const u16 ip_header_size = static_cast<u16>(IPv4Header::SIZE + ipv4_options.size());
|
||||||
std::size_t offset = EthernetHeader::SIZE + IPv4Header::SIZE;
|
const u16 ip_total_len = ip_header_size + udp_length;
|
||||||
if (ipv4_options.size() > 0)
|
Common::BitCastPtr<u16>(ip_ptr + offsetof(IPv4Header, total_len)) = htons(ip_total_len);
|
||||||
{
|
|
||||||
result.insert(result.end(), ipv4_options.begin(), ipv4_options.end());
|
auto ip_checksum_bitcast_ptr =
|
||||||
offset += ipv4_options.size();
|
Common::BitCastPtr<u16>(ip_ptr + offsetof(IPv4Header, header_checksum));
|
||||||
}
|
ip_checksum_bitcast_ptr = u16(0);
|
||||||
udp_header.checksum = 0;
|
ip_checksum_bitcast_ptr = htons(Common::ComputeNetworkChecksum(ip_ptr, ip_header_size));
|
||||||
const u8* udp_ptr = reinterpret_cast<const u8*>(&udp_header);
|
|
||||||
result.insert(result.end(), udp_ptr, udp_ptr + UDPHeader::SIZE);
|
auto checksum_bitcast_ptr = Common::BitCastPtr<u16>(udp_ptr + offsetof(UDPHeader, checksum));
|
||||||
const std::size_t udp_offset = offset;
|
checksum_bitcast_ptr = u16(0);
|
||||||
offset += UDPHeader::SIZE;
|
checksum_bitcast_ptr = ComputeTCPNetworkChecksum(
|
||||||
if (data.size() > 0)
|
ip_header.source_addr, ip_header.destination_addr, udp_ptr, udp_length, IPPROTO_UDP);
|
||||||
{
|
|
||||||
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<u16>(result.size() - udp_offset), IPPROTO_UDP);
|
|
||||||
std::copy(udp_ptr, udp_ptr + UDPHeader::SIZE, result.begin() + udp_offset);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
@ -47,6 +48,7 @@ struct EthernetHeader
|
|||||||
{
|
{
|
||||||
EthernetHeader();
|
EthernetHeader();
|
||||||
explicit EthernetHeader(u16 ether_type);
|
explicit EthernetHeader(u16 ether_type);
|
||||||
|
EthernetHeader(const MACAddress& dest, const MACAddress& src, u16 ether_type);
|
||||||
u16 Size() const;
|
u16 Size() const;
|
||||||
|
|
||||||
static constexpr std::size_t SIZE = 14;
|
static constexpr std::size_t SIZE = 14;
|
||||||
@ -56,6 +58,7 @@ struct EthernetHeader
|
|||||||
u16 ethertype = 0;
|
u16 ethertype = 0;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(EthernetHeader) == EthernetHeader::SIZE);
|
static_assert(sizeof(EthernetHeader) == EthernetHeader::SIZE);
|
||||||
|
static_assert(std::is_standard_layout_v<EthernetHeader>);
|
||||||
|
|
||||||
struct IPv4Header
|
struct IPv4Header
|
||||||
{
|
{
|
||||||
@ -78,6 +81,7 @@ struct IPv4Header
|
|||||||
IPAddress destination_addr{};
|
IPAddress destination_addr{};
|
||||||
};
|
};
|
||||||
static_assert(sizeof(IPv4Header) == IPv4Header::SIZE);
|
static_assert(sizeof(IPv4Header) == IPv4Header::SIZE);
|
||||||
|
static_assert(std::is_standard_layout_v<IPv4Header>);
|
||||||
|
|
||||||
struct TCPHeader
|
struct TCPHeader
|
||||||
{
|
{
|
||||||
@ -100,6 +104,7 @@ struct TCPHeader
|
|||||||
u16 urgent_pointer = 0;
|
u16 urgent_pointer = 0;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(TCPHeader) == TCPHeader::SIZE);
|
static_assert(sizeof(TCPHeader) == TCPHeader::SIZE);
|
||||||
|
static_assert(std::is_standard_layout_v<TCPHeader>);
|
||||||
|
|
||||||
struct UDPHeader
|
struct UDPHeader
|
||||||
{
|
{
|
||||||
@ -116,6 +121,7 @@ struct UDPHeader
|
|||||||
u16 checksum = 0;
|
u16 checksum = 0;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(UDPHeader) == UDPHeader::SIZE);
|
static_assert(sizeof(UDPHeader) == UDPHeader::SIZE);
|
||||||
|
static_assert(std::is_standard_layout_v<UDPHeader>);
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct ARPHeader
|
struct ARPHeader
|
||||||
@ -194,10 +200,9 @@ static_assert(sizeof(ARPPacket) == ARPPacket::SIZE);
|
|||||||
struct TCPPacket
|
struct TCPPacket
|
||||||
{
|
{
|
||||||
TCPPacket();
|
TCPPacket();
|
||||||
TCPPacket(const MACAddress& destination, const MACAddress& source);
|
|
||||||
TCPPacket(const MACAddress& destination, const MACAddress& source, const sockaddr_in& from,
|
TCPPacket(const MACAddress& destination, const MACAddress& source, const sockaddr_in& from,
|
||||||
const sockaddr_in& to, u32 seq, u32 ack, u16 flags);
|
const sockaddr_in& to, u32 seq, u32 ack, u16 flags);
|
||||||
std::vector<u8> Build();
|
std::vector<u8> Build() const;
|
||||||
u16 Size() const;
|
u16 Size() const;
|
||||||
|
|
||||||
EthernetHeader eth_header;
|
EthernetHeader eth_header;
|
||||||
@ -213,10 +218,9 @@ struct TCPPacket
|
|||||||
struct UDPPacket
|
struct UDPPacket
|
||||||
{
|
{
|
||||||
UDPPacket();
|
UDPPacket();
|
||||||
UDPPacket(const MACAddress& destination, const MACAddress& source);
|
|
||||||
UDPPacket(const MACAddress& destination, const MACAddress& source, const sockaddr_in& from,
|
UDPPacket(const MACAddress& destination, const MACAddress& source, const sockaddr_in& from,
|
||||||
const sockaddr_in& to, const std::vector<u8>& payload);
|
const sockaddr_in& to, const std::vector<u8>& payload);
|
||||||
std::vector<u8> Build();
|
std::vector<u8> Build() const;
|
||||||
u16 Size() const;
|
u16 Size() const;
|
||||||
|
|
||||||
EthernetHeader eth_header;
|
EthernetHeader eth_header;
|
||||||
|
@ -12,12 +12,123 @@
|
|||||||
|
|
||||||
namespace ExpansionInterface
|
namespace ExpansionInterface
|
||||||
{
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
u64 GetTickCountStd()
|
u64 GetTickCountStd()
|
||||||
{
|
{
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
return duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
|
return duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<u8> 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<u8> 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<u16>(ip_id_ptr) = htons(value);
|
||||||
|
|
||||||
|
u8* const ip_checksum_ptr = ip_ptr + offsetof(Common::IPv4Header, header_checksum);
|
||||||
|
auto checksum_bitcast_ptr = Common::BitCastPtr<u16>(ip_checksum_ptr);
|
||||||
|
checksum_bitcast_ptr = u16(0);
|
||||||
|
checksum_bitcast_ptr = htons(Common::ComputeNetworkChecksum(ip_ptr, ip_header_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::vector<u8>> 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<u8, MAX_UDP_LENGTH> 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<u8> 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<u8, MAX_TCP_LENGTH> 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<u8>(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<u32>(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()
|
bool CEXIETHERNET::BuiltInBBAInterface::Activate()
|
||||||
{
|
{
|
||||||
if (IsActivated())
|
if (IsActivated())
|
||||||
@ -142,7 +253,7 @@ void CEXIETHERNET::BuiltInBBAInterface::HandleDHCP(const Common::UDPPacket& pack
|
|||||||
reply.AddOption(3, ip_part); // router ip
|
reply.AddOption(3, ip_part); // router ip
|
||||||
reply.AddOption(255, {}); // end
|
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());
|
WriteToQueue(response.Build());
|
||||||
}
|
}
|
||||||
@ -177,23 +288,6 @@ StackRef* CEXIETHERNET::BuiltInBBAInterface::GetTCPSlot(u16 src_port, u16 dst_po
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> 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);
|
|
||||||
|
|
||||||
for (auto& tcp_buf : ref->tcp_buffers)
|
|
||||||
tcp_buf.used = false;
|
|
||||||
return result.Build();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<u8> 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);
|
|
||||||
return result.Build();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CEXIETHERNET::BuiltInBBAInterface::HandleTCPFrame(const Common::TCPPacket& packet)
|
void CEXIETHERNET::BuiltInBBAInterface::HandleTCPFrame(const Common::TCPPacket& packet)
|
||||||
{
|
{
|
||||||
const auto& [hwdata, ip_header, tcp_header, ip_options, tcp_options, data] = 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::vector<u8>> 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<u8, MAX_UDP_LENGTH> 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<u8> udp_data(buffer.begin(), buffer.begin() + datasize);
|
|
||||||
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<u8, MAX_TCP_LENGTH> 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<u8>(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<u32>(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<u16>(ip_id_ptr) = htons(value);
|
|
||||||
|
|
||||||
u8* const ip_checksum_ptr = ip_ptr + offsetof(Common::IPv4Header, header_checksum);
|
|
||||||
auto checksum_bitcast_ptr = Common::BitCastPtr<u16>(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)
|
void CEXIETHERNET::BuiltInBBAInterface::ReadThreadHandler(CEXIETHERNET::BuiltInBBAInterface* self)
|
||||||
{
|
{
|
||||||
while (!self->m_read_thread_shutdown.IsSet())
|
while (!self->m_read_thread_shutdown.IsSet())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user