Port stun address resolve to use SocketAddress
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
#include "network/network.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
#include "network/server_config.hpp"
|
||||
#include "network/socket_address.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "network/stk_ipv6.hpp"
|
||||
#include "online/xml_request.hpp"
|
||||
@@ -191,17 +192,17 @@ void NetworkConfig::detectIPType()
|
||||
{
|
||||
m_nat64_prefix_data.fill(-1);
|
||||
#ifdef ENABLE_IPV6
|
||||
ENetAddress addr;
|
||||
addr.host = STKHost::HOST_ANY;
|
||||
addr.port = STKHost::PORT_ANY;
|
||||
ENetAddress eaddr;
|
||||
eaddr.host = STKHost::HOST_ANY;
|
||||
eaddr.port = STKHost::PORT_ANY;
|
||||
// We don't need to result of stun, just to check if the socket can be
|
||||
// used in ipv4 or ipv6
|
||||
uint8_t stun_tansaction_id[16] = {};
|
||||
BareNetworkString s = STKHost::getStunRequest(stun_tansaction_id);
|
||||
setIPv6Socket(0);
|
||||
auto ipv4 = std::unique_ptr<Network>(new Network(1, 1, 0, 0, &addr));
|
||||
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, &addr));
|
||||
auto ipv6 = std::unique_ptr<Network>(new Network(1, 1, 0, 0, &eaddr));
|
||||
setIPv6Socket(0);
|
||||
|
||||
auto ipv4_it = UserConfigParams::m_stun_servers_v4.begin();
|
||||
@@ -211,57 +212,34 @@ void NetworkConfig::detectIPType()
|
||||
adv = rand() % UserConfigParams::m_stun_servers.size();
|
||||
std::advance(ipv6_it, adv);
|
||||
|
||||
std::vector<std::string> addrv4_and_port =
|
||||
StringUtils::split(ipv4_it->first, ':');
|
||||
if (addrv4_and_port.size() != 2)
|
||||
{
|
||||
Log::error("NetworkConfig", "Wrong server address and port");
|
||||
return;
|
||||
}
|
||||
|
||||
struct addrinfo hints;
|
||||
struct addrinfo* res = NULL;
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
int status = getaddrinfo_compat(addrv4_and_port[0].c_str(),
|
||||
addrv4_and_port[1].c_str(), &hints, &res);
|
||||
SocketAddress stun_v4(ipv4_it->first, 0/*port specified in addr*/,
|
||||
AF_INET);
|
||||
bool sent_ipv4 = false;
|
||||
if (status == 0 && res != NULL)
|
||||
if (!stun_v4.isUnset())
|
||||
{
|
||||
if (res->ai_family == AF_INET)
|
||||
{
|
||||
sendto(ipv4->getENetHost()->socket, s.getData(), s.size(), 0,
|
||||
res->ai_addr, sizeof(sockaddr_in));
|
||||
sent_ipv4 = true;
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
sendto(ipv4->getENetHost()->socket, s.getData(), s.size(), 0,
|
||||
stun_v4.getSockaddr(), stun_v4.getSocklen());
|
||||
sent_ipv4 = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("NetworkConfig", "Invalid IPv4: %s",
|
||||
ipv4_it->first.c_str());
|
||||
}
|
||||
|
||||
std::vector<std::string> addrv6_and_port =
|
||||
StringUtils::split(ipv6_it->first, ':');
|
||||
if (addrv6_and_port.size() != 2)
|
||||
{
|
||||
Log::error("NetworkConfig", "Wrong server address and port");
|
||||
return;
|
||||
}
|
||||
|
||||
res = NULL;
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_INET6;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
status = getaddrinfo_compat(addrv6_and_port[0].c_str(),
|
||||
addrv6_and_port[1].c_str(), &hints, &res);
|
||||
SocketAddress stun_v6(ipv6_it->first, 0/*port specified in addr*/,
|
||||
AF_INET6);
|
||||
bool sent_ipv6 = false;
|
||||
if (status == 0 && res != NULL)
|
||||
if (!stun_v6.isUnset())
|
||||
{
|
||||
if (res->ai_family == AF_INET6)
|
||||
{
|
||||
sendto(ipv6->getENetHost()->socket, s.getData(), s.size(), 0,
|
||||
res->ai_addr, sizeof(sockaddr_in6));
|
||||
sent_ipv6 = true;
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
sendto(ipv6->getENetHost()->socket, s.getData(), s.size(), 0,
|
||||
stun_v6.getSockaddr(), stun_v6.getSocklen());
|
||||
sent_ipv6 = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("NetworkConfig", "Invalid IPv6: %s",
|
||||
ipv6_it->first.c_str());
|
||||
}
|
||||
|
||||
bool has_ipv4 = false;
|
||||
@@ -291,39 +269,27 @@ void NetworkConfig::detectIPType()
|
||||
// All IPv4 only stun servers are *.supertuxkart.net which only
|
||||
// have A record, so the below code which forces to get an AF_INET6
|
||||
// will return their NAT64 addresses
|
||||
res = NULL;
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_INET6;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
status = getaddrinfo_compat(addrv4_and_port[0].c_str(),
|
||||
addrv4_and_port[1].c_str(), &hints, &res);
|
||||
if (status == 0 && res != NULL)
|
||||
SocketAddress nat64(ipv4_it->first, 0/*port specified in addr*/,
|
||||
AF_INET6);
|
||||
if (!nat64.isUnset() && nat64.getFamily() == AF_INET6)
|
||||
{
|
||||
if (res->ai_family == AF_INET6)
|
||||
{
|
||||
struct sockaddr_in6 nat64 = {};
|
||||
// Copy first 12 bytes
|
||||
struct sockaddr_in6* out =
|
||||
(struct sockaddr_in6*)res->ai_addr;
|
||||
memcpy(nat64.sin6_addr.s6_addr, out->sin6_addr.s6_addr,
|
||||
12);
|
||||
m_nat64_prefix_data[0] =
|
||||
((uint32_t)(nat64.sin6_addr.s6_addr[0]) << 8) | nat64.sin6_addr.s6_addr[1];
|
||||
m_nat64_prefix_data[1] =
|
||||
((uint32_t)(nat64.sin6_addr.s6_addr[2]) << 8) | nat64.sin6_addr.s6_addr[3];
|
||||
m_nat64_prefix_data[2] =
|
||||
((uint32_t)(nat64.sin6_addr.s6_addr[4]) << 8) | nat64.sin6_addr.s6_addr[5];
|
||||
m_nat64_prefix_data[3] =
|
||||
((uint32_t)(nat64.sin6_addr.s6_addr[6]) << 8) | nat64.sin6_addr.s6_addr[7];
|
||||
m_nat64_prefix_data[4] =
|
||||
((uint32_t)(nat64.sin6_addr.s6_addr[8]) << 8) | nat64.sin6_addr.s6_addr[9];
|
||||
m_nat64_prefix_data[5] =
|
||||
((uint32_t)(nat64.sin6_addr.s6_addr[10]) << 8) | nat64.sin6_addr.s6_addr[11];
|
||||
m_nat64_prefix_data[6] = 0;
|
||||
m_nat64_prefix_data[7] = 0;
|
||||
m_nat64_prefix = getIPV6ReadableFromIn6(&nat64);
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
// Remove last 4 bytes which is IPv4 format
|
||||
struct sockaddr_in6* in6 =
|
||||
(struct sockaddr_in6*)nat64.getSockaddr();
|
||||
uint8_t* byte = &(in6->sin6_addr.s6_addr[0]);
|
||||
byte[12] = 0;
|
||||
byte[13] = 0;
|
||||
byte[14] = 0;
|
||||
byte[15] = 0;
|
||||
m_nat64_prefix_data[0] = ((uint32_t)(byte[0]) << 8) | byte[1];
|
||||
m_nat64_prefix_data[1] = ((uint32_t)(byte[2]) << 8) | byte[3];
|
||||
m_nat64_prefix_data[2] = ((uint32_t)(byte[4]) << 8) | byte[5];
|
||||
m_nat64_prefix_data[3] = ((uint32_t)(byte[6]) << 8) | byte[7];
|
||||
m_nat64_prefix_data[4] = ((uint32_t)(byte[8]) << 8) | byte[9];
|
||||
m_nat64_prefix_data[5] = ((uint32_t)(byte[10]) << 8) | byte[11];
|
||||
m_nat64_prefix_data[6] = 0;
|
||||
m_nat64_prefix_data[7] = 0;
|
||||
m_nat64_prefix = getIPV6ReadableFromIn6(in6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,10 +506,15 @@ void SocketAddress::convertForIPv6Socket()
|
||||
std::string ipv4 = toString(false/*show_port*/);
|
||||
uint16_t port = getPort();
|
||||
auto ip_type = NetworkConfig::get()->getIPType();
|
||||
if (ip_type == NetworkConfig::IP_DUAL_STACK)
|
||||
ipv4 = std::string("::ffff:") + ipv4;
|
||||
else if (ip_type == NetworkConfig::IP_V6_NAT64)
|
||||
if (ip_type == NetworkConfig::IP_V6_NAT64)
|
||||
{
|
||||
ipv4 = NetworkConfig::get()->getNAT64Prefix() + ipv4;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume the system has dual stack if it uses an IPv6 socket
|
||||
ipv4 = std::string("::ffff:") + ipv4;
|
||||
}
|
||||
init(ipv4, port);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -58,11 +58,12 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** IPv4 Constructor (4 bytes). */
|
||||
SocketAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4,
|
||||
uint16_t port=0);
|
||||
uint16_t port = 0);
|
||||
// ------------------------------------------------------------------------
|
||||
SocketAddress(const std::string& str, uint16_t port_number = 0)
|
||||
SocketAddress(const std::string& str, uint16_t port_number = 0,
|
||||
short family = AF_UNSPEC)
|
||||
{
|
||||
init(str, port_number);
|
||||
init(str, port_number, family);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
bool operator==(const SocketAddress& other) const;
|
||||
@@ -122,6 +123,16 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
short getFamily() const { return m_family; }
|
||||
// ------------------------------------------------------------------------
|
||||
void setIPv6(const uint8_t* bytes, uint16_t port = 0)
|
||||
{
|
||||
m_family = AF_INET6;
|
||||
m_sockaddr.fill(0);
|
||||
sockaddr_in6* in6 = (sockaddr_in6*)m_sockaddr.data();
|
||||
in6->sin6_family = AF_INET6;
|
||||
memcpy(in6->sin6_addr.s6_addr, bytes, 16);
|
||||
setPort(port);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
bool isPublicAddressLocalhost() const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return true if this is an IPv6 address, if it's an IPv4 mapped IPv6
|
||||
|
||||
@@ -411,92 +411,37 @@ BareNetworkString STKHost::getStunRequest(uint8_t* stun_tansaction_id)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void STKHost::getIPFromStun(int socket, const std::string& stun_address,
|
||||
bool ipv4, std::string* ip_string, uint16_t* port)
|
||||
bool ipv4, SocketAddress* result)
|
||||
{
|
||||
std::vector<std::string> addr_and_port =
|
||||
StringUtils::split(stun_address, ':');
|
||||
if (addr_and_port.size() != 2)
|
||||
{
|
||||
Log::error("STKHost", "Wrong server address and port");
|
||||
return;
|
||||
}
|
||||
struct addrinfo hints;
|
||||
struct addrinfo* res = NULL;
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = ipv4 ? AF_INET : AF_INET6;
|
||||
|
||||
short family = ipv4 ? AF_INET : AF_INET6;
|
||||
// The IPv4 stun address has no AAAA record, so give it an AF_INET6 will
|
||||
// return one using NAT64 and DNS64
|
||||
if (isIPv6Socket() && ipv4 &&
|
||||
NetworkConfig::get()->getIPType() == NetworkConfig::IP_V6_NAT64)
|
||||
hints.ai_family = AF_INET6;
|
||||
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
// Resolve the stun server name so we can send it a STUN request
|
||||
int status = getaddrinfo_compat(addr_and_port[0].c_str(),
|
||||
addr_and_port[1].c_str(), &hints, &res);
|
||||
if (status != 0)
|
||||
{
|
||||
Log::error("STKHost", "Error in getaddrinfo for stun server"
|
||||
" %s: %s", addr_and_port[0].c_str(), gai_strerror(status));
|
||||
return;
|
||||
}
|
||||
family = AF_INET6;
|
||||
|
||||
SocketAddress stun(stun_address, 0/*port is specified in address*/,
|
||||
family);
|
||||
// We specify ai_family, so only IPv4 or IPv6 is found
|
||||
if (res == NULL)
|
||||
if (stun.isUnset())
|
||||
return;
|
||||
stun.convertForIPv6Socket();
|
||||
|
||||
struct sockaddr* stun_addr = NULL;
|
||||
if (isIPv6Socket())
|
||||
// We only need to keep the stun address for server to keep the port open
|
||||
if (NetworkConfig::get()->isServer())
|
||||
{
|
||||
if (res->ai_family == AF_INET)
|
||||
{
|
||||
struct sockaddr_in* ipv4_addr = (struct sockaddr_in*)(res->ai_addr);
|
||||
SocketAddress stun_v4;
|
||||
stun_v4.setIP(ntohl(ipv4_addr->sin_addr.s_addr));
|
||||
stun_v4.setPort(ntohs(ipv4_addr->sin_port));
|
||||
// Change address to ::ffff:IPv4 format for dual stack socket
|
||||
std::string ipv4_mapped = "::ffff:";
|
||||
ipv4_mapped += stun_v4.toString(false/*show_port*/);
|
||||
freeaddrinfo(res);
|
||||
res = NULL;
|
||||
hints.ai_family = AF_INET6;
|
||||
status = getaddrinfo_compat(ipv4_mapped.c_str(),
|
||||
addr_and_port[1].c_str(), &hints, &res);
|
||||
if (status != 0 || res == NULL)
|
||||
{
|
||||
Log::error("STKHost", "Error in getaddrinfo for stun server"
|
||||
" %s: %s", addr_and_port[0].c_str(), gai_strerror(status));
|
||||
return;
|
||||
}
|
||||
stun_addr = res->ai_addr;
|
||||
m_stun_ipv4.reset(new SocketAddress());
|
||||
m_stun_ipv4->setSockAddrIn(AF_INET6, stun_addr,
|
||||
sizeof(sockaddr_in6));
|
||||
}
|
||||
if (stun.isIPv6())
|
||||
m_stun_ipv6.reset(new SocketAddress(stun));
|
||||
else
|
||||
{
|
||||
stun_addr = res->ai_addr;
|
||||
m_stun_ipv6.reset(new SocketAddress());
|
||||
m_stun_ipv6->setSockAddrIn(AF_INET6, stun_addr,
|
||||
sizeof(sockaddr_in6));
|
||||
}
|
||||
}
|
||||
else if (ipv4)
|
||||
{
|
||||
stun_addr = res->ai_addr;
|
||||
m_stun_ipv4.reset(new SocketAddress());
|
||||
m_stun_ipv4->setSockAddrIn(AF_INET, stun_addr, sizeof(sockaddr_in));
|
||||
m_stun_ipv4.reset(new SocketAddress(stun));
|
||||
}
|
||||
|
||||
uint8_t stun_tansaction_id[16];
|
||||
constexpr uint32_t magic_cookie = 0x2112A442;
|
||||
BareNetworkString s = getStunRequest(stun_tansaction_id);
|
||||
|
||||
sendto(socket, s.getData(), s.size(), 0, stun_addr, isIPv6Socket() ?
|
||||
sizeof(sockaddr_in6) : sizeof(sockaddr_in));
|
||||
sendto(socket, s.getData(), s.size(), 0, stun.getSockaddr(),
|
||||
stun.getSocklen());
|
||||
|
||||
// Recieve now
|
||||
const int LEN = 2048;
|
||||
@@ -522,12 +467,9 @@ void STKHost::getIPFromStun(int socket, const std::string& stun_address,
|
||||
if (len <= 0)
|
||||
{
|
||||
Log::error("STKHost", "STUN response contains no data at all");
|
||||
freeaddrinfo(res);
|
||||
return;
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
|
||||
// Convert to network string.
|
||||
BareNetworkString response(buffer, len);
|
||||
if (response.size() < 20)
|
||||
@@ -564,8 +506,7 @@ void STKHost::getIPFromStun(int socket, const std::string& stun_address,
|
||||
|
||||
// The stun message is valid, so we parse it now:
|
||||
// Those are the port and the address to be detected
|
||||
SocketAddress addr, non_xor_addr, xor_addr;
|
||||
std::string ipv6_addr_non_xor, ipv6_addr_xor;
|
||||
SocketAddress non_xor_addr, xor_addr;
|
||||
while (true)
|
||||
{
|
||||
if (response.size() < 4)
|
||||
@@ -609,20 +550,20 @@ void STKHost::getIPFromStun(int socket, const std::string& stun_address,
|
||||
Log::error("STKHost", "Invalid STUN mapped address length.");
|
||||
return;
|
||||
}
|
||||
*port = response.getUInt16();
|
||||
uint16_t port = response.getUInt16();
|
||||
uint32_t ip = response.getUInt32();
|
||||
if (type == xor_mapped_address)
|
||||
{
|
||||
// Obfuscation is described in Section 15.2 of RFC 5389.
|
||||
*port ^= magic_cookie >> 16;
|
||||
port ^= magic_cookie >> 16;
|
||||
ip ^= magic_cookie;
|
||||
xor_addr.setIP(ip);
|
||||
xor_addr.setPort(*port);
|
||||
xor_addr.setPort(port);
|
||||
}
|
||||
else
|
||||
{
|
||||
non_xor_addr.setIP(ip);
|
||||
non_xor_addr.setPort(*port);
|
||||
non_xor_addr.setPort(port);
|
||||
}
|
||||
}
|
||||
else if (ip_type == ipv6_returned)
|
||||
@@ -633,23 +574,20 @@ void STKHost::getIPFromStun(int socket, const std::string& stun_address,
|
||||
Log::error("STKHost", "Invalid STUN mapped address length.");
|
||||
return;
|
||||
}
|
||||
*port = response.getUInt16();
|
||||
struct sockaddr_in6 ipv6_addr = {};
|
||||
uint16_t port = response.getUInt16();
|
||||
uint8_t bytes[16];
|
||||
for (int i = 0; i < 16; i++)
|
||||
bytes[i] = response.getUInt8();
|
||||
if (type == xor_mapped_address)
|
||||
{
|
||||
*port ^= magic_cookie >> 16;
|
||||
port ^= magic_cookie >> 16;
|
||||
for (int i = 0; i < 16; i++)
|
||||
bytes[i] ^= stun_tansaction_id[i];
|
||||
memcpy(&(ipv6_addr.sin6_addr), &bytes[0], 16);
|
||||
ipv6_addr_xor = getIPV6ReadableFromIn6(&ipv6_addr);
|
||||
xor_addr.setIPv6(bytes, port);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&(ipv6_addr.sin6_addr), &bytes[0], 16);
|
||||
ipv6_addr_non_xor = getIPV6ReadableFromIn6(&ipv6_addr);
|
||||
non_xor_addr.setIPv6(bytes, port);
|
||||
}
|
||||
}
|
||||
} // type == mapped_address || type == xor_mapped_address
|
||||
@@ -662,36 +600,21 @@ void STKHost::getIPFromStun(int socket, const std::string& stun_address,
|
||||
}
|
||||
} // while true
|
||||
// Found public address and port
|
||||
if (ipv4)
|
||||
if (!xor_addr.isUnset() || !non_xor_addr.isUnset())
|
||||
{
|
||||
if (!xor_addr.isUnset() || !non_xor_addr.isUnset())
|
||||
// Use XOR mapped address when possible to avoid translation of
|
||||
// the packet content by application layer gateways (ALGs) that
|
||||
// perform deep packet inspection in an attempt to perform
|
||||
// alternate NAT traversal methods.
|
||||
if (!xor_addr.isUnset())
|
||||
{
|
||||
// Use XOR mapped address when possible to avoid translation of
|
||||
// the packet content by application layer gateways (ALGs) that
|
||||
// perform deep packet inspection in an attempt to perform
|
||||
// alternate NAT traversal methods.
|
||||
if (!xor_addr.isUnset())
|
||||
{
|
||||
addr = xor_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::warn("STKHost", "Only non xor-mapped address returned.");
|
||||
addr = non_xor_addr;
|
||||
}
|
||||
*result = xor_addr;
|
||||
}
|
||||
*ip_string = addr.toString(false/*show_port*/);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ipv6_addr_xor.empty() && ipv6_addr_non_xor.empty())
|
||||
return;
|
||||
if (ipv6_addr_xor.empty())
|
||||
else
|
||||
{
|
||||
Log::warn("STKHost", "Only non xor-mapped address returned.");
|
||||
*ip_string = ipv6_addr_non_xor;
|
||||
*result = non_xor_addr;
|
||||
}
|
||||
*ip_string = ipv6_addr_xor;
|
||||
}
|
||||
} // getIPFromStun
|
||||
|
||||
@@ -726,16 +649,15 @@ void STKHost::setPublicAddress(bool ipv4)
|
||||
stun_map[server_name] = (uint32_t)-1;
|
||||
Log::debug("STKHost", "Using STUN server %s", server_name.c_str());
|
||||
uint64_t ping = StkTime::getMonoTimeMs();
|
||||
std::string ip_string;
|
||||
uint16_t port = 0;
|
||||
SocketAddress result;
|
||||
getIPFromStun((int)m_network->getENetHost()->socket, server_name, ipv4,
|
||||
&ip_string, &port);
|
||||
if (!ip_string.empty())
|
||||
&result);
|
||||
if (!result.isUnset())
|
||||
{
|
||||
// For dual stack server we get the IPv6 address and then IPv4, if
|
||||
// their ports differ we discard the public IPv6 address of server
|
||||
if (NetworkConfig::get()->isServer() && ipv4 &&
|
||||
port != m_public_address->getPort())
|
||||
result.getPort() != m_public_address->getPort())
|
||||
{
|
||||
if (isIPv6Socket())
|
||||
{
|
||||
@@ -745,10 +667,10 @@ void STKHost::setPublicAddress(bool ipv4)
|
||||
m_public_ipv6_address.clear();
|
||||
}
|
||||
if (ipv4)
|
||||
m_public_address->init(ip_string);
|
||||
*m_public_address = result;
|
||||
else
|
||||
m_public_ipv6_address = ip_string;
|
||||
m_public_address->setPort(port);
|
||||
m_public_ipv6_address = result.toString(false/*show_port*/);
|
||||
m_public_address->setPort(result.getPort());
|
||||
ping = StkTime::getMonoTimeMs() - ping;
|
||||
// Succeed, save ping
|
||||
stun_map[server_name] = (uint32_t)(ping);
|
||||
|
||||
@@ -176,7 +176,7 @@ private:
|
||||
void mainLoop();
|
||||
// ------------------------------------------------------------------------
|
||||
void getIPFromStun(int socket, const std::string& stun_address, bool ipv4,
|
||||
std::string* ip_string, uint16_t* port);
|
||||
SocketAddress* result);
|
||||
public:
|
||||
/** If a network console should be started. */
|
||||
static bool m_enable_console;
|
||||
|
||||
Reference in New Issue
Block a user