OpenTTD Source
1.11.0-beta2
|
Go to the documentation of this file.
10 #include "../stdafx.h"
12 #include "../ai/ai.hpp"
13 #include "../game/game.hpp"
14 #include "../window_func.h"
16 #include "../base_media_base.h"
17 #include "../settings_type.h"
20 #include "table/strings.h"
22 #if defined(WITH_ZLIB)
27 # include <emscripten.h>
30 #include "../safeguards.h"
65 for (uint j = 0; j <
sizeof(ci->
md5sum); j++) {
107 proc = AI::HasAILibrary;
break;
115 proc = Game::HasGameLibrary;
break;
127 if (proc !=
nullptr) {
128 if (proc(ci,
true)) {
132 if (proc(ci,
false)) ci->
upgrade =
true;
143 if (ici->type == ci->
type && ici->unique_id == ci->
unique_id &&
144 memcmp(ci->
md5sum, ici->md5sum,
sizeof(ci->
md5sum)) == 0) {
147 if (ici->IsSelected()) ci->
state = ici->state;
155 ici->TransferFrom(ci);
169 this->infos.push_back(ci);
224 uint p_count = std::min<uint>(count, (
SEND_MTU -
sizeof(
PacketSize) -
sizeof(
byte) -
sizeof(uint16)) /
sizeof(uint32));
229 for (uint i = 0; i < p_count; i++) {
235 content_ids += p_count;
246 if (cv ==
nullptr)
return;
250 assert(cv->size() < 255);
252 (
sizeof(uint8) +
sizeof(uint32) + (send_md5sum ? 16 : 0)));
260 if (!send_md5sum)
continue;
262 for (uint j = 0; j <
sizeof(ci->md5sum); j++) {
272 if (ci->type == ci2->type && ci->unique_id == ci2->unique_id &&
273 (!send_md5sum || memcmp(ci->md5sum, ci2->md5sum,
sizeof(ci->md5sum)) == 0)) {
279 this->infos.push_back(ci);
296 #ifdef __EMSCRIPTEN__
307 content.push_back(ci->id);
308 bytes += ci->filesize;
311 files = (uint)content.size();
314 if (files == 0)
return;
329 uint count = (uint)content.size();
335 uint bytes = (10 + 1) * count + 1;
336 char *content_request = MallocT<char>(bytes);
337 const char *
lastof = content_request + bytes - 1;
339 char *p = content_request;
357 uint count = (uint)content.size();
358 const ContentID *content_ids = content.data();
366 uint p_count = std::min<uint>(count, (
SEND_MTU -
sizeof(
PacketSize) -
sizeof(
byte) -
sizeof(uint16)) /
sizeof(uint32));
371 for (uint i = 0; i < p_count; i++) {
377 content_ids += p_count;
395 buf += compressed ?
".tar.gz" :
".tar";
407 #if defined(WITH_ZLIB)
412 if (ftmp ==
nullptr)
return false;
414 gzFile fin = gzdopen(dup(fileno(ftmp)),
"rb");
419 if (fin ==
nullptr || fout ==
nullptr) {
424 int read = gzread(fin, buff,
sizeof(buff));
439 gzerror(fin, &errnum);
440 if (errnum != 0 && errnum != Z_STREAM_END) ret =
false;
443 if (read < 0 || (
size_t)read != fwrite(buff, 1, read, fout)) {
453 if (fin !=
nullptr) gzclose(fin);
454 if (fout !=
nullptr) fclose(fout);
464 if (this->
curFile ==
nullptr) {
479 size_t toRead = (size_t)(p->
size - p->
pos);
480 if (fwrite(p->
buffer + p->
pos, 1, toRead, this->curFile) != toRead) {
482 ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD, STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE,
WL_ERROR);
513 if (filename.empty() || (this->curFile = fopen(filename.c_str(),
"wb")) ==
nullptr) {
516 ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD, STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE,
WL_ERROR);
547 unlink(fname.c_str());
550 #ifdef __EMSCRIPTEN__
551 EM_ASM(
if (window[
"openttd_syncfs"]) openttd_syncfs());
571 if (this->
curFile !=
nullptr) {
573 long size = ftell(this->
curFile);
583 assert(data ==
nullptr || length != 0);
589 if (data !=
nullptr) {
602 if (data !=
nullptr) {
604 if (fwrite(data, 1, length, this->
curFile) != length) {
615 if (this->
curFile !=
nullptr) {
633 #define check_not_null(p) { if ((p) == nullptr) { this->OnFailure(); return; } }
635 #define check_and_terminate(p) { check_not_null(p); *(p) = '\0'; }
639 char *p = strchr(str,
'\n');
640 check_and_terminate(p);
646 p = strchr(str,
',');
647 check_and_terminate(p);
652 p = strchr(str,
',');
653 check_and_terminate(p);
658 p = strchr(str,
',');
659 check_and_terminate(p);
665 if (strncmp(str,
"ottd", 4) == 0) {
674 p = strrchr(str,
'/');
684 for (uint i = 0; i < 2; i++) {
685 p = strrchr(tmp,
'.');
686 check_and_terminate(p);
703 #undef check_and_terminate
711 http_response_index(-2),
769 if (this->
sock == INVALID_SOCKET)
return;
805 if (std::find(this->
requested.begin(), this->requested.end(), cid) != this->requested.end())
return;
819 if (ci->id == cid)
return ci;
845 if (ci ==
nullptr || !ci->
IsSelected())
return;
907 if (ci == child)
continue;
909 for (uint i = 0; i < ci->dependency_count; i++) {
910 if (ci->dependencies[i] == child->
id) {
911 parents.push_back(ci);
925 tree.push_back(child);
931 for (uint i = 0; i < tree.size(); i++) {
972 if (!c->IsSelected())
continue;
991 bool force_selection =
false;
996 if (sel_count == 0) {
1002 if (force_selection)
continue;
1012 force_selection =
true;
1017 if (force_selection)
continue;
1037 this->infos.clear();
1045 for (
size_t i = 0; i < this->
callbacks.size(); ) {
1049 if (i != this->
callbacks.size() && this->callbacks[i] == cb) i++;
1055 for (
size_t i = 0; i < this->
callbacks.size(); ) {
1058 if (i != this->
callbacks.size() && this->callbacks[i] == cb) i++;
1064 for (
size_t i = 0; i < this->
callbacks.size(); ) {
1068 if (i != this->
callbacks.size() && this->callbacks[i] == cb) i++;
1074 for (
size_t i = 0; i < this->
callbacks.size(); ) {
1077 if (i != this->
callbacks.size() && this->callbacks[i] == cb) i++;
1084 if (ci !=
nullptr) {
1088 for (
size_t i = 0; i < this->
callbacks.size(); ) {
1092 if (i != this->
callbacks.size() && this->callbacks[i] == cb) i++;
bool IsSelected() const
Is the state either selected or autoselected?
@ SP_AUTODOWNLOAD_DIR
Search within the autodownload directory.
Callbacks for notifying others about incoming data.
void OnConnect(bool success) override
Callback for when the connection has finished.
uint8 tag_count
Number of tags.
bool ExtractTar(const std::string &tar_filename, Subdirectory subdir)
Extract the tar with the given filename in the directory where the tar resides.
ContentType type
Type of content.
Base socket handler for all Content TCP sockets.
void ReverseLookupDependency(ConstContentVector &parents, const ContentInfo *child) const
Reverse lookup the dependencies of (direct) parents over a given child.
@ SVS_ALLOW_NEWLINE
Allow newlines.
void SendReceive()
Check whether we received/can send some data from/to the content server and when that's the case hand...
void Recv_string(char *buffer, size_t size, StringValidationSettings settings=SVS_REPLACE_WITH_QUESTION_MARK)
Reads a string till it finds a '\0' in the stream.
const GRFConfig * FindGRFConfig(uint32 grfid, FindGRFConfigMode mode, const uint8 *md5sum, uint32 desired_version)
Find a NewGRF in the scanned list.
ContentType
The values in the enum are important; they are used as database 'keys'.
byte * buffer
The buffer of this packet, of basically variable length up to SEND_MTU.
bool upgrade
This item is an upgrade.
@ DOES_NOT_EXIST
The content does not exist in the content system.
"Helper" class for creating TCP connections in a non-blocking manner
static const uint16 NETWORK_CONTENT_MIRROR_PORT
The default port of the content mirror (TCP)
@ CONTENT_TYPE_BASE_SOUNDS
The content consists of base sounds.
bool HasScenario(const ContentInfo *ci, bool md5sum)
Check whether we've got a given scenario based on its unique ID.
@ BASESET_DIR
Subdirectory for all base data (base sets, intro game)
@ CONTENT_TYPE_AI
The content consists of an AI.
char(* tags)[32]
Malloced array of tags (strings)
std::chrono::steady_clock::time_point lastActivity
The last time there was network activity.
static const char *const NETWORK_CONTENT_SERVER_HOST
DNS hostname of the content server.
int http_response_index
Where we are, in the response, with handling it.
virtual void OnConnect(bool success)
Callback for when the connection has finished.
@ CONTENT_TYPE_BASE_GRAPHICS
The content consists of base graphics.
@ PACKET_CONTENT_CLIENT_CONTENT
Request a content file given an internal ID.
std::vector< ContentInfo * > ContentVector
Vector with content info.
bool include(std::vector< T > &vec, const T &item)
Helper function to append an item to a vector if it is not already contained Consider using std::set,...
SOCKET sock
The socket currently connected to.
bool ReceivePackets()
Receive a packet at TCP level.
void CheckDependencyState(ContentInfo *ci)
Check the dependencies (recursively) of this content info.
Socket handler for the content server connection.
ClientSettings _settings_client
The current settings for this game.
virtual void OnDownloadComplete(ContentID cid)
We have finished downloading a file.
char filename[48]
Filename (for the .tar.gz; only valid on download)
void Clear()
Clear all downloaded content information.
bool isConnecting
Whether we're connecting.
void Send_uint8(uint8 data)
Package a 8 bits integer in the packet.
static bool HasGRFConfig(const ContentInfo *ci, bool md5sum)
Wrapper function for the HasProc.
bool IsValid() const
Is the information from this content info valid?
@ CONTENT_TYPE_BASE_MUSIC
The content consists of base music.
Connect with a HTTP server and do ONE query.
ContentInfo * curInfo
Information about the currently downloaded file.
void DownloadSelectedContentHTTP(const ContentIDList &content)
Initiate downloading the content over HTTP.
void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x=0, int y=0, const GRFFile *textref_stack_grffile=nullptr, uint textref_stack_size=0, const uint32 *textref_stack=nullptr)
Display an error message in a window.
Subdirectory GetContentInfoSubDir(ContentType type)
Helper to get the subdirectory a ContentInfo is located in.
void Send_uint32(uint32 data)
Package a 32 bits integer in the packet.
bool no_http_content_downloads
do not do content downloads over HTTP
void RequestContentList(ContentType type)
Request the content list for the given type.
@ FGCM_ANY
Use first found.
virtual void OnReceiveContentInfo(const ContentInfo *ci)
We received a content info.
static std::string GetFullFilename(const ContentInfo *ci, bool compressed)
Determine the full filename of a piece of content information.
void OnDisconnect() override
Callback for when the connection got disconnected.
@ UNSELECTED
The content has not been selected.
uint32 Recv_uint32()
Read a 32 bits integer from the packet.
void OnFailure() override
Callback for when the connection attempt failed.
void Reopen()
Reopen the socket so we can send/receive stuff again.
@ CONTENT_TYPE_HEIGHTMAP
The content consists of a heightmap.
ContentVector infos
All content info we received.
void DownloadContentInfo(ContentID cid)
Download information of a given Content ID if not already tried.
~ClientNetworkContentSocketHandler()
Clear up the mess ;)
void UnselectAll()
Unselect everything that we've not downloaded so far.
Container for all important information about a piece of content.
PacketSize size
The size of the whole packet for received packets.
static const uint16 SEND_MTU
Number of bytes we can pack in a single packet.
static const char *const NETWORK_CONTENT_MIRROR_URL
URL of the HTTP mirror system.
byte md5sum[16]
The MD5 checksum.
void OnReceiveData(const char *data, size_t length) override
We're receiving data.
void Unselect(ContentID cid)
Unselect a specific content id.
static bool HasAI(const struct ContentInfo *ci, bool md5sum)
Wrapper function for AIScanner::HasAI.
@ CONTENT_TYPE_GAME
The content consists of a game script.
@ CONTENT_TYPE_SCENARIO
The content consists of a scenario.
void OnFailure() override
An error has occurred and the connection has been closed.
void Close() override
Disconnect from the content server.
void Send_uint16(uint16 data)
Package a 16 bits integer in the packet.
virtual void SendPacket(Packet *packet)
This function puts the packet in the send-queue and it is send as soon as possible.
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
@ SELECTED
The content has been manually selected.
@ CONTENT_TYPE_AI_LIBRARY
The content consists of an AI library.
static constexpr std::chrono::seconds IDLE_TIMEOUT
The idle timeout; when to close the connection because it's idle.
@ PACKET_CONTENT_CLIENT_INFO_ID
Queries the content server for information about a list of internal IDs.
FILE * curFile
Currently downloaded file.
bool(* HasProc)(const ContentInfo *ci, bool md5sum)
Check whether a function piece of content is locally known.
void OnDownloadComplete(ContentID cid) override
We have finished downloading a file.
void OnDownloadProgress(const ContentInfo *ci, int bytes) override
We have progress in the download of a file.
char url[96]
URL related to the content.
Internal entity of a packet.
void DownloadSelectedContent(uint &files, uint &bytes, bool fallback=false)
Actually begin downloading the content we selected.
NetworkAddress address
Address we're connecting to.
byte * buf
Buffer we're going to write to/read from.
static uint32 BSWAP32(uint32 x)
Perform a 32 bits endianness bitswap on x.
@ CONTENT_TYPE_GAME_LIBRARY
The content consists of a GS library.
@ CONTENT_TYPE_NEWGRF
The content consists of a NewGRF.
std::vector< char > http_response
The HTTP response to the requests we've been doing.
static const uint16 NETWORK_CONTENT_SERVER_PORT
The default port of the content server (TCP)
bool AddFile(const std::string &filename, size_t basepath_length, const std::string &tar_filename={}) override
Add a file with the given filename.
char description[512]
Description of the content.
static int Connect(char *uri, HTTPCallback *callback, const char *data=nullptr, int depth=0)
Connect to the given URI.
@ PACKET_CONTENT_CLIENT_INFO_LIST
Queries the content server for a list of info of a given content type.
ClientNetworkContentSocketHandler _network_content_client
The client we use to connect to the server.
std::vector< ContentID > ContentIDList
List of content IDs to (possibly) select.
SendPacketsState SendPackets(bool closing_down=false)
Sends all the buffered packets out for this client.
Wrapper for (un)resolved network addresses; there's no reason to transform a numeric IP to a string a...
bool CanSendReceive()
Check whether this socket can send or receive something.
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
Delete a window by its class and window number (if it is open).
@ ALREADY_HERE
The content is already at the client side.
uint16 PacketSize
Size of the whole packet.
void ReverseLookupTreeDependency(ConstContentVector &tree, const ContentInfo *child) const
Reverse lookup the dependencies of all parents over a given child.
void Connect()
Connect with the content server.
@ AUTOSELECTED
The content has been selected as dependency.
@ NO_DIRECTORY
A path without any base directory.
void ToggleSelectedState(const ContentInfo *ci)
Toggle the state of a content info and check its dependencies.
@ WC_NETWORK_STATUS_WINDOW
Network status window; Window numbers:
std::vector< ContentCallback * > callbacks
Callbacks to notify "the world".
@ PACKET_CONTENT_CLIENT_INFO_EXTID
Queries the content server for information about a list of external IDs.
static bool HasGame(const struct ContentInfo *ci, bool md5sum)
Wrapper function for GameScanner::HasGame.
uint8 dependency_count
Number of dependencies.
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
void Select(ContentID cid)
Select a specific content id.
static bool GunzipFile(const ContentInfo *ci)
Gunzip a given file and remove the .gz if successful.
Subdirectory
The different kinds of subdirectories OpenTTD uses.
ContentIDList requested
ContentIDs we already requested (so we don't do it again)
uint8 Recv_uint8()
Read a 8 bits integer from the packet.
Connect to the content server.
static const char *const NETWORK_CONTENT_MIRROR_HOST
DNS hostname of the HTTP-content mirror server.
void DownloadSelectedContentFallback(const ContentIDList &content)
Initiate downloading the content over the fallback protocol.
@ WL_ERROR
Errors (eg. saving/loading failed)
char version[16]
Version of the content.
void OnReceiveContentInfo(const ContentInfo *ci) override
We received a content info.
State state
Whether the content info is selected (for download)
uint32 unique_id
Unique ID; either GRF ID or shortname.
Helper for scanning for files with tar as extension.
#define lengthof(x)
Return the length of an fixed size array.
NetworkSettings network
settings related to the network
void SelectAll()
Select everything we can select.
ContentID
Unique identifier for the content.
NetworkContentConnecter(const NetworkAddress &address)
Initiate the connecting.
bool BeforeDownload()
Handle the opening of the file before downloading.
void Close() override
Really close the socket.
char name[32]
Name of the content.
@ FGCM_EXACT
Only find Grfs matching md5sum.
bool Receive_SERVER_INFO(Packet *p) override
Server sending list of content info: byte type (invalid ID == does not exist) uint32 id uint32 file_s...
void SelectUpgrade()
Select everything that's an update for something we've got.
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
ContentID * dependencies
Malloced array of dependencies (unique server side ids)
ContentID id
Unique (server side) ID for the content.
void AfterDownload()
Handle the closing and extracting of a file after downloading it has been done.
void OnConnect(SOCKET s) override
Callback when the connection succeeded.
ClientNetworkContentSocketHandler()
Create a socket handler to handle the connection.
virtual void OnDisconnect()
Callback for when the connection got disconnected.
#define lastof(x)
Get the last element of an fixed size array.
ContentInfo * GetContent(ContentID cid)
Get the content info based on a ContentID.
@ SVS_REPLACE_WITH_QUESTION_MARK
Replace the unknown/bad bits with question marks.
std::vector< const ContentInfo * > ConstContentVector
Vector with constant content info.
bool Receive_SERVER_CONTENT(Packet *p) override
Server sending list of content info: uint32 unique id uint32 file size (0 == does not exist) string f...
@ WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD
Network content download status.
@ CONTENT_TYPE_END
Helper to mark the end of the types.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
uint32 filesize
Size of the file.
virtual void OnDownloadProgress(const ContentInfo *ci, int bytes)
We have progress in the download of a file.
PacketSize pos
The current read/write position in the packet.
@ PACKET_CONTENT_CLIENT_INFO_EXTID_MD5
Queries the content server for information about a list of external IDs and MD5.