forked from Mirrors/openclonk
Implement Happy Eyeballs for C4Network2HTTPClient
This should make masterserver requests more reliable for users with a bad IPv6 connection. See RFC6555ipv6
parent
f9c97e91f0
commit
d7659713dc
|
@ -407,7 +407,7 @@ bool C4Network2HTTPClient::Decompress(StdBuf *pData)
|
|||
bool C4Network2HTTPClient::OnConn(const C4NetIO::addr_t &AddrPeer, const C4NetIO::addr_t &AddrConnect, const C4NetIO::addr_t *pOwnAddr, C4NetIO *pNetIO)
|
||||
{
|
||||
// Make sure we're actually waiting for this connection
|
||||
if (AddrConnect != ServerAddr)
|
||||
if (fConnected || (AddrConnect != ServerAddr && AddrConnect != ServerAddrFallback))
|
||||
return false;
|
||||
// Save pack peer address
|
||||
PeerAddr = AddrPeer;
|
||||
|
@ -445,10 +445,19 @@ void C4Network2HTTPClient::OnPacket(const class C4NetIOPacket &rPacket, C4NetIO
|
|||
bool C4Network2HTTPClient::Execute(int iMaxTime)
|
||||
{
|
||||
// Check timeout
|
||||
if (fBusy && time(nullptr) > iRequestTimeout)
|
||||
if (fBusy)
|
||||
{
|
||||
Cancel("Request timeout");
|
||||
return true;
|
||||
if (C4TimeMilliseconds::Now() > HappyEyeballsTimeout)
|
||||
{
|
||||
HappyEyeballsTimeout = C4TimeMilliseconds::PositiveInfinity;
|
||||
Application.InteractiveThread.ThreadLogS("HTTP: Starting fallback connection to %s (%s)", Server.getData(), ServerAddrFallback.ToString().getData());
|
||||
Connect(ServerAddrFallback);
|
||||
}
|
||||
if (time(nullptr) > iRequestTimeout)
|
||||
{
|
||||
Cancel("Request timeout");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Execute normally
|
||||
return C4NetIOTCP::Execute(iMaxTime);
|
||||
|
@ -462,7 +471,9 @@ C4TimeMilliseconds C4Network2HTTPClient::GetNextTick(C4TimeMilliseconds tNow)
|
|||
|
||||
C4TimeMilliseconds tHTTPClientTick = tNow + 1000 * std::max<time_t>(iRequestTimeout - time(nullptr), 0);
|
||||
|
||||
return std::max(tNetIOTCPTick, tHTTPClientTick);
|
||||
C4TimeMilliseconds HappyEyeballsTick = tNow + std::max(HappyEyeballsTimeout - C4TimeMilliseconds::Now(), 0);
|
||||
|
||||
return std::min({tNetIOTCPTick, tHTTPClientTick, HappyEyeballsTick});
|
||||
}
|
||||
|
||||
bool C4Network2HTTPClient::Query(const StdBuf &Data, bool fBinary)
|
||||
|
@ -512,6 +523,11 @@ bool C4Network2HTTPClient::Query(const StdBuf &Data, bool fBinary)
|
|||
// Start connecting
|
||||
if (!Connect(ServerAddr))
|
||||
return false;
|
||||
// Also try the fallback address after some time (if there is one)
|
||||
if (!ServerAddrFallback.IsNull())
|
||||
HappyEyeballsTimeout = C4TimeMilliseconds::Now() + C4Network2HTTPHappyEyeballsTimeout;
|
||||
else
|
||||
HappyEyeballsTimeout = C4TimeMilliseconds::PositiveInfinity;
|
||||
// Okay, request will be performed when connection is complete
|
||||
fBusy = true;
|
||||
iDataOffset = 0;
|
||||
|
@ -529,7 +545,7 @@ void C4Network2HTTPClient::ResetRequestTimeout()
|
|||
void C4Network2HTTPClient::Cancel(const char *szReason)
|
||||
{
|
||||
// Close connection - and connection attempt
|
||||
Close(ServerAddr); Close(PeerAddr);
|
||||
Close(ServerAddr); Close(ServerAddrFallback); Close(PeerAddr);
|
||||
// Reset flags
|
||||
fBusy = fSuccess = fConnected = fBinary = false;
|
||||
iDownloadedSize = iTotalSize = iDataOffset = 0;
|
||||
|
@ -567,6 +583,14 @@ bool C4Network2HTTPClient::SetServer(const char *szServerAddress)
|
|||
return false;
|
||||
}
|
||||
ServerAddr.SetDefaultPort(GetDefaultPort());
|
||||
if (ServerAddr.GetFamily() == C4NetIO::HostAddress::IPv6)
|
||||
{
|
||||
// Try to find a fallback IPv4 address for Happy Eyeballs.
|
||||
ServerAddrFallback.SetAddress(Server, C4NetIO::HostAddress::IPv4);
|
||||
ServerAddrFallback.SetDefaultPort(GetDefaultPort());
|
||||
}
|
||||
else
|
||||
ServerAddrFallback.Clear();
|
||||
// Remove port
|
||||
const char *firstColon = strchr(Server.getData(), ':');
|
||||
const char *lastColon = strrchr(Server.getData(), ':');
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "lib/C4InputValidation.h"
|
||||
|
||||
const int C4Network2HTTPQueryTimeout = 10; // (s)
|
||||
const uint32_t C4Network2HTTPHappyEyeballsTimeout = 300; // (ms)
|
||||
|
||||
// Session data
|
||||
class C4Network2Reference
|
||||
|
@ -129,7 +130,7 @@ public:
|
|||
private:
|
||||
|
||||
// Address information
|
||||
C4NetIO::addr_t ServerAddr, PeerAddr;
|
||||
C4NetIO::addr_t ServerAddr, ServerAddrFallback, PeerAddr;
|
||||
StdCopyStrBuf Server, RequestPath;
|
||||
|
||||
bool fBinary;
|
||||
|
@ -137,6 +138,7 @@ private:
|
|||
size_t iDataOffset;
|
||||
StdCopyBuf Request;
|
||||
time_t iRequestTimeout;
|
||||
C4TimeMilliseconds HappyEyeballsTimeout;
|
||||
|
||||
// Response header data
|
||||
size_t iDownloadedSize, iTotalSize;
|
||||
|
|
Loading…
Reference in New Issue