#pragma once #include #include #include #include "util/types.hpp" #include "Utilities/mutex.h" #ifdef _WIN32 #include #include #else #ifdef __clang__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wold-style-cast" #endif #include #include #include #ifdef __clang__ #pragma GCC diagnostic pop #endif #endif #ifdef _WIN32 using socket_type = uptr; #else using socket_type = int; #endif template <> struct std::hash> { std::size_t operator()(const std::array& array) const noexcept { std::size_t hash = 0; std::hash hasher; for (auto byte : array) { hash ^= hasher(byte) + 0x9e3779b9 + (hash << 6) + (hash >> 2); } return hash; } }; namespace np { class ip_address_translator { public: static bool is_ipv6(u32 addr_be); u32 register_ipv6(const std::array& ipv6_addr); sockaddr_in6 get_ipv6_sockaddr(u32 addr_be, u16 port_be); private: static constexpr u32 translation_range_begin = 0x00'00'00'01; static constexpr u32 translation_range_end = 0x00'00'FF'FF; shared_mutex mutex; u32 cur_addr = translation_range_begin; std::unordered_map, u32> ipv6_to_ipv4; std::vector> ipv4_to_ipv6; }; u32 register_ip(const flatbuffers::Vector* vec); enum class IPV6_SUPPORT : u8 { IPV6_UNKNOWN, IPV6_UNSUPPORTED, IPV6_SUPPORTED, }; bool is_ipv6_supported(std::optional force_state = std::nullopt); s32 sendto_possibly_ipv6(socket_type native_socket, const char* data, u32 size, const sockaddr_in* addr, int native_flags); sockaddr_in6 sockaddr_to_sockaddr6(const sockaddr_in& addr); sockaddr_in sockaddr6_to_sockaddr(const sockaddr_in6& addr); void close_socket(socket_type socket); void set_socket_non_blocking(socket_type socket); } // namespace np