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 
8 /** @file network_content.h Part of the network protocol handling content distribution. */
9 
10 #ifndef NETWORK_CONTENT_H
11 #define NETWORK_CONTENT_H
12 
13 #include "core/tcp_content.h"
14 #include "core/tcp_http.h"
15 #include <unordered_map>
16 
17 /** Vector with content info */
18 typedef std::vector<ContentInfo *> ContentVector;
19 /** Vector with constant content info */
20 typedef std::vector<const ContentInfo *> ConstContentVector;
21 
22 /** Iterator for the content vector */
23 typedef ContentInfo **ContentIterator;
24 /** Iterator for the constant content vector */
25 typedef const ContentInfo * const * ConstContentIterator;
26 
27 /** Callbacks for notifying others about incoming data */
28 struct ContentCallback {
29 	/**
30 	 * Callback for when the connection has finished
31 	 * @param success whether the connection was made or that we failed to make it
32 	 */
OnConnectContentCallback33 	virtual void OnConnect(bool success) {}
34 
35 	/**
36 	 * Callback for when the connection got disconnected.
37 	 */
OnDisconnectContentCallback38 	virtual void OnDisconnect() {}
39 
40 	/**
41 	 * We received a content info.
42 	 * @param ci the content info
43 	 */
OnReceiveContentInfoContentCallback44 	virtual void OnReceiveContentInfo(const ContentInfo *ci) {}
45 
46 	/**
47 	 * We have progress in the download of a file
48 	 * @param ci the content info of the file
49 	 * @param bytes the number of bytes downloaded since the previous call
50 	 */
OnDownloadProgressContentCallback51 	virtual void OnDownloadProgress(const ContentInfo *ci, int bytes) {}
52 
53 	/**
54 	 * We have finished downloading a file
55 	 * @param cid the ContentID of the downloaded file
56 	 */
OnDownloadCompleteContentCallback57 	virtual void OnDownloadComplete(ContentID cid) {}
58 
59 	/** Silentium */
~ContentCallbackContentCallback60 	virtual ~ContentCallback() {}
61 };
62 
63 /**
64  * Socket handler for the content server connection
65  */
66 class ClientNetworkContentSocketHandler : public NetworkContentSocketHandler, ContentCallback, HTTPCallback {
67 protected:
68 	typedef std::vector<ContentID> ContentIDList; ///< List of content IDs to (possibly) select.
69 	std::vector<ContentCallback *> callbacks;     ///< Callbacks to notify "the world"
70 	ContentIDList requested;                      ///< ContentIDs we already requested (so we don't do it again)
71 	ContentVector infos;                          ///< All content info we received
72 	std::unordered_multimap<ContentID, ContentID> reverse_dependency_map; ///< Content reverse dependency map
73 	std::vector<char> http_response;              ///< The HTTP response to the requests we've been doing
74 	int http_response_index;                      ///< Where we are, in the response, with handling it
75 
76 	FILE *curFile;        ///< Currently downloaded file
77 	ContentInfo *curInfo; ///< Information about the currently downloaded file
78 	bool isConnecting;    ///< Whether we're connecting
79 	std::chrono::steady_clock::time_point lastActivity;  ///< The last time there was network activity
80 
81 	friend class NetworkContentConnecter;
82 
83 	bool Receive_SERVER_INFO(Packet *p) override;
84 	bool Receive_SERVER_CONTENT(Packet *p) override;
85 
86 	ContentInfo *GetContent(ContentID cid) const;
87 	void DownloadContentInfo(ContentID cid);
88 
89 	void OnConnect(bool success) override;
90 	void OnDisconnect() override;
91 	void OnReceiveContentInfo(const ContentInfo *ci) override;
92 	void OnDownloadProgress(const ContentInfo *ci, int bytes) override;
93 	void OnDownloadComplete(ContentID cid) override;
94 
95 	void OnFailure() override;
96 	void OnReceiveData(const char *data, size_t length) override;
97 
98 	bool BeforeDownload();
99 	void AfterDownload();
100 
101 	void DownloadSelectedContentHTTP(const ContentIDList &content);
102 	void DownloadSelectedContentFallback(const ContentIDList &content);
103 public:
104 	/** The idle timeout; when to close the connection because it's idle. */
105 	static constexpr std::chrono::seconds IDLE_TIMEOUT = std::chrono::seconds(60);
106 
107 	ClientNetworkContentSocketHandler();
108 	~ClientNetworkContentSocketHandler();
109 
110 	void Connect();
111 	void SendReceive();
112 	NetworkRecvStatus CloseConnection(bool error = true) override;
113 
114 	void RequestContentList(ContentType type);
115 	void RequestContentList(uint count, const ContentID *content_ids);
116 	void RequestContentList(ContentVector *cv, bool send_md5sum = true);
117 
118 	void DownloadSelectedContent(uint &files, uint &bytes, bool fallback = false);
119 
120 	void Select(ContentID cid);
121 	void Unselect(ContentID cid);
122 	void SelectAll();
123 	void SelectUpgrade();
124 	void UnselectAll();
125 	void ToggleSelectedState(const ContentInfo *ci);
126 
127 	void ReverseLookupDependency(ConstContentVector &parents, const ContentInfo *child) const;
128 	void ReverseLookupTreeDependency(ConstContentVector &tree, const ContentInfo *child) const;
129 	void CheckDependencyState(ContentInfo *ci);
130 
131 	/** Get the number of content items we know locally. */
Length()132 	uint Length() const { return (uint)this->infos.size(); }
133 	/** Get the begin of the content inf iterator. */
Begin()134 	ConstContentIterator Begin() const { return this->infos.data(); }
135 	/** Get the nth position of the content inf iterator. */
Get(uint32 index)136 	ConstContentIterator Get(uint32 index) const { return this->infos.data() + index; }
137 	/** Get the end of the content inf iterator. */
End()138 	ConstContentIterator End() const { return this->Begin() + this->Length(); }
139 
140 	void Clear();
141 
142 	/** Add a callback to this class */
AddCallback(ContentCallback * cb)143 	void AddCallback(ContentCallback *cb) { include(this->callbacks, cb); }
144 	/** Remove a callback */
RemoveCallback(ContentCallback * cb)145 	void RemoveCallback(ContentCallback *cb) { this->callbacks.erase(std::find(this->callbacks.begin(), this->callbacks.end(), cb)); }
146 };
147 
148 extern ClientNetworkContentSocketHandler _network_content_client;
149 
150 void ShowNetworkContentListWindow(ContentVector *cv = nullptr, ContentType type1 = CONTENT_TYPE_END, ContentType type2 = CONTENT_TYPE_END);
151 
152 void ShowMissingContentWindow(const struct GRFConfig *list);
153 
154 #endif /* NETWORK_CONTENT_H */
155