mirror of https://github.com/OpenTTD/OpenTTD.git
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!
This commit is contained in:
parent
61fdef8457
commit
8a2da49413
|
@ -12,8 +12,6 @@
|
|||
#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 */
|
||||
|
@ -22,10 +20,7 @@ static const char * const NETWORK_CONTENT_SERVER_HOST = "content.opent
|
|||
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)
|
||||
|
@ -54,7 +49,6 @@ static const uint16 COMPAT_MTU = 1460; ///< Numbe
|
|||
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'
|
||||
|
|
|
@ -23,45 +23,6 @@
|
|||
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
|
||||
|
@ -149,31 +110,6 @@ 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.
|
||||
|
|
|
@ -33,10 +33,8 @@ struct NetworkGameList {
|
|||
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 */
|
||||
|
|
|
@ -23,12 +23,10 @@
|
|||
#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"
|
||||
|
||||
|
@ -40,79 +38,32 @@ 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.
|
||||
|
@ -124,307 +75,40 @@ public:
|
|||
|
||||
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()
|
||||
{
|
||||
|
@ -446,8 +130,6 @@ void NetworkUDPInitialize()
|
|||
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;
|
||||
|
@ -461,7 +143,6 @@ void NetworkUDPInitialize()
|
|||
/** 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();
|
||||
}
|
||||
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
|
||||
void NetworkUDPInitialize();
|
||||
void NetworkUDPSearchGame();
|
||||
void NetworkUDPQueryMasterServer();
|
||||
void NetworkUDPQueryServer(const std::string &connection_string, bool manually = false);
|
||||
void NetworkUDPClose();
|
||||
void NetworkUDPServerListen();
|
||||
void NetworkBackgroundUDPLoop();
|
||||
|
|
|
@ -270,7 +270,7 @@ struct NetworkSettings {
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue