Randomly use stun servers of the low ping from top-half of the list

This commit is contained in:
Benau 2018-03-23 18:51:26 +08:00
parent 52dc38d03b
commit 3ee3d8d5bd
5 changed files with 75 additions and 230 deletions

View File

@ -181,146 +181,6 @@ void GroupUserConfigParam::addChild(UserConfigParam* child)
m_attributes.push_back(child);
} // addChild
// ============================================================================
template<typename T, typename U>
ListUserConfigParam<T, U>::ListUserConfigParam(const char* param_name,
const char* comment)
{
m_param_name = param_name;
all_params.push_back(this);
if(comment != NULL) m_comment = comment;
} // ListUserConfigParam
// ============================================================================
template<typename T, typename U>
ListUserConfigParam<T,U>::ListUserConfigParam(const char* param_name,
const char* comment,
int nb_elements,
...)
{
m_param_name = param_name;
all_params.push_back(this);
if(comment != NULL) m_comment = comment;
// add the default list
va_list arguments;
va_start ( arguments, nb_elements );
for ( int i = 0; i < nb_elements; i++ )
m_elements.push_back(T(va_arg ( arguments, U )));
va_end ( arguments ); // Cleans up the list
} // ListUserConfigParam
// ============================================================================
template<typename T, typename U>
ListUserConfigParam<T, U>::ListUserConfigParam(const char* param_name,
GroupUserConfigParam* group,
const char* comment)
{
m_param_name = param_name;
group->addChild(this);
if(comment != NULL) m_comment = comment;
} // ListUserConfigParam
// ============================================================================
template<typename T, typename U>
ListUserConfigParam<T, U>::ListUserConfigParam(const char* param_name,
GroupUserConfigParam* group,
const char* comment,
int nb_elements,
...)
{
m_param_name = param_name;
group->addChild(this);
if(comment != NULL) m_comment = comment;
// add the default list
va_list arguments;
va_start ( arguments, nb_elements );
for ( int i = 0; i < nb_elements; i++ )
m_elements.push_back(va_arg ( arguments, T ));
va_end ( arguments ); // Cleans up the list
} // ListUserConfigParam
// ----------------------------------------------------------------------------
template<typename T, typename U>
void ListUserConfigParam<T, U>::write(std::ofstream& stream) const
{
const int elts_amount = (int)m_elements.size();
// comment
if(m_comment.size() > 0) stream << " <!-- " << m_comment.c_str();
stream << " -->\n <" << m_param_name.c_str() << "\n";
stream << " Size=\"" << elts_amount << "\"\n";
// actual elements
for (int n=0; n<elts_amount; n++)
{
stream << " " << n << "=\"" << m_elements[n].c_str() << "\"\n";
}
stream << " >\n";
stream << " </" << m_param_name.c_str() << ">\n\n";
} // write
// ----------------------------------------------------------------------------
template<typename T, typename U>
void ListUserConfigParam<T, U>::findYourDataInAChildOf(const XMLNode* node)
{
const XMLNode* child = node->getNode( m_param_name );
if (child == NULL)
{
//Log::error("User Config", "Couldn't find parameter group %s", m_param_name.c_str());
return;
}
int attr_count = 0;
child->get( "Size", &attr_count);
for (int n=0; n<attr_count; n++)
{
T elt;
std::string str;
child->get( StringUtils::toString(n), &str);
StringUtils::fromString<T>(str, elt);
// check if the element is already there :
bool there = false;
for (unsigned int i = 0; i < m_elements.size(); i++)
{
if (elt == m_elements[i])
{
there = true;
break;
}
}
if (!there)
{
m_elements.push_back(elt);
}
}
} // findYourDataInAChildOf
// ----------------------------------------------------------------------------
template<typename T, typename U>
void ListUserConfigParam<T, U>::findYourDataInAnAttributeOf(const XMLNode* node)
{
} // findYourDataInAnAttributeOf
// ----------------------------------------------------------------------------
template<typename T, typename U>
void ListUserConfigParam<T,U>::addElement(T element)
{
m_elements.push_back(element);
} // findYourDataInAnAttributeOf
// ----------------------------------------------------------------------------
template<typename T, typename U>
core::stringc ListUserConfigParam<T, U>::toString() const
{
return "";
} // toString
// ----------------------------------------------------------------------------
template<typename T, typename U>
MapUserConfigParam<T, U>::MapUserConfigParam(const char* param_name,
@ -374,7 +234,7 @@ void MapUserConfigParam<T, U>::write(std::ofstream& stream) const
if (m_comment.size() > 0) stream << " <!-- " << m_comment.c_str();
stream << " -->\n <" << m_param_name.c_str() << "\n";
for (const auto& kv : m_elements)
for (const auto& kv : m_elements)
{
stream << " " << kv.first << "=\"" << kv.second << "\"\n";
}
@ -383,7 +243,6 @@ void MapUserConfigParam<T, U>::write(std::ofstream& stream) const
} // write
// ----------------------------------------------------------------------------
template<typename T, typename U>
void MapUserConfigParam<T, U>::findYourDataInAChildOf(const XMLNode* node)
{

View File

@ -37,6 +37,7 @@
cause an undefined game action now
6: Added stick configurations.
*/
#include <iterator>
#include <string>
#include <map>
#include <vector>
@ -98,44 +99,6 @@ public:
}; // GroupUserConfigParam
// ============================================================================
template<typename T, typename U>
class ListUserConfigParam : public UserConfigParam
{
std::vector<T> m_elements;
public:
ListUserConfigParam(const char* param_name,
const char* comment = NULL);
ListUserConfigParam(const char* param_name,
const char* comment,
int nb_elts,
...);
ListUserConfigParam(const char* param_name,
GroupUserConfigParam* group,
const char* comment = NULL);
ListUserConfigParam(const char* param_name,
GroupUserConfigParam* group,
const char* comment,
int nb_elts,
...);
void write(std::ofstream& stream) const;
void findYourDataInAChildOf(const XMLNode* node);
void findYourDataInAnAttributeOf(const XMLNode* node);
void addElement(T element);
irr::core::stringc toString() const;
operator std::vector<T>() const
{ return m_elements; }
float& operator=(const std::vector<T>& v)
{ m_elements = std::vector<T>(v); return m_elements; }
float& operator=(const ListUserConfigParam& v)
{ m_elements = std::vector<T>(v); return m_elements; }
}; // ListUserConfigParam
typedef ListUserConfigParam<std::string, const char*> StringListUserConfigParam;
template<typename T, typename U>
class MapUserConfigParam : public UserConfigParam
{
@ -163,10 +126,18 @@ public:
irr::core::stringc toString() const;
operator std::map<T,U>() const
operator std::map<T, U>() const
{
return m_elements;
}
typename std::map<T, U>::iterator begin()
{
return m_elements.begin();
}
typename std::map<T, U>::iterator end()
{
return m_elements.end();
}
std::map<T, U>& operator=(const std::map<T,U>& v)
{
m_elements = std::map<T, U>(v);
@ -181,7 +152,7 @@ public:
{
return m_elements[key];
}
}; // ListUserConfigParam
}; // MapUserConfigParam
typedef MapUserConfigParam<uint32_t, uint32_t> UIntToUIntUserConfigParam;
typedef MapUserConfigParam<std::string, uint32_t> StringToUIntUserConfigParam;
// ============================================================================
@ -707,44 +678,25 @@ namespace UserConfigParams
* can store. */
PARAM_PREFIX float m_profiler_buffer_duration PARAM_DEFAULT(20.0f);
// not saved to file
// ---- Networking
PARAM_PREFIX IntUserConfigParam m_server_max_players
PARAM_DEFAULT( IntUserConfigParam(12, "server_max_players",
"Maximum number of players on the server.") );
PARAM_PREFIX StringListUserConfigParam m_stun_servers_list
PARAM_DEFAULT( StringListUserConfigParam("Stun_servers_list",
"The stun servers that will be used to know the public address.",
10,
"stun.cope.es",
"stun.12connect.com",
"stun.callwithus.com",
"stun.counterpath.net",
"stun.ekiga.net",
"stun.schlund.de",
"stun.stunprotocol.org",
"stun.voip.aebc.com",
"numb.viagenie.ca",
"stun.ivao.aero") );
// ---- Gamemode setup
PARAM_PREFIX UIntToUIntUserConfigParam m_num_karts_per_gamemode
PARAM_DEFAULT(UIntToUIntUserConfigParam("num_karts_per_gamemode",
"The Number of karts per gamemode.",
PARAM_PREFIX StringToUIntUserConfigParam m_stun_list
PARAM_DEFAULT(StringToUIntUserConfigParam("stun_list",
"The stun servers that will be used to know the public address,"
" LHS: server address, RHS: ping time.",
{
{ 0u, 4u },
{ 1002u, 5u },
{ 1100u, 4u },
{ 1101u, 4u },
{ 2000u, 4u },
{ 2001u, 4u },
{ "numb.viagenie.ca", 0u },
{ "stun.12connect.com", 0u },
{ "stun.callwithus.com", 0u },
{ "stun.cope.es", 0u },
{ "stun.counterpath.net", 0u },
{ "stun.ekiga.net", 0u },
{ "stun.ivao.aero", 0u },
{ "stun.schlund.de", 0u },
{ "stun.stunprotocol.org", 0u },
{ "stun.voip.aebc.com", 0u }
}
));
// ---- Network
PARAM_PREFIX GroupUserConfigParam m_network_group
PARAM_DEFAULT(GroupUserConfigParam("Network", "Network Settings"));
PARAM_PREFIX BoolUserConfigParam m_log_packets
@ -760,7 +712,10 @@ namespace UserConfigParams
PARAM_PREFIX FloatUserConfigParam m_voting_timeout
PARAM_DEFAULT(FloatUserConfigParam(10.0f, "voting-timeout",
&m_network_group, "Timeout in seconds for voting tracks in server."));
// ---- Gamemode setup
PARAM_PREFIX IntUserConfigParam m_server_max_players
PARAM_DEFAULT(IntUserConfigParam(12, "server_max_players",
&m_network_group, "Maximum number of players on the server."));
PARAM_PREFIX StringToUIntUserConfigParam m_server_ban_list
PARAM_DEFAULT(StringToUIntUserConfigParam("server_ban_list",
"LHS: IP in x.x.x.x format, RHS: online id, if 0 than all players "
@ -768,6 +723,20 @@ namespace UserConfigParams
{ { "0.0.0.0", 0u } }
));
// ---- Gamemode setup
PARAM_PREFIX UIntToUIntUserConfigParam m_num_karts_per_gamemode
PARAM_DEFAULT(UIntToUIntUserConfigParam("num_karts_per_gamemode",
"The Number of karts per gamemode.",
{
{ 0u, 4u },
{ 1002u, 5u },
{ 1100u, 4u },
{ 1101u, 4u },
{ 2000u, 4u },
{ 2001u, 4u }
}
));
// ---- Graphic Quality
PARAM_PREFIX GroupUserConfigParam m_graphics_quality
PARAM_DEFAULT( GroupUserConfigParam("GFX",

View File

@ -107,9 +107,7 @@ void mainLoop(STKHost* host)
}
else if (str == "listban")
{
std::map<std::string, uint32_t> ban_list =
UserConfigParams::m_server_ban_list;
for (auto& ban : ban_list)
for (auto& ban : UserConfigParams::m_server_ban_list)
{
if (ban.first == "0.0.0.0")
continue;

View File

@ -1242,8 +1242,10 @@ void ServerLobby::updateBanList()
{
std::lock_guard<std::mutex> lock(m_connection_mutex);
m_ban_list.clear();
std::map<std::string, uint32_t> ban_list =
UserConfigParams::m_server_ban_list;
for (auto& ban : ban_list)
for (auto& ban : UserConfigParams::m_server_ban_list)
{
if (ban.first == "0.0.0.0")
continue;
m_ban_list[TransportAddress(ban.first).getIP()] = ban.second;
}
} // updateBanList

View File

@ -385,17 +385,29 @@ void STKHost::shutdown()
*/
void STKHost::setPublicAddress()
{
std::vector<std::string> untried_server =
UserConfigParams::m_stun_servers_list;
// Generate random list of stun servers
std::vector<std::pair<std::string, uint32_t> > untried_server;
for (auto& p : UserConfigParams::m_stun_list)
untried_server.push_back(p);
assert(untried_server.size() > 2);
// Randomly use stun servers of the low ping from top-half of the list
std::sort(untried_server.begin(), untried_server.end(),
[] (const std::pair<std::string, uint32_t>& a,
const std::pair<std::string, uint32_t>& b)->bool
{
return a.second > b.second;
});
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(untried_server.begin(), untried_server.end(), g);
std::shuffle(untried_server.begin() + (untried_server.size() / 2),
untried_server.end(), g);
while (!untried_server.empty())
{
// Pick last element in untried servers
const char* server_name = untried_server.back().c_str();
Log::debug("STKHost", "Using STUN server %s", server_name);
std::string server_name = untried_server.back().first.c_str();
UserConfigParams::m_stun_list[server_name] = (uint32_t)-1;
Log::debug("STKHost", "Using STUN server %s", server_name.c_str());
struct addrinfo hints, *res;
@ -404,11 +416,11 @@ void STKHost::setPublicAddress()
hints.ai_socktype = SOCK_STREAM;
// Resolve the stun server name so we can send it a STUN request
int status = getaddrinfo(server_name, NULL, &hints, &res);
int status = getaddrinfo(server_name.c_str(), NULL, &hints, &res);
if (status != 0)
{
Log::error("STKHost", "Error in getaddrinfo for stun server"
" %s: %s", server_name, gai_strerror(status));
" %s: %s", server_name.c_str(), gai_strerror(status));
untried_server.pop_back();
continue;
}
@ -439,6 +451,7 @@ void STKHost::setPublicAddress()
}
m_network->sendRawPacket(s, m_stun_address);
double ping = StkTime::getRealTime();
freeaddrinfo(res);
// Recieve now
@ -446,6 +459,7 @@ void STKHost::setPublicAddress()
const int LEN = 2048;
char buffer[LEN];
int len = m_network->receiveRawPacket(buffer, LEN, &sender, 2000);
ping = StkTime::getRealTime() - ping;
if (sender.getIP() != m_stun_address.getIP())
{
@ -583,6 +597,9 @@ void STKHost::setPublicAddress()
Log::warn("STKHost", "Only non xor-mapped address returned.");
m_public_address.copy(non_xor_addr);
}
// Succeed, save ping
UserConfigParams::m_stun_list[server_name] =
(uint32_t)(ping * 1000.0);
untried_server.clear();
}
}