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) 26 #include "../safeguards.h" 61 for (uint j = 0; j <
sizeof(ci->
md5sum); j++) {
103 proc = AI::HasAILibrary;
break;
111 proc = Game::HasGameLibrary;
break;
123 if (proc !=
nullptr) {
124 if (proc(ci,
true)) {
128 if (proc(ci,
false)) ci->
upgrade =
true;
139 if (ici->type == ci->
type && ici->unique_id == ci->
unique_id &&
140 memcmp(ci->
md5sum, ici->md5sum,
sizeof(ci->
md5sum)) == 0) {
143 if (ici->IsSelected()) ci->
state = ici->state;
151 ici->TransferFrom(ci);
165 this->infos.push_back(ci);
220 uint p_count =
min(count, (
SEND_MTU -
sizeof(
PacketSize) -
sizeof(byte) -
sizeof(uint16)) /
sizeof(uint32));
225 for (uint i = 0; i < p_count; i++) {
231 content_ids += p_count;
242 if (cv ==
nullptr)
return;
246 assert(cv->size() < 255);
248 (
sizeof(uint8) +
sizeof(uint32) + (send_md5sum ? 16 : 0)));
251 p->Send_uint8((uint8)cv->size());
254 p->Send_uint8((byte)ci->type);
255 p->Send_uint32(ci->unique_id);
256 if (!send_md5sum)
continue;
258 for (uint j = 0; j <
sizeof(ci->md5sum); j++) {
259 p->Send_uint8(ci->md5sum[j]);
268 if (ci->type == ci2->type && ci->unique_id == ci2->unique_id &&
269 (!send_md5sum || memcmp(ci->md5sum, ci2->md5sum,
sizeof(ci->md5sum)) == 0)) {
275 this->infos.push_back(ci);
296 content.push_back(ci->id);
297 bytes += ci->filesize;
300 files = (uint)content.size();
303 if (files == 0)
return;
318 uint count = (uint)content.size();
324 uint bytes = (10 + 1) * count + 1;
325 char *content_request = MallocT<char>(bytes);
326 const char *
lastof = content_request + bytes - 1;
328 char *p = content_request;
330 p +=
seprintf(p, lastof,
"%d\n",
id);
346 uint count = (uint)content.size();
347 const ContentID *content_ids = content.data();
355 uint p_count =
min(count, (
SEND_MTU -
sizeof(
PacketSize) -
sizeof(byte) -
sizeof(uint16)) /
sizeof(uint32));
360 for (uint i = 0; i < p_count; i++) {
366 content_ids += p_count;
382 static char buf[MAX_PATH];
396 #if defined(WITH_ZLIB) 401 if (ftmp ==
nullptr)
return false;
403 gzFile fin = gzdopen(dup(fileno(ftmp)),
"rb");
408 if (fin ==
nullptr || fout ==
nullptr) {
413 int read = gzread(fin, buff,
sizeof(buff));
428 gzerror(fin, &errnum);
429 if (errnum != 0 && errnum != Z_STREAM_END) ret =
false;
432 if (read < 0 || (
size_t)read != fwrite(buff, 1, read, fout)) {
442 if (fin !=
nullptr) gzclose(fin);
443 if (fout !=
nullptr) fclose(fout);
453 if (this->
curFile ==
nullptr) {
468 size_t toRead = (size_t)(p->
size - p->
pos);
469 if (fwrite(p->
buffer + p->
pos, 1, toRead, this->curFile) != toRead) {
471 ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD, STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE,
WL_ERROR);
502 if (filename ==
nullptr || (this->
curFile = fopen(filename,
"wb")) ==
nullptr) {
505 ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD, STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE,
WL_ERROR);
555 if (this->
curFile !=
nullptr) {
557 long size = ftell(this->
curFile);
567 assert(data ==
nullptr || length != 0);
573 if (data !=
nullptr) {
586 if (data !=
nullptr) {
588 if (fwrite(data, 1, length, this->
curFile) != length) {
599 if (this->
curFile !=
nullptr) {
617 #define check_not_null(p) { if ((p) == nullptr) { this->OnFailure(); return; } } 619 #define check_and_terminate(p) { check_not_null(p); *(p) = '\0'; } 623 char *p = strchr(str,
'\n');
624 check_and_terminate(p);
630 p = strchr(str,
',');
631 check_and_terminate(p);
636 p = strchr(str,
',');
637 check_and_terminate(p);
642 p = strchr(str,
',');
643 check_and_terminate(p);
649 if (strncmp(str,
"ottd", 4) == 0) {
658 p = strrchr(str,
'/');
668 for (uint i = 0; i < 2; i++) {
669 p = strrchr(tmp,
'.');
670 check_and_terminate(p);
687 #undef check_and_terminate 724 _network_content_client.
OnConnect(
false);
729 assert(_network_content_client.
sock == INVALID_SOCKET);
731 _network_content_client.
sock = s;
732 _network_content_client.
Reopen();
754 if (this->
sock == INVALID_SOCKET)
return;
804 if (ci->id == cid)
return ci;
830 if (ci ==
nullptr || !ci->
IsSelected())
return;
892 if (ci == child)
continue;
894 for (uint i = 0; i < ci->dependency_count; i++) {
895 if (ci->dependencies[i] == child->
id) {
896 parents.push_back(ci);
910 tree.push_back(child);
916 for (uint i = 0; i < tree.size(); i++) {
957 if (!c->IsSelected())
continue;
976 bool force_selection =
false;
981 if (sel_count == 0) {
987 if (force_selection)
continue;
997 force_selection =
true;
1002 if (force_selection)
continue;
1022 this->infos.clear();
1030 for (
size_t i = 0; i < this->
callbacks.size(); ) {
1040 for (
size_t i = 0; i < this->
callbacks.size(); ) {
1049 for (
size_t i = 0; i < this->
callbacks.size(); ) {
1059 for (
size_t i = 0; i < this->
callbacks.size(); ) {
1069 if (ci !=
nullptr) {
1073 for (
size_t i = 0; i < this->
callbacks.size(); ) {
void Close() override
Disconnect from the content server.
Helper to mark the end of the types.
ContentVector infos
All content info we received.
void CheckDependencyState(ContentInfo *ci)
Check the dependencies (recursively) of this content info.
The content consists of base graphics.
bool IsSelected() const
Is the state either selected or autoselected?
Connect with a HTTP server and do ONE query.
void DownloadSelectedContent(uint &files, uint &bytes, bool fallback=false)
Actually begin downloading the content we selected.
char filename[48]
Filename (for the .tar.gz; only valid on download)
SOCKET sock
The socket currently connected to.
uint32 unique_id
Unique ID; either GRF ID or shortname.
uint32 _realtime_tick
The real time in the game.
Internal entity of a packet.
std::vector< char > http_response
The HTTP response to the requests we've been doing.
Queries the content server for information about a list of external IDs.
static char * strecat(char *dst, const char *src, const char *last)
Appends characters from one string to another.
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...
Socket handler for the content server connection.
Subdirectory
The different kinds of subdirectories OpenTTD uses.
uint32 Recv_uint32()
Read a 32 bits integer from the packet.
PacketSize pos
The current read/write position in the packet.
"Helper" class for creating TCP connections in a non-blocking manner
static bool GunzipFile(const ContentInfo *ci)
Gunzip a given file and remove the .gz if successful.
Base socket handler for all Content TCP sockets.
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
std::vector< ContentCallback * > callbacks
Callbacks to notify "the world".
Callbacks for notifying others about incoming data.
uint32 filesize
Size of the file.
void Connect()
Connect with the content server.
The content consists of a scenario.
void DownloadContentInfo(ContentID cid)
Download information of a given Content ID if not already tried.
void OnDownloadComplete(ContentID cid) override
We have finished downloading a file.
uint8 dependency_count
Number of dependencies.
void Send_uint8(uint8 data)
Package a 8 bits integer in the packet.
char(* tags)[32]
Malloced array of tags (strings)
static bool HasGame(const struct ContentInfo *ci, bool md5sum)
Wrapper function for GameScanner::HasGame.
bool(* HasProc)(const ContentInfo *ci, bool md5sum)
Check whether a function piece of content is locally known.
void SendReceive()
Check whether we received/can send some data from/to the content server and when that's the case hand...
void ReverseLookupTreeDependency(ConstContentVector &tree, const ContentInfo *child) const
Reverse lookup the dependencies of all parents over a given child.
void OnDisconnect() override
Callback for when the connection got disconnected.
Wrapper for (un)resolved network addresses; there's no reason to transform a numeric IP to a string a...
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.
ContentID * dependencies
Malloced array of dependencies (unique server side ids)
Helper for scanning for files with tar as extension.
The content has been selected as dependency.
void Send_uint32(uint32 data)
Package a 32 bits integer in the packet.
#define lastof(x)
Get the last element of an fixed size array.
void OnDownloadProgress(const ContentInfo *ci, int bytes) override
We have progress in the download of a file.
void OnConnect(bool success) override
Callback for when the connection has finished.
const GRFConfig * FindGRFConfig(uint32 grfid, FindGRFConfigMode mode, const uint8 *md5sum, uint32 desired_version)
Find a NewGRF in the scanned list.
void OnFailure() override
An error has occurred and the connection has been closed.
Subdirectory for all base data (base sets, intro game)
ContentID
Unique identifier for the content.
The content has not been selected.
Queries the content server for information about a list of internal IDs.
void Reopen()
Reopen the socket so we can send/receive stuff again.
SendPacketsState SendPackets(bool closing_down=false)
Sends all the buffered packets out for this client.
void Unselect(ContentID cid)
Unselect a specific content id.
The content does not exist in the content system.
bool ReceivePackets()
Receive a packet at TCP level.
void UnselectAll()
Unselect everything that we've not downloaded so far.
bool isConnecting
Whether we're connecting.
static int Connect(char *uri, HTTPCallback *callback, const char *data=nullptr, int depth=0)
Connect to the given URI.
char name[32]
Name of the content.
virtual void OnDisconnect()
Callback for when the connection got disconnected.
The content consists of a game script.
NetworkSettings network
settings related to the network
std::vector< ContentID > ContentIDList
List of content IDs to (possibly) select.
~ClientNetworkContentSocketHandler()
Clear up the mess ;)
byte * buffer
The buffer of this packet, of basically variable length up to SEND_MTU.
std::vector< ContentInfo * > ContentVector
Vector with content info.
uint8 tag_count
Number of tags.
char version[16]
Version of the content.
void SelectUpgrade()
Select everything that's an update for something we've got.
void Send_uint16(uint16 data)
Package a 16 bits integer in the packet.
uint32 lastActivity
The last time there was network activity.
static const char *const NETWORK_CONTENT_SERVER_HOST
DNS hostname of the content server.
virtual void OnDownloadProgress(const ContentInfo *ci, int bytes)
We have progress in the download of a file.
static char * GetFullFilename(const ContentInfo *ci, bool compressed)
Determine the full filename of a piece of content information.
ClientSettings _settings_client
The current settings for this game.
A path without any base directory.
The content is already at the client side.
ContentIDList requested
ContentIDs we already requested (so we don't do it again)
ContentID id
Unique (server side) ID for the content.
Connect to the content server.
void Clear()
Clear all downloaded content information.
void RequestContentList(ContentType type)
Request the content list for the given type.
static const char *const NETWORK_CONTENT_MIRROR_HOST
DNS hostname of the HTTP-content mirror server.
State state
Whether the content info is selected (for download)
byte * buf
Buffer we're going to write to/read from.
Search within the autodownload directory.
Part of the network protocol handling content distribution.
PacketSize size
The size of the whole packet for received packets.
void OnReceiveContentInfo(const ContentInfo *ci) override
We received a content info.
void Close() override
Really close the socket.
#define lengthof(x)
Return the length of an fixed size array.
static T min(const T a, const T b)
Returns the minimum of two values.
static const int IDLE_TIMEOUT
The idle timeout; when to close the connection because it's idle.
Queries the content server for a list of info of a given content type.
byte md5sum[16]
The MD5 checksum.
The content consists of a GS library.
bool BeforeDownload()
Handle the opening of the file before downloading.
static bool HasAI(const struct ContentInfo *ci, bool md5sum)
Wrapper function for AIScanner::HasAI.
ContentInfo * GetContent(ContentID cid)
Get the content info based on a ContentID.
The content consists of a NewGRF.
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...
bool AddFile(const char *filename, size_t basepath_length, const char *tar_filename=nullptr) override
Add a file with the given filename.
ContentType
The values in the enum are important; they are used as database 'keys'.
Network status window; Window numbers:
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
Delete a window by its class and window number (if it is open).
Queries the content server for information about a list of external IDs and MD5.
void OnConnect(SOCKET s) override
Callback when the connection succeeded.
void Select(ContentID cid)
Select a specific content id.
The content consists of an AI library.
uint8 Recv_uint8()
Read a 8 bits integer from the packet.
void SelectAll()
Select everything we can select.
void ReverseLookupDependency(ConstContentVector &parents, const ContentInfo *child) const
Reverse lookup the dependencies of (direct) parents over a given child.
Request a content file given an internal ID.
static const char *const NETWORK_CONTENT_MIRROR_URL
URL of the HTTP mirror system.
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Replace the unknown/bad bits with question marks.
The content consists of a heightmap.
The content consists of an AI.
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...
ContentType type
Type of content.
bool upgrade
This item is an upgrade.
void DownloadSelectedContentFallback(const ContentIDList &content)
Initiate downloading the content over the fallback protocol.
void OnFailure() override
Callback for when the connection attempt failed.
void AfterDownload()
Handle the closing and extracting of a file after downloading it has been done.
static const uint16 NETWORK_CONTENT_MIRROR_PORT
The default port of the content mirror (TCP)
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
The content consists of base music.
bool no_http_content_downloads
do not do content downloads over HTTP
virtual void OnReceiveContentInfo(const ContentInfo *ci)
We received a content info.
bool HasScenario(const ContentInfo *ci, bool md5sum)
Check whether we've got a given scenario based on its unique ID.
ClientNetworkContentSocketHandler()
Create a socket handler to handle the connection.
static const uint16 SEND_MTU
Number of bytes we can pack in a single packet.
NetworkContentConnecter(const NetworkAddress &address)
Initiate the connecting.
ContentInfo * curInfo
Information about the currently downloaded file.
virtual void OnConnect(bool success)
Callback for when the connection has finished.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
bool ExtractTar(const char *tar_filename, Subdirectory subdir)
Extract the tar with the given filename in the directory where the tar resides.
The content has been manually selected.
virtual void SendPacket(Packet *packet)
This function puts the packet in the send-queue and it is send as soon as possible.
static const uint16 NETWORK_CONTENT_SERVER_PORT
The default port of the content server (TCP)
int http_response_index
Where we are, in the response, with handling it.
virtual void OnDownloadComplete(ContentID cid)
We have finished downloading a file.
void OnReceiveData(const char *data, size_t length) override
We're receiving data.
bool CanSendReceive()
Check whether this socket can send or receive something.
static uint32 BSWAP32(uint32 x)
Perform a 32 bits endianness bitswap on x.
Only find Grfs matching md5sum.
Subdirectory GetContentInfoSubDir(ContentType type)
Helper to get the subdirectory a ContentInfo is located in.
char url[96]
URL related to the content.
static bool HasGRFConfig(const ContentInfo *ci, bool md5sum)
Wrapper function for the HasProc.
Errors (eg. saving/loading failed)
void DownloadSelectedContentHTTP(const ContentIDList &content)
Initiate downloading the content over HTTP.
char description[512]
Description of the content.
uint16 PacketSize
Size of the whole packet.
FILE * curFile
Currently downloaded file.
Container for all important information about a piece of content.
bool IsValid() const
Is the information from this content info valid?
Network content download status.
ClientNetworkContentSocketHandler _network_content_client
The client we use to connect to the server.
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.
std::vector< const ContentInfo * > ConstContentVector
Vector with constant content info.
void ToggleSelectedState(const ContentInfo *ci)
Toggle the state of a content info and check its dependencies.
The content consists of base sounds.