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