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

OpenTTD Source 1.11.0-RC1

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 <http://www.gnu.org/licenses/>.
6 */
7
12 #include "../../stdafx.h"
13 #ifndef OPENTTD_MSU
14 #include "../../textfile_gui.h"
15 #include "../../newgrf_config.h"
16 #include "../../base_media_base.h"
17 #include "../../ai/ai.hpp"
18 #include "../../game/game.hpp"
19 #include "../../fios.h"
20 #endif /* OPENTTD_MSU */
21 #include "tcp_content.h"
22
23 #include "../../safeguards.h"
24
26 ContentInfo::ContentInfo()
27 {
28 memset(this, 0, sizeof(*this));
29 }
30
32 ContentInfo::~ContentInfo()
33 {
34 free(this->dependencies);
35 free(this->tags);
36 }
37
42 void ContentInfo::TransferFrom(ContentInfo *other)
43 {
44 if (other != this) {
45 free(this->dependencies);
46 free(this->tags);
47 memcpy(this, other, sizeof(ContentInfo));
48 other->dependencies = nullptr;
49 other->tags = nullptr;
50 }
51 }
52
57 size_t ContentInfo::Size() const
58 {
59 size_t len = 0;
60 for (uint i = 0; i < this->tag_count; i++) len += strlen(this->tags[i]) + 1;
61
62 /* The size is never larger than the content info size plus the size of the
63 * tags and dependencies */
64 return sizeof(*this) +
65 sizeof(this->dependency_count) +
66 sizeof(*this->dependencies) * this->dependency_count;
67 }
68
73 bool ContentInfo::IsSelected() const
74 {
75 switch (this->state) {
76 case ContentInfo::SELECTED:
77 case ContentInfo::AUTOSELECTED:
78 case ContentInfo::ALREADY_HERE:
79 return true;
80
81 default:
82 return false;
83 }
84 }
85
90 bool ContentInfo::IsValid() const
91 {
92 return this->state < ContentInfo::INVALID && this->type >= CONTENT_TYPE_BEGIN && this->type < CONTENT_TYPE_END;
93 }
94
95 #ifndef OPENTTD_MSU
96
101 const char *ContentInfo::GetTextfile(TextfileType type) const
102 {
103 if (this->state == INVALID) return nullptr;
104 const char *tmp;
105 switch (this->type) {
106 default: NOT_REACHED();
107 case CONTENT_TYPE_AI:
108 tmp = AI::GetScannerInfo()->FindMainScript(this, true);
109 break;
110 case CONTENT_TYPE_AI_LIBRARY:
111 tmp = AI::GetScannerLibrary()->FindMainScript(this, true);
112 break;
113 case CONTENT_TYPE_GAME:
114 tmp = Game::GetScannerInfo()->FindMainScript(this, true);
115 break;
116 case CONTENT_TYPE_GAME_LIBRARY:
117 tmp = Game::GetScannerLibrary()->FindMainScript(this, true);
118 break;
119 case CONTENT_TYPE_NEWGRF: {
120 const GRFConfig *gc = FindGRFConfig(BSWAP32(this->unique_id), FGCM_EXACT, this->md5sum);
121 tmp = gc != nullptr ? gc->filename : nullptr;
122 break;
123 }
124 case CONTENT_TYPE_BASE_GRAPHICS:
125 tmp = TryGetBaseSetFile(this, true, BaseGraphics::GetAvailableSets());
126 break;
127 case CONTENT_TYPE_BASE_SOUNDS:
128 tmp = TryGetBaseSetFile(this, true, BaseSounds::GetAvailableSets());
129 break;
130 case CONTENT_TYPE_BASE_MUSIC:
131 tmp = TryGetBaseSetFile(this, true, BaseMusic::GetAvailableSets());
132 break;
133 case CONTENT_TYPE_SCENARIO:
134 case CONTENT_TYPE_HEIGHTMAP:
135 extern const char *FindScenario(const ContentInfo *ci, bool md5sum);
136 tmp = FindScenario(this, true);
137 break;
138 }
139 if (tmp == nullptr) return nullptr;
140 return ::GetTextfile(type, GetContentInfoSubDir(this->type), tmp);
141 }
142 #endif /* OPENTTD_MSU */
143
144 void NetworkContentSocketHandler::Close()
145 {
146 CloseConnection();
147 if (this->sock == INVALID_SOCKET) return;
148
149 closesocket(this->sock);
150 this->sock = INVALID_SOCKET;
151 }
152
159 bool NetworkContentSocketHandler::HandlePacket(Packet *p)
160 {
161 PacketContentType type = (PacketContentType)p->Recv_uint8();
162
163 switch (this->HasClientQuit() ? PACKET_CONTENT_END : type) {
164 case PACKET_CONTENT_CLIENT_INFO_LIST: return this->Receive_CLIENT_INFO_LIST(p);
165 case PACKET_CONTENT_CLIENT_INFO_ID: return this->Receive_CLIENT_INFO_ID(p);
166 case PACKET_CONTENT_CLIENT_INFO_EXTID: return this->Receive_CLIENT_INFO_EXTID(p);
167 case PACKET_CONTENT_CLIENT_INFO_EXTID_MD5: return this->Receive_CLIENT_INFO_EXTID_MD5(p);
168 case PACKET_CONTENT_SERVER_INFO: return this->Receive_SERVER_INFO(p);
169 case PACKET_CONTENT_CLIENT_CONTENT: return this->Receive_CLIENT_CONTENT(p);
170 case PACKET_CONTENT_SERVER_CONTENT: return this->Receive_SERVER_CONTENT(p);
171
172 default:
173 if (this->HasClientQuit()) {
174 DEBUG(net, 0, "[tcp/content] received invalid packet type %d from %s", type, this->client_addr.GetAddressAsString().c_str());
175 } else {
176 DEBUG(net, 0, "[tcp/content] received illegal packet from %s", this->client_addr.GetAddressAsString().c_str());
177 }
178 return false;
179 }
180 }
181
186 bool NetworkContentSocketHandler::ReceivePackets()
187 {
188 /*
189 * We read only a few of the packets. This as receiving packets can be expensive
190 * due to the re-resolving of the parent/child relations and checking the toggle
191 * state of all bits. We cannot do this all in one go, as we want to show the
192 * user what we already received. Otherwise, it can take very long before any
193 * progress is shown to the end user that something has been received.
194 * It is also the case that we request extra content from the content server in
195 * case there is an unknown (in the content list) piece of content. These will
196 * come in after the main lists have been requested. As a result, we won't be
197 * getting everything reliably in one batch. Thus, we need to make subsequent
198 * updates in that case as well.
199 *
200 * As a result, we simple handle an arbitrary number of packets in one cycle,
201 * and let the rest be handled in subsequent cycles. These are ran, almost,
202 * immediately after this cycle so in speed it does not matter much, except
203 * that the user inferface will appear better responding.
204 *
205 * What arbitrary number to choose is the ultimate question though.
206 */
207 Packet *p;
208 static const int MAX_PACKETS_TO_RECEIVE = 42;
209 int i = MAX_PACKETS_TO_RECEIVE;
210 while (--i != 0 && (p = this->ReceivePacket()) != nullptr) {
211 bool cont = this->HandlePacket(p);
212 delete p;
213 if (!cont) return true;
214 }
215
216 return i != MAX_PACKETS_TO_RECEIVE - 1;
217 }
218
219
225 bool NetworkContentSocketHandler::ReceiveInvalidPacket(PacketContentType type)
226 {
227 DEBUG(net, 0, "[tcp/content] received illegal packet type %d from %s", type, this->client_addr.GetAddressAsString().c_str());
228 return false;
229 }
230
231 bool NetworkContentSocketHandler::Receive_CLIENT_INFO_LIST(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CONTENT_CLIENT_INFO_LIST); }
232 bool NetworkContentSocketHandler::Receive_CLIENT_INFO_ID(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CONTENT_CLIENT_INFO_ID); }
233 bool NetworkContentSocketHandler::Receive_CLIENT_INFO_EXTID(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CONTENT_CLIENT_INFO_EXTID); }
234 bool NetworkContentSocketHandler::Receive_CLIENT_INFO_EXTID_MD5(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CONTENT_CLIENT_INFO_EXTID_MD5); }
235 bool NetworkContentSocketHandler::Receive_SERVER_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CONTENT_SERVER_INFO); }
236 bool NetworkContentSocketHandler::Receive_CLIENT_CONTENT(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CONTENT_CLIENT_CONTENT); }
237 bool NetworkContentSocketHandler::Receive_SERVER_CONTENT(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CONTENT_SERVER_CONTENT); }
238
239 #ifndef OPENTTD_MSU
240
245 Subdirectory GetContentInfoSubDir(ContentType type)
246 {
247 switch (type) {
248 default: return NO_DIRECTORY;
249 case CONTENT_TYPE_AI: return AI_DIR;
250 case CONTENT_TYPE_AI_LIBRARY: return AI_LIBRARY_DIR;
251 case CONTENT_TYPE_GAME: return GAME_DIR;
252 case CONTENT_TYPE_GAME_LIBRARY: return GAME_LIBRARY_DIR;
253 case CONTENT_TYPE_NEWGRF: return NEWGRF_DIR;
254
255 case CONTENT_TYPE_BASE_GRAPHICS:
256 case CONTENT_TYPE_BASE_SOUNDS:
257 case CONTENT_TYPE_BASE_MUSIC:
258 return BASESET_DIR;
259
260 case CONTENT_TYPE_SCENARIO: return SCENARIO_DIR;
261 case CONTENT_TYPE_HEIGHTMAP: return HEIGHTMAP_DIR;
262 }
263 }
264 #endif /* OPENTTD_MSU */
ContentInfo::IsSelected
bool IsSelected() const
Is the state either selected or autoselected?
Definition: tcp_content.cpp:73
BaseMedia< GraphicsSet >::GetAvailableSets
static GraphicsSet * GetAvailableSets()
Return the available sets.
Definition: base_media_func.h:367
ContentInfo::tag_count
uint8 tag_count
Number of tags.
Definition: tcp_content.h:77
ContentInfo::~ContentInfo
~ContentInfo()
Free everything allocated.
Definition: tcp_content.cpp:32
ContentInfo::GetTextfile
const char * GetTextfile(TextfileType type) const
Search a textfile file next to this file in the content list.
Definition: tcp_content.cpp:101
ContentInfo::type
ContentType type
Type of content.
Definition: tcp_content.h:65
NetworkContentSocketHandler::Receive_SERVER_CONTENT
virtual bool Receive_SERVER_CONTENT(Packet *p)
Server sending list of content info: uint32 unique id uint32 file size (0 == does not exist) string f...
Definition: tcp_content.cpp:237
AI::GetScannerInfo
static AIScannerInfo * GetScannerInfo()
Gets the ScriptScanner instance that is used to find AIs.
Definition: ai_core.cpp:377
FindGRFConfig
const GRFConfig * FindGRFConfig(uint32 grfid, FindGRFConfigMode mode, const uint8 *md5sum, uint32 desired_version)
Find a NewGRF in the scanned list.
Definition: newgrf_config.cpp:737
ContentType
ContentType
The values in the enum are important; they are used as database 'keys'.
Definition: tcp_content.h:21
PacketContentType
PacketContentType
Enum with all types of TCP content packets.
Definition: tcp_content.h:37
CONTENT_TYPE_BASE_SOUNDS
@ CONTENT_TYPE_BASE_SOUNDS
The content consists of base sounds.
Definition: tcp_content.h:29
BASESET_DIR
@ BASESET_DIR
Subdirectory for all base data (base sets, intro game)
Definition: fileio_type.h:116
CONTENT_TYPE_AI
@ CONTENT_TYPE_AI
The content consists of an AI.
Definition: tcp_content.h:25
ContentInfo::tags
char(* tags)[32]
Malloced array of tags (strings)
Definition: tcp_content.h:78
GAME_LIBRARY_DIR
@ GAME_LIBRARY_DIR
Subdirectory for all GS libraries.
Definition: fileio_type.h:122
TryGetBaseSetFile
const char * TryGetBaseSetFile(const ContentInfo *ci, bool md5sum, const Tbase_set *s)
Check whether there's a base set matching some information.
Definition: base_media_func.h:279
PACKET_CONTENT_END
@ PACKET_CONTENT_END
Must ALWAYS be on the end of this list!! (period)
Definition: tcp_content.h:45
CONTENT_TYPE_BASE_GRAPHICS
@ CONTENT_TYPE_BASE_GRAPHICS
The content consists of base graphics.
Definition: tcp_content.h:23
PACKET_CONTENT_CLIENT_CONTENT
@ PACKET_CONTENT_CLIENT_CONTENT
Request a content file given an internal ID.
Definition: tcp_content.h:43
HEIGHTMAP_DIR
@ HEIGHTMAP_DIR
Subdirectory of scenario for heightmaps.
Definition: fileio_type.h:113
NetworkTCPSocketHandler::sock
SOCKET sock
The socket currently connected to.
Definition: tcp.h:34
NetworkContentSocketHandler::ReceivePackets
bool ReceivePackets()
Receive a packet at TCP level.
Definition: tcp_content.cpp:186
PACKET_CONTENT_SERVER_CONTENT
@ PACKET_CONTENT_SERVER_CONTENT
Reply with the content of the given ID.
Definition: tcp_content.h:44
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:234
ContentInfo::IsValid
bool IsValid() const
Is the information from this content info valid?
Definition: tcp_content.cpp:90
CONTENT_TYPE_BASE_MUSIC
@ CONTENT_TYPE_BASE_MUSIC
The content consists of base music.
Definition: tcp_content.h:30
GetContentInfoSubDir
Subdirectory GetContentInfoSubDir(ContentType type)
Helper to get the subdirectory a ContentInfo is located in.
Definition: tcp_content.cpp:245
NetworkTCPSocketHandler::ReceivePacket
virtual Packet * ReceivePacket()
Receives a packet for the given client.
Definition: tcp.cpp:145
ContentInfo::TransferFrom
void TransferFrom(ContentInfo *other)
Copy data from other ContentInfo and take ownership of allocated stuff.
Definition: tcp_content.cpp:42
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:233
Game::GetScannerLibrary
static GameScannerLibrary * GetScannerLibrary()
Gets the ScriptScanner instance that is used to find Game Libraries.
Definition: game_core.cpp:278
NetworkContentSocketHandler::client_addr
NetworkAddress client_addr
The address we're connected to.
Definition: tcp_content.h:98
tcp_content.h
CONTENT_TYPE_HEIGHTMAP
@ CONTENT_TYPE_HEIGHTMAP
The content consists of a heightmap.
Definition: tcp_content.h:28
GRFConfig
Information about GRF, used in the game and (part of it) in savegames.
Definition: newgrf_config.h:152
AI_DIR
@ AI_DIR
Subdirectory for all AI files.
Definition: fileio_type.h:119
DEBUG
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:35
ContentInfo
Container for all important information about a piece of content.
Definition: tcp_content.h:54
NetworkTCPSocketHandler::CloseConnection
NetworkRecvStatus CloseConnection(bool error=true) override
Close the current connection; for TCP this will be mostly equivalent to Close(), but for UDP it just ...
Definition: tcp.cpp:38
ContentInfo::md5sum
byte md5sum[16]
The MD5 checksum.
Definition: tcp_content.h:74
AI::GetScannerLibrary
static AIScannerLibrary * GetScannerLibrary()
Gets the ScriptScanner instance that is used to find AI Libraries.
Definition: ai_core.cpp:382
CONTENT_TYPE_GAME
@ CONTENT_TYPE_GAME
The content consists of a game script.
Definition: tcp_content.h:31
CONTENT_TYPE_SCENARIO
@ CONTENT_TYPE_SCENARIO
The content consists of a scenario.
Definition: tcp_content.h:27
GAME_DIR
@ GAME_DIR
Subdirectory for all game scripts.
Definition: fileio_type.h:121
SCENARIO_DIR
@ SCENARIO_DIR
Base directory for all scenarios.
Definition: fileio_type.h:112
ContentInfo::SELECTED
@ SELECTED
The content has been manually selected.
Definition: tcp_content.h:58
CONTENT_TYPE_AI_LIBRARY
@ CONTENT_TYPE_AI_LIBRARY
The content consists of an AI library.
Definition: tcp_content.h:26
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.h:39
Packet
Internal entity of a packet.
Definition: packet.h:40
BSWAP32
static uint32 BSWAP32(uint32 x)
Perform a 32 bits endianness bitswap on x.
Definition: bitmath_func.hpp:380
NEWGRF_DIR
@ NEWGRF_DIR
Subdirectory for all NewGRFs.
Definition: fileio_type.h:117
CONTENT_TYPE_GAME_LIBRARY
@ CONTENT_TYPE_GAME_LIBRARY
The content consists of a GS library.
Definition: tcp_content.h:32
CONTENT_TYPE_NEWGRF
@ CONTENT_TYPE_NEWGRF
The content consists of a NewGRF.
Definition: tcp_content.h:24
NetworkContentSocketHandler::ReceiveInvalidPacket
bool ReceiveInvalidPacket(PacketContentType type)
Helper for logging receiving invalid packets.
Definition: tcp_content.cpp:225
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.h:38
NetworkSocketHandler::HasClientQuit
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition: core.h:67
GetTextfile
const char * GetTextfile(TextfileType type, Subdirectory dir, const char *filename)
Search a textfile file next to the given content.
Definition: textfile_gui.cpp:385
ContentInfo::ALREADY_HERE
@ ALREADY_HERE
The content is already at the client side.
Definition: tcp_content.h:60
NetworkContentSocketHandler::Receive_CLIENT_CONTENT
virtual bool Receive_CLIENT_CONTENT(Packet *p)
Client requesting the actual content: uint16 count of unique ids uint32 unique id (count times)
Definition: tcp_content.cpp:236
ContentInfo::AUTOSELECTED
@ AUTOSELECTED
The content has been selected as dependency.
Definition: tcp_content.h:59
NO_DIRECTORY
@ NO_DIRECTORY
A path without any base directory.
Definition: fileio_type.h:125
ContentInfo::Size
size_t Size() const
Get the size of the data as send over the network.
Definition: tcp_content.cpp:57
NetworkContentSocketHandler::Receive_CLIENT_INFO_LIST
virtual bool Receive_CLIENT_INFO_LIST(Packet *p)
Client requesting a list of content info: byte type uint32 openttd version.
Definition: tcp_content.cpp:231
NetworkContentSocketHandler::Receive_CLIENT_INFO_ID
virtual bool Receive_CLIENT_INFO_ID(Packet *p)
Client requesting a list of content info: uint16 count of ids uint32 id (count times)
Definition: tcp_content.cpp:232
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.h:40
ContentInfo::ContentInfo
ContentInfo()
Clear everything in the struct.
Definition: tcp_content.cpp:26
ContentInfo::dependency_count
uint8 dependency_count
Number of dependencies.
Definition: tcp_content.h:75
Subdirectory
Subdirectory
The different kinds of subdirectories OpenTTD uses.
Definition: fileio_type.h:108
Packet::Recv_uint8
uint8 Recv_uint8()
Read a 8 bits integer from the packet.
Definition: packet.cpp:217
ContentInfo::state
State state
Whether the content info is selected (for download)
Definition: tcp_content.h:79
ContentInfo::unique_id
uint32 unique_id
Unique ID; either GRF ID or shortname.
Definition: tcp_content.h:73
AI_LIBRARY_DIR
@ AI_LIBRARY_DIR
Subdirectory for all AI libraries.
Definition: fileio_type.h:120
CONTENT_TYPE_BEGIN
@ CONTENT_TYPE_BEGIN
Helper to mark the begin of the types.
Definition: tcp_content.h:22
Game::GetScannerInfo
static GameScannerInfo * GetScannerInfo()
Gets the ScriptScanner instance that is used to find Game scripts.
Definition: game_core.cpp:274
TextfileType
TextfileType
Additional text files accompanying Tar archives.
Definition: textfile_type.h:14
NetworkContentSocketHandler::HandlePacket
bool HandlePacket(Packet *p)
Handle the given packet, i.e.
Definition: tcp_content.cpp:159
NetworkContentSocketHandler::Close
void Close() override
Really close the socket.
Definition: tcp_content.cpp:144
FGCM_EXACT
@ FGCM_EXACT
Only find Grfs matching md5sum.
Definition: newgrf_config.h:193
ScriptScanner::FindMainScript
const char * FindMainScript(const ContentInfo *ci, bool md5sum)
Find a script of a ContentInfo.
Definition: script_scanner.cpp:259
GRFConfig::filename
char * filename
Filename - either with or without full path.
Definition: newgrf_config.h:159
ContentInfo::INVALID
@ INVALID
The content's invalid.
Definition: tcp_content.h:62
ContentInfo::dependencies
ContentID * dependencies
Malloced array of dependencies (unique server side ids)
Definition: tcp_content.h:76
free
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: stdafx.h:454
NetworkContentSocketHandler::Receive_SERVER_INFO
virtual bool Receive_SERVER_INFO(Packet *p)
Server sending list of content info: byte type (invalid ID == does not exist) uint32 id uint32 file_s...
Definition: tcp_content.cpp:235
FindScenario
const char * FindScenario(const ContentInfo *ci, bool md5sum)
Find a given scenario based on its unique ID.
Definition: fios.cpp:720
PACKET_CONTENT_SERVER_INFO
@ PACKET_CONTENT_SERVER_INFO
Reply of content server with information about content.
Definition: tcp_content.h:42
NetworkAddress::GetAddressAsString
void GetAddressAsString(char *buffer, const char *last, bool with_family=true)
Get the address as a string, e.g.
Definition: address.cpp:77
CONTENT_TYPE_END
@ CONTENT_TYPE_END
Helper to mark the end of the types.
Definition: tcp_content.h:33
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.h:41