OpenTTD Source: src/network/core/tcp_content.cpp Source File

OpenTTD Source 15.3

tcp_content.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
12#include "../../stdafx.h"
13#include "../../textfile_gui.h"
14#include "../../newgrf_config.h"
15#include "../../base_media_base.h"
16#include "../../base_media_graphics.h"
17#include "../../base_media_music.h"
18#include "../../base_media_sounds.h"
19#include "../../ai/ai.hpp"
20#include "../../game/game.hpp"
21#include "../../fios.h"
22#include "tcp_content.h"
23
24#include "table/strings.h"
25
26#include "../../safeguards.h"
27
32 bool ContentInfo::IsSelected() const
33{
34 switch (this->state) {
35 case ContentInfo::State::Selected:
36 case ContentInfo::State::Autoselected:
37 case ContentInfo::State::AlreadyHere:
38 return true;
39
40 default:
41 return false;
42 }
43}
44
49 bool ContentInfo::IsValid() const
50{
51 return this->state < ContentInfo::State::Invalid && this->type >= CONTENT_TYPE_BEGIN && this->type < CONTENT_TYPE_END;
52}
53
59std::optional<std::string> ContentInfo::GetTextfile(TextfileType type) const
60{
61 if (this->state == ContentInfo::State::Invalid) return std::nullopt;
62 std::optional<std::string_view> tmp;
63 switch (this->type) {
64 default: NOT_REACHED();
65 case CONTENT_TYPE_AI:
66 tmp = AI::GetScannerInfo()->FindMainScript(*this, true);
67 break;
68 case CONTENT_TYPE_AI_LIBRARY:
69 tmp = AI::GetScannerLibrary()->FindMainScript(*this, true);
70 break;
71 case CONTENT_TYPE_GAME:
72 tmp = Game::GetScannerInfo()->FindMainScript(*this, true);
73 break;
74 case CONTENT_TYPE_GAME_LIBRARY:
75 tmp = Game::GetScannerLibrary()->FindMainScript(*this, true);
76 break;
77 case CONTENT_TYPE_NEWGRF: {
78 const GRFConfig *gc = FindGRFConfig(std::byteswap(this->unique_id), FGCM_EXACT, &this->md5sum);
79 if (gc != nullptr) tmp = gc->filename;
80 break;
81 }
82 case CONTENT_TYPE_BASE_GRAPHICS:
83 tmp = TryGetBaseSetFile(*this, true, BaseGraphics::GetAvailableSets());
84 break;
85 case CONTENT_TYPE_BASE_SOUNDS:
86 tmp = TryGetBaseSetFile(*this, true, BaseSounds::GetAvailableSets());
87 break;
88 case CONTENT_TYPE_BASE_MUSIC:
89 tmp = TryGetBaseSetFile(*this, true, BaseMusic::GetAvailableSets());
90 break;
91 case CONTENT_TYPE_SCENARIO:
92 case CONTENT_TYPE_HEIGHTMAP:
93 tmp = FindScenario(*this, true);
94 break;
95 }
96 if (!tmp.has_value()) return std::nullopt;
97 return ::GetTextfile(type, GetContentInfoSubDir(this->type), *tmp);
98}
99
106 bool NetworkContentSocketHandler::HandlePacket(Packet &p)
107{
108 PacketContentType type = (PacketContentType)p.Recv_uint8();
109
110 switch (this->HasClientQuit() ? PACKET_CONTENT_END : type) {
111 case PACKET_CONTENT_CLIENT_INFO_LIST: return this->Receive_CLIENT_INFO_LIST(p);
112 case PACKET_CONTENT_CLIENT_INFO_ID: return this->Receive_CLIENT_INFO_ID(p);
113 case PACKET_CONTENT_CLIENT_INFO_EXTID: return this->Receive_CLIENT_INFO_EXTID(p);
114 case PACKET_CONTENT_CLIENT_INFO_EXTID_MD5: return this->Receive_CLIENT_INFO_EXTID_MD5(p);
115 case PACKET_CONTENT_SERVER_INFO: return this->Receive_SERVER_INFO(p);
116 case PACKET_CONTENT_CLIENT_CONTENT: return this->Receive_CLIENT_CONTENT(p);
117 case PACKET_CONTENT_SERVER_CONTENT: return this->Receive_SERVER_CONTENT(p);
118
119 default:
120 if (this->HasClientQuit()) {
121 Debug(net, 0, "[tcp/content] Received invalid packet type {}", type);
122 } else {
123 Debug(net, 0, "[tcp/content] Received illegal packet");
124 }
125 return false;
126 }
127}
128
133 bool NetworkContentSocketHandler::ReceivePackets()
134{
135 /*
136 * We read only a few of the packets. This as receiving packets can be expensive
137 * due to the re-resolving of the parent/child relations and checking the toggle
138 * state of all bits. We cannot do this all in one go, as we want to show the
139 * user what we already received. Otherwise, it can take very long before any
140 * progress is shown to the end user that something has been received.
141 * It is also the case that we request extra content from the content server in
142 * case there is an unknown (in the content list) piece of content. These will
143 * come in after the main lists have been requested. As a result, we won't be
144 * getting everything reliably in one batch. Thus, we need to make subsequent
145 * updates in that case as well.
146 *
147 * As a result, we simple handle an arbitrary number of packets in one cycle,
148 * and let the rest be handled in subsequent cycles. These are ran, almost,
149 * immediately after this cycle so in speed it does not matter much, except
150 * that the user interface will appear better responding.
151 *
152 * What arbitrary number to choose is the ultimate question though.
153 */
154 std::unique_ptr<Packet> p;
155 static const int MAX_PACKETS_TO_RECEIVE = 42;
156 int i = MAX_PACKETS_TO_RECEIVE;
157 while (--i != 0 && (p = this->ReceivePacket()) != nullptr) {
158 bool cont = this->HandlePacket(*p);
159 if (!cont) return true;
160 }
161
162 return i != MAX_PACKETS_TO_RECEIVE - 1;
163}
164
165
171 bool NetworkContentSocketHandler::ReceiveInvalidPacket(PacketContentType type)
172{
173 Debug(net, 0, "[tcp/content] Received illegal packet type {}", type);
174 return false;
175}
176
177 bool NetworkContentSocketHandler::Receive_CLIENT_INFO_LIST(Packet &) { return this->ReceiveInvalidPacket(PACKET_CONTENT_CLIENT_INFO_LIST); }
178 bool NetworkContentSocketHandler::Receive_CLIENT_INFO_ID(Packet &) { return this->ReceiveInvalidPacket(PACKET_CONTENT_CLIENT_INFO_ID); }
179 bool NetworkContentSocketHandler::Receive_CLIENT_INFO_EXTID(Packet &) { return this->ReceiveInvalidPacket(PACKET_CONTENT_CLIENT_INFO_EXTID); }
180 bool NetworkContentSocketHandler::Receive_CLIENT_INFO_EXTID_MD5(Packet &) { return this->ReceiveInvalidPacket(PACKET_CONTENT_CLIENT_INFO_EXTID_MD5); }
181 bool NetworkContentSocketHandler::Receive_SERVER_INFO(Packet &) { return this->ReceiveInvalidPacket(PACKET_CONTENT_SERVER_INFO); }
182 bool NetworkContentSocketHandler::Receive_CLIENT_CONTENT(Packet &) { return this->ReceiveInvalidPacket(PACKET_CONTENT_CLIENT_CONTENT); }
183 bool NetworkContentSocketHandler::Receive_SERVER_CONTENT(Packet &) { return this->ReceiveInvalidPacket(PACKET_CONTENT_SERVER_CONTENT); }
184
190 Subdirectory GetContentInfoSubDir(ContentType type)
191{
192 switch (type) {
193 default: return NO_DIRECTORY;
194 case CONTENT_TYPE_AI: return AI_DIR;
195 case CONTENT_TYPE_AI_LIBRARY: return AI_LIBRARY_DIR;
196 case CONTENT_TYPE_GAME: return GAME_DIR;
197 case CONTENT_TYPE_GAME_LIBRARY: return GAME_LIBRARY_DIR;
198 case CONTENT_TYPE_NEWGRF: return NEWGRF_DIR;
199
200 case CONTENT_TYPE_BASE_GRAPHICS:
201 case CONTENT_TYPE_BASE_SOUNDS:
202 case CONTENT_TYPE_BASE_MUSIC:
203 return BASESET_DIR;
204
205 case CONTENT_TYPE_SCENARIO: return SCENARIO_DIR;
206 case CONTENT_TYPE_HEIGHTMAP: return HEIGHTMAP_DIR;
207 }
208}
TryGetBaseSetFile
std::optional< std::string_view > TryGetBaseSetFile(const ContentInfo &ci, bool md5sum, std::span< const std::unique_ptr< Tbase_set > > sets)
Check whether there's a base set matching some information.
Definition base_media_func.h:328
AI::GetScannerLibrary
static AIScannerLibrary * GetScannerLibrary()
Gets the ScriptScanner instance that is used to find AI Libraries.
Definition ai_core.cpp:352
AI::GetScannerInfo
static AIScannerInfo * GetScannerInfo()
Gets the ScriptScanner instance that is used to find AIs.
Definition ai_core.cpp:347
BaseMedia< GraphicsSet >::GetAvailableSets
static std::span< const std::unique_ptr< GraphicsSet > > GetAvailableSets()
Return the available sets.
Definition base_media_base.h:203
Game::GetScannerLibrary
static GameScannerLibrary * GetScannerLibrary()
Gets the ScriptScanner instance that is used to find Game Libraries.
Definition game_core.cpp:259
Game::GetScannerInfo
static GameScannerInfo * GetScannerInfo()
Gets the ScriptScanner instance that is used to find Game scripts.
Definition game_core.cpp:255
NetworkContentSocketHandler::Receive_CLIENT_CONTENT
virtual bool Receive_CLIENT_CONTENT(Packet &p)
Client requesting the actual content: uint16_t count of unique ids uint32_t unique id (count times)
Definition tcp_content.cpp:182
NetworkContentSocketHandler::Receive_CLIENT_INFO_EXTID
virtual bool Receive_CLIENT_INFO_EXTID(Packet &p)
Client requesting a list of content info based on an external 'unique' id; GRF ID for NewGRFS,...
Definition tcp_content.cpp:179
NetworkContentSocketHandler::Receive_CLIENT_INFO_EXTID_MD5
virtual bool Receive_CLIENT_INFO_EXTID_MD5(Packet &p)
Client requesting a list of content info based on an external 'unique' id; GRF ID + MD5 checksum for ...
Definition tcp_content.cpp:180
NetworkContentSocketHandler::Receive_SERVER_INFO
virtual bool Receive_SERVER_INFO(Packet &p)
Server sending list of content info: uint8_t type (invalid ID == does not exist) uint32_t id uint32_t...
Definition tcp_content.cpp:181
NetworkContentSocketHandler::Receive_CLIENT_INFO_ID
virtual bool Receive_CLIENT_INFO_ID(Packet &p)
Client requesting a list of content info: uint16_t count of ids uint32_t id (count times)
Definition tcp_content.cpp:178
NetworkContentSocketHandler::Receive_SERVER_CONTENT
virtual bool Receive_SERVER_CONTENT(Packet &p)
Server sending list of content info: uint32_t unique id uint32_t file size (0 == does not exist) stri...
Definition tcp_content.cpp:183
NetworkContentSocketHandler::ReceivePackets
bool ReceivePackets()
Receive a packet at TCP level.
Definition tcp_content.cpp:133
NetworkContentSocketHandler::Receive_CLIENT_INFO_LIST
virtual bool Receive_CLIENT_INFO_LIST(Packet &p)
Client requesting a list of content info: uint8_t type uint32_t openttd version (or 0xFFFFFFFF if usi...
Definition tcp_content.cpp:177
NetworkContentSocketHandler::ReceiveInvalidPacket
bool ReceiveInvalidPacket(PacketContentType type)
Helper for logging receiving invalid packets.
Definition tcp_content.cpp:171
NetworkContentSocketHandler::HandlePacket
bool HandlePacket(Packet &p)
Handle the given packet, i.e.
Definition tcp_content.cpp:106
NetworkSocketHandler::HasClientQuit
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition core.h:74
NetworkTCPSocketHandler::ReceivePacket
virtual std::unique_ptr< Packet > ReceivePacket()
Receives a packet for the given client.
Definition tcp.cpp:119
ScriptScanner::FindMainScript
std::optional< std::string_view > FindMainScript(const ContentInfo &ci, bool md5sum)
Find a script of a ContentInfo.
Definition script_scanner.cpp:233
Debug
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
Subdirectory
Subdirectory
The different kinds of subdirectories OpenTTD uses.
Definition fileio_type.h:88
NO_DIRECTORY
@ NO_DIRECTORY
A path without any base directory.
Definition fileio_type.h:107
AI_LIBRARY_DIR
@ AI_LIBRARY_DIR
Subdirectory for all AI libraries.
Definition fileio_type.h:100
GAME_LIBRARY_DIR
@ GAME_LIBRARY_DIR
Subdirectory for all GS libraries.
Definition fileio_type.h:102
AI_DIR
@ AI_DIR
Subdirectory for all AI files.
Definition fileio_type.h:99
SCENARIO_DIR
@ SCENARIO_DIR
Base directory for all scenarios.
Definition fileio_type.h:92
HEIGHTMAP_DIR
@ HEIGHTMAP_DIR
Subdirectory of scenario for heightmaps.
Definition fileio_type.h:93
NEWGRF_DIR
@ NEWGRF_DIR
Subdirectory for all NewGRFs.
Definition fileio_type.h:97
BASESET_DIR
@ BASESET_DIR
Subdirectory for all base data (base sets, intro game)
Definition fileio_type.h:96
GAME_DIR
@ GAME_DIR
Subdirectory for all game scripts.
Definition fileio_type.h:101
FindScenario
std::optional< std::string_view > FindScenario(const ContentInfo &ci, bool md5sum)
Find a given scenario based on its unique ID.
Definition fios.cpp:664
FindGRFConfig
const GRFConfig * FindGRFConfig(uint32_t grfid, FindGRFConfigMode mode, const MD5Hash *md5sum, uint32_t desired_version)
Find a NewGRF in the scanned list.
Definition newgrf_config.cpp:596
FGCM_EXACT
@ FGCM_EXACT
Only find Grfs matching md5sum.
Definition newgrf_config.h:208
ContentInfo::unique_id
uint32_t unique_id
Unique ID; either GRF ID or shortname.
Definition tcp_content_type.h:75
ContentInfo::IsValid
bool IsValid() const
Is the information from this content info valid?
Definition tcp_content.cpp:49
ContentInfo::md5sum
MD5Hash md5sum
The MD5 checksum.
Definition tcp_content_type.h:76
ContentInfo::state
State state
Whether the content info is selected (for download)
Definition tcp_content_type.h:79
ContentInfo::GetTextfile
std::optional< std::string > GetTextfile(TextfileType type) const
Search a textfile file next to this file in the content list.
Definition tcp_content.cpp:59
ContentInfo::IsSelected
bool IsSelected() const
Is the state either selected or autoselected?
Definition tcp_content.cpp:32
ContentInfo::type
ContentType type
Type of content.
Definition tcp_content_type.h:67
ContentInfo::State::Invalid
@ Invalid
The content's invalid.
ContentInfo::State::AlreadyHere
@ AlreadyHere
The content is already at the client side.
ContentInfo::State::Selected
@ Selected
The content has been manually selected.
ContentInfo::State::Autoselected
@ Autoselected
The content has been selected as dependency.
GRFConfig
Information about GRF, used in the game and (part of it) in savegames.
Definition newgrf_config.h:158
GRFConfig::filename
std::string filename
Filename - either with or without full path.
Definition newgrf_config.h:170
Packet
Internal entity of a packet.
Definition packet.h:43
Packet::Recv_uint8
uint8_t Recv_uint8()
Read a 8 bits integer from the packet.
Definition packet.cpp:318
GetContentInfoSubDir
Subdirectory GetContentInfoSubDir(ContentType type)
Helper to get the subdirectory a ContentInfo is located in.
Definition tcp_content.cpp:190
tcp_content.h
Basic functions to receive and send TCP packets to/from the content server.
ContentType
ContentType
The values in the enum are important; they are used as database 'keys'.
Definition tcp_content_type.h:21
CONTENT_TYPE_AI_LIBRARY
@ CONTENT_TYPE_AI_LIBRARY
The content consists of an AI library.
Definition tcp_content_type.h:26
CONTENT_TYPE_BASE_SOUNDS
@ CONTENT_TYPE_BASE_SOUNDS
The content consists of base sounds.
Definition tcp_content_type.h:29
CONTENT_TYPE_GAME_LIBRARY
@ CONTENT_TYPE_GAME_LIBRARY
The content consists of a GS library.
Definition tcp_content_type.h:32
CONTENT_TYPE_BASE_GRAPHICS
@ CONTENT_TYPE_BASE_GRAPHICS
The content consists of base graphics.
Definition tcp_content_type.h:23
CONTENT_TYPE_AI
@ CONTENT_TYPE_AI
The content consists of an AI.
Definition tcp_content_type.h:25
CONTENT_TYPE_SCENARIO
@ CONTENT_TYPE_SCENARIO
The content consists of a scenario.
Definition tcp_content_type.h:27
CONTENT_TYPE_NEWGRF
@ CONTENT_TYPE_NEWGRF
The content consists of a NewGRF.
Definition tcp_content_type.h:24
CONTENT_TYPE_BEGIN
@ CONTENT_TYPE_BEGIN
Helper to mark the begin of the types.
Definition tcp_content_type.h:22
CONTENT_TYPE_BASE_MUSIC
@ CONTENT_TYPE_BASE_MUSIC
The content consists of base music.
Definition tcp_content_type.h:30
CONTENT_TYPE_GAME
@ CONTENT_TYPE_GAME
The content consists of a game script.
Definition tcp_content_type.h:31
CONTENT_TYPE_END
@ CONTENT_TYPE_END
Helper to mark the end of the types.
Definition tcp_content_type.h:33
CONTENT_TYPE_HEIGHTMAP
@ CONTENT_TYPE_HEIGHTMAP
The content consists of a heightmap.
Definition tcp_content_type.h:28
PacketContentType
PacketContentType
Enum with all types of TCP content packets.
Definition tcp_content_type.h:39
PACKET_CONTENT_CLIENT_CONTENT
@ PACKET_CONTENT_CLIENT_CONTENT
Request a content file given an internal ID.
Definition tcp_content_type.h:45
PACKET_CONTENT_END
@ PACKET_CONTENT_END
Must ALWAYS be on the end of this list!! (period)
Definition tcp_content_type.h:47
PACKET_CONTENT_CLIENT_INFO_LIST
@ PACKET_CONTENT_CLIENT_INFO_LIST
Queries the content server for a list of info of a given content type.
Definition tcp_content_type.h:40
PACKET_CONTENT_CLIENT_INFO_EXTID_MD5
@ PACKET_CONTENT_CLIENT_INFO_EXTID_MD5
Queries the content server for information about a list of external IDs and MD5.
Definition tcp_content_type.h:43
PACKET_CONTENT_SERVER_INFO
@ PACKET_CONTENT_SERVER_INFO
Reply of content server with information about content.
Definition tcp_content_type.h:44
PACKET_CONTENT_SERVER_CONTENT
@ PACKET_CONTENT_SERVER_CONTENT
Reply with the content of the given ID.
Definition tcp_content_type.h:46
PACKET_CONTENT_CLIENT_INFO_ID
@ PACKET_CONTENT_CLIENT_INFO_ID
Queries the content server for information about a list of internal IDs.
Definition tcp_content_type.h:41
PACKET_CONTENT_CLIENT_INFO_EXTID
@ PACKET_CONTENT_CLIENT_INFO_EXTID
Queries the content server for information about a list of external IDs.
Definition tcp_content_type.h:42
TextfileType
TextfileType
Additional text files accompanying Tar archives.
Definition textfile_type.h:14