Changeset - r25803:2bb6ece6b23e
[Not reviewed]
master
0 6 0
Patric Stout - 3 years ago 2021-04-29 15:52:09
truebrain@openttd.org
Remove: old server listing via Master Server

This removes all UDP from the game except for a local broadcast
to find LAN games.

So long Master Server, and tnx for all the fish!
6 files changed with 8 insertions and 401 deletions:
0 comments (0 inline, 0 general)
src/network/core/config.h
Show inline comments
 
@@ -9,26 +9,21 @@
 
 * @file config.h Configuration options of the network stuff. It is used even when compiling without network support.
 
 */
 

	
 
#ifndef NETWORK_CORE_CONFIG_H
 
#define NETWORK_CORE_CONFIG_H
 

	
 
/** DNS hostname of the masterserver */
 
static const char * const NETWORK_MASTER_SERVER_HOST            = "master.openttd.org";
 
/** DNS hostname of the Game Coordinator server */
 
static const char * const NETWORK_COORDINATOR_SERVER_HOST       = "coordinator.openttd.org";
 
/** DNS hostname of the content server */
 
static const char * const NETWORK_CONTENT_SERVER_HOST           = "content.openttd.org";
 
/** DNS hostname of the HTTP-content mirror server */
 
static const char * const NETWORK_CONTENT_MIRROR_HOST           = "binaries.openttd.org";
 
/** URL of the HTTP mirror system */
 
static const char * const NETWORK_CONTENT_MIRROR_URL            = "/bananas";
 
/** Message sent to the masterserver to 'identify' this client as OpenTTD */
 
static const char * const NETWORK_MASTER_SERVER_WELCOME_MESSAGE = "OpenTTDRegister";
 

	
 
static const uint16 NETWORK_MASTER_SERVER_PORT      = 3978;           ///< The default port of the master server (UDP)
 
static const uint16 NETWORK_COORDINATOR_SERVER_PORT = 3976;           ///< The default port of the Game Coordinator server (TCP)
 
static const uint16 NETWORK_CONTENT_SERVER_PORT     = 3978;           ///< The default port of the content server (TCP)
 
static const uint16 NETWORK_CONTENT_MIRROR_PORT     =   80;           ///< The default port of the content mirror (TCP)
 
static const uint16 NETWORK_DEFAULT_PORT            = 3979;           ///< The default port of the game server (TCP & UDP)
 
static const uint16 NETWORK_ADMIN_PORT              = 3977;           ///< The default port for admin network
 
static const uint16 NETWORK_DEFAULT_DEBUGLOG_PORT   = 3982;           ///< The default port debug-log is sent to (TCP)
 
@@ -51,13 +46,12 @@ static const uint16 UDP_MTU             
 
static const uint16 TCP_MTU                         = 32767;          ///< Number of bytes we can pack in a single TCP packet
 
static const uint16 COMPAT_MTU                      = 1460;           ///< Number of bytes we can pack in a single packet for backward compatibility
 

	
 
static const byte NETWORK_GAME_ADMIN_VERSION        =    1;           ///< What version of the admin network do we use?
 
static const byte NETWORK_GAME_INFO_VERSION         =    4;           ///< What version of game-info do we use?
 
static const byte NETWORK_COMPANY_INFO_VERSION      =    6;           ///< What version of company info is this?
 
static const byte NETWORK_MASTER_SERVER_VERSION     =    2;           ///< What version of master-server-protocol do we use?
 
static const byte NETWORK_COORDINATOR_VERSION       =    1;           ///< What version of game-coordinator-protocol do we use?
 

	
 
static const uint NETWORK_NAME_LENGTH               =   80;           ///< The maximum length of the server name and map name, in bytes including '\0'
 
static const uint NETWORK_COMPANY_NAME_LENGTH       =  128;           ///< The maximum length of the company name, in bytes including '\0'
 
static const uint NETWORK_HOSTNAME_LENGTH           =   80;           ///< The maximum length of the host name, in bytes including '\0'
 
static const uint NETWORK_HOSTNAME_PORT_LENGTH      =   80 + 6;       ///< The maximum length of the host name + port, in bytes including '\0'. The extra six is ":" + port number (with a max of 65536)
src/network/network_gamelist.cpp
Show inline comments
 
@@ -20,51 +20,12 @@
 

	
 
#include "../safeguards.h"
 

	
 
NetworkGameList *_network_game_list = nullptr; ///< Game list of this client.
 
int _network_game_list_version = 0; ///< Current version of all items in the list.
 

	
 
/** The games to insert when the GUI thread has time for us. */
 
static std::atomic<NetworkGameList *> _network_game_delayed_insertion_list(nullptr);
 

	
 
/**
 
 * Add a new item to the linked gamelist, but do it delayed in the next tick
 
 * or so to prevent race conditions.
 
 * @param item the item to add. Will be freed once added.
 
 */
 
void NetworkGameListAddItemDelayed(NetworkGameList *item)
 
{
 
	item->next = _network_game_delayed_insertion_list.load(std::memory_order_relaxed);
 
	while (!_network_game_delayed_insertion_list.compare_exchange_weak(item->next, item, std::memory_order_acq_rel)) {}
 
}
 

	
 
/** Perform the delayed (thread safe) insertion into the game list */
 
static void NetworkGameListHandleDelayedInsert()
 
{
 
	while (true) {
 
		NetworkGameList *ins_item = _network_game_delayed_insertion_list.load(std::memory_order_relaxed);
 
		while (ins_item != nullptr && !_network_game_delayed_insertion_list.compare_exchange_weak(ins_item, ins_item->next, std::memory_order_acq_rel)) {}
 
		if (ins_item == nullptr) break; // No item left.
 

	
 
		NetworkGameList *item = NetworkGameListAddItem(ins_item->connection_string);
 

	
 
		if (item != nullptr) {
 
			if (item->info.server_name.empty()) {
 
				ClearGRFConfigList(&item->info.grfconfig);
 
				item->info = {};
 
				item->info.server_name = ins_item->info.server_name;
 
				item->online = false;
 
			}
 
			item->manually |= ins_item->manually;
 
			if (item->manually) NetworkRebuildHostList();
 
			UpdateNetworkGameWindow();
 
		}
 
		delete ins_item;
 
	}
 
}
 

	
 
/**
 
 * Add a new item to the linked gamelist. If the IP and Port match
 
 * return the existing item instead of adding it again
 
 * @param address the address of the to-be added item
 
 * @return a point to the newly added or already existing item
 
 */
 
@@ -146,37 +107,12 @@ void NetworkGameListRemoveExpired()
 
		}
 
	}
 

	
 
	UpdateNetworkGameWindow();
 
}
 

	
 
static const uint MAX_GAME_LIST_REQUERY_COUNT  = 10; ///< How often do we requery in number of times per server?
 
static const uint REQUERY_EVERY_X_GAMELOOPS    = 60; ///< How often do we requery in time?
 
static const uint REFRESH_GAMEINFO_X_REQUERIES = 50; ///< Refresh the game info itself after REFRESH_GAMEINFO_X_REQUERIES * REQUERY_EVERY_X_GAMELOOPS game loops
 

	
 
/** Requeries the (game) servers we have not gotten a reply from */
 
void NetworkGameListRequery()
 
{
 
	NetworkGameListHandleDelayedInsert();
 

	
 
	static uint8 requery_cnt = 0;
 

	
 
	if (++requery_cnt < REQUERY_EVERY_X_GAMELOOPS) return;
 
	requery_cnt = 0;
 

	
 
	for (NetworkGameList *item = _network_game_list; item != nullptr; item = item->next) {
 
		item->retries++;
 
		if (item->retries < REFRESH_GAMEINFO_X_REQUERIES && (item->online || item->retries >= MAX_GAME_LIST_REQUERY_COUNT)) continue;
 

	
 
		/* item gets mostly zeroed by NetworkUDPQueryServer */
 
		uint8 retries = item->retries;
 
		NetworkUDPQueryServer(item->connection_string);
 
		item->retries = (retries >= REFRESH_GAMEINFO_X_REQUERIES) ? 0 : retries;
 
	}
 
}
 

	
 
/**
 
 * Rebuild the GRFConfig's of the servers in the game list as we did
 
 * a rescan and might have found new NewGRFs.
 
 */
 
void NetworkAfterNewGRFScan()
 
{
src/network/network_gamelist.h
Show inline comments
 
@@ -30,13 +30,11 @@ struct NetworkGameList {
 
	NetworkGameList *next = nullptr; ///< Next pointer to make a linked game list
 
};
 

	
 
extern NetworkGameList *_network_game_list;
 
extern int _network_game_list_version;
 

	
 
void NetworkGameListAddItemDelayed(NetworkGameList *item);
 
NetworkGameList *NetworkGameListAddItem(const std::string &connection_string);
 
void NetworkGameListRemoveItem(NetworkGameList *remove);
 
void NetworkGameListRemoveExpired();
 
void NetworkGameListRequery();
 

	
 
#endif /* NETWORK_GAMELIST_H */
src/network/network_udp.cpp
Show inline comments
 
@@ -20,414 +20,98 @@
 
#include "network_gamelist.h"
 
#include "network_internal.h"
 
#include "network_udp.h"
 
#include "network.h"
 
#include "../core/endian_func.hpp"
 
#include "../company_base.h"
 
#include "../thread.h"
 
#include "../rev.h"
 
#include "../newgrf_text.h"
 
#include "../strings_func.h"
 
#include "table/strings.h"
 
#include <mutex>
 

	
 
#include "core/udp.h"
 

	
 
#include "../safeguards.h"
 

	
 
static bool _network_udp_server;         ///< Is the UDP server started?
 
static uint16 _network_udp_broadcast;    ///< Timeout for the UDP broadcasts.
 

	
 
/** Some information about a socket, which exists before the actual socket has been created to provide locking and the likes. */
 
struct UDPSocket {
 
	const std::string name;                     ///< The name of the socket.
 
	std::mutex mutex;                           ///< Mutex for everything that (indirectly) touches the sockets within the handler.
 
	NetworkUDPSocketHandler *socket;            ///< The actual socket, which may be nullptr when not initialized yet.
 
	std::atomic<int> receive_iterations_locked; ///< The number of receive iterations the mutex was locked.
 

	
 
	UDPSocket(const std::string &name_) : name(name_), socket(nullptr) {}
 
	UDPSocket(const std::string &name) : name(name), socket(nullptr) {}
 

	
 
	void CloseSocket()
 
	{
 
		std::lock_guard<std::mutex> lock(mutex);
 
		socket->CloseSocket();
 
		delete socket;
 
		socket = nullptr;
 
		this->socket->CloseSocket();
 
		delete this->socket;
 
		this->socket = nullptr;
 
	}
 

	
 
	void ReceivePackets()
 
	{
 
		std::unique_lock<std::mutex> lock(mutex, std::defer_lock);
 
		if (!lock.try_lock()) {
 
			if (++receive_iterations_locked % 32 == 0) {
 
				Debug(net, 0, "{} background UDP loop processing appears to be blocked. Your OS may be low on UDP send buffers.", name);
 
			}
 
			return;
 
		}
 

	
 
		receive_iterations_locked.store(0);
 
		socket->ReceivePackets();
 
		this->socket->ReceivePackets();
 
	}
 
};
 

	
 
static UDPSocket _udp_client("Client"); ///< udp client socket
 
static UDPSocket _udp_server("Server"); ///< udp server socket
 

	
 
/**
 
 * Helper function doing the actual work for querying the server.
 
 * @param connection_string The address of the server.
 
 * @param needs_mutex Whether we need to acquire locks when sending the packet or not.
 
 * @param manually Whether the address was entered manually.
 
 */
 
static void DoNetworkUDPQueryServer(const std::string &connection_string, bool needs_mutex, bool manually)
 
{
 
	/* Clear item in gamelist */
 
	NetworkGameList *item = new NetworkGameList(connection_string, manually);
 
	item->info.server_name = connection_string;
 
	NetworkGameListAddItemDelayed(item);
 

	
 
	std::unique_lock<std::mutex> lock(_udp_client.mutex, std::defer_lock);
 
	if (needs_mutex) lock.lock();
 
	/* Init the packet */
 
	NetworkAddress address = NetworkAddress(ParseConnectionString(connection_string, NETWORK_DEFAULT_PORT));
 
	Packet p(PACKET_UDP_CLIENT_FIND_SERVER);
 
	if (_udp_client.socket != nullptr) _udp_client.socket->SendPacket(&p, &address);
 
}
 

	
 
/**
 
 * Query a specific server.
 
 * @param connection_string The address of the server.
 
 * @param manually Whether the address was entered manually.
 
 */
 
void NetworkUDPQueryServer(const std::string &connection_string, bool manually)
 
{
 
	if (!StartNewThread(nullptr, "ottd:udp-query", &DoNetworkUDPQueryServer, std::move(connection_string), true, std::move(manually))) {
 
		DoNetworkUDPQueryServer(connection_string, true, manually);
 
	}
 
}
 

	
 
///*** Communication with clients (we are server) ***/
 

	
 
/** Helper class for handling all server side communication. */
 
class ServerNetworkUDPSocketHandler : public NetworkUDPSocketHandler {
 
protected:
 
	void Receive_CLIENT_FIND_SERVER(Packet *p, NetworkAddress *client_addr) override;
 
	void Receive_CLIENT_DETAIL_INFO(Packet *p, NetworkAddress *client_addr) override;
 
	void Receive_CLIENT_GET_NEWGRFS(Packet *p, NetworkAddress *client_addr) override;
 
public:
 
	/**
 
	 * Create the socket.
 
	 * @param addresses The addresses to bind on.
 
	 */
 
	ServerNetworkUDPSocketHandler(NetworkAddressList *addresses) : NetworkUDPSocketHandler(addresses) {}
 
	virtual ~ServerNetworkUDPSocketHandler() {}
 
};
 

	
 
void ServerNetworkUDPSocketHandler::Receive_CLIENT_FIND_SERVER(Packet *p, NetworkAddress *client_addr)
 
{
 
	/* Just a fail-safe.. should never happen */
 
	if (!_network_udp_server) {
 
		return;
 
	}
 

	
 
	Packet packet(PACKET_UDP_SERVER_RESPONSE);
 
	SerializeNetworkGameInfo(&packet, GetCurrentNetworkServerGameInfo());
 

	
 
	/* Let the client know that we are here */
 
	this->SendPacket(&packet, client_addr);
 

	
 
	Debug(net, 7, "Queried from {}", client_addr->GetHostname());
 
}
 

	
 
void ServerNetworkUDPSocketHandler::Receive_CLIENT_DETAIL_INFO(Packet *p, NetworkAddress *client_addr)
 
{
 
	/* Just a fail-safe.. should never happen */
 
	if (!_network_udp_server) return;
 

	
 
	Packet packet(PACKET_UDP_SERVER_DETAIL_INFO);
 

	
 
	/* Send the amount of active companies */
 
	packet.Send_uint8 (NETWORK_COMPANY_INFO_VERSION);
 
	packet.Send_uint8 ((uint8)Company::GetNumItems());
 

	
 
	/* Fetch the latest version of the stats */
 
	NetworkCompanyStats company_stats[MAX_COMPANIES];
 
	NetworkPopulateCompanyStats(company_stats);
 

	
 
	/* The minimum company information "blob" size. */
 
	static const uint MIN_CI_SIZE = 54;
 
	uint max_cname_length = NETWORK_COMPANY_NAME_LENGTH;
 

	
 
	if (!packet.CanWriteToPacket(Company::GetNumItems() * (MIN_CI_SIZE + NETWORK_COMPANY_NAME_LENGTH))) {
 
		/* Assume we can at least put the company information in the packets. */
 
		assert(packet.CanWriteToPacket(Company::GetNumItems() * MIN_CI_SIZE));
 

	
 
		/* At this moment the company names might not fit in the
 
		 * packet. Check whether that is really the case. */
 

	
 
		for (;;) {
 
			size_t required = 0;
 
			for (const Company *company : Company::Iterate()) {
 
				char company_name[NETWORK_COMPANY_NAME_LENGTH];
 
				SetDParam(0, company->index);
 
				GetString(company_name, STR_COMPANY_NAME, company_name + max_cname_length - 1);
 
				required += MIN_CI_SIZE;
 
				required += strlen(company_name);
 
			}
 
			if (packet.CanWriteToPacket(required)) break;
 

	
 
			/* Try again, with slightly shorter strings. */
 
			assert(max_cname_length > 0);
 
			max_cname_length--;
 
		}
 
	}
 

	
 
	/* Go through all the companies */
 
	for (const Company *company : Company::Iterate()) {
 
		/* Send the information */
 
		this->SendCompanyInformation(&packet, company, &company_stats[company->index], max_cname_length);
 
	}
 

	
 
	this->SendPacket(&packet, client_addr);
 
}
 

	
 
/**
 
 * A client has requested the names of some NewGRFs.
 
 *
 
 * Replying this can be tricky as we have a limit of UDP_MTU bytes
 
 * in the reply packet and we can send up to 100 bytes per NewGRF
 
 * (GRF ID, MD5sum and NETWORK_GRF_NAME_LENGTH bytes for the name).
 
 * As UDP_MTU is _much_ less than 100 * NETWORK_MAX_GRF_COUNT, it
 
 * could be that a packet overflows. To stop this we only reply
 
 * with the first N NewGRFs so that if the first N + 1 NewGRFs
 
 * would be sent, the packet overflows.
 
 * in_reply and in_reply_count are used to keep a list of GRFs to
 
 * send in the reply.
 
 */
 
void ServerNetworkUDPSocketHandler::Receive_CLIENT_GET_NEWGRFS(Packet *p, NetworkAddress *client_addr)
 
{
 
	uint8 num_grfs;
 
	uint i;
 

	
 
	const GRFConfig *in_reply[NETWORK_MAX_GRF_COUNT];
 
	uint8 in_reply_count = 0;
 
	size_t packet_len = 0;
 

	
 
	Debug(net, 7, "NewGRF data request from {}", client_addr->GetAddressAsString());
 

	
 
	num_grfs = p->Recv_uint8 ();
 
	if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
 

	
 
	for (i = 0; i < num_grfs; i++) {
 
		GRFIdentifier c;
 
		const GRFConfig *f;
 

	
 
		DeserializeGRFIdentifier(p, &c);
 

	
 
		/* Find the matching GRF file */
 
		f = FindGRFConfig(c.grfid, FGCM_EXACT, c.md5sum);
 
		if (f == nullptr) continue; // The GRF is unknown to this server
 

	
 
		/* If the reply might exceed the size of the packet, only reply
 
		 * the current list and do not send the other data.
 
		 * The name could be an empty string, if so take the filename. */
 
		packet_len += sizeof(c.grfid) + sizeof(c.md5sum) +
 
				std::min(strlen(f->GetName()) + 1, (size_t)NETWORK_GRF_NAME_LENGTH);
 
		if (packet_len > UDP_MTU - 4) { // 4 is 3 byte header + grf count in reply
 
			break;
 
		}
 
		in_reply[in_reply_count] = f;
 
		in_reply_count++;
 
	}
 

	
 
	if (in_reply_count == 0) return;
 

	
 
	Packet packet(PACKET_UDP_SERVER_NEWGRFS);
 
	packet.Send_uint8(in_reply_count);
 
	for (i = 0; i < in_reply_count; i++) {
 
		char name[NETWORK_GRF_NAME_LENGTH];
 

	
 
		/* The name could be an empty string, if so take the filename */
 
		strecpy(name, in_reply[i]->GetName(), lastof(name));
 
		SerializeGRFIdentifier(&packet, &in_reply[i]->ident);
 
		packet.Send_string(name);
 
	}
 

	
 
	this->SendPacket(&packet, client_addr);
 
}
 

	
 
///*** Communication with servers (we are client) ***/
 

	
 
/** Helper class for handling all client side communication. */
 
class ClientNetworkUDPSocketHandler : public NetworkUDPSocketHandler {
 
protected:
 
	void Receive_SERVER_RESPONSE(Packet *p, NetworkAddress *client_addr) override;
 
	void Receive_MASTER_RESPONSE_LIST(Packet *p, NetworkAddress *client_addr) override;
 
	void Receive_SERVER_NEWGRFS(Packet *p, NetworkAddress *client_addr) override;
 
public:
 
	virtual ~ClientNetworkUDPSocketHandler() {}
 
};
 

	
 
void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet *p, NetworkAddress *client_addr)
 
{
 
	NetworkGameList *item;
 

	
 
	/* Just a fail-safe.. should never happen */
 
	if (_network_udp_server) return;
 

	
 
	Debug(net, 3, "Server response from {}", client_addr->GetAddressAsString());
 

	
 
	/* Find next item */
 
	item = NetworkGameListAddItem(client_addr->GetAddressAsString(false));
 

	
 
	/* Clear any existing GRFConfig chain. */
 
	ClearGRFConfigList(&item->info.grfconfig);
 
	/* Retrieve the NetworkGameInfo from the packet. */
 
	DeserializeNetworkGameInfo(p, &item->info);
 
	/* Check for compatability with the client. */
 
	CheckGameCompatibility(item->info);
 
	/* Ensure we consider the server online. */
 
	item->online = true;
 
	/* Make sure this entry never expires. */
 
	item->version = INT32_MAX;
 

	
 
	{
 
		/* Checks whether there needs to be a request for names of GRFs and makes
 
		 * the request if necessary. GRFs that need to be requested are the GRFs
 
		 * that do not exist on the clients system and we do not have the name
 
		 * resolved of, i.e. the name is still UNKNOWN_GRF_NAME_PLACEHOLDER.
 
		 * The in_request array and in_request_count are used so there is no need
 
		 * to do a second loop over the GRF list, which can be relatively expensive
 
		 * due to the string comparisons. */
 
		const GRFConfig *in_request[NETWORK_MAX_GRF_COUNT];
 
		const GRFConfig *c;
 
		uint in_request_count = 0;
 

	
 
		for (c = item->info.grfconfig; c != nullptr; c = c->next) {
 
			if (c->status != GCS_NOT_FOUND || strcmp(c->GetName(), UNKNOWN_GRF_NAME_PLACEHOLDER) != 0) continue;
 
			in_request[in_request_count] = c;
 
			in_request_count++;
 
		}
 

	
 
		if (in_request_count > 0) {
 
			/* There are 'unknown' GRFs, now send a request for them */
 
			uint i;
 
			Packet packet(PACKET_UDP_CLIENT_GET_NEWGRFS);
 

	
 
			packet.Send_uint8(in_request_count);
 
			for (i = 0; i < in_request_count; i++) {
 
				SerializeGRFIdentifier(&packet, &in_request[i]->ident);
 
			}
 

	
 
			NetworkAddress address = NetworkAddress(ParseConnectionString(item->connection_string, NETWORK_DEFAULT_PORT));
 
			this->SendPacket(&packet, &address);
 
		}
 
	}
 

	
 
	if (client_addr->GetAddress()->ss_family == AF_INET6) {
 
		item->info.server_name.append(" (IPv6)");
 
	}
 

	
 
	UpdateNetworkGameWindow();
 
}
 

	
 
void ClientNetworkUDPSocketHandler::Receive_MASTER_RESPONSE_LIST(Packet *p, NetworkAddress *client_addr)
 
{
 
	/* packet begins with the protocol version (uint8)
 
	 * then an uint16 which indicates how many
 
	 * ip:port pairs are in this packet, after that
 
	 * an uint32 (ip) and an uint16 (port) for each pair.
 
	 */
 

	
 
	ServerListType type = (ServerListType)(p->Recv_uint8() - 1);
 

	
 
	if (type < SLT_END) {
 
		for (int i = p->Recv_uint16(); i != 0 ; i--) {
 
			sockaddr_storage addr_storage;
 
			memset(&addr_storage, 0, sizeof(addr_storage));
 

	
 
			if (type == SLT_IPv4) {
 
				addr_storage.ss_family = AF_INET;
 
				((sockaddr_in*)&addr_storage)->sin_addr.s_addr = TO_LE32(p->Recv_uint32());
 
			} else {
 
				assert(type == SLT_IPv6);
 
				addr_storage.ss_family = AF_INET6;
 
				byte *addr = (byte*)&((sockaddr_in6*)&addr_storage)->sin6_addr;
 
				for (uint i = 0; i < sizeof(in6_addr); i++) *addr++ = p->Recv_uint8();
 
			}
 
			NetworkAddress addr(addr_storage, type == SLT_IPv4 ? sizeof(sockaddr_in) : sizeof(sockaddr_in6));
 
			addr.SetPort(p->Recv_uint16());
 

	
 
			/* Somehow we reached the end of the packet */
 
			if (this->HasClientQuit()) return;
 

	
 
			DoNetworkUDPQueryServer(addr.GetAddressAsString(false), false, false);
 
		}
 
	}
 
}
 

	
 
/** The return of the client's request of the names of some NewGRFs */
 
void ClientNetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet *p, NetworkAddress *client_addr)
 
{
 
	uint8 num_grfs;
 
	uint i;
 

	
 
	Debug(net, 7, "NewGRF data reply from {}", client_addr->GetAddressAsString());
 

	
 
	num_grfs = p->Recv_uint8 ();
 
	if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
 

	
 
	for (i = 0; i < num_grfs; i++) {
 
		GRFIdentifier c;
 

	
 
		DeserializeGRFIdentifier(p, &c);
 
		std::string name = p->Recv_string(NETWORK_GRF_NAME_LENGTH);
 

	
 
		/* An empty name is not possible under normal circumstances
 
		 * and causes problems when showing the NewGRF list. */
 
		if (name.empty()) continue;
 

	
 
		/* Try to find the GRFTextWrapper for the name of this GRF ID and MD5sum tuple.
 
		 * If it exists and not resolved yet, then name of the fake GRF is
 
		 * overwritten with the name from the reply. */
 
		GRFTextWrapper unknown_name = FindUnknownGRFName(c.grfid, c.md5sum, false);
 
		if (unknown_name && strcmp(GetGRFStringFromGRFText(unknown_name), UNKNOWN_GRF_NAME_PLACEHOLDER) == 0) {
 
			AddGRFTextToList(unknown_name, name);
 
		}
 
	}
 
	NetworkAddServer(client_addr->GetAddressAsString(false), false, true);
 
}
 

	
 
/** Broadcast to all ips */
 
static void NetworkUDPBroadCast(NetworkUDPSocketHandler *socket)
 
{
 
	for (NetworkAddress &addr : _broadcast_list) {
 
		Packet p(PACKET_UDP_CLIENT_FIND_SERVER);
 

	
 
		Debug(net, 5, "Broadcasting to {}", addr.GetHostname());
 

	
 
		Packet p(PACKET_UDP_CLIENT_FIND_SERVER);
 
		socket->SendPacket(&p, &addr, true, true);
 
	}
 
}
 

	
 

	
 
/** Request the the server-list from the master server */
 
void NetworkUDPQueryMasterServer()
 
{
 
	Packet p(PACKET_UDP_CLIENT_GET_LIST);
 
	NetworkAddress out_addr(NETWORK_MASTER_SERVER_HOST, NETWORK_MASTER_SERVER_PORT);
 

	
 
	/* packet only contains protocol version */
 
	p.Send_uint8(NETWORK_MASTER_SERVER_VERSION);
 
	p.Send_uint8(SLT_AUTODETECT);
 

	
 
	std::lock_guard<std::mutex> lock(_udp_client.mutex);
 
	_udp_client.socket->SendPacket(&p, &out_addr, true);
 

	
 
	Debug(net, 6, "Master server queried at {}", out_addr.GetAddressAsString());
 
}
 

	
 
/** Find all servers */
 
void NetworkUDPSearchGame()
 
{
 
	/* We are still searching.. */
 
	if (_network_udp_broadcast > 0) return;
 

	
 
@@ -443,14 +127,12 @@ void NetworkUDPInitialize()
 
	/* If not closed, then do it. */
 
	if (_udp_server.socket != nullptr) NetworkUDPClose();
 

	
 
	Debug(net, 3, "Initializing UDP listeners");
 
	assert(_udp_client.socket == nullptr && _udp_server.socket == nullptr);
 

	
 
	std::scoped_lock lock(_udp_client.mutex, _udp_server.mutex);
 

	
 
	_udp_client.socket = new ClientNetworkUDPSocketHandler();
 

	
 
	NetworkAddressList server;
 
	GetBindAddresses(&server, _settings_client.network.server_port);
 
	_udp_server.socket = new ServerNetworkUDPSocketHandler(&server);
 

	
 
@@ -458,13 +140,12 @@ void NetworkUDPInitialize()
 
	_network_udp_broadcast = 0;
 
}
 

	
 
/** Start the listening of the UDP server component. */
 
void NetworkUDPServerListen()
 
{
 
	std::lock_guard<std::mutex> lock(_udp_server.mutex);
 
	_network_udp_server = _udp_server.socket->Listen();
 
}
 

	
 
/** Close all UDP related stuff. */
 
void NetworkUDPClose()
 
{
src/network/network_udp.h
Show inline comments
 
@@ -11,13 +11,11 @@
 
#define NETWORK_UDP_H
 

	
 
#include "core/address.h"
 

	
 
void NetworkUDPInitialize();
 
void NetworkUDPSearchGame();
 
void NetworkUDPQueryMasterServer();
 
void NetworkUDPQueryServer(const std::string &connection_string, bool manually = false);
 
void NetworkUDPClose();
 
void NetworkUDPServerListen();
 
void NetworkBackgroundUDPLoop();
 

	
 
#endif /* NETWORK_UDP_H */
src/settings_type.h
Show inline comments
 
@@ -267,13 +267,13 @@ struct NetworkSettings {
 
	uint16      server_admin_port;                        ///< port the server listens on for the admin network
 
	bool        server_admin_chat;                        ///< allow private chat for the server to be distributed to the admin network
 
	std::string server_name;                              ///< name of the server
 
	std::string server_password;                          ///< password for joining this server
 
	std::string rcon_password;                            ///< password for rconsole (server side)
 
	std::string admin_password;                           ///< password for the admin network
 
	bool        server_advertise;                         ///< advertise the server to the masterserver
 
	bool        server_advertise;                         ///< Advertise the server to the game coordinator.
 
	std::string client_name;                              ///< name of the player (as client)
 
	std::string default_company_pass;                     ///< default password for new companies in encrypted form
 
	std::string connect_to_ip;                            ///< default for the "Add server" query
 
	std::string network_id;                               ///< network ID for servers
 
	bool        autoclean_companies;                      ///< automatically remove companies that are not in use
 
	uint8       autoclean_unprotected;                    ///< remove passwordless companies after this many months
0 comments (0 inline, 0 general)