add IPv6 support in proxy
This commit is contained in:
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user