diff --git a/lib/enet/protocol.c b/lib/enet/protocol.c index 3b56df31c..101d923e0 100644 --- a/lib/enet/protocol.c +++ b/lib/enet/protocol.c @@ -9,10 +9,6 @@ #include "enet/time.h" #include "enet/enet.h" -#ifdef ENABLE_IPV6 -extern void removeMappedAddress(const ENetAddress* ea); -#endif - static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] = { 0, @@ -88,10 +84,6 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event) event -> peer = peer; event -> data = peer -> eventData; -#ifdef ENABLE_IPV6 - removeMappedAddress(&peer->address); -#endif - enet_peer_reset (peer); return 1; @@ -156,10 +148,6 @@ enet_protocol_notify_disconnect (ENetHost * host, ENetPeer * peer, ENetEvent * e event -> peer = peer; event -> data = 0; -#ifdef ENABLE_IPV6 - removeMappedAddress(&peer->address); -#endif - enet_peer_reset (peer); } else diff --git a/src/network/stk_host.cpp b/src/network/stk_host.cpp index 667cdb8e3..f909cb3e3 100644 --- a/src/network/stk_host.cpp +++ b/src/network/stk_host.cpp @@ -881,6 +881,7 @@ void STKHost::mainLoop() uint64_t last_ping_time = StkTime::getMonoTimeMs(); uint64_t last_update_speed_time = StkTime::getMonoTimeMs(); uint64_t last_ping_time_update_for_client = StkTime::getMonoTimeMs(); + uint64_t last_disconnect_time_update = StkTime::getMonoTimeMs(); std::map ctp; while (m_exit_timeout.load() > StkTime::getMonoTimeMs()) { @@ -920,6 +921,15 @@ void STKHost::mainLoop() if (is_server) { + if (isIPV6() && + last_disconnect_time_update < StkTime::getMonoTimeMs()) + { + // Check per 20 second, don't need to check client because it + // only has 1 peer + last_disconnect_time_update = StkTime::getMonoTimeMs() + 20000; + removeDisconnectedMappedAddress(); + } + std::unique_lock peer_lock(m_peers_mutex); const float timeout = ServerConfig::m_validation_timeout; bool need_ping = false; diff --git a/src/network/unix_ipv6.cpp b/src/network/unix_ipv6.cpp index 2f2ac910a..c777de56e 100644 --- a/src/network/unix_ipv6.cpp +++ b/src/network/unix_ipv6.cpp @@ -152,22 +152,39 @@ std::string getIPV6ReadableFromMappedAddress(const ENetAddress* ea) return ""; } // getIPV6ReadableFromMappedAddress +// ---------------------------------------------------------------------------- +void removeDisconnectedMappedAddress() +{ +} // removeDisconnectedMappedAddress + #else #include "network/unix_ipv6.hpp" #include "network/transport_address.hpp" #include "utils/string_utils.hpp" #include "utils/log.hpp" +#include "utils/time.hpp" #include "utils/types.hpp" #include -#include #include // ============================================================================ uint32_t g_mapped_ipv6_used; int g_ipv6; -std::vector > g_mapped_ips; +struct MappedAddress +{ + ENetAddress m_addr; + struct sockaddr_in6 m_in6; + uint64_t m_last_activity; + MappedAddress(const ENetAddress& addr, const struct sockaddr_in6& in6) + { + m_addr = addr; + m_in6 = in6; + m_last_activity = StkTime::getMonoTimeMs(); + } +}; +std::vector g_mapped_ips; // ============================================================================ int isIPV6() { @@ -189,39 +206,18 @@ void unixInitialize() g_mapped_ips.clear(); } // unixInitialize -// ---------------------------------------------------------------------------- -/* Called when a peer is disconnected and we remove its reference to the ipv6. - */ -void removeMappedAddress(const ENetAddress* ea) -{ - auto it = std::find_if(g_mapped_ips.begin(), g_mapped_ips.end(), - [ea](const std::pair& addr) - { - return ea->host == addr.first.host && ea->port == addr.first.port; - }); - if (it != g_mapped_ips.end()) - { - TransportAddress addr(it->first); - Log::debug("IPV6", "Removing %s, ipv4 address %s.", - getIPV6ReadableFromIn6(&it->second).c_str(), - addr.toString().c_str()); - g_mapped_ips.erase(it); - Log::debug("IPV6", "Mapped address size now: %d.", - g_mapped_ips.size()); - } -} // removeMappedAddress - // ---------------------------------------------------------------------------- std::string getIPV6ReadableFromMappedAddress(const ENetAddress* ea) { std::string result; auto it = std::find_if(g_mapped_ips.begin(), g_mapped_ips.end(), - [ea](const std::pair& addr) + [ea](const MappedAddress& addr) { - return ea->host == addr.first.host && ea->port == addr.first.port; + return ea->host == addr.m_addr.host && + ea->port == addr.m_addr.port; }); if (it != g_mapped_ips.end()) - result = getIPV6ReadableFromIn6(&it->second); + result = getIPV6ReadableFromIn6(&it->m_in6); return result; } // getIPV6ReadableFromMappedAddress @@ -243,12 +239,16 @@ void addMappedAddress(const ENetAddress* ea, const struct sockaddr_in6* in6) void getIPV6FromMappedAddress(const ENetAddress* ea, struct sockaddr_in6* in6) { auto it = std::find_if(g_mapped_ips.begin(), g_mapped_ips.end(), - [ea](const std::pair& addr) + [ea](const MappedAddress& addr) { - return ea->host == addr.first.host && ea->port == addr.first.port; + return ea->host == addr.m_addr.host && + ea->port == addr.m_addr.port; }); if (it != g_mapped_ips.end()) - memcpy(in6, &it->second, sizeof(struct sockaddr_in6)); + { + it->m_last_activity = StkTime::getMonoTimeMs(); + memcpy(in6, &it->m_in6, sizeof(struct sockaddr_in6)); + } else memset(in6, 0, sizeof(struct sockaddr_in6)); } // getIPV6FromMappedAddress @@ -260,13 +260,14 @@ void getIPV6FromMappedAddress(const ENetAddress* ea, struct sockaddr_in6* in6) void getMappedFromIPV6(const struct sockaddr_in6* in6, ENetAddress* ea) { auto it = std::find_if(g_mapped_ips.begin(), g_mapped_ips.end(), - [in6](const std::pair& addr) + [in6](const MappedAddress& addr) { - return sameIPV6(in6, &addr.second); + return sameIPV6(in6, &addr.m_in6); }); if (it != g_mapped_ips.end()) { - *ea = it->first; + it->m_last_activity = StkTime::getMonoTimeMs(); + *ea = it->m_addr; return; } @@ -296,4 +297,27 @@ void getMappedFromIPV6(const struct sockaddr_in6* in6, ENetAddress* ea) } } // getMappedFromIPV6 +// ---------------------------------------------------------------------------- +/* Called when a peer is expired (no activity for 20 seconds) and we remove its + * reference to the ipv6. + */ +void removeDisconnectedMappedAddress() +{ + for (auto it = g_mapped_ips.begin(); it != g_mapped_ips.end();) + { + if (it->m_last_activity + 20000 < StkTime::getMonoTimeMs()) + { + TransportAddress addr(it->m_addr); + Log::debug("IPV6", "Removing expired %s, ipv4 address %s.", + getIPV6ReadableFromIn6(&it->m_in6).c_str(), + addr.toString().c_str()); + it = g_mapped_ips.erase(it); + Log::debug("IPV6", "Mapped address size now: %d.", + g_mapped_ips.size()); + } + else + it++; + } +} // removeDisconnectedMappedAddress + #endif diff --git a/src/network/unix_ipv6.hpp b/src/network/unix_ipv6.hpp index 6bd813d29..333b36241 100644 --- a/src/network/unix_ipv6.hpp +++ b/src/network/unix_ipv6.hpp @@ -24,7 +24,6 @@ extern "C" { int isIPV6(); void setIPV6(int val); void unixInitialize(); -void removeMappedAddress(const ENetAddress* ea); void getIPV6FromMappedAddress(const ENetAddress* ea, struct sockaddr_in6* in6); void getMappedFromIPV6(const struct sockaddr_in6* in6, ENetAddress* ea); void addMappedAddress(const ENetAddress* ea, const struct sockaddr_in6* in6); @@ -37,3 +36,4 @@ std::string getIPV6ReadableFromMappedAddress(const ENetAddress* ea); std::string getIPV6ReadableFromIn6(const struct sockaddr_in6* in); bool sameIPV6(const struct sockaddr_in6* in_1, const struct sockaddr_in6* in_2); +void removeDisconnectedMappedAddress();