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);
|
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) {
|
inline std::string str_for_endpoint(const asio::ip::tcp::endpoint& ep) {
|
||||||
return ep.address().to_string() + std::format(":{}", ep.port());
|
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>;
|
using S_Reconnect_19 = S_ReconnectT<le_uint16_t>;
|
||||||
check_struct_size(S_Reconnect_19, 8);
|
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
|
// 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
|
// 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
|
// 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())) {
|
if (is_patch(c->version())) {
|
||||||
auto& cmd = msg.check_size_t<S_Reconnect_Patch_14>();
|
auto& cmd = msg.check_size_t<S_Reconnect_Patch_14>();
|
||||||
new_ep = make_endpoint_ipv4(cmd.address, cmd.port);
|
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 {
|
} else {
|
||||||
// This weird maximum size is here to properly handle the version-split
|
// This weird maximum size is here to properly handle the version-split
|
||||||
// command that some servers (including newserv) use on port 9100
|
// command that some servers (including newserv) use on port 9100
|
||||||
|
|||||||
Reference in New Issue
Block a user