Fix crash in case system doesn't support IPv4 or IPv6

This commit is contained in:
Benau 2020-04-14 11:35:43 +08:00
parent 8e64433c3a
commit 93cf4bab52
4 changed files with 70 additions and 0 deletions

View File

@ -2018,6 +2018,7 @@ int main(int argc, char *argv[])
// ServerConfig will use stk_config for server version testing
stk_config->load(file_manager->getAsset("stk_config.xml"));
NetworkConfig::initSystemIP();
// Client port depends on user config file and stk_config
NetworkConfig::get()->initClientPort();
bool no_graphics = !CommandLine::has("--graphical-server");

View File

@ -59,6 +59,48 @@
#endif
NetworkConfig *NetworkConfig::m_network_config[PT_COUNT];
bool NetworkConfig::m_system_ipv4 = false;
bool NetworkConfig::m_system_ipv6 = false;
/** Initialize detection of system IPv4 or IPv6 support. */
void NetworkConfig::initSystemIP()
{
// It calls WSAStartup in enet, for the rest new Network function we don't
// need this because request manager runs curl_global_init which will do
// WSAStartup too
if (enet_initialize() != 0)
{
Log::error("NetworkConfig", "Could not initialize enet.");
return;
}
ENetAddress eaddr = {};
setIPv6Socket(0);
auto ipv4 = std::unique_ptr<Network>(new Network(1, 1, 0, 0, &eaddr));
setIPv6Socket(1);
auto ipv6 = std::unique_ptr<Network>(new Network(1, 1, 0, 0, &eaddr));
setIPv6Socket(0);
if (ipv4 && ipv4->getENetHost())
m_system_ipv4 = true;
if (ipv6 && ipv6->getENetHost())
m_system_ipv6 = true;
// If any 1 of them is missing set default network setting accordingly
if (!m_system_ipv4)
{
Log::warn("NetworkConfig", "System doesn't support IPv4");
if (m_system_ipv6)
{
UserConfigParams::m_ipv6_lan = true;
ServerConfig::m_ipv6_connection = true;
}
}
else if (!m_system_ipv6)
{
Log::warn("NetworkConfig", "System doesn't support IPv6");
UserConfigParams::m_ipv6_lan = false;
ServerConfig::m_ipv6_connection = false;
}
enet_deinitialize();
} // initSystemIP
/** \class NetworkConfig
* This class is the interface between STK and the online code, particularly
@ -224,6 +266,16 @@ void NetworkConfig::detectIPType()
return;
}
#ifdef ENABLE_IPV6
if (!m_system_ipv4 || !m_system_ipv6)
{
// Don't test connection if only IPv4 or IPv6 system support
if (m_system_ipv4)
m_ip_type.store(IP_V4);
else if (m_system_ipv6)
m_ip_type.store(IP_V6);
return;
}
ENetAddress eaddr = {};
// We don't need to result of stun, just to check if the socket can be
// used in ipv4 or ipv6
@ -235,6 +287,10 @@ void NetworkConfig::detectIPType()
auto ipv6 = std::unique_ptr<Network>(new Network(1, 1, 0, 0, &eaddr));
setIPv6Socket(0);
// This should only happen if system doesn't support all socket types
if (!ipv4->getENetHost() || !ipv6->getENetHost())
return;
auto& stunv4_map = UserConfigParams::m_stun_servers_v4;
for (auto& s : getStunList(true/*ipv4*/))
{

View File

@ -59,6 +59,10 @@ private:
/** The singleton instance. */
static NetworkConfig *m_network_config[PT_COUNT];
static bool m_system_ipv4;
static bool m_system_ipv6;
enum NetworkType : int
{
NETWORK_NONE, NETWORK_WAN, NETWORK_LAN
@ -125,6 +129,8 @@ private:
const std::string& dns);
public:
static void initSystemIP();
// ------------------------------------------------------------------------
/** Singleton get, which creates this object if necessary. */
static NetworkConfig *get()
{

View File

@ -164,6 +164,13 @@ std::shared_ptr<Online::XMLRequest> ServersManager::getLANRefreshRequest() const
NetworkConfig::get()->setIPType(UserConfigParams::m_ipv6_lan ?
NetworkConfig::IP_DUAL_STACK : NetworkConfig::IP_V4);
Network *broadcast = new Network(1, 1, 0, 0, &addr);
if (!broadcast->getENetHost())
{
setIPv6Socket(0);
m_success = true;
delete broadcast;
return;
}
const std::vector<SocketAddress> &all_bcast =
ServersManager::get()->getBroadcastAddresses(
UserConfigParams::m_ipv6_lan);