Allow getting stun server list using SRV records
This commit is contained in:
parent
7598dc7b37
commit
364936e37b
@ -23,6 +23,7 @@ import java.util.Set;
|
|||||||
|
|
||||||
import org.minidns.hla.DnssecResolverApi;
|
import org.minidns.hla.DnssecResolverApi;
|
||||||
import org.minidns.hla.ResolverResult;
|
import org.minidns.hla.ResolverResult;
|
||||||
|
import org.minidns.record.SRV;
|
||||||
import org.minidns.record.TXT;
|
import org.minidns.record.TXT;
|
||||||
|
|
||||||
public class SuperTuxKartActivity extends NativeActivity
|
public class SuperTuxKartActivity extends NativeActivity
|
||||||
@ -244,4 +245,24 @@ public class SuperTuxKartActivity extends NativeActivity
|
|||||||
return new String[0];
|
return new String[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
public String[] getDNSSrvRecords(String domain)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ResolverResult<SRV> srvs =
|
||||||
|
DnssecResolverApi.INSTANCE.resolve(domain, SRV.class);
|
||||||
|
Set<SRV> ans = srvs.getAnswers();
|
||||||
|
String[] result = new String[ans.size()];
|
||||||
|
int i = 0;
|
||||||
|
for (SRV s : ans)
|
||||||
|
result[i++] = s.target.toString() + ":" + s.port;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,6 +180,11 @@
|
|||||||
password-reset="https://online.supertuxkart.net/password-reset.php"
|
password-reset="https://online.supertuxkart.net/password-reset.php"
|
||||||
assets-download="https://github.com/supertuxkart/stk-assets-mobile/releases/download/"/>
|
assets-download="https://github.com/supertuxkart/stk-assets-mobile/releases/download/"/>
|
||||||
|
|
||||||
|
<!-- STK will use dns query of the SRV records with these domains to get the list of
|
||||||
|
stun servers to use for IPv4 and IPv6. -->
|
||||||
|
<stun ipv4="_stunv4._udp.supertuxkart.net"
|
||||||
|
ipv6="_stunv6._udp.supertuxkart.net"/>
|
||||||
|
|
||||||
<!-- Skidmark data: maximum number of skid marks, and
|
<!-- Skidmark data: maximum number of skid marks, and
|
||||||
time for skidmarks to fade out. Maximum number will over
|
time for skidmarks to fade out. Maximum number will over
|
||||||
current number of karts, so the more karts, the less
|
current number of karts, so the more karts, the less
|
||||||
|
@ -496,6 +496,12 @@ void STKConfig::getAllData(const XMLNode * root)
|
|||||||
urls->get("assets-download", &m_assets_download_url);
|
urls->get("assets-download", &m_assets_download_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (const XMLNode *urls = root->getNode("stun"))
|
||||||
|
{
|
||||||
|
urls->get("ipv4", &m_stun_ipv4);
|
||||||
|
urls->get("ipv6", &m_stun_ipv6);
|
||||||
|
}
|
||||||
|
|
||||||
if (const XMLNode *fonts_list = root->getNode("fonts-list"))
|
if (const XMLNode *fonts_list = root->getNode("fonts-list"))
|
||||||
{
|
{
|
||||||
fonts_list->get("normal-ttf", &m_normal_ttf);
|
fonts_list->get("normal-ttf", &m_normal_ttf);
|
||||||
|
@ -207,6 +207,10 @@ public:
|
|||||||
std::string m_password_reset_url;
|
std::string m_password_reset_url;
|
||||||
std::string m_assets_download_url;
|
std::string m_assets_download_url;
|
||||||
|
|
||||||
|
/* SRV records for stun server lists created */
|
||||||
|
std::string m_stun_ipv4;
|
||||||
|
std::string m_stun_ipv6;
|
||||||
|
|
||||||
/** Lists of TTF files used in STK. */
|
/** Lists of TTF files used in STK. */
|
||||||
std::vector<std::string> m_normal_ttf;
|
std::vector<std::string> m_normal_ttf;
|
||||||
std::vector<std::string> m_digit_ttf;
|
std::vector<std::string> m_digit_ttf;
|
||||||
|
@ -138,7 +138,7 @@ public:
|
|||||||
|
|
||||||
irr::core::stringc toString() const;
|
irr::core::stringc toString() const;
|
||||||
|
|
||||||
operator std::map<T, U>() const
|
operator std::map<T, U>&() const
|
||||||
{
|
{
|
||||||
return m_elements;
|
return m_elements;
|
||||||
}
|
}
|
||||||
@ -150,7 +150,19 @@ public:
|
|||||||
{
|
{
|
||||||
return m_elements.end();
|
return m_elements.end();
|
||||||
}
|
}
|
||||||
std::map<T, U>& operator=(const std::map<T,U>& v)
|
typename std::map<T, U>::iterator find(const T& key)
|
||||||
|
{
|
||||||
|
return m_elements.find(key);
|
||||||
|
}
|
||||||
|
size_t erase(const T& key)
|
||||||
|
{
|
||||||
|
return m_elements.erase(key);
|
||||||
|
}
|
||||||
|
bool empty() const
|
||||||
|
{
|
||||||
|
return m_elements.empty();
|
||||||
|
}
|
||||||
|
std::map<T, U>& operator=(const std::map<T, U>& v)
|
||||||
{
|
{
|
||||||
m_elements = std::map<T, U>(v);
|
m_elements = std::map<T, U>(v);
|
||||||
return m_elements;
|
return m_elements;
|
||||||
@ -771,29 +783,13 @@ namespace UserConfigParams
|
|||||||
PARAM_DEFAULT(StringToUIntUserConfigParam("stun-servers-ipv4",
|
PARAM_DEFAULT(StringToUIntUserConfigParam("stun-servers-ipv4",
|
||||||
"The stun servers that will be used to know the public address "
|
"The stun servers that will be used to know the public address "
|
||||||
"(ipv4 only) with port", {{ "stun-server", "address", "ping" }},
|
"(ipv4 only) with port", {{ "stun-server", "address", "ping" }},
|
||||||
{
|
{ }));
|
||||||
{ "stunv4.1.supertuxkart.net:3478", 0u },
|
|
||||||
{ "stunv4.2.supertuxkart.net:19302", 0u },
|
|
||||||
{ "stunv4.3.supertuxkart.net:19302", 0u },
|
|
||||||
{ "stunv4.4.supertuxkart.net:19302", 0u },
|
|
||||||
{ "stunv4.5.supertuxkart.net:19302", 0u },
|
|
||||||
{ "stunv4.6.supertuxkart.net:19302", 0u }
|
|
||||||
}
|
|
||||||
));
|
|
||||||
|
|
||||||
PARAM_PREFIX StringToUIntUserConfigParam m_stun_servers
|
PARAM_PREFIX StringToUIntUserConfigParam m_stun_servers
|
||||||
PARAM_DEFAULT(StringToUIntUserConfigParam("stun-servers-ipv6",
|
PARAM_DEFAULT(StringToUIntUserConfigParam("stun-servers-ipv6",
|
||||||
"The stun servers that will be used to know the public address "
|
"The stun servers that will be used to know the public address "
|
||||||
"(including ipv6) with port", {{ "stun-server", "address", "ping" }},
|
"(including ipv6) with port", {{ "stun-server", "address", "ping" }},
|
||||||
{
|
{ }));
|
||||||
{ "stun.stunprotocol.org:3478", 0u },
|
|
||||||
{ "stun.l.google.com:19302", 0u },
|
|
||||||
{ "stun1.l.google.com:19302", 0u },
|
|
||||||
{ "stun2.l.google.com:19302", 0u },
|
|
||||||
{ "stun3.l.google.com:19302", 0u },
|
|
||||||
{ "stun4.l.google.com:19302", 0u }
|
|
||||||
}
|
|
||||||
));
|
|
||||||
|
|
||||||
PARAM_PREFIX GroupUserConfigParam m_network_group
|
PARAM_PREFIX GroupUserConfigParam m_network_group
|
||||||
PARAM_DEFAULT(GroupUserConfigParam("Network", "Network Settings"));
|
PARAM_DEFAULT(GroupUserConfigParam("Network", "Network Settings"));
|
||||||
|
@ -35,13 +35,27 @@
|
|||||||
#include "states_screens/online/online_profile_servers.hpp"
|
#include "states_screens/online/online_profile_servers.hpp"
|
||||||
#include "states_screens/online/online_screen.hpp"
|
#include "states_screens/online/online_screen.hpp"
|
||||||
#include "states_screens/state_manager.hpp"
|
#include "states_screens/state_manager.hpp"
|
||||||
|
#include "utils/string_utils.hpp"
|
||||||
#include "utils/time.hpp"
|
#include "utils/time.hpp"
|
||||||
|
#include "utils/utf8/unchecked.h"
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
# include <winsock2.h>
|
# include <windns.h>
|
||||||
# include <ws2tcpip.h>
|
# include <ws2tcpip.h>
|
||||||
|
#ifndef __MINGW32__
|
||||||
|
# pragma comment(lib, "dnsapi.lib")
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
|
# include <arpa/nameser.h>
|
||||||
|
# include <arpa/nameser_compat.h>
|
||||||
# include <netdb.h>
|
# include <netdb.h>
|
||||||
|
# include <netinet/in.h>
|
||||||
|
# include <resolv.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ANDROID
|
||||||
|
#include "../../../lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.h"
|
||||||
|
#include "graphics/irr_driver.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NetworkConfig *NetworkConfig::m_network_config[PT_COUNT];
|
NetworkConfig *NetworkConfig::m_network_config[PT_COUNT];
|
||||||
@ -221,11 +235,28 @@ void NetworkConfig::detectIPType()
|
|||||||
auto ipv6 = std::unique_ptr<Network>(new Network(1, 1, 0, 0, &eaddr));
|
auto ipv6 = std::unique_ptr<Network>(new Network(1, 1, 0, 0, &eaddr));
|
||||||
setIPv6Socket(0);
|
setIPv6Socket(0);
|
||||||
|
|
||||||
auto ipv4_it = UserConfigParams::m_stun_servers_v4.begin();
|
auto& stunv4_map = UserConfigParams::m_stun_servers_v4;
|
||||||
int adv = StkTime::getMonoTimeMs() % UserConfigParams::m_stun_servers_v4.size();
|
for (auto& s : getStunList(true/*ipv4*/))
|
||||||
|
{
|
||||||
|
if (stunv4_map.find(s) == stunv4_map.end())
|
||||||
|
stunv4_map[s] = 0;
|
||||||
|
}
|
||||||
|
if (stunv4_map.empty())
|
||||||
|
return;
|
||||||
|
auto ipv4_it = stunv4_map.begin();
|
||||||
|
int adv = StkTime::getMonoTimeMs() % stunv4_map.size();
|
||||||
std::advance(ipv4_it, adv);
|
std::advance(ipv4_it, adv);
|
||||||
auto ipv6_it = UserConfigParams::m_stun_servers.begin();
|
|
||||||
adv = StkTime::getMonoTimeMs() % UserConfigParams::m_stun_servers.size();
|
auto& stunv6_map = UserConfigParams::m_stun_servers;
|
||||||
|
for (auto& s : getStunList(false/*ipv4*/))
|
||||||
|
{
|
||||||
|
if (stunv6_map.find(s) == stunv6_map.end())
|
||||||
|
stunv6_map[s] = 0;
|
||||||
|
}
|
||||||
|
if (stunv6_map.empty())
|
||||||
|
return;
|
||||||
|
auto ipv6_it = stunv6_map.begin();
|
||||||
|
adv = StkTime::getMonoTimeMs() % stunv6_map.size();
|
||||||
std::advance(ipv6_it, adv);
|
std::advance(ipv6_it, adv);
|
||||||
|
|
||||||
SocketAddress::g_ignore_error_message = true;
|
SocketAddress::g_ignore_error_message = true;
|
||||||
@ -343,3 +374,206 @@ void NetworkConfig::detectIPType()
|
|||||||
m_ip_type = IP_V4;
|
m_ip_type = IP_V4;
|
||||||
#endif
|
#endif
|
||||||
} // detectIPType
|
} // detectIPType
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
void NetworkConfig::fillStunList(std::vector<std::string>& l,
|
||||||
|
const std::string& dns)
|
||||||
|
{
|
||||||
|
#if defined(WIN32)
|
||||||
|
PDNS_RECORD dns_record = NULL;
|
||||||
|
DnsQuery(StringUtils::utf8ToWide(dns).c_str(), DNS_TYPE_SRV,
|
||||||
|
DNS_QUERY_STANDARD, NULL, &dns_record, NULL);
|
||||||
|
if (dns_record)
|
||||||
|
{
|
||||||
|
for (PDNS_RECORD curr = dns_record; curr; curr = curr->pNext)
|
||||||
|
{
|
||||||
|
if (curr->wType == DNS_TYPE_SRV)
|
||||||
|
{
|
||||||
|
l.push_back(
|
||||||
|
StringUtils::wideToUtf8(curr->Data.SRV.pNameTarget) +
|
||||||
|
":" + StringUtils::toString(curr->Data.SRV.wPort));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DnsRecordListFree(dns_record, DnsFreeRecordListDeep);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(ANDROID)
|
||||||
|
CIrrDeviceAndroid* dev =
|
||||||
|
dynamic_cast<CIrrDeviceAndroid*>(irr_driver->getDevice());
|
||||||
|
if (!dev)
|
||||||
|
return;
|
||||||
|
android_app* android = dev->getAndroid();
|
||||||
|
if (!android)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool was_detached = false;
|
||||||
|
JNIEnv* env = NULL;
|
||||||
|
|
||||||
|
jint status = android->activity->vm->GetEnv((void**)&env, JNI_VERSION_1_6);
|
||||||
|
if (status == JNI_EDETACHED)
|
||||||
|
{
|
||||||
|
JavaVMAttachArgs args;
|
||||||
|
args.version = JNI_VERSION_1_6;
|
||||||
|
args.name = "NativeThread";
|
||||||
|
args.group = NULL;
|
||||||
|
|
||||||
|
status = android->activity->vm->AttachCurrentThread(&env, &args);
|
||||||
|
was_detached = true;
|
||||||
|
}
|
||||||
|
if (status != JNI_OK)
|
||||||
|
{
|
||||||
|
Log::error("NetworkConfig",
|
||||||
|
"Cannot attach current thread in getDNSSrvRecords.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject native_activity = android->activity->clazz;
|
||||||
|
jclass class_native_activity = env->GetObjectClass(native_activity);
|
||||||
|
|
||||||
|
if (class_native_activity == NULL)
|
||||||
|
{
|
||||||
|
Log::error("NetworkConfig",
|
||||||
|
"getDNSSrvRecords unable to find object class.");
|
||||||
|
if (was_detached)
|
||||||
|
{
|
||||||
|
android->activity->vm->DetachCurrentThread();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
jmethodID method_id = env->GetMethodID(class_native_activity,
|
||||||
|
"getDNSSrvRecords", "(Ljava/lang/String;)[Ljava/lang/String;");
|
||||||
|
|
||||||
|
if (method_id == NULL)
|
||||||
|
{
|
||||||
|
Log::error("NetworkConfig",
|
||||||
|
"getDNSSrvRecords unable to find method id.");
|
||||||
|
if (was_detached)
|
||||||
|
{
|
||||||
|
android->activity->vm->DetachCurrentThread();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint16_t> jstr_data;
|
||||||
|
utf8::unchecked::utf8to16(
|
||||||
|
dns.c_str(), dns.c_str() + dns.size(), std::back_inserter(jstr_data));
|
||||||
|
jstring text =
|
||||||
|
env->NewString((const jchar*)jstr_data.data(), jstr_data.size());
|
||||||
|
if (text == NULL)
|
||||||
|
{
|
||||||
|
Log::error("NetworkConfig",
|
||||||
|
"Failed to create text for domain name.");
|
||||||
|
if (was_detached)
|
||||||
|
{
|
||||||
|
android->activity->vm->DetachCurrentThread();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
jobjectArray arr =
|
||||||
|
(jobjectArray)env->CallObjectMethod(native_activity, method_id, text);
|
||||||
|
if (arr == NULL)
|
||||||
|
{
|
||||||
|
Log::error("NetworkConfig", "No array is created.");
|
||||||
|
if (was_detached)
|
||||||
|
{
|
||||||
|
android->activity->vm->DetachCurrentThread();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int len = env->GetArrayLength(arr);
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
jstring jstr = (jstring)(env->GetObjectArrayElement(arr, i));
|
||||||
|
if (!jstr)
|
||||||
|
continue;
|
||||||
|
const uint16_t* utf16_text =
|
||||||
|
(const uint16_t*)env->GetStringChars(jstr, NULL);
|
||||||
|
if (utf16_text == NULL)
|
||||||
|
continue;
|
||||||
|
const size_t str_len = env->GetStringLength(jstr);
|
||||||
|
std::string tmp;
|
||||||
|
utf8::unchecked::utf16to8(
|
||||||
|
utf16_text, utf16_text + str_len, std::back_inserter(tmp));
|
||||||
|
l.push_back(tmp);
|
||||||
|
env->ReleaseStringChars(jstr, utf16_text);
|
||||||
|
}
|
||||||
|
if (was_detached)
|
||||||
|
{
|
||||||
|
android->activity->vm->DetachCurrentThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define SRV_PORT (RRFIXEDSZ+4)
|
||||||
|
#define SRV_SERVER (RRFIXEDSZ+6)
|
||||||
|
#define SRV_FIXEDSZ (RRFIXEDSZ+6)
|
||||||
|
|
||||||
|
unsigned char response[512] = {};
|
||||||
|
int response_len = res_query(dns.c_str(), C_IN, T_SRV, response, 512);
|
||||||
|
if (response_len > 0)
|
||||||
|
{
|
||||||
|
HEADER* header = (HEADER*)response;
|
||||||
|
unsigned char* start = response + NS_HFIXEDSZ;
|
||||||
|
|
||||||
|
if ((header->tc) || (response_len < NS_HFIXEDSZ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (header->rcode >= 1 && header->rcode <= 5)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int ancount = ntohs(header->ancount);
|
||||||
|
int qdcount = ntohs(header->qdcount);
|
||||||
|
if (ancount == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ancount > NS_PACKETSZ)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int count = qdcount; count > 0; count--)
|
||||||
|
{
|
||||||
|
int str_len = dn_skipname(start, response + response_len);
|
||||||
|
start += str_len + NS_QFIXEDSZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned char*> srv;
|
||||||
|
for (int count = ancount; count > 0; count--)
|
||||||
|
{
|
||||||
|
int str_len = dn_skipname(start, response + response_len);
|
||||||
|
start += str_len;
|
||||||
|
srv.push_back(start);
|
||||||
|
start += SRV_FIXEDSZ;
|
||||||
|
start += dn_skipname(start, response + response_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < srv.size(); i++)
|
||||||
|
{
|
||||||
|
char server_name[512] = {};
|
||||||
|
if (ns_name_ntop(srv[i] + SRV_SERVER, server_name, 512) < 0)
|
||||||
|
continue;
|
||||||
|
uint16_t port = ns_get16(srv[i] + SRV_PORT);
|
||||||
|
l.push_back(std::string(server_name) + ":" +
|
||||||
|
StringUtils::toString(port));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} // fillStunList
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
const std::vector<std::string>& NetworkConfig::getStunList(bool ipv4)
|
||||||
|
{
|
||||||
|
static std::vector<std::string> ipv4_list;
|
||||||
|
static std::vector<std::string> ipv6_list;
|
||||||
|
if (ipv4)
|
||||||
|
{
|
||||||
|
if (ipv4_list.empty())
|
||||||
|
NetworkConfig::fillStunList(ipv4_list, stk_config->m_stun_ipv4);
|
||||||
|
return ipv4_list;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ipv6_list.empty())
|
||||||
|
NetworkConfig::fillStunList(ipv6_list, stk_config->m_stun_ipv6);
|
||||||
|
return ipv6_list;
|
||||||
|
}
|
||||||
|
} // getStunList
|
||||||
|
@ -120,6 +120,10 @@ private:
|
|||||||
* addresses they use the same prefix for each initIPTest. */
|
* addresses they use the same prefix for each initIPTest. */
|
||||||
std::string m_nat64_prefix;
|
std::string m_nat64_prefix;
|
||||||
std::array<uint32_t, 8> m_nat64_prefix_data;
|
std::array<uint32_t, 8> m_nat64_prefix_data;
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
static void fillStunList(std::vector<std::string>& l,
|
||||||
|
const std::string& dns);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Singleton get, which creates this object if necessary. */
|
/** Singleton get, which creates this object if necessary. */
|
||||||
static NetworkConfig *get()
|
static NetworkConfig *get()
|
||||||
@ -294,6 +298,8 @@ public:
|
|||||||
void setNumFixedAI(unsigned num) { m_num_fixed_ai = num; }
|
void setNumFixedAI(unsigned num) { m_num_fixed_ai = num; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
unsigned getNumFixedAI() const { return m_num_fixed_ai; }
|
unsigned getNumFixedAI() const { return m_num_fixed_ai; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
static const std::vector<std::string>& getStunList(bool ipv4);
|
||||||
}; // class NetworkConfig
|
}; // class NetworkConfig
|
||||||
|
|
||||||
#endif // HEADER_NETWORK_CONFIG
|
#endif // HEADER_NETWORK_CONFIG
|
||||||
|
@ -635,13 +635,26 @@ void STKHost::getIPFromStun(int socket, const std::string& stun_address,
|
|||||||
*/
|
*/
|
||||||
void STKHost::setPublicAddress(short family)
|
void STKHost::setPublicAddress(short family)
|
||||||
{
|
{
|
||||||
|
auto& stunv4_map = UserConfigParams::m_stun_servers_v4;
|
||||||
|
for (auto& s : NetworkConfig::getStunList(true/*ipv4*/))
|
||||||
|
{
|
||||||
|
if (stunv4_map.find(s) == stunv4_map.end())
|
||||||
|
stunv4_map[s] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& stunv6_map = UserConfigParams::m_stun_servers;
|
||||||
|
for (auto& s : NetworkConfig::getStunList(false/*ipv4*/))
|
||||||
|
{
|
||||||
|
if (stunv6_map.find(s) == stunv6_map.end())
|
||||||
|
stunv6_map[s] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
auto& stun_map = family == AF_INET ? UserConfigParams::m_stun_servers_v4 :
|
auto& stun_map = family == AF_INET ? UserConfigParams::m_stun_servers_v4 :
|
||||||
UserConfigParams::m_stun_servers;
|
UserConfigParams::m_stun_servers;
|
||||||
std::vector<std::pair<std::string, uint32_t> > untried_server;
|
std::vector<std::pair<std::string, uint32_t> > untried_server;
|
||||||
for (auto& p : stun_map)
|
for (auto& p : stun_map)
|
||||||
untried_server.push_back(p);
|
untried_server.push_back(p);
|
||||||
|
|
||||||
assert(untried_server.size() > 2);
|
|
||||||
// Randomly use stun servers of the low ping from top-half of the list
|
// Randomly use stun servers of the low ping from top-half of the list
|
||||||
std::sort(untried_server.begin(), untried_server.end(),
|
std::sort(untried_server.begin(), untried_server.end(),
|
||||||
[] (const std::pair<std::string, uint32_t>& a,
|
[] (const std::pair<std::string, uint32_t>& a,
|
||||||
@ -651,8 +664,16 @@ void STKHost::setPublicAddress(short family)
|
|||||||
});
|
});
|
||||||
std::random_device rd;
|
std::random_device rd;
|
||||||
std::mt19937 g(rd());
|
std::mt19937 g(rd());
|
||||||
std::shuffle(untried_server.begin() + (untried_server.size() / 2),
|
if (untried_server.size() > 2)
|
||||||
untried_server.end(), g);
|
{
|
||||||
|
std::shuffle(untried_server.begin() + (untried_server.size() / 2),
|
||||||
|
untried_server.end(), g);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log::warn("STKHost", "Failed to get enough stun servers using SRV"
|
||||||
|
" record.");
|
||||||
|
}
|
||||||
|
|
||||||
while (!untried_server.empty() && !ProtocolManager::lock()->isExiting())
|
while (!untried_server.empty() && !ProtocolManager::lock()->isExiting())
|
||||||
{
|
{
|
||||||
@ -698,7 +719,13 @@ void STKHost::setPublicAddress(short family)
|
|||||||
untried_server.clear();
|
untried_server.clear();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
// Erase from user config in stun, if it's provide by SRV records
|
||||||
|
// from STK then it will be re-added next time, and STK team will
|
||||||
|
// remove it if it stops working
|
||||||
|
stun_map.erase(untried_server.back().first);
|
||||||
untried_server.pop_back();
|
untried_server.pop_back();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // setPublicAddress
|
} // setPublicAddress
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user