OpenTTD Source
12.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++) {
74 ci->
tags.reserve(tag_count);
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) {
146 if (ci->
name.empty()) ci->
name = ici->name;
147 if (ici->IsSelected()) ci->
state = ici->state;
168 this->infos.push_back(ci);
223 uint p_count = std::min<uint>(count, (
TCP_MTU -
sizeof(
PacketSize) -
sizeof(
byte) -
sizeof(uint16)) /
sizeof(uint32));
228 for (uint i = 0; i < p_count; i++) {
234 content_ids += p_count;
245 if (cv ==
nullptr)
return;
249 assert(cv->size() < 255);
250 assert(cv->size() < (
TCP_MTU -
sizeof(
PacketSize) -
sizeof(
byte) -
sizeof(uint8)) /
251 (
sizeof(uint8) +
sizeof(uint32) + (send_md5sum ? 16 : 0)));
259 if (!send_md5sum)
continue;
261 for (uint j = 0; j <
sizeof(ci->md5sum); j++) {
271 if (ci->type == ci2->type && ci->unique_id == ci2->unique_id &&
272 (!send_md5sum || memcmp(ci->md5sum, ci2->md5sum,
sizeof(ci->md5sum)) == 0)) {
278 this->infos.push_back(ci);
295 #ifdef __EMSCRIPTEN__
306 content.push_back(ci->id);
307 bytes += ci->filesize;
310 files = (uint)content.size();
313 if (files == 0)
return;
328 uint count = (uint)content.size();
334 uint bytes = (10 + 1) * count + 1;
335 char *content_request = MallocT<char>(bytes);
336 const char *
lastof = content_request + bytes - 1;
338 char *p = content_request;
355 uint count = (uint)content.size();
356 const ContentID *content_ids = content.data();
364 uint p_count = std::min<uint>(count, (
TCP_MTU -
sizeof(
PacketSize) -
sizeof(
byte) -
sizeof(uint16)) /
sizeof(uint32));
369 for (uint i = 0; i < p_count; i++) {
375 content_ids += p_count;
393 buf += compressed ?
".tar.gz" :
".tar";
405 #if defined(WITH_ZLIB)
410 if (ftmp ==
nullptr)
return false;
412 int fdup = dup(fileno(ftmp));
413 gzFile fin = gzdopen(fdup,
"rb");
418 if (fin ==
nullptr || fout ==
nullptr) {
423 int read = gzread(fin, buff,
sizeof(buff));
438 gzerror(fin, &errnum);
439 if (errnum != 0 && errnum != Z_STREAM_END) ret =
false;
442 if (read < 0 || (
size_t)read != fwrite(buff, 1, read, fout)) {
452 if (fin !=
nullptr) {
454 }
else if (fdup != -1) {
458 if (fout !=
nullptr) fclose(fout);
475 return fwrite(buffer, 1, amount, file);
480 if (this->
curFile ==
nullptr) {
498 ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD, STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE,
WL_ERROR);
529 if (filename.empty() || (this->curFile = fopen(filename.c_str(),
"wb")) ==
nullptr) {
532 ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD, STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE,
WL_ERROR);
563 unlink(fname.c_str());
566 #ifdef __EMSCRIPTEN__
567 EM_ASM(
if (window[
"openttd_syncfs"]) openttd_syncfs());
587 if (this->
curFile !=
nullptr) {
589 long size = ftell(this->
curFile);
599 assert(data ==
nullptr || length != 0);
605 if (data !=
nullptr) {
618 if (data !=
nullptr) {
620 if (fwrite(data, 1, length, this->
curFile) != length) {
631 if (this->
curFile !=
nullptr) {
649 #define check_not_null(p) { if ((p) == nullptr) { this->OnFailure(); return; } }
651 #define check_and_terminate(p) { check_not_null(p); *(p) = '\0'; }
655 char *p = strchr(str,
'\n');
656 check_and_terminate(p);
662 p = strchr(str,
',');
663 check_and_terminate(p);
668 p = strchr(str,
',');
669 check_and_terminate(p);
674 p = strchr(str,
',');
675 check_and_terminate(p);
681 if (strncmp(str,
"ottd", 4) == 0) {
690 p = strrchr(str,
'/');
700 for (uint i = 0; i < 2; i++) {
701 p = strrchr(tmp,
'.');
702 check_and_terminate(p);
719 #undef check_and_terminate
727 http_response_index(-2),
825 if (std::find(this->
requested.begin(), this->requested.end(), cid) != this->requested.end())
return;
839 if (ci->id == cid)
return ci;
865 if (ci ==
nullptr || !ci->
IsSelected())
return;
927 if (ci == child)
continue;
929 for (
auto &dependency : ci->dependencies) {
930 if (dependency == child->
id) {
931 parents.push_back(ci);
945 tree.push_back(child);
951 for (uint i = 0; i < tree.size(); i++) {
992 if (!c->IsSelected())
continue;
1011 bool force_selection =
false;
1013 if (parent_ci->IsSelected()) sel_count++;
1016 if (sel_count == 0) {
1022 if (force_selection)
continue;
1032 force_selection =
true;
1037 if (force_selection)
continue;
1057 this->infos.clear();
1065 for (
size_t i = 0; i < this->
callbacks.size(); ) {
1069 if (i != this->
callbacks.size() && this->callbacks[i] == cb) i++;
1075 for (
size_t i = 0; i < this->
callbacks.size(); ) {
1078 if (i != this->
callbacks.size() && this->callbacks[i] == cb) i++;
1084 for (
size_t i = 0; i < this->
callbacks.size(); ) {
1088 if (i != this->
callbacks.size() && this->callbacks[i] == cb) i++;
1094 for (
size_t i = 0; i < this->
callbacks.size(); ) {
1097 if (i != this->
callbacks.size() && this->callbacks[i] == cb) i++;
1104 if (ci !=
nullptr) {
1108 for (
size_t i = 0; i < this->
callbacks.size(); ) {
1112 if (i != this->
callbacks.size() && this->callbacks[i] == cb) i++;
bool IsSelected() const
Is the state either selected or autoselected?
NetworkContentConnecter(const std::string &connection_string)
Initiate the connecting.
@ 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.
std::string name
Name of the content.
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.
std::string connection_string
Current address we are connecting to (before resolving).
void SendReceive()
Check whether we received/can send some data from/to the content server and when that's the case hand...
const GRFConfig * FindGRFConfig(uint32 grfid, FindGRFConfigMode mode, const uint8 *md5sum, uint32 desired_version)
Find a NewGRF in the scanned list.
const char * NetworkContentMirrorConnectionString()
Get the connection string for the content mirror from the environment variable OTTD_CONTENT_MIRROR_CS...
@ CONTENT_TYPE_GAME_LIBRARY
The content consists of a GS library.
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
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)
std::chrono::steady_clock::time_point lastActivity
The last time there was network activity.
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_NEWGRF
The content consists of a NewGRF.
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.
std::string url
URL related to the content.
void CheckDependencyState(ContentInfo *ci)
Check the dependencies (recursively) of this content info.
static const uint NETWORK_CONTENT_VERSION_LENGTH
The maximum length of a content's version, in bytes including '\0'.
Socket handler for the content server connection.
ssize_t TransferOut(F transfer_function, D destination, Args &&... args)
Transfer data from the packet to the given function.
ClientSettings _settings_client
The current settings for this game.
virtual void OnDownloadComplete(ContentID cid)
We have finished downloading a file.
@ CONTENT_TYPE_END
Helper to mark the end of the types.
std::string version
Version of the content.
@ PACKET_CONTENT_CLIENT_INFO_EXTID_MD5
Queries the content server for information about a list of external IDs and MD5.
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?
ContentType
The values in the enum are important; they are used as database 'keys'.
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
std::string Recv_string(size_t length, StringValidationSettings settings=SVS_REPLACE_WITH_QUESTION_MARK)
Reads characters (bytes) from the packet until it finds a '\0', or reaches a maximum of length charac...
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.
@ CONTENT_TYPE_GAME
The content consists of a game script.
void OnDisconnect() override
Callback for when the connection got disconnected.
@ UNSELECTED
The content has not been selected.
@ PACKET_CONTENT_CLIENT_INFO_ID
Queries the content server for information about a list of internal IDs.
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.
static const uint NETWORK_CONTENT_DESC_LENGTH
The maximum length of a content's description, in bytes including '\0'.
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.
static ssize_t TransferOutFWrite(FILE *file, const char *buffer, size_t amount)
Simple wrapper around fwrite to be able to pass it to Packet's TransferOut.
Container for all important information about a piece of content.
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.
void OnFailure() override
An error has occurred and the connection has been closed.
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.
const char * NetworkContentServerConnectionString()
Get the connection string for the content server from the environment variable OTTD_CONTENT_SERVER_CS...
virtual NetworkRecvStatus CloseConnection(bool error=true)
This will put this socket handler in a close state.
@ SELECTED
The content has been manually selected.
static constexpr std::chrono::seconds IDLE_TIMEOUT
The idle timeout; when to close the connection because it's idle.
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.
static const uint16 TCP_MTU
Number of bytes we can pack in a single TCP packet.
@ PACKET_CONTENT_CLIENT_CONTENT
Request a content file given an internal ID.
StringList tags
Tags associated with the content.
Internal entity of a packet.
void DownloadSelectedContent(uint &files, uint &bytes, bool fallback=false)
Actually begin downloading the content we selected.
static uint32 BSWAP32(uint32 x)
Perform a 32 bits endianness bitswap on x.
std::vector< char > http_response
The HTTP response to the requests we've been doing.
std::vector< ContentID > dependencies
The dependencies (unique server side ids)
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.
static int Connect(char *uri, HTTPCallback *callback, const char *data=nullptr, int depth=0)
Connect to the given URI.
static const uint NETWORK_CONTENT_FILENAME_LENGTH
The maximum length of a content's filename, in bytes including '\0'.
@ PACKET_CONTENT_CLIENT_INFO_EXTID
Queries the content server for information about a list of external IDs.
@ CONTENT_TYPE_AI
The content consists of an AI.
ClientNetworkContentSocketHandler _network_content_client
The client we use to connect to the server.
std::vector< ContentID > ContentIDList
List of content IDs to (possibly) select.
@ CONTENT_TYPE_BASE_GRAPHICS
The content consists of base graphics.
SendPacketsState SendPackets(bool closing_down=false)
Sends all the buffered packets out for this client.
bool CanSendReceive()
Check whether this socket can send or receive something.
@ 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.
@ CONTENT_TYPE_AI_LIBRARY
The content consists of an AI library.
@ NO_DIRECTORY
A path without any base directory.
void ToggleSelectedState(const ContentInfo *ci)
Toggle the state of a content info and check its dependencies.
NetworkRecvStatus
Status of a network client; reasons why a client has quit.
@ WC_NETWORK_STATUS_WINDOW
Network status window; Window numbers:
ContentID
Unique identifier for the content.
std::string filename
Filename (for the .tar.gz; only valid on download)
std::vector< ContentCallback * > callbacks
Callbacks to notify "the world".
static bool HasGame(const struct ContentInfo *ci, bool md5sum)
Wrapper function for GameScanner::HasGame.
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.
void DownloadSelectedContentFallback(const ContentIDList &content)
Initiate downloading the content over the fallback protocol.
@ WL_ERROR
Errors (eg. saving/loading failed)
void CDECL error(const char *s,...)
Error handling for fatal non-user errors.
void OnReceiveContentInfo(const ContentInfo *ci) override
We received a content info.
State state
Whether the content info is selected (for download)
@ CONTENT_TYPE_BASE_SOUNDS
The content consists of base sounds.
uint32 unique_id
Unique ID; either GRF ID or shortname.
Helper for scanning for files with tar as extension.
NetworkSettings network
settings related to the network
void SelectAll()
Select everything we can select.
void CloseWindowById(WindowClass cls, WindowNumber number, bool force)
Close a window by its class and window number (if it is open).
static const uint NETWORK_CONTENT_NAME_LENGTH
The maximum length of a content's name, in bytes including '\0'.
@ PACKET_CONTENT_CLIENT_INFO_LIST
Queries the content server for a list of info of a given content type.
@ NETWORK_RECV_STATUS_OKAY
Everything is okay.
@ CONTENT_TYPE_SCENARIO
The content consists of a scenario.
bool BeforeDownload()
Handle the opening of the file before downloading.
@ FGCM_EXACT
Only find Grfs matching md5sum.
static const uint NETWORK_CONTENT_TAG_LENGTH
The maximum length of a content's tag, in bytes including '\0'.
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...
NetworkRecvStatus CloseConnection(bool error=true) override
Disconnect from the content server.
static const uint NETWORK_CONTENT_URL_LENGTH
The maximum length of a content's url, in bytes including '\0'.
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 id
Unique (server side) ID for the content.
size_t RemainingBytesToTransfer() const
Get the amount of bytes that are still available for the Transfer functions.
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.
std::string description
Description of the content.
@ CONTENT_TYPE_HEIGHTMAP
The content consists of a heightmap.
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.
void CloseSocket()
Close the actual socket of the connection.
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.
@ CONTENT_TYPE_BASE_MUSIC
The content consists of base music.