From 4f2f3f4bbac6d0c705b32b89ebf45ed0715d4913 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Wed, 21 Sep 2022 21:34:33 +0200 Subject: [PATCH 1/2] Only start registering once the server is fully started This works around, i.e. fixes #5858 for curl versions < 7.77.0, as long as the servers are only registered via IPv4 **OR** IPv6. The bug that's being worked around is this: https://github.com/curl/curl/commit/84d2839740ca78041ac7419d9aaeac55c1e1c729. The bug makes curl reuse IPv6 connections when it is being requested to connect via IPv4, making the registering fail. This commit works around that by letting the server only register after having completely read the config, so any `sv_register ipv4` should already be in effect. --- src/engine/server/register.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/engine/server/register.cpp b/src/engine/server/register.cpp index d61449271..1d6eef4af 100644 --- a/src/engine/server/register.cpp +++ b/src/engine/server/register.cpp @@ -118,6 +118,9 @@ class CRegister : public IRegister CConfig *m_pConfig; IConsole *m_pConsole; IEngine *m_pEngine; + // Don't start sending registers before the server has initialized + // completely. + bool m_GotFirstUpdateCall = false; int m_ServerPort; char m_aConnlessTokenHex[16]; @@ -505,6 +508,7 @@ CRegister::CRegister(CConfig *pConfig, IConsole *pConsole, IEngine *pEngine, int void CRegister::Update() { + m_GotFirstUpdateCall = true; if(!m_GotServerInfo) { return; @@ -605,6 +609,11 @@ void CRegister::OnConfigChange() str_copy(m_aaExtraHeaders[m_NumExtraHeaders], aHeader); m_NumExtraHeaders += 1; } + // Don't start registering before the first `CRegister::Update` call. + if(!m_GotFirstUpdateCall) + { + return; + } for(int i = 0; i < NUM_PROTOCOLS; i++) { if(aOldProtocolEnabled[i] == m_aProtocolEnabled[i]) @@ -670,6 +679,12 @@ void CRegister::OnNewInfo(const char *pInfo) m_pGlobal->m_InfoSerial += 1; } + // Don't start registering before the first `CRegister::Update` call. + if(!m_GotFirstUpdateCall) + { + return; + } + // Immediately send new info if it changes, but at most once per second. int64_t Now = time_get(); int64_t Freq = time_freq(); From 884cf75cb8daff441c8b732498e7c77b54bc1724 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Thu, 22 Sep 2022 00:09:02 +0200 Subject: [PATCH 2/2] Stop server if started with old curl and incompatible `sv_register` This prevents accidentally falling victim to the bug #5858. --- src/engine/server/register.cpp | 11 ++++++++++- src/engine/shared/http.cpp | 7 +++++++ src/engine/shared/http.h | 1 + 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/engine/server/register.cpp b/src/engine/server/register.cpp index 1d6eef4af..298ee6248 100644 --- a/src/engine/server/register.cpp +++ b/src/engine/server/register.cpp @@ -508,7 +508,16 @@ CRegister::CRegister(CConfig *pConfig, IConsole *pConsole, IEngine *pEngine, int void CRegister::Update() { - m_GotFirstUpdateCall = true; + if(!m_GotFirstUpdateCall) + { + bool Ipv6 = m_aProtocolEnabled[PROTOCOL_TW6_IPV6] || m_aProtocolEnabled[PROTOCOL_TW7_IPV6]; + bool Ipv4 = m_aProtocolEnabled[PROTOCOL_TW6_IPV4] || m_aProtocolEnabled[PROTOCOL_TW7_IPV4]; + if(Ipv6 && Ipv4) + { + dbg_assert(!HttpHasIpresolveBug(), "curl version < 7.77.0 does not support registering via both IPv4 and IPv6, set `sv_register ipv6` or `sv_register ipv4`"); + } + m_GotFirstUpdateCall = true; + } if(!m_GotServerInfo) { return; diff --git a/src/engine/shared/http.cpp b/src/engine/shared/http.cpp index b3d93f3c2..ede4a2f35 100644 --- a/src/engine/shared/http.cpp +++ b/src/engine/shared/http.cpp @@ -116,6 +116,13 @@ void EscapeUrl(char *pBuf, int Size, const char *pStr) curl_free(pEsc); } +bool HttpHasIpresolveBug() +{ + // curl < 7.77.0 doesn't use CURLOPT_IPRESOLVE correctly wrt. + // connection caches. + return curl_version_info(CURLVERSION_NOW)->version_num < 0x074d00; +} + CHttpRequest::CHttpRequest(const char *pUrl) { str_copy(m_aUrl, pUrl); diff --git a/src/engine/shared/http.h b/src/engine/shared/http.h index f6a90c9ab..dc9cbe25e 100644 --- a/src/engine/shared/http.h +++ b/src/engine/shared/http.h @@ -194,4 +194,5 @@ inline std::unique_ptr HttpPostJson(const char *pUrl, const char * bool HttpInit(IStorage *pStorage); void EscapeUrl(char *pBuf, int Size, const char *pStr); +bool HttpHasIpresolveBug(); #endif // ENGINE_SHARED_HTTP_H