summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/console_cmds.cpp1
-rw-r--r--src/network/core/CMakeLists.txt3
-rw-r--r--src/network/core/core.cpp28
-rw-r--r--src/network/core/core.h2
-rw-r--r--src/network/core/game_info.cpp323
-rw-r--r--src/network/core/game_info.h (renamed from src/network/core/game.h)62
-rw-r--r--src/network/core/tcp_http.cpp1
-rw-r--r--src/network/core/udp.cpp137
-rw-r--r--src/network/core/udp.h48
-rw-r--r--src/network/network.cpp81
-rw-r--r--src/network/network_admin.cpp1
-rw-r--r--src/network/network_base.h1
-rw-r--r--src/network/network_client.cpp3
-rw-r--r--src/network/network_func.h2
-rw-r--r--src/network/network_gamelist.h1
-rw-r--r--src/network/network_gui.h1
-rw-r--r--src/network/network_internal.h2
-rw-r--r--src/network/network_server.cpp3
-rw-r--r--src/network/network_type.h2
-rw-r--r--src/network/network_udp.cpp54
20 files changed, 407 insertions, 349 deletions
diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp
index 048b8b3e9..8cdf9c664 100644
--- a/src/console_cmds.cpp
+++ b/src/console_cmds.cpp
@@ -13,6 +13,7 @@
#include "engine_func.h"
#include "landscape.h"
#include "saveload/saveload.h"
+#include "network/core/game_info.h"
#include "network/network.h"
#include "network/network_func.h"
#include "network/network_base.h"
diff --git a/src/network/core/CMakeLists.txt b/src/network/core/CMakeLists.txt
index c9368a5b4..37cc3e195 100644
--- a/src/network/core/CMakeLists.txt
+++ b/src/network/core/CMakeLists.txt
@@ -4,7 +4,8 @@ add_files(
config.h
core.cpp
core.h
- game.h
+ game_info.cpp
+ game_info.h
host.cpp
host.h
os_abstraction.h
diff --git a/src/network/core/core.cpp b/src/network/core/core.cpp
index 8c5c5c229..5c12cb224 100644
--- a/src/network/core/core.cpp
+++ b/src/network/core/core.cpp
@@ -65,31 +65,3 @@ const char *NetworkGetErrorString(int error)
return buffer;
}
#endif /* defined(_WIN32) */
-
-/**
- * Serializes the GRFIdentifier (GRF ID and MD5 checksum) to the packet
- * @param p the packet to write the data to
- * @param grf the GRFIdentifier to serialize
- */
-void NetworkSocketHandler::SendGRFIdentifier(Packet *p, const GRFIdentifier *grf)
-{
- uint j;
- p->Send_uint32(grf->grfid);
- for (j = 0; j < sizeof(grf->md5sum); j++) {
- p->Send_uint8 (grf->md5sum[j]);
- }
-}
-
-/**
- * Deserializes the GRFIdentifier (GRF ID and MD5 checksum) from the packet
- * @param p the packet to read the data from
- * @param grf the GRFIdentifier to deserialize
- */
-void NetworkSocketHandler::ReceiveGRFIdentifier(Packet *p, GRFIdentifier *grf)
-{
- uint j;
- grf->grfid = p->Recv_uint32();
- for (j = 0; j < sizeof(grf->md5sum); j++) {
- grf->md5sum[j] = p->Recv_uint8();
- }
-}
diff --git a/src/network/core/core.h b/src/network/core/core.h
index bf83adc72..aac36080f 100644
--- a/src/network/core/core.h
+++ b/src/network/core/core.h
@@ -71,8 +71,6 @@ public:
*/
void Reopen() { this->has_quit = false; }
- void SendGRFIdentifier(Packet *p, const GRFIdentifier *grf);
- void ReceiveGRFIdentifier(Packet *p, GRFIdentifier *grf);
void SendCompanyInformation(Packet *p, const struct Company *c, const struct NetworkCompanyStats *stats, uint max_len = NETWORK_COMPANY_NAME_LENGTH);
};
diff --git a/src/network/core/game_info.cpp b/src/network/core/game_info.cpp
new file mode 100644
index 000000000..bea687af8
--- /dev/null
+++ b/src/network/core/game_info.cpp
@@ -0,0 +1,323 @@
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file game_info.cpp Functions to convert NetworkGameInfo to Packet and back.
+ */
+
+#include "../../stdafx.h"
+#include "game_info.h"
+#include "../../core/bitmath_func.hpp"
+#include "../../company_base.h"
+#include "../../date_func.h"
+#include "../../debug.h"
+#include "../../map_func.h"
+#include "../../settings_type.h"
+#include "../../string_func.h"
+#include "../../rev.h"
+#include "../network_func.h"
+#include "../network.h"
+#include "packet.h"
+
+#include "../../safeguards.h"
+
+
+/**
+ * How many hex digits of the git hash to include in network revision string.
+ * Determined as 10 hex digits + 2 characters for -g/-u/-m prefix.
+ */
+static const uint GITHASH_SUFFIX_LEN = 12;
+
+NetworkServerGameInfo _network_game_info; ///< Information about our game.
+
+/**
+ * Get the network version string used by this build.
+ * The returned string is guaranteed to be at most NETWORK_REVISON_LENGTH bytes.
+ */
+const char *GetNetworkRevisionString()
+{
+ /* This will be allocated on heap and never free'd, but only once so not a "real" leak. */
+ static char *network_revision = nullptr;
+
+ if (!network_revision) {
+ /* Start by taking a chance on the full revision string. */
+ network_revision = stredup(_openttd_revision);
+ /* Ensure it's not longer than the packet buffer length. */
+ if (strlen(network_revision) >= NETWORK_REVISION_LENGTH) network_revision[NETWORK_REVISION_LENGTH - 1] = '\0';
+
+ /* Tag names are not mangled further. */
+ if (_openttd_revision_tagged) {
+ DEBUG(net, 1, "Network revision name is '%s'", network_revision);
+ return network_revision;
+ }
+
+ /* Prepare a prefix of the git hash.
+ * Size is length + 1 for terminator, +2 for -g prefix. */
+ assert(_openttd_revision_modified < 3);
+ char githash_suffix[GITHASH_SUFFIX_LEN + 1] = "-";
+ githash_suffix[1] = "gum"[_openttd_revision_modified];
+ for (uint i = 2; i < GITHASH_SUFFIX_LEN; i++) {
+ githash_suffix[i] = _openttd_revision_hash[i-2];
+ }
+
+ /* Where did the hash start in the original string?
+ * Overwrite from that position, unless that would go past end of packet buffer length. */
+ ptrdiff_t hashofs = strrchr(_openttd_revision, '-') - _openttd_revision;
+ if (hashofs + strlen(githash_suffix) + 1 > NETWORK_REVISION_LENGTH) hashofs = strlen(network_revision) - strlen(githash_suffix);
+ /* Replace the git hash in revision string. */
+ strecpy(network_revision + hashofs, githash_suffix, network_revision + NETWORK_REVISION_LENGTH);
+ assert(strlen(network_revision) < NETWORK_REVISION_LENGTH); // strlen does not include terminator, constant does, hence strictly less than
+ DEBUG(net, 1, "Network revision name is '%s'", network_revision);
+ }
+
+ return network_revision;
+}
+
+/**
+ * Extract the git hash from the revision string.
+ * @param revstr The revision string (formatted as DATE-BRANCH-GITHASH).
+ * @return The git has part of the revision.
+ */
+static const char *ExtractNetworkRevisionHash(const char *revstr)
+{
+ return strrchr(revstr, '-');
+}
+
+/**
+ * Checks whether the given version string is compatible with our version.
+ * First tries to match the full string, if that fails, attempts to compare just git hashes.
+ * @param other the version string to compare to
+ */
+bool IsNetworkCompatibleVersion(const char *other)
+{
+ if (strncmp(GetNetworkRevisionString(), other, NETWORK_REVISION_LENGTH - 1) == 0) return true;
+
+ /* If this version is tagged, then the revision string must be a complete match,
+ * since there is no git hash suffix in it.
+ * This is needed to avoid situations like "1.9.0-beta1" comparing equal to "2.0.0-beta1". */
+ if (_openttd_revision_tagged) return false;
+
+ const char *hash1 = ExtractNetworkRevisionHash(GetNetworkRevisionString());
+ const char *hash2 = ExtractNetworkRevisionHash(other);
+ return hash1 && hash2 && (strncmp(hash1, hash2, GITHASH_SUFFIX_LEN) == 0);
+}
+
+/**
+ * Fill a NetworkGameInfo structure with the latest information of the server.
+ * @param ngi the NetworkGameInfo struct to fill with data.
+ */
+void FillNetworkGameInfo(NetworkGameInfo &ngi)
+{
+ /* Update some game_info */
+ ngi.clients_on = _network_game_info.clients_on;
+ ngi.start_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
+
+ ngi.use_password = !StrEmpty(_settings_client.network.server_password);
+ ngi.clients_max = _settings_client.network.max_clients;
+ ngi.companies_on = (byte)Company::GetNumItems();
+ ngi.companies_max = _settings_client.network.max_companies;
+ ngi.spectators_on = NetworkSpectatorCount();
+ ngi.spectators_max = _settings_client.network.max_spectators;
+ ngi.game_date = _date;
+ ngi.map_width = MapSizeX();
+ ngi.map_height = MapSizeY();
+ ngi.map_set = _settings_game.game_creation.landscape;
+ ngi.dedicated = _network_dedicated;
+ ngi.grfconfig = _grfconfig;
+
+ strecpy(ngi.server_name, _settings_client.network.server_name, lastof(ngi.server_name));
+ strecpy(ngi.server_revision, GetNetworkRevisionString(), lastof(ngi.server_revision));
+}
+
+/**
+ * Function that is called for every GRFConfig that is read when receiving
+ * a NetworkGameInfo. Only grfid and md5sum are set, the rest is zero. This
+ * function must set all appropriate fields. This GRF is later appended to
+ * the grfconfig list of the NetworkGameInfo.
+ * @param config the GRF to handle.
+ */
+static void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config)
+{
+ /* Find the matching GRF file */
+ const GRFConfig *f = FindGRFConfig(config->ident.grfid, FGCM_EXACT, config->ident.md5sum);
+ if (f == nullptr) {
+ /* Don't know the GRF, so mark game incompatible and the (possibly)
+ * already resolved name for this GRF (another server has sent the
+ * name of the GRF already */
+ config->name = FindUnknownGRFName(config->ident.grfid, config->ident.md5sum, true);
+ config->status = GCS_NOT_FOUND;
+ } else {
+ config->filename = f->filename;
+ config->name = f->name;
+ config->info = f->info;
+ config->url = f->url;
+ }
+ SetBit(config->flags, GCF_COPY);
+}
+
+/**
+ * Serializes the NetworkGameInfo struct to the packet.
+ * @param p the packet to write the data to.
+ * @param info the NetworkGameInfo struct to serialize from.
+ */
+void SerializeNetworkGameInfo(Packet *p, const NetworkGameInfo *info)
+{
+ p->Send_uint8 (NETWORK_GAME_INFO_VERSION);
+
+ /*
+ * Please observe the order.
+ * The parts must be read in the same order as they are sent!
+ */
+
+ /* Update the documentation in game_info.h on changes
+ * to the NetworkGameInfo wire-protocol! */
+
+ /* NETWORK_GAME_INFO_VERSION = 4 */
+ {
+ /* Only send the GRF Identification (GRF_ID and MD5 checksum) of
+ * the GRFs that are needed, i.e. the ones that the server has
+ * selected in the NewGRF GUI and not the ones that are used due
+ * to the fact that they are in [newgrf-static] in openttd.cfg */
+ const GRFConfig *c;
+ uint count = 0;
+
+ /* Count number of GRFs to send information about */
+ for (c = info->grfconfig; c != nullptr; c = c->next) {
+ if (!HasBit(c->flags, GCF_STATIC)) count++;
+ }
+ p->Send_uint8 (count); // Send number of GRFs
+
+ /* Send actual GRF Identifications */
+ for (c = info->grfconfig; c != nullptr; c = c->next) {
+ if (!HasBit(c->flags, GCF_STATIC)) SerializeGRFIdentifier(p, &c->ident);
+ }
+ }
+
+ /* NETWORK_GAME_INFO_VERSION = 3 */
+ p->Send_uint32(info->game_date);
+ p->Send_uint32(info->start_date);
+
+ /* NETWORK_GAME_INFO_VERSION = 2 */
+ p->Send_uint8 (info->companies_max);
+ p->Send_uint8 (info->companies_on);
+ p->Send_uint8 (info->spectators_max);
+
+ /* NETWORK_GAME_INFO_VERSION = 1 */
+ p->Send_string(info->server_name);
+ p->Send_string(info->server_revision);
+ p->Send_uint8 (0); // Used to be server-lang.
+ p->Send_bool (info->use_password);
+ p->Send_uint8 (info->clients_max);
+ p->Send_uint8 (info->clients_on);
+ p->Send_uint8 (info->spectators_on);
+ p->Send_string(""); // Used to be map-name.
+ p->Send_uint16(info->map_width);
+ p->Send_uint16(info->map_height);
+ p->Send_uint8 (info->map_set);
+ p->Send_bool (info->dedicated);
+}
+
+/**
+ * Deserializes the NetworkGameInfo struct from the packet.
+ * @param p the packet to read the data from.
+ * @param info the NetworkGameInfo to deserialize into.
+ */
+void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info)
+{
+ static const Date MAX_DATE = ConvertYMDToDate(MAX_YEAR, 11, 31); // December is month 11
+
+ info->game_info_version = p->Recv_uint8();
+
+ /*
+ * Please observe the order.
+ * The parts must be read in the same order as they are sent!
+ */
+
+ /* Update the documentation in game_info.h on changes
+ * to the NetworkGameInfo wire-protocol! */
+
+ switch (info->game_info_version) {
+ case 4: {
+ GRFConfig **dst = &info->grfconfig;
+ uint i;
+ uint num_grfs = p->Recv_uint8();
+
+ /* Broken/bad data. It cannot have that many NewGRFs. */
+ if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
+
+ for (i = 0; i < num_grfs; i++) {
+ GRFConfig *c = new GRFConfig();
+ DeserializeGRFIdentifier(p, &c->ident);
+ HandleIncomingNetworkGameInfoGRFConfig(c);
+
+ /* Append GRFConfig to the list */
+ *dst = c;
+ dst = &c->next;
+ }
+ FALLTHROUGH;
+ }
+
+ case 3:
+ info->game_date = Clamp(p->Recv_uint32(), 0, MAX_DATE);
+ info->start_date = Clamp(p->Recv_uint32(), 0, MAX_DATE);
+ FALLTHROUGH;
+
+ case 2:
+ info->companies_max = p->Recv_uint8 ();
+ info->companies_on = p->Recv_uint8 ();
+ info->spectators_max = p->Recv_uint8 ();
+ FALLTHROUGH;
+
+ case 1:
+ p->Recv_string(info->server_name, sizeof(info->server_name));
+ p->Recv_string(info->server_revision, sizeof(info->server_revision));
+ p->Recv_uint8 (); // Used to contain server-lang.
+ info->use_password = p->Recv_bool ();
+ info->clients_max = p->Recv_uint8 ();
+ info->clients_on = p->Recv_uint8 ();
+ info->spectators_on = p->Recv_uint8 ();
+ if (info->game_info_version < 3) { // 16 bits dates got scrapped and are read earlier
+ info->game_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
+ info->start_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
+ }
+ while (p->Recv_uint8() != 0) {} // Used to contain the map-name.
+ info->map_width = p->Recv_uint16();
+ info->map_height = p->Recv_uint16();
+ info->map_set = p->Recv_uint8 ();
+ info->dedicated = p->Recv_bool ();
+
+ if (info->map_set >= NETWORK_NUM_LANDSCAPES) info->map_set = 0;
+ }
+}
+
+/**
+ * Serializes the GRFIdentifier (GRF ID and MD5 checksum) to the packet
+ * @param p the packet to write the data to.
+ * @param grf the GRFIdentifier to serialize.
+ */
+void SerializeGRFIdentifier(Packet *p, const GRFIdentifier *grf)
+{
+ uint j;
+ p->Send_uint32(grf->grfid);
+ for (j = 0; j < sizeof(grf->md5sum); j++) {
+ p->Send_uint8(grf->md5sum[j]);
+ }
+}
+
+/**
+ * Deserializes the GRFIdentifier (GRF ID and MD5 checksum) from the packet
+ * @param p the packet to read the data from.
+ * @param grf the GRFIdentifier to deserialize.
+ */
+void DeserializeGRFIdentifier(Packet *p, GRFIdentifier *grf)
+{
+ uint j;
+ grf->grfid = p->Recv_uint32();
+ for (j = 0; j < sizeof(grf->md5sum); j++) {
+ grf->md5sum[j] = p->Recv_uint8();
+ }
+}
diff --git a/src/network/core/game.h b/src/network/core/game_info.h
index 29eca418f..776700511 100644
--- a/src/network/core/game.h
+++ b/src/network/core/game_info.h
@@ -6,17 +6,56 @@
*/
/**
- * @file game.h Information about a game that is sent between a
- * game server, game client and masterserver.
+ * @file game_info.h Convert NetworkGameInfo to Packet and back.
*/
-#ifndef NETWORK_CORE_GAME_H
-#define NETWORK_CORE_GAME_H
+#ifndef NETWORK_CORE_GAME_INFO_H
+#define NETWORK_CORE_GAME_INFO_H
#include "config.h"
+#include "core.h"
#include "../../newgrf_config.h"
#include "../../date_type.h"
+/*
+ * NetworkGameInfo has several revisions which we still need to support on the
+ * wire. The table below shows the version and size for each field of the
+ * serialized NetworkGameInfo.
+ *
+ * Version: Bytes: Description:
+ * all 1 the version of this packet's structure
+ *
+ * 4+ 1 number of GRFs attached (n)
+ * 4+ n * 20 unique identifier for GRF files. Consists of:
+ * - one 4 byte variable with the GRF ID
+ * - 16 bytes (sent sequentially) for the MD5 checksum
+ * of the GRF
+ *
+ * 3+ 4 current game date in days since 1-1-0 (DMY)
+ * 3+ 4 game introduction date in days since 1-1-0 (DMY)
+ *
+ * 2+ 1 maximum number of companies allowed on the server
+ * 2+ 1 number of companies on the server
+ * 2+ 1 maximum number of spectators allowed on the server
+ *
+ * 1+ var string with the name of the server
+ * 1+ var string with the revision of the server
+ * 1+ 1 the language run on the server
+ * (0 = any, 1 = English, 2 = German, 3 = French)
+ * 1+ 1 whether the server uses a password (0 = no, 1 = yes)
+ * 1+ 1 maximum number of clients allowed on the server
+ * 1+ 1 number of clients on the server
+ * 1+ 1 number of spectators on the server
+ * 1 & 2 2 current game date in days since 1-1-1920 (DMY)
+ * 1 & 2 2 game introduction date in days since 1-1-1920 (DMY)
+ * 1+ var string with the name of the map
+ * 1+ 2 width of the map in tiles
+ * 1+ 2 height of the map in tiles
+ * 1+ 1 type of map:
+ * (0 = temperate, 1 = arctic, 2 = desert, 3 = toyland)
+ * 1+ 1 whether the server is dedicated (0 = no, 1 = yes)
+ */
+
/**
* The game information that is not generated on-the-fly and has to
* be sent to the clients.
@@ -50,6 +89,17 @@ struct NetworkGameInfo : NetworkServerGameInfo {
byte map_set; ///< Graphical set
};
-const char * GetNetworkRevisionString();
+extern NetworkServerGameInfo _network_game_info;
+
+const char *GetNetworkRevisionString();
+bool IsNetworkCompatibleVersion(const char *other);
+
+void FillNetworkGameInfo(NetworkGameInfo &ngi);
+
+void DeserializeGRFIdentifier(Packet *p, GRFIdentifier *grf);
+void SerializeGRFIdentifier(Packet *p, const GRFIdentifier *grf);
+
+void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info);
+void SerializeNetworkGameInfo(Packet *p, const NetworkGameInfo *info);
-#endif /* NETWORK_CORE_GAME_H */
+#endif /* NETWORK_CORE_GAME_INFO_H */
diff --git a/src/network/core/tcp_http.cpp b/src/network/core/tcp_http.cpp
index d57f4eceb..ee74c4507 100644
--- a/src/network/core/tcp_http.cpp
+++ b/src/network/core/tcp_http.cpp
@@ -13,6 +13,7 @@
#include "../../debug.h"
#include "../../rev.h"
#include "../network_func.h"
+#include "game_info.h"
#include "tcp_http.h"
diff --git a/src/network/core/udp.cpp b/src/network/core/udp.cpp
index df5140e2b..ffc86d825 100644
--- a/src/network/core/udp.cpp
+++ b/src/network/core/udp.cpp
@@ -12,6 +12,7 @@
#include "../../stdafx.h"
#include "../../date_func.h"
#include "../../debug.h"
+#include "game_info.h"
#include "udp.h"
#include "../../safeguards.h"
@@ -150,142 +151,6 @@ void NetworkUDPSocketHandler::ReceivePackets()
}
}
-
-/**
- * Serializes the NetworkGameInfo struct to the packet
- * @param p the packet to write the data to
- * @param info the NetworkGameInfo struct to serialize
- */
-void NetworkUDPSocketHandler::SendNetworkGameInfo(Packet *p, const NetworkGameInfo *info)
-{
- p->Send_uint8 (NETWORK_GAME_INFO_VERSION);
-
- /*
- * Please observe the order.
- * The parts must be read in the same order as they are sent!
- */
-
- /* Update the documentation in udp.h on changes
- * to the NetworkGameInfo wire-protocol! */
-
- /* NETWORK_GAME_INFO_VERSION = 4 */
- {
- /* Only send the GRF Identification (GRF_ID and MD5 checksum) of
- * the GRFs that are needed, i.e. the ones that the server has
- * selected in the NewGRF GUI and not the ones that are used due
- * to the fact that they are in [newgrf-static] in openttd.cfg */
- const GRFConfig *c;
- uint count = 0;
-
- /* Count number of GRFs to send information about */
- for (c = info->grfconfig; c != nullptr; c = c->next) {
- if (!HasBit(c->flags, GCF_STATIC)) count++;
- }
- p->Send_uint8 (count); // Send number of GRFs
-
- /* Send actual GRF Identifications */
- for (c = info->grfconfig; c != nullptr; c = c->next) {
- if (!HasBit(c->flags, GCF_STATIC)) this->SendGRFIdentifier(p, &c->ident);
- }
- }
-
- /* NETWORK_GAME_INFO_VERSION = 3 */
- p->Send_uint32(info->game_date);
- p->Send_uint32(info->start_date);
-
- /* NETWORK_GAME_INFO_VERSION = 2 */
- p->Send_uint8 (info->companies_max);
- p->Send_uint8 (info->companies_on);
- p->Send_uint8 (info->spectators_max);
-
- /* NETWORK_GAME_INFO_VERSION = 1 */
- p->Send_string(info->server_name);
- p->Send_string(info->server_revision);
- p->Send_uint8 (0); // Used to be server-lang.
- p->Send_bool (info->use_password);
- p->Send_uint8 (info->clients_max);
- p->Send_uint8 (info->clients_on);
- p->Send_uint8 (info->spectators_on);
- p->Send_string(""); // Used to be map-name.
- p->Send_uint16(info->map_width);
- p->Send_uint16(info->map_height);
- p->Send_uint8 (info->map_set);
- p->Send_bool (info->dedicated);
-}
-
-/**
- * Deserializes the NetworkGameInfo struct from the packet
- * @param p the packet to read the data from
- * @param info the NetworkGameInfo to deserialize into
- */
-void NetworkUDPSocketHandler::ReceiveNetworkGameInfo(Packet *p, NetworkGameInfo *info)
-{
- static const Date MAX_DATE = ConvertYMDToDate(MAX_YEAR, 11, 31); // December is month 11
-
- info->game_info_version = p->Recv_uint8();
-
- /*
- * Please observe the order.
- * The parts must be read in the same order as they are sent!
- */
-
- /* Update the documentation in udp.h on changes
- * to the NetworkGameInfo wire-protocol! */
-
- switch (info->game_info_version) {
- case 4: {
- GRFConfig **dst = &info->grfconfig;
- uint i;
- uint num_grfs = p->Recv_uint8();
-
- /* Broken/bad data. It cannot have that many NewGRFs. */
- if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
-
- for (i = 0; i < num_grfs; i++) {
- GRFConfig *c = new GRFConfig();
- this->ReceiveGRFIdentifier(p, &c->ident);
- this->HandleIncomingNetworkGameInfoGRFConfig(c);
-
- /* Append GRFConfig to the list */
- *dst = c;
- dst = &c->next;
- }
- FALLTHROUGH;
- }
-
- case 3:
- info->game_date = Clamp(p->Recv_uint32(), 0, MAX_DATE);
- info->start_date = Clamp(p->Recv_uint32(), 0, MAX_DATE);
- FALLTHROUGH;
-
- case 2:
- info->companies_max = p->Recv_uint8 ();
- info->companies_on = p->Recv_uint8 ();
- info->spectators_max = p->Recv_uint8 ();
- FALLTHROUGH;
-
- case 1:
- p->Recv_string(info->server_name, sizeof(info->server_name));
- p->Recv_string(info->server_revision, sizeof(info->server_revision));
- p->Recv_uint8 (); // Used to contain server-lang.
- info->use_password = p->Recv_bool ();
- info->clients_max = p->Recv_uint8 ();
- info->clients_on = p->Recv_uint8 ();
- info->spectators_on = p->Recv_uint8 ();
- if (info->game_info_version < 3) { // 16 bits dates got scrapped and are read earlier
- info->game_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
- info->start_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
- }
- while (p->Recv_uint8() != 0) {} // Used to contain the map-name.
- info->map_width = p->Recv_uint16();
- info->map_height = p->Recv_uint16();
- info->map_set = p->Recv_uint8 ();
- info->dedicated = p->Recv_bool ();
-
- if (info->map_set >= NETWORK_NUM_LANDSCAPES) info->map_set = 0;
- }
-}
-
/**
* Handle an incoming packets by sending it to the correct function.
* @param p the received packet
diff --git a/src/network/core/udp.h b/src/network/core/udp.h
index ddbbd4515..881fb0a61 100644
--- a/src/network/core/udp.h
+++ b/src/network/core/udp.h
@@ -13,7 +13,6 @@
#define NETWORK_CORE_UDP_H
#include "address.h"
-#include "game.h"
#include "packet.h"
/** Enum with all types of UDP packets. The order MUST not be changed **/
@@ -63,40 +62,7 @@ protected:
/**
* Return of server information to the client.
- * This packet has several legacy versions, so we list the version and size of each "field":
- *
- * Version: Bytes: Description:
- * all 1 the version of this packet's structure
- *
- * 4+ 1 number of GRFs attached (n)
- * 4+ n * 20 unique identifier for GRF files. Consists of:
- * - one 4 byte variable with the GRF ID
- * - 16 bytes (sent sequentially) for the MD5 checksum
- * of the GRF
- *
- * 3+ 4 current game date in days since 1-1-0 (DMY)
- * 3+ 4 game introduction date in days since 1-1-0 (DMY)
- *
- * 2+ 1 maximum number of companies allowed on the server
- * 2+ 1 number of companies on the server
- * 2+ 1 maximum number of spectators allowed on the server
- *
- * 1+ var string with the name of the server
- * 1+ var string with the revision of the server
- * 1+ 1 the language run on the server
- * (0 = any, 1 = English, 2 = German, 3 = French)
- * 1+ 1 whether the server uses a password (0 = no, 1 = yes)
- * 1+ 1 maximum number of clients allowed on the server
- * 1+ 1 number of clients on the server
- * 1+ 1 number of spectators on the server
- * 1 & 2 2 current game date in days since 1-1-1920 (DMY)
- * 1 & 2 2 game introduction date in days since 1-1-1920 (DMY)
- * 1+ var string with the name of the map
- * 1+ 2 width of the map in tiles
- * 1+ 2 height of the map in tiles
- * 1+ 1 type of map:
- * (0 = temperate, 1 = arctic, 2 = desert, 3 = toyland)
- * 1+ 1 whether the server is dedicated (0 = no, 1 = yes)
+ * Serialized NetworkGameInfo. See game_info.h for details.
* @param p The received packet.
* @param client_addr The origin of the packet.
*/
@@ -217,15 +183,6 @@ protected:
virtual void Receive_MASTER_SESSION_KEY(Packet *p, NetworkAddress *client_addr);
void HandleUDPPacket(Packet *p, NetworkAddress *client_addr);
-
- /**
- * Function that is called for every GRFConfig that is read when receiving
- * a NetworkGameInfo. Only grfid and md5sum are set, the rest is zero. This
- * function must set all appropriate fields. This GRF is later appended to
- * the grfconfig list of the NetworkGameInfo.
- * @param config the GRF to handle
- */
- virtual void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config) { NOT_REACHED(); }
public:
NetworkUDPSocketHandler(NetworkAddressList *bind = nullptr);
@@ -237,9 +194,6 @@ public:
void SendPacket(Packet *p, NetworkAddress *recv, bool all = false, bool broadcast = false);
void ReceivePackets();
-
- void SendNetworkGameInfo(Packet *p, const NetworkGameInfo *info);
- void ReceiveNetworkGameInfo(Packet *p, NetworkGameInfo *info);
};
#endif /* NETWORK_CORE_UDP_H */
diff --git a/src/network/network.cpp b/src/network/network.cpp
index 812456b4e..9a45ce06e 100644
--- a/src/network/network.cpp
+++ b/src/network/network.cpp
@@ -54,7 +54,6 @@ bool _network_server; ///< network-server is active
bool _network_available; ///< is network mode available?
bool _network_dedicated; ///< are we a dedicated server?
bool _is_network_server; ///< Does this client wants to be a network-server?
-NetworkServerGameInfo _network_game_info; ///< Information about our game.
NetworkCompanyState *_network_company_states = nullptr; ///< Statistics about some companies.
ClientID _network_own_client_id; ///< Our client identifier.
ClientID _redirect_console_to_client; ///< If not invalid, redirect the console output to a client.
@@ -603,9 +602,10 @@ public:
}
};
-/* Query a server to fetch his game-info
- * If game_info is true, only the gameinfo is fetched,
- * else only the client_info is fetched */
+/**
+ * Query a server to fetch his game-info.
+ * @param address the address to query.
+ */
void NetworkTCPQueryServer(NetworkAddress address)
{
if (!_network_available) return;
@@ -1110,79 +1110,6 @@ void NetworkShutDown()
NetworkCoreShutdown();
}
-/**
- * How many hex digits of the git hash to include in network revision string.
- * Determined as 10 hex digits + 2 characters for -g/-u/-m prefix.
- */
-static const uint GITHASH_SUFFIX_LEN = 12;
-
-/**
- * Get the network version string used by this build.
- * The returned string is guaranteed to be at most NETWORK_REVISON_LENGTH bytes.
- */
-const char * GetNetworkRevisionString()
-{
- /* This will be allocated on heap and never free'd, but only once so not a "real" leak. */
- static char *network_revision = nullptr;
-
- if (!network_revision) {
- /* Start by taking a chance on the full revision string. */
- network_revision = stredup(_openttd_revision);
- /* Ensure it's not longer than the packet buffer length. */
- if (strlen(network_revision) >= NETWORK_REVISION_LENGTH) network_revision[NETWORK_REVISION_LENGTH - 1] = '\0';
-
- /* Tag names are not mangled further. */
- if (_openttd_revision_tagged) {
- DEBUG(net, 1, "Network revision name is '%s'", network_revision);
- return network_revision;
- }
-
- /* Prepare a prefix of the git hash.
- * Size is length + 1 for terminator, +2 for -g prefix. */
- assert(_openttd_revision_modified < 3);
- char githash_suffix[GITHASH_SUFFIX_LEN + 1] = "-";
- githash_suffix[1] = "gum"[_openttd_revision_modified];
- for (uint i = 2; i < GITHASH_SUFFIX_LEN; i++) {
- githash_suffix[i] = _openttd_revision_hash[i-2];
- }
-
- /* Where did the hash start in the original string?
- * Overwrite from that position, unless that would go past end of packet buffer length. */
- ptrdiff_t hashofs = strrchr(_openttd_revision, '-') - _openttd_revision;
- if (hashofs + strlen(githash_suffix) + 1 > NETWORK_REVISION_LENGTH) hashofs = strlen(network_revision) - strlen(githash_suffix);
- /* Replace the git hash in revision string. */
- strecpy(network_revision + hashofs, githash_suffix, network_revision + NETWORK_REVISION_LENGTH);
- assert(strlen(network_revision) < NETWORK_REVISION_LENGTH); // strlen does not include terminator, constant does, hence strictly less than
- DEBUG(net, 1, "Network revision name is '%s'", network_revision);
- }
-
- return network_revision;
-}
-
-static const char *ExtractNetworkRevisionHash(const char *revstr)
-{
- return strrchr(revstr, '-');
-}
-
-/**
- * Checks whether the given version string is compatible with our version.
- * First tries to match the full string, if that fails, attempts to compare just git hashes.
- * @param other the version string to compare to
- */
-bool IsNetworkCompatibleVersion(const char *other)
-{
- if (strncmp(GetNetworkRevisionString(), other, NETWORK_REVISION_LENGTH - 1) == 0) return true;
-
- /* If this version is tagged, then the revision string must be a complete match,
- * since there is no git hash suffix in it.
- * This is needed to avoid situations like "1.9.0-beta1" comparing equal to "2.0.0-beta1". */
- if (_openttd_revision_tagged) return false;
-
- const char *hash1 = ExtractNetworkRevisionHash(GetNetworkRevisionString());
- const char *hash2 = ExtractNetworkRevisionHash(other);
- return hash1 && hash2 && (strncmp(hash1, hash2, GITHASH_SUFFIX_LEN) == 0);
-}
-
#ifdef __EMSCRIPTEN__
extern "C" {
diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp
index 1b86c3e56..7b4975451 100644
--- a/src/network/network_admin.cpp
+++ b/src/network/network_admin.cpp
@@ -10,6 +10,7 @@
#include "../stdafx.h"
#include "../strings_func.h"
#include "../date_func.h"
+#include "core/game_info.h"
#include "network_admin.h"
#include "network_base.h"
#include "network_server.h"
diff --git a/src/network/network_base.h b/src/network/network_base.h
index 15f410dbc..9ad030062 100644
--- a/src/network/network_base.h
+++ b/src/network/network_base.h
@@ -14,6 +14,7 @@
#include "core/address.h"
#include "../core/pool_type.hpp"
#include "../company_type.h"
+#include "../date_type.h"
/** Type for the pool with client information. */
typedef Pool<NetworkClientInfo, ClientIndex, 8, MAX_CLIENT_SLOTS, PT_NCLIENT> NetworkClientInfoPool;
diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp
index d5fe64b11..f49692307 100644
--- a/src/network/network_client.cpp
+++ b/src/network/network_client.cpp
@@ -23,6 +23,7 @@
#include "../gfx_func.h"
#include "../error.h"
#include "../rev.h"
+#include "core/game_info.h"
#include "network.h"
#include "network_base.h"
#include "network_client.h"
@@ -730,7 +731,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHECK_NEWGRFS(P
/* Check all GRFs */
for (; grf_count > 0; grf_count--) {
GRFIdentifier c;
- this->ReceiveGRFIdentifier(p, &c);
+ DeserializeGRFIdentifier(p, &c);
/* Check whether we know this GRF */
const GRFConfig *f = FindGRFConfig(c.grfid, FGCM_EXACT, c.md5sum);
diff --git a/src/network/network_func.h b/src/network/network_func.h
index 66719b216..a0f163345 100644
--- a/src/network/network_func.h
+++ b/src/network/network_func.h
@@ -22,8 +22,8 @@
#include "../gfx_type.h"
#include "../openttd.h"
#include "../company_type.h"
+#include "../string_type.h"
-extern NetworkServerGameInfo _network_game_info;
extern NetworkCompanyState *_network_company_states;
extern ClientID _network_own_client_id;
diff --git a/src/network/network_gamelist.h b/src/network/network_gamelist.h
index 8e61f3a93..ce35c01d8 100644
--- a/src/network/network_gamelist.h
+++ b/src/network/network_gamelist.h
@@ -11,6 +11,7 @@
#define NETWORK_GAMELIST_H
#include "core/address.h"
+#include "core/game_info.h"
#include "network_type.h"
/** Structure with information shown in the game list (GUI) */
diff --git a/src/network/network_gui.h b/src/network/network_gui.h
index 512495562..b8ed68225 100644
--- a/src/network/network_gui.h
+++ b/src/network/network_gui.h
@@ -11,6 +11,7 @@
#define NETWORK_GUI_H
#include "../company_type.h"
+#include "../date_type.h"
#include "../economy_type.h"
#include "../window_type.h"
#include "network_type.h"
diff --git a/src/network/network_internal.h b/src/network/network_internal.h
index 352416320..c64eac795 100644
--- a/src/network/network_internal.h
+++ b/src/network/network_internal.h
@@ -94,8 +94,6 @@ void NetworkAddServer(const char *b);
void NetworkRebuildHostList();
void UpdateNetworkGameWindow();
-bool IsNetworkCompatibleVersion(const char *version);
-
/* From network_command.cpp */
/**
* Everything we need to know about a command to be able to execute it.
diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp
index 67952bca6..6bc6f8291 100644
--- a/src/network/network_server.cpp
+++ b/src/network/network_server.cpp
@@ -10,6 +10,7 @@
#include "../stdafx.h"
#include "../strings_func.h"
#include "../date_func.h"
+#include "core/game_info.h"
#include "network_admin.h"
#include "network_server.h"
#include "network_udp.h"
@@ -477,7 +478,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendNewGRFCheck()
p->Send_uint8 (grf_count);
for (c = _grfconfig; c != nullptr; c = c->next) {
- if (!HasBit(c->flags, GCF_STATIC)) this->SendGRFIdentifier(p, &c->ident);
+ if (!HasBit(c->flags, GCF_STATIC)) SerializeGRFIdentifier(p, &c->ident);
}
this->SendPacket(p);
diff --git a/src/network/network_type.h b/src/network/network_type.h
index 4c75346da..4dcdd8c03 100644
--- a/src/network/network_type.h
+++ b/src/network/network_type.h
@@ -10,7 +10,7 @@
#ifndef NETWORK_TYPE_H
#define NETWORK_TYPE_H
-#include "core/game.h"
+#include "core/config.h"
/** How many clients can we have */
static const uint MAX_CLIENTS = 255;
diff --git a/src/network/network_udp.cpp b/src/network/network_udp.cpp
index f7db689d4..8e661e939 100644
--- a/src/network/network_udp.cpp
+++ b/src/network/network_udp.cpp
@@ -16,6 +16,7 @@
#include "../date_func.h"
#include "../map_func.h"
#include "../debug.h"
+#include "core/game_info.h"
#include "network_gamelist.h"
#include "network_internal.h"
#include "network_udp.h"
@@ -171,29 +172,10 @@ void ServerNetworkUDPSocketHandler::Receive_CLIENT_FIND_SERVER(Packet *p, Networ
}
NetworkGameInfo ngi;
-
- /* Update some game_info */
- ngi.clients_on = _network_game_info.clients_on;
- ngi.start_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
-
- ngi.use_password = !StrEmpty(_settings_client.network.server_password);
- ngi.clients_max = _settings_client.network.max_clients;
- ngi.companies_on = (byte)Company::GetNumItems();
- ngi.companies_max = _settings_client.network.max_companies;
- ngi.spectators_on = NetworkSpectatorCount();
- ngi.spectators_max = _settings_client.network.max_spectators;
- ngi.game_date = _date;
- ngi.map_width = MapSizeX();
- ngi.map_height = MapSizeY();
- ngi.map_set = _settings_game.game_creation.landscape;
- ngi.dedicated = _network_dedicated;
- ngi.grfconfig = _grfconfig;
-
- strecpy(ngi.server_name, _settings_client.network.server_name, lastof(ngi.server_name));
- strecpy(ngi.server_revision, GetNetworkRevisionString(), lastof(ngi.server_revision));
+ FillNetworkGameInfo(ngi);
Packet packet(PACKET_UDP_SERVER_RESPONSE);
- this->SendNetworkGameInfo(&packet, &ngi);
+ SerializeNetworkGameInfo(&packet, &ngi);
/* Let the client know that we are here */
this->SendPacket(&packet, client_addr);
@@ -284,7 +266,7 @@ void ServerNetworkUDPSocketHandler::Receive_CLIENT_GET_NEWGRFS(Packet *p, Networ
GRFIdentifier c;
const GRFConfig *f;
- this->ReceiveGRFIdentifier(p, &c);
+ DeserializeGRFIdentifier(p, &c);
/* Find the matching GRF file */
f = FindGRFConfig(c.grfid, FGCM_EXACT, c.md5sum);
@@ -311,7 +293,7 @@ void ServerNetworkUDPSocketHandler::Receive_CLIENT_GET_NEWGRFS(Packet *p, Networ
/* The name could be an empty string, if so take the filename */
strecpy(name, in_reply[i]->GetName(), lastof(name));
- this->SendGRFIdentifier(&packet, &in_reply[i]->ident);
+ SerializeGRFIdentifier(&packet, &in_reply[i]->ident);
packet.Send_string(name);
}
@@ -326,7 +308,6 @@ 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;
- void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config) override;
public:
virtual ~ClientNetworkUDPSocketHandler() {}
};
@@ -344,7 +325,7 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet *p, NetworkAd
item = NetworkGameListAddItem(*client_addr);
ClearGRFConfigList(&item->info.grfconfig);
- this->ReceiveNetworkGameInfo(p, &item->info);
+ DeserializeNetworkGameInfo(p, &item->info);
item->info.compatible = true;
{
@@ -373,7 +354,7 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet *p, NetworkAd
packet.Send_uint8(in_request_count);
for (i = 0; i < in_request_count; i++) {
- this->SendGRFIdentifier(&packet, &in_request[i]->ident);
+ SerializeGRFIdentifier(&packet, &in_request[i]->ident);
}
this->SendPacket(&packet, &item->address);
@@ -447,7 +428,7 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet *p, NetworkAdd
char name[NETWORK_GRF_NAME_LENGTH];
GRFIdentifier c;
- this->ReceiveGRFIdentifier(p, &c);
+ DeserializeGRFIdentifier(p, &c);
p->Recv_string(name, sizeof(name));
/* An empty name is not possible under normal circumstances
@@ -464,25 +445,6 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet *p, NetworkAdd
}
}
-void ClientNetworkUDPSocketHandler::HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config)
-{
- /* Find the matching GRF file */
- const GRFConfig *f = FindGRFConfig(config->ident.grfid, FGCM_EXACT, config->ident.md5sum);
- if (f == nullptr) {
- /* Don't know the GRF, so mark game incompatible and the (possibly)
- * already resolved name for this GRF (another server has sent the
- * name of the GRF already */
- config->name = FindUnknownGRFName(config->ident.grfid, config->ident.md5sum, true);
- config->status = GCS_NOT_FOUND;
- } else {
- config->filename = f->filename;
- config->name = f->name;
- config->info = f->info;
- config->url = f->url;
- }
- SetBit(config->flags, GCF_COPY);
-}
-
/** Broadcast to all ips */
static void NetworkUDPBroadCast(NetworkUDPSocketHandler *socket)
{