Skip to content

Commit c541d80

Browse files
committed
Refactor server's client address functions, handle debug dummies
Generate unique local addresses (IPv6 addresses) for debug dummies so address-based functions work with debug dummies. Every debug dummy's ULA has a randomly generated global ID such that debug dummy addresses are most likely unique. The ULA's subnet ID is set to a constant value. The ULA's interface ID is set to the dummy's client ID. See https://en.wikipedia.org/wiki/Unique_local_address for details about the format. The port is generated randomly in the same way that normal clients select their port. Change the `const char (*::CNetServer::ClientAddrString(int ClientID) const)[NETADDR_MAXSTRSIZE]` function signature to `const std::array<char, NETADDR_MAXSTRSIZE> &ClientAddrString(int ClientId, bool IncludePort) const` and change the `const char (*CNetConnection::PeerAddressString() const)[NETADDR_MAXSTRSIZE]` function signature to `const std::array<char, NETADDR_MAXSTRSIZE> &PeerAddressString(bool IncludePort) const` to optionally include the port and because a reference to an `std::array` is more readable then a pointer/reference to a C-array. The address string is now cached separately with and without port by `CNetConnection`. Add the `CNetConnection::SetPeerAddr` and `CNetConnection::ClearPeerAddr` functions to avoid duplicate code. Fix the peer address string not being initialized for 0.7 connections, though this is currently unused from the client-side so it had no effect. Change the `void IServer::GetClientAddr(int ClientId, NETADDR *pAddr) const` function signature to `const NETADDR *ClientAddr(int ClientId) const`. This simplifies the usage as most address-based functions take pointers to `NETADDR` as arguments. Use this function consistently instead of the `CNetServer::ClientAddr` function, as the `IServer::ClientAddr` function has assertions and returns the generated ULA for debug dummies. Change the `void IServer::GetClientAddr(int ClientId, char *pAddrStr, int Size) const` function signature to `const std::array<char, NETADDR_MAXSTRSIZE> &ClientAddrStringImpl(int ClientId, bool IncludePort) const` and add the `inline const char *ClientAddrString(int ClientId, bool IncludePort) const` wrapper function. This also simplifies the usage in most cases while retaining the static size information for the address strings. These functions can return the string with and without port, whereas before the string was always returned without port. Use this function consistently instead of the `CNetServer::ClientAddrString` function and instead of the `net_addr_str` function together with the `IServer::GetClientAddr` function, as the `IServer::ClientAddrString` function has assertions and returns the generated ULA strings for debug dummies. This should also slightly improves performance as the cached address strings are thereby used in all cases. Note that the `CNetServer::ClientAddrString` function previously returned the address string with port, whereas the `IServer::GetClientAddr` function returned the address string without port. Compare `NETADDR`s directly without ports instead of converting to strings without ports when counting votes. Closes ddnet#9554.
1 parent 00bb74c commit c541d80

File tree

8 files changed

+176
-144
lines changed

8 files changed

+176
-144
lines changed

src/engine/server.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#ifndef ENGINE_SERVER_H
44
#define ENGINE_SERVER_H
55

6+
#include <array>
67
#include <optional>
78
#include <type_traits>
89

@@ -60,7 +61,9 @@ class IServer : public IInterface
6061
virtual bool ClientIngame(int ClientId) const = 0;
6162
virtual bool GetClientInfo(int ClientId, CClientInfo *pInfo) const = 0;
6263
virtual void SetClientDDNetVersion(int ClientId, int DDNetVersion) = 0;
63-
virtual void GetClientAddr(int ClientId, char *pAddrStr, int Size) const = 0;
64+
virtual const NETADDR *ClientAddr(int ClientId) const = 0;
65+
virtual const std::array<char, NETADDR_MAXSTRSIZE> &ClientAddrStringImpl(int ClientId, bool IncludePort) const = 0;
66+
inline const char *ClientAddrString(int ClientId, bool IncludePort) const { return ClientAddrStringImpl(ClientId, IncludePort).data(); }
6467

6568
/**
6669
* Returns the version of the client with the given client ID.
@@ -265,8 +268,6 @@ class IServer : public IInterface
265268
virtual bool IsRecording(int ClientId) = 0;
266269
virtual void StopDemos() = 0;
267270

268-
virtual void GetClientAddr(int ClientId, NETADDR *pAddr) const = 0;
269-
270271
virtual int *GetIdMap(int ClientId) = 0;
271272

272273
virtual bool DnsblWhite(int ClientId) = 0;

src/engine/server/server.cpp

Lines changed: 96 additions & 71 deletions
Large diffs are not rendered by default.

src/engine/server/server.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ class CServer : public IServer
162162
int m_Flags;
163163
bool m_ShowIps;
164164
bool m_DebugDummy;
165+
NETADDR m_DebugDummyAddr;
166+
std::array<char, NETADDR_MAXSTRSIZE> m_aDebugDummyAddrString;
167+
std::array<char, NETADDR_MAXSTRSIZE> m_aDebugDummyAddrStringNoPort;
165168

166169
const IConsole::CCommandInfo *m_pRconCmdToSend;
167170

@@ -300,7 +303,8 @@ class CServer : public IServer
300303
void GetMapInfo(char *pMapName, int MapNameSize, int *pMapSize, SHA256_DIGEST *pMapSha256, int *pMapCrc) override;
301304
bool GetClientInfo(int ClientId, CClientInfo *pInfo) const override;
302305
void SetClientDDNetVersion(int ClientId, int DDNetVersion) override;
303-
void GetClientAddr(int ClientId, char *pAddrStr, int Size) const override;
306+
const NETADDR *ClientAddr(int ClientId) const override;
307+
const std::array<char, NETADDR_MAXSTRSIZE> &ClientAddrStringImpl(int ClientId, bool IncludePort) const override;
304308
const char *ClientName(int ClientId) const override;
305309
const char *ClientClan(int ClientId) const override;
306310
int ClientCountry(int ClientId) const override;
@@ -445,7 +449,6 @@ class CServer : public IServer
445449

446450
// DDRace
447451

448-
void GetClientAddr(int ClientId, NETADDR *pAddr) const override;
449452
int m_aPrevStates[MAX_CLIENTS];
450453
const char *GetAnnouncementLine() override;
451454
void ReadAnnouncementsFile();

src/engine/shared/network.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <base/math.h>
1010
#include <base/system.h>
1111

12+
#include <array>
13+
1214
class CHuffman;
1315
class CNetBan;
1416
class CPacker;
@@ -265,13 +267,16 @@ class CNetConnection
265267
NETSOCKET m_Socket;
266268
NETSTATS m_Stats;
267269

268-
char m_aPeerAddrStr[NETADDR_MAXSTRSIZE];
270+
std::array<char, NETADDR_MAXSTRSIZE> m_aPeerAddrStr;
271+
std::array<char, NETADDR_MAXSTRSIZE> m_aPeerAddrStrNoPort;
269272
// client 0.7
270273
static TOKEN GenerateToken7(const NETADDR *pPeerAddr);
271274
class CNetBase *m_pNetBase;
272275
bool IsSixup() { return m_Sixup; }
273276

274277
//
278+
void SetPeerAddr(const NETADDR *pAddr);
279+
void ClearPeerAddr();
275280
void ResetStats();
276281
void SetError(const char *pString);
277282
void AckChunks(int Ack);
@@ -305,7 +310,10 @@ class CNetConnection
305310
void SignalResend();
306311
int State() const { return m_State; }
307312
const NETADDR *PeerAddress() const { return &m_PeerAddr; }
308-
const char (*PeerAddressString() const)[NETADDR_MAXSTRSIZE] { return &m_aPeerAddrStr; }
313+
const std::array<char, NETADDR_MAXSTRSIZE> &PeerAddressString(bool IncludePort) const
314+
{
315+
return IncludePort ? m_aPeerAddrStr : m_aPeerAddrStrNoPort;
316+
}
309317
void ConnectAddresses(const NETADDR **ppAddrs, int *pNumAddrs) const
310318
{
311319
*ppAddrs = m_aConnectAddrs;
@@ -455,7 +463,7 @@ class CNetServer
455463

456464
// status requests
457465
const NETADDR *ClientAddr(int ClientId) const { return m_aSlots[ClientId].m_Connection.PeerAddress(); }
458-
const char (*ClientAddrString(int ClientID) const)[NETADDR_MAXSTRSIZE] { return m_aSlots[ClientID].m_Connection.PeerAddressString(); }
466+
const std::array<char, NETADDR_MAXSTRSIZE> &ClientAddrString(int ClientId, bool IncludePort) const { return m_aSlots[ClientId].m_Connection.PeerAddressString(IncludePort); }
459467
bool HasSecurityToken(int ClientId) const { return m_aSlots[ClientId].m_Connection.SecurityToken() != NET_SECURITY_TOKEN_UNSUPPORTED; }
460468
NETADDR Address() const { return m_Address; }
461469
NETSOCKET Socket() const { return m_Socket; }

src/engine/shared/network_conn.cpp

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,24 @@
44
#include "network.h"
55
#include <base/system.h>
66

7-
void CNetConnection::ResetStats()
7+
void CNetConnection::SetPeerAddr(const NETADDR *pAddr)
8+
{
9+
m_PeerAddr = *pAddr;
10+
net_addr_str(pAddr, m_aPeerAddrStr.data(), m_aPeerAddrStr.size(), true);
11+
net_addr_str(pAddr, m_aPeerAddrStrNoPort.data(), m_aPeerAddrStrNoPort.size(), false);
12+
}
13+
14+
void CNetConnection::ClearPeerAddr()
815
{
9-
mem_zero(&m_Stats, sizeof(m_Stats));
1016
mem_zero(&m_PeerAddr, sizeof(m_PeerAddr));
1117
m_aPeerAddrStr[0] = '\0';
18+
m_aPeerAddrStrNoPort[0] = '\0';
19+
}
20+
21+
void CNetConnection::ResetStats()
22+
{
23+
mem_zero(&m_Stats, sizeof(m_Stats));
24+
ClearPeerAddr();
1225
m_LastUpdateTime = 0;
1326
}
1427

@@ -32,11 +45,9 @@ void CNetConnection::Reset(bool Rejoin)
3245

3346
m_LastSendTime = 0;
3447
m_LastRecvTime = 0;
35-
//m_LastUpdateTime = 0;
3648

3749
mem_zero(&m_aConnectAddrs, sizeof(m_aConnectAddrs));
3850
m_NumConnectAddrs = 0;
39-
//mem_zero(&m_PeerAddr, sizeof(m_PeerAddr));
4051
m_UnknownSeq = false;
4152

4253
m_Buffer.Init();
@@ -196,8 +207,7 @@ int CNetConnection::Connect(const NETADDR *pAddr, int NumAddrs)
196207

197208
// init connection
198209
Reset();
199-
mem_zero(&m_PeerAddr, sizeof(m_PeerAddr));
200-
m_aPeerAddrStr[0] = '\0';
210+
ClearPeerAddr();
201211

202212
for(int i = 0; i < NumAddrs; i++)
203213
{
@@ -224,14 +234,13 @@ int CNetConnection::Connect7(const NETADDR *pAddr, int NumAddrs)
224234

225235
// init connection
226236
Reset();
227-
mem_zero(&m_PeerAddr, sizeof(m_PeerAddr));
228237
for(int i = 0; i < NumAddrs; i++)
229238
{
230239
m_aConnectAddrs[i] = pAddr[i];
231240
}
232241
m_LastRecvTime = time_get();
233242
m_NumConnectAddrs = NumAddrs;
234-
m_PeerAddr = *pAddr;
243+
SetPeerAddr(pAddr);
235244
SetToken7(GenerateToken7(pAddr));
236245
mem_zero(m_aErrorString, sizeof(m_aErrorString));
237246
m_State = NET_CONNSTATE_TOKEN;
@@ -287,8 +296,7 @@ void CNetConnection::DirectInit(const NETADDR &Addr, SECURITY_TOKEN SecurityToke
287296

288297
m_State = NET_CONNSTATE_ONLINE;
289298

290-
m_PeerAddr = Addr;
291-
net_addr_str(&Addr, m_aPeerAddrStr, sizeof(m_aPeerAddrStr), true);
299+
SetPeerAddr(&Addr);
292300
mem_zero(m_aErrorString, sizeof(m_aErrorString));
293301

294302
int64_t Now = time_get();
@@ -420,8 +428,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr, SECURITY_
420428
// send response and init connection
421429
Reset();
422430
m_State = NET_CONNSTATE_PENDING;
423-
m_PeerAddr = *pAddr;
424-
net_addr_str(pAddr, m_aPeerAddrStr, sizeof(m_aPeerAddrStr), true);
431+
SetPeerAddr(pAddr);
425432
mem_zero(m_aErrorString, sizeof(m_aErrorString));
426433
m_LastSendTime = Now;
427434
m_LastRecvTime = Now;
@@ -448,8 +455,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr, SECURITY_
448455
// connection made
449456
if(CtrlMsg == NET_CTRLMSG_CONNECTACCEPT)
450457
{
451-
m_PeerAddr = *pAddr;
452-
net_addr_str(pAddr, m_aPeerAddrStr, sizeof(m_aPeerAddrStr), true);
458+
SetPeerAddr(pAddr);
453459
if(m_SecurityToken == NET_SECURITY_TOKEN_UNKNOWN && pPacket->m_DataSize >= (int)(1 + sizeof(SECURITY_TOKEN_MAGIC) + sizeof(m_SecurityToken)) && !mem_comp(&pPacket->m_aChunkData[1], SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC)))
454460
{
455461
m_SecurityToken = ToSecurityToken(&pPacket->m_aChunkData[1 + sizeof(SECURITY_TOKEN_MAGIC)]);
@@ -576,8 +582,7 @@ void CNetConnection::SetTimedOut(const NETADDR *pAddr, int Sequence, int Ack, SE
576582
m_RemoteClosed = 0;
577583

578584
m_State = NET_CONNSTATE_ONLINE;
579-
m_PeerAddr = *pAddr;
580-
net_addr_str(pAddr, m_aPeerAddrStr, sizeof(m_aPeerAddrStr), true);
585+
SetPeerAddr(pAddr);
581586
mem_zero(m_aErrorString, sizeof(m_aErrorString));
582587
m_LastSendTime = Now;
583588
m_LastRecvTime = Now;

src/engine/shared/network_server.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,7 @@ int CNetServer::TryAcceptClient(NETADDR &Addr, SECURITY_TOKEN SecurityToken, boo
254254

255255
if(g_Config.m_Debug)
256256
{
257-
char aAddrStr[NETADDR_MAXSTRSIZE];
258-
net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr), true);
259-
dbg_msg("security", "client accepted %s", aAddrStr);
257+
dbg_msg("security", "client accepted %s", m_aSlots[Slot].m_Connection.PeerAddressString(true).data());
260258
}
261259

262260
if(VanillaAuth)

src/game/server/ddracecommands.cpp

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -610,12 +610,11 @@ void CGameContext::ConVoteMute(IConsole::IResult *pResult, void *pUserData)
610610
return;
611611
}
612612

613-
NETADDR Addr;
614-
pSelf->Server()->GetClientAddr(Victim, &Addr);
613+
const NETADDR *pAddr = pSelf->Server()->ClientAddr(Victim);
615614

616615
int Seconds = clamp(pResult->GetInteger(1), 1, 86400);
617616
const char *pReason = pResult->NumArguments() > 2 ? pResult->GetString(2) : "";
618-
pSelf->VoteMute(&Addr, Seconds, pReason, pSelf->Server()->ClientName(Victim), pResult->m_ClientId);
617+
pSelf->VoteMute(pAddr, Seconds, pReason, pSelf->Server()->ClientName(Victim), pResult->m_ClientId);
619618
}
620619

621620
void CGameContext::ConVoteUnmute(IConsole::IResult *pResult, void *pUserData)
@@ -629,10 +628,9 @@ void CGameContext::ConVoteUnmute(IConsole::IResult *pResult, void *pUserData)
629628
return;
630629
}
631630

632-
NETADDR Addr;
633-
pSelf->Server()->GetClientAddr(Victim, &Addr);
631+
const NETADDR *pAddr = pSelf->Server()->ClientAddr(Victim);
634632

635-
bool Found = pSelf->VoteUnmute(&Addr, pSelf->Server()->ClientName(Victim), pResult->m_ClientId);
633+
bool Found = pSelf->VoteUnmute(pAddr, pSelf->Server()->ClientName(Victim), pResult->m_ClientId);
636634
if(Found)
637635
{
638636
char aBuf[128];
@@ -655,7 +653,7 @@ void CGameContext::ConVoteMutes(IConsole::IResult *pResult, void *pUserData)
655653
return;
656654
}
657655

658-
char aIpBuf[64];
656+
char aIpBuf[NETADDR_MAXSTRSIZE];
659657
char aBuf[128];
660658
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "votemutes",
661659
"Active vote mutes:");
@@ -689,12 +687,11 @@ void CGameContext::ConMuteId(IConsole::IResult *pResult, void *pUserData)
689687
return;
690688
}
691689

692-
NETADDR Addr;
693-
pSelf->Server()->GetClientAddr(Victim, &Addr);
690+
const NETADDR *pAddr = pSelf->Server()->ClientAddr(Victim);
694691

695692
const char *pReason = pResult->NumArguments() > 2 ? pResult->GetString(2) : "";
696693

697-
pSelf->Mute(&Addr, clamp(pResult->GetInteger(1), 1, 86400),
694+
pSelf->Mute(pAddr, clamp(pResult->GetInteger(1), 1, 86400),
698695
pSelf->Server()->ClientName(Victim), pReason);
699696
}
700697

@@ -721,7 +718,7 @@ void CGameContext::ConUnmute(IConsole::IResult *pResult, void *pUserData)
721718
if(Index < 0 || Index >= pSelf->m_NumMutes)
722719
return;
723720

724-
char aIpBuf[64];
721+
char aIpBuf[NETADDR_MAXSTRSIZE];
725722
char aBuf[64];
726723
net_addr_str(&pSelf->m_aMutes[Index].m_Addr, aIpBuf, sizeof(aIpBuf), false);
727724
str_format(aBuf, sizeof(aBuf), "Unmuted %s", aIpBuf);
@@ -740,14 +737,13 @@ void CGameContext::ConUnmuteId(IConsole::IResult *pResult, void *pUserData)
740737
if(Victim < 0 || Victim > MAX_CLIENTS || !pSelf->m_apPlayers[Victim])
741738
return;
742739

743-
NETADDR Addr;
744-
pSelf->Server()->GetClientAddr(Victim, &Addr);
740+
const NETADDR *pAddr = pSelf->Server()->ClientAddr(Victim);
745741

746742
for(int i = 0; i < pSelf->m_NumMutes; i++)
747743
{
748-
if(net_addr_comp_noport(&pSelf->m_aMutes[i].m_Addr, &Addr) == 0)
744+
if(net_addr_comp_noport(&pSelf->m_aMutes[i].m_Addr, pAddr) == 0)
749745
{
750-
char aIpBuf[64];
746+
char aIpBuf[NETADDR_MAXSTRSIZE];
751747
char aBuf[64];
752748
net_addr_str(&pSelf->m_aMutes[i].m_Addr, aIpBuf, sizeof(aIpBuf), false);
753749
str_format(aBuf, sizeof(aBuf), "Unmuted %s", aIpBuf);
@@ -975,7 +971,7 @@ void CGameContext::LogEvent(const char *Description, int ClientId)
975971
if(!pNewEntry->m_FromServer)
976972
{
977973
pNewEntry->m_ClientVersion = Server()->GetClientVersion(ClientId);
978-
Server()->GetClientAddr(ClientId, pNewEntry->m_aClientAddrStr, sizeof(pNewEntry->m_aClientAddrStr));
974+
str_copy(pNewEntry->m_aClientAddrStr, Server()->ClientAddrString(ClientId, false));
979975
str_copy(pNewEntry->m_aClientName, Server()->ClientName(ClientId));
980976
}
981977
}

0 commit comments

Comments
 (0)