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