ddnet/src/engine/client/serverbrowser.h

169 lines
5 KiB
C
Raw Normal View History

2010-11-20 10:37:14 +00:00
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
#ifndef ENGINE_CLIENT_SERVERBROWSER_H
#define ENGINE_CLIENT_SERVERBROWSER_H
2010-05-29 07:25:38 +00:00
2022-06-16 17:50:46 +00:00
#include <base/system.h>
#include <engine/console.h>
2010-05-29 07:25:38 +00:00
#include <engine/serverbrowser.h>
#include <engine/shared/memheap.h>
2010-05-29 07:25:38 +00:00
#include <unordered_map>
typedef struct _json_value json_value;
2022-06-16 17:50:46 +00:00
class CNetClient;
class IConfigManager;
class IConsole;
class IEngine;
class IFavorites;
class IFriends;
Add client-side HTTP server info Summary ======= The idea of this is that clients will not have to ping each server for server infos which takes long, leaks the client's IP address even to servers the user does not join and is a DoS vector of the game servers for attackers. For the Internet, DDNet and KoG tab, the server list is entirely fetched from the master server, filtering out servers that don't belong into the list. The favorites tab is also supposed to work that way, except for servers that are marked as "also ping this server if it's not in the master server list". The LAN tab continues to broadcast the server info packet to find servers in the LAN. How does it work? ================= The client ships with a list of master server list URLs. On first start, the client checks which of these work and selects the fastest one. Querying the server list is a HTTP GET request on that URL. The response is a JSON document that contains server infos, server addresses as URLs and an approximate location. It can also contain a legacy server list which is a list of bare IP addresses similar to the functionality the old master servers provided via UDP. This allows us to backtrack on the larger update if it won't work out. Lost functionality ================== (also known as user-visible changes) Since the client doesn't ping each server in the list anymore, it has no way of knowing its latency to the servers. This is alleviated a bit by providing an approximate location for each server (continent) so the client only has to know its own location for approximating pings.
2018-07-11 20:46:04 +00:00
class IServerBrowserHttp;
2021-04-17 14:05:24 +00:00
class IServerBrowserPingCache;
class IStorage;
Add client-side HTTP server info Summary ======= The idea of this is that clients will not have to ping each server for server infos which takes long, leaks the client's IP address even to servers the user does not join and is a DoS vector of the game servers for attackers. For the Internet, DDNet and KoG tab, the server list is entirely fetched from the master server, filtering out servers that don't belong into the list. The favorites tab is also supposed to work that way, except for servers that are marked as "also ping this server if it's not in the master server list". The LAN tab continues to broadcast the server info packet to find servers in the LAN. How does it work? ================= The client ships with a list of master server list URLs. On first start, the client checks which of these work and selects the fastest one. Querying the server list is a HTTP GET request on that URL. The response is a JSON document that contains server infos, server addresses as URLs and an approximate location. It can also contain a legacy server list which is a list of bare IP addresses similar to the functionality the old master servers provided via UDP. This allows us to backtrack on the larger update if it won't work out. Lost functionality ================== (also known as user-visible changes) Since the client doesn't ping each server in the list anymore, it has no way of knowing its latency to the servers. This is alleviated a bit by providing an approximate location for each server (continent) so the client only has to know its own location for approximating pings.
2018-07-11 20:46:04 +00:00
2010-05-29 07:25:38 +00:00
class CServerBrowser : public IServerBrowser
{
public:
class CServerEntry
{
public:
2021-06-23 05:05:49 +00:00
int64_t m_RequestTime;
bool m_RequestIgnoreInfo;
2010-05-29 07:25:38 +00:00
int m_GotInfo;
CServerInfo m_Info;
CServerEntry *m_pPrevReq; // request list
CServerEntry *m_pNextReq;
};
CServerBrowser();
virtual ~CServerBrowser();
2010-05-29 07:25:38 +00:00
// interface functions
void Refresh(int Type) override;
bool IsRefreshing() const override;
bool IsGettingServerlist() const override;
int LoadingProgression() const override;
void RequestResort() { m_NeedResort = true; }
2010-05-29 07:25:38 +00:00
int NumServers() const override { return m_NumServers; }
int Players(const CServerInfo &Item) const override;
int Max(const CServerInfo &Item) const override;
int NumSortedServers() const override { return m_NumSortedServers; }
const CServerInfo *SortedGet(int Index) const override;
2010-05-29 07:25:38 +00:00
const char *GetTutorialServer() override;
void LoadDDNetRanks();
void RecheckOfficial();
void LoadDDNetServers();
void LoadDDNetInfoJson();
const json_value *LoadDDNetInfo();
void UpdateServerFilteredPlayers(CServerInfo *pInfo) const;
CServerInfo::ERankState HasRank(const char *pMap);
2014-12-14 15:45:18 +00:00
const std::vector<CCommunity> &Communities() const override;
const CCommunity *Community(const char *pCommunityId) const override;
2014-12-14 15:45:18 +00:00
void DDNetFilterAdd(char *pFilter, int FilterSize, const char *pName) const override;
void DDNetFilterRem(char *pFilter, int FilterSize, const char *pName) const override;
bool DDNetFiltered(const char *pFilter, const char *pName) const override;
void CountryFilterClean(int CommunityIndex) override;
void TypeFilterClean(int CommunityIndex) override;
2014-12-14 15:45:18 +00:00
2010-05-29 07:25:38 +00:00
//
void Update();
void OnServerInfoUpdate(const NETADDR &Addr, int Token, const CServerInfo *pInfo);
void SetHttpInfo(const CServerInfo *pInfo);
void RequestCurrentServer(const NETADDR &Addr) const;
void RequestCurrentServerWithRandomToken(const NETADDR &Addr, int *pBasicToken, int *pToken) const;
void SetCurrentServerPing(const NETADDR &Addr, int Ping);
2010-05-29 07:25:38 +00:00
void SetBaseInfo(class CNetClient *pClient, const char *pNetVersion);
void OnInit();
2010-05-29 07:25:38 +00:00
2014-01-14 20:40:55 +00:00
void QueueRequest(CServerEntry *pEntry);
2014-01-08 05:15:56 +00:00
CServerEntry *Find(const NETADDR &Addr);
int GetCurrentType() override { return m_ServerlistType; }
bool IsRegistered(const NETADDR &Addr);
2014-01-08 05:15:56 +00:00
2010-05-29 07:25:38 +00:00
private:
CNetClient *m_pNetClient = nullptr;
IConfigManager *m_pConfigManager = nullptr;
IConsole *m_pConsole = nullptr;
IEngine *m_pEngine = nullptr;
IFriends *m_pFriends = nullptr;
IFavorites *m_pFavorites = nullptr;
IStorage *m_pStorage = nullptr;
2010-05-29 07:25:38 +00:00
char m_aNetVersion[128];
Add client-side HTTP server info Summary ======= The idea of this is that clients will not have to ping each server for server infos which takes long, leaks the client's IP address even to servers the user does not join and is a DoS vector of the game servers for attackers. For the Internet, DDNet and KoG tab, the server list is entirely fetched from the master server, filtering out servers that don't belong into the list. The favorites tab is also supposed to work that way, except for servers that are marked as "also ping this server if it's not in the master server list". The LAN tab continues to broadcast the server info packet to find servers in the LAN. How does it work? ================= The client ships with a list of master server list URLs. On first start, the client checks which of these work and selects the fastest one. Querying the server list is a HTTP GET request on that URL. The response is a JSON document that contains server infos, server addresses as URLs and an approximate location. It can also contain a legacy server list which is a list of bare IP addresses similar to the functionality the old master servers provided via UDP. This allows us to backtrack on the larger update if it won't work out. Lost functionality ================== (also known as user-visible changes) Since the client doesn't ping each server in the list anymore, it has no way of knowing its latency to the servers. This is alleviated a bit by providing an approximate location for each server (continent) so the client only has to know its own location for approximating pings.
2018-07-11 20:46:04 +00:00
bool m_RefreshingHttp = false;
IServerBrowserHttp *m_pHttp = nullptr;
2021-04-17 14:05:24 +00:00
IServerBrowserPingCache *m_pPingCache = nullptr;
const char *m_pHttpPrevBestUrl = nullptr;
Add client-side HTTP server info Summary ======= The idea of this is that clients will not have to ping each server for server infos which takes long, leaks the client's IP address even to servers the user does not join and is a DoS vector of the game servers for attackers. For the Internet, DDNet and KoG tab, the server list is entirely fetched from the master server, filtering out servers that don't belong into the list. The favorites tab is also supposed to work that way, except for servers that are marked as "also ping this server if it's not in the master server list". The LAN tab continues to broadcast the server info packet to find servers in the LAN. How does it work? ================= The client ships with a list of master server list URLs. On first start, the client checks which of these work and selects the fastest one. Querying the server list is a HTTP GET request on that URL. The response is a JSON document that contains server infos, server addresses as URLs and an approximate location. It can also contain a legacy server list which is a list of bare IP addresses similar to the functionality the old master servers provided via UDP. This allows us to backtrack on the larger update if it won't work out. Lost functionality ================== (also known as user-visible changes) Since the client doesn't ping each server in the list anymore, it has no way of knowing its latency to the servers. This is alleviated a bit by providing an approximate location for each server (continent) so the client only has to know its own location for approximating pings.
2018-07-11 20:46:04 +00:00
2010-05-29 07:25:38 +00:00
CHeap m_ServerlistHeap;
CServerEntry **m_ppServerlist;
int *m_pSortedServerlist;
std::unordered_map<NETADDR, int> m_ByAddr;
2010-05-29 07:25:38 +00:00
std::vector<CCommunity> m_vCommunities;
int m_OwnLocation = CServerInfo::LOC_UNKNOWN;
json_value *m_pDDNetInfo;
2014-12-14 15:45:18 +00:00
2010-05-29 07:25:38 +00:00
CServerEntry *m_pFirstReqServer; // request list
CServerEntry *m_pLastReqServer;
int m_NumRequests;
2015-07-09 00:08:14 +00:00
bool m_NeedResort;
int m_Sorthash;
2021-07-08 17:18:01 +00:00
// used instead of g_Config.br_max_requests to get more servers
int m_CurrentMaxRequests;
2015-07-09 00:08:14 +00:00
2010-05-29 07:25:38 +00:00
int m_NumSortedServers;
int m_NumSortedServersCapacity;
int m_NumServers;
int m_NumServerCapacity;
int m_ServerlistType;
2021-06-23 05:05:49 +00:00
int64_t m_BroadcastTime;
unsigned char m_aTokenSeed[16];
int GenerateToken(const NETADDR &Addr) const;
static int GetBasicToken(int Token);
static int GetExtraToken(int Token);
2010-05-29 07:25:38 +00:00
// sorting criteria
2010-05-29 07:25:38 +00:00
bool SortCompareName(int Index1, int Index2) const;
bool SortCompareMap(int Index1, int Index2) const;
bool SortComparePing(int Index1, int Index2) const;
bool SortCompareGametype(int Index1, int Index2) const;
bool SortCompareNumPlayers(int Index1, int Index2) const;
bool SortCompareNumClients(int Index1, int Index2) const;
bool SortCompareNumPlayersAndPing(int Index1, int Index2) const;
2010-05-29 07:25:38 +00:00
//
void Filter();
void Sort();
int SortHash() const;
2021-07-08 17:18:01 +00:00
void CleanUp();
Add client-side HTTP server info Summary ======= The idea of this is that clients will not have to ping each server for server infos which takes long, leaks the client's IP address even to servers the user does not join and is a DoS vector of the game servers for attackers. For the Internet, DDNet and KoG tab, the server list is entirely fetched from the master server, filtering out servers that don't belong into the list. The favorites tab is also supposed to work that way, except for servers that are marked as "also ping this server if it's not in the master server list". The LAN tab continues to broadcast the server info packet to find servers in the LAN. How does it work? ================= The client ships with a list of master server list URLs. On first start, the client checks which of these work and selects the fastest one. Querying the server list is a HTTP GET request on that URL. The response is a JSON document that contains server infos, server addresses as URLs and an approximate location. It can also contain a legacy server list which is a list of bare IP addresses similar to the functionality the old master servers provided via UDP. This allows us to backtrack on the larger update if it won't work out. Lost functionality ================== (also known as user-visible changes) Since the client doesn't ping each server in the list anymore, it has no way of knowing its latency to the servers. This is alleviated a bit by providing an approximate location for each server (continent) so the client only has to know its own location for approximating pings.
2018-07-11 20:46:04 +00:00
void UpdateFromHttp();
CServerEntry *Add(const NETADDR *pAddrs, int NumAddrs);
2010-05-29 07:25:38 +00:00
void RemoveRequest(CServerEntry *pEntry);
void RequestImpl(const NETADDR &Addr, CServerEntry *pEntry, int *pBasicToken, int *pToken, bool RandomToken) const;
2010-05-29 07:25:38 +00:00
void RegisterCommands();
static void Con_LeakIpAddress(IConsole::IResult *pResult, void *pUserData);
2010-05-29 07:25:38 +00:00
void SetInfo(CServerEntry *pEntry, const CServerInfo &Info);
void SetLatency(NETADDR Addr, int Latency);
2010-05-29 07:25:38 +00:00
};
#endif