1
0
forked from 0ad/0ad

Try to punch a hole through local firewalls, and fallback to localhost.

Fixes (probably rare) regression in 2034136560.

Differential Revision: https://code.wildfiregames.com/D3999
This was SVN commit r25515.
This commit is contained in:
wraitii 2021-05-22 08:34:00 +00:00
parent 0dfebc8d2b
commit d7a4fb7c20
3 changed files with 48 additions and 18 deletions

View File

@ -862,7 +862,7 @@ bool XmppClient::handleIq(const glooxwrapper::IQ& iq)
}
g_NetClient->SetupServerData(cd->m_Ip.to_string(), stoi(cd->m_Port.to_string()), !cd->m_UseSTUN.empty());
g_NetClient->TryToConnect(iq.from().full());
g_NetClient->TryToConnect(iq.from().full(), !cd->m_IsLocalIP.empty());
}
if (gq)
{
@ -995,6 +995,7 @@ bool XmppClient::handleIq(const glooxwrapper::IQ& iq)
connectionData->m_Ip = g_NetServer->GetPublicIp();
connectionData->m_Port = std::to_string(g_NetServer->GetPublicPort());
connectionData->m_UseSTUN = g_NetServer->GetUseSTUN() ? "true" : "";
connectionData->m_IsLocalIP = "";
}
else
{
@ -1004,6 +1005,7 @@ bool XmppClient::handleIq(const glooxwrapper::IQ& iq)
connectionData->m_Ip = ip;
connectionData->m_Port = std::to_string(g_NetServer->GetLocalPort());
connectionData->m_UseSTUN = "";
connectionData->m_IsLocalIP = "true";
}
else
connectionData->m_Error = "local_ip_failed";

View File

@ -231,7 +231,7 @@ void CNetClient::HandleGetServerDataFailed(const CStr& error)
);
}
bool CNetClient::TryToConnect(const CStr& hostJID)
bool CNetClient::TryToConnect(const CStr& hostJID, bool localNetwork)
{
if (m_Session)
return false;
@ -245,11 +245,8 @@ bool CNetClient::TryToConnect(const CStr& hostJID)
return false;
}
ENetHost* enetClient = nullptr;
if (g_XmppClient && m_UseSTUN)
{
ENetAddress hostAddr{ ENET_HOST_ANY, ENET_PORT_ANY };
enetClient = enet_host_create(&hostAddr, 1, 1, 0, 0);
ENetHost* enetClient = enet_host_create(&hostAddr, 1, 1, 0, 0);
if (!enetClient)
{
@ -262,6 +259,8 @@ bool CNetClient::TryToConnect(const CStr& hostJID)
CStr ip;
u16 port;
if (g_XmppClient && m_UseSTUN)
{
if (!StunClient::FindPublicIP(*enetClient, ip, port))
{
PushGuiMessage(
@ -280,11 +279,39 @@ bool CNetClient::TryToConnect(const CStr& hostJID)
// Return true anyways - we're on a success path here.
return true;
}
}
else if (g_XmppClient && localNetwork)
{
// We may need to punch a hole through the local firewall, so fetch our local IP.
// NB: we'll ignore failures here, and hope that the firewall will be open to connection
// if we fail to fetch the local IP (which is unlikely anyways).
if (!StunClient::FindLocalIP(ip))
ip = "";
// Check if we're hosting on localhost, and if so, explicitly use that
// (this circumvents, at least, the 'block all incoming connections' setting
// on the MacOS firewall).
if (ip == m_ServerAddress)
{
m_ServerAddress = "127.0.0.1";
ip = "";
}
port = enetClient->address.port;
}
LOGMESSAGE("NetClient: connecting to server at %s:%i", m_ServerAddress, m_ServerPort);
if (!ip.empty())
{
// UDP hole-punching
// Step 0: send a message, via XMPP, to the server with our external IP & port.
g_XmppClient->SendStunEndpointToHost(ip, port, hostJID);
// Step 1b: Wait some time - we need the host to receive the stun endpoint and start punching a hole themselves before
// we try to establish the connection below.
SDL_Delay(1000);
// Step 2: Send a message ourselves to the server so that the NAT, if any, routes incoming trafic correctly.
// TODO: verify if this step is necessary, since we'll try and connect anyways below.
StunClient::SendHolePunchingMessages(*enetClient, m_ServerAddress, m_ServerPort);
}

View File

@ -134,9 +134,10 @@ public:
/**
* Connect to the remote networked server using lobby.
* Push netstatus messages on failure.
* @param localNetwork - if true, assume we are trying to connect on the local network.
* @return true on success, false on connection failure
*/
bool TryToConnect(const CStr& hostJID);
bool TryToConnect(const CStr& hostJID, bool localNetwork);
/**
* Destroy the connection to the server.