diff --git a/src/network/network.cpp b/src/network/network.cpp index da048b643..33f7e8a09 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -63,6 +63,7 @@ Network::Network(int peer_count, int channel_limit, uint32_t max_outgoing_bandwidth, ENetAddress* address, bool change_port_if_bound) { + m_ipv6_socket = false; m_port = 0; m_host = enet_host_create(address, peer_count, channel_limit, 0, 0); if (!m_host && change_port_if_bound) @@ -77,29 +78,30 @@ Network::Network(int peer_count, int channel_limit, if (!m_host) Log::fatal("Network", "Failed to create socket with any port."); } - if (m_host && isIPv6Socket()) + if (m_host) { - struct sockaddr_in6 sin6; - socklen_t len = sizeof(sin6); - if (getsockname(m_host->socket, (struct sockaddr*)&sin6, &len) == -1) + struct sockaddr_storage ss; + memset(&ss, 0, sizeof (struct sockaddr_storage)); + socklen_t len = sizeof(ss); + if (getsockname(m_host->socket, (struct sockaddr*)&ss, &len) == -1) { Log::error("STKHost", "Error while using getsockname()."); m_port = 0; } else - m_port = ntohs(sin6.sin6_port); - } - else if (m_host) - { - struct sockaddr_in sin; - socklen_t len = sizeof(sin); - if (getsockname(m_host->socket, (struct sockaddr*)&sin, &len) == -1) { - Log::error("STKHost", "Error while using getsockname()."); - m_port = 0; + m_ipv6_socket = ss.ss_family == AF_INET6; + if (m_ipv6_socket) + { + sockaddr_in6* sin6 = (sockaddr_in6*)&ss; + m_port = ntohs(sin6->sin6_port); + } + else + { + sockaddr_in* sin = (sockaddr_in*)&ss; + m_port = ntohs(sin->sin_port); + } } - else - m_port = ntohs(sin.sin_port); } } // Network diff --git a/src/network/network.hpp b/src/network/network.hpp index daf6aa650..3802f3891 100644 --- a/src/network/network.hpp +++ b/src/network/network.hpp @@ -50,6 +50,7 @@ private: uint16_t m_port; + bool m_ipv6_socket; /** Where to log packets. If NULL for FILE* logging is disabled. */ static Synchronised m_log_file; @@ -77,6 +78,8 @@ public: // ------------------------------------------------------------------------ /** Returns a pointer to the ENet host object. */ ENetHost* getENetHost() { return m_host; } + // ------------------------------------------------------------------------ + bool isIPv6Socket() { return m_ipv6_socket; } }; // class Network #endif // HEADER_ENET_SOCKET_HPP diff --git a/src/network/protocols/connect_to_server.cpp b/src/network/protocols/connect_to_server.cpp index 68ea7b6da..de92bcc89 100644 --- a/src/network/protocols/connect_to_server.cpp +++ b/src/network/protocols/connect_to_server.cpp @@ -231,12 +231,13 @@ void ConnectToServer::asynchronousUpdate() // Auto enable IPv6 socket in client with NAT64, then we convert // the IPv4 address to NAT64 one in GOT_SERVER_ADDRESS - if (m_server->useIPV6Connection() || - NetworkConfig::get()->getIPType() == NetworkConfig::IP_V6_NAT64) + bool ipv6_socket = m_server->useIPV6Connection() || + NetworkConfig::get()->getIPType() == NetworkConfig::IP_V6_NAT64; + if (STKHost::get()->getNetwork()->isIPv6Socket() != ipv6_socket) { // Free the bound socket first delete STKHost::get()->getNetwork(); - setIPv6Socket(1); + setIPv6Socket(ipv6_socket ? 1 : 0); ENetAddress addr = {}; addr.port = NetworkConfig::get()->getClientPort(); auto new_network = new Network(/*peer_count*/1,