5859: Only start registering once the server is fully started r=def- a=heinrich5991

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:
84d2839740.

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.

Also stop server if started with old curl and incompatible `sv_register`.

## Checklist

- [ ] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: heinrich5991 <heinrich5991@gmail.com>
This commit is contained in:
bors[bot] 2022-09-21 22:22:56 +00:00 committed by GitHub
commit f7c7852927
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 32 additions and 0 deletions

View file

@ -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,16 @@ CRegister::CRegister(CConfig *pConfig, IConsole *pConsole, IEngine *pEngine, int
void CRegister::Update()
{
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;
@ -605,6 +618,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 +688,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();

View file

@ -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);

View file

@ -194,4 +194,5 @@ inline std::unique_ptr<CHttpRequest> 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