add IPv6 support in proxy

This commit is contained in:
Martin Michelsen
2025-06-17 01:19:21 -07:00
parent 923cc4ebb0
commit 28ab1bea9c
3 changed files with 25 additions and 0 deletions
+8
View File
@@ -224,6 +224,14 @@ inline asio::ip::tcp::endpoint make_endpoint_ipv4(uint32_t addr, uint16_t port)
return asio::ip::tcp::endpoint(asio::ip::address_v4(addr), port);
}
inline asio::ip::tcp::endpoint make_endpoint_ipv6(const void* addr, uint16_t port) {
std::array<uint8_t, 0x10> bytes;
for (size_t z = 0; z < 0x10; z++) {
bytes[z] = reinterpret_cast<const uint8_t*>(addr)[z];
}
return asio::ip::tcp::endpoint(asio::ip::address_v6(bytes), port);
}
inline std::string str_for_endpoint(const asio::ip::tcp::endpoint& ep) {
return ep.address().to_string() + std::format(":{}", ep.port());
}
+14
View File
@@ -807,6 +807,20 @@ struct C_WriteFileConfirmation_V3_BB_13_A7 {
using S_Reconnect_19 = S_ReconnectT<le_uint16_t>;
check_struct_size(S_Reconnect_19, 8);
// Sylverant implements an IPv6 version of this command, but it's not obvious
// why. IPv6 technically did exist as a draft standard at the time of PSO's
// development, but it wasn't widely used until over a decade later. IPv6
// support is not implemented in any version of the PSO client that I've seen,
// but we implement Sylverant's version of this command anyway because newserv
// may connect to Sylverant via IPv6 when using the proxy. Sylverant sends the
// value 6 in header.flag in this case, presumably to indicate the protocol.
struct S_ReconnectIPv6_Extension_19 {
parray<uint8_t, 0x10> address;
le_uint16_t port = 0;
le_uint16_t unused = 0;
} __packed_ws__(S_ReconnectIPv6_Extension_19, 0x14);
// Because PSO PC and some versions of PSO DC/GC use the same port but different
// protocols, we use a specially-crafted 19 command to send them to two
// different ports depending on the client version. I first saw this technique
+3
View File
@@ -779,6 +779,9 @@ static asio::awaitable<HandlerResult> S_19_U_14(shared_ptr<Client> c, Channel::M
if (is_patch(c->version())) {
auto& cmd = msg.check_size_t<S_Reconnect_Patch_14>();
new_ep = make_endpoint_ipv4(cmd.address, cmd.port);
} else if (msg.flag == 6 && msg.data.size() >= sizeof(S_ReconnectIPv6_Extension_19)) {
auto& cmd = msg.check_size_t<S_ReconnectIPv6_Extension_19>(0xFFFF);
new_ep = make_endpoint_ipv6(cmd.address.data(), cmd.port);
} else {
// This weird maximum size is here to properly handle the version-split
// command that some servers (including newserv) use on port 9100