3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #ifndef CLIENTMEDIA_HEADER
21 #define CLIENTMEDIA_HEADER
23 #include "irrlichttypes.h"
24 #include "filecache.h"
29 #include <unordered_map>
32 struct HTTPFetchResult;
34 #define MTHASHSET_FILE_SIGNATURE 0x4d544853 // 'MTHS'
35 #define MTHASHSET_FILE_NAME "index.mth"
37 class ClientMediaDownloader
40 ClientMediaDownloader();
41 ~ClientMediaDownloader();
43 float getProgress() const {
44 if (m_uncached_count >= 1)
45 return 1.0 * m_uncached_received_count /
51 bool isStarted() const {
52 return m_initial_step_done;
55 // If this returns true, the downloader is done and can be deleted
57 return m_initial_step_done &&
58 m_uncached_received_count == m_uncached_count;
61 // Add a file to the list of required file (but don't fetch it yet)
62 void addFile(const std::string &name, const std::string &sha1);
64 // Add a remote server to the list; ignored if not built with cURL
65 void addRemoteServer(const std::string &baseurl);
67 // Steps the media downloader:
68 // - May load media into client by calling client->loadMedia()
69 // - May check media cache for files
70 // - May add files to media cache
71 // - May start remote transfers by calling httpfetch_async
72 // - May check for completion of current remote transfers
73 // - May start conventional transfers by calling client->request_media()
74 // - May inform server that all media has been loaded
75 // by calling client->received_media()
76 // After step has been called once, don't call addFile/addRemoteServer.
77 void step(Client *client);
79 // Must be called for each file received through TOCLIENT_MEDIA
80 void conventionalTransferDone(
81 const std::string &name,
82 const std::string &data,
90 std::vector<s32> available_remotes;
93 struct RemoteServerStatus {
96 bool request_by_filename;
99 void initialStep(Client *client);
100 void remoteHashSetReceived(const HTTPFetchResult &fetch_result);
101 void remoteMediaReceived(const HTTPFetchResult &fetch_result,
103 s32 selectRemoteServer(FileStatus *filestatus);
104 void startRemoteMediaTransfers();
105 void startConventionalTransfers(Client *client);
107 bool checkAndLoad(const std::string &name, const std::string &sha1,
108 const std::string &data, bool is_from_cache,
111 std::string serializeRequiredHashSet();
112 static void deSerializeHashSet(const std::string &data,
113 std::set<std::string> &result);
115 // Maps filename to file status
116 std::map<std::string, FileStatus*> m_files;
118 // Array of remote media servers
119 std::vector<RemoteServerStatus*> m_remotes;
121 // Filesystem-based media cache
122 FileCache m_media_cache;
124 // Has an attempt been made to load media files from the file cache?
125 // Have hash sets been requested from remote servers?
126 bool m_initial_step_done = false;
128 // Total number of media files to load
129 s32 m_uncached_count = 0;
131 // Number of media files that have been received
132 s32 m_uncached_received_count = 0;
134 // Status of remote transfers
135 unsigned long m_httpfetch_caller;
136 unsigned long m_httpfetch_next_id = 0;
137 long m_httpfetch_timeout = 0;
138 s32 m_httpfetch_active = 0;
139 s32 m_httpfetch_active_limit = 0;
140 s32 m_outstanding_hash_sets = 0;
141 std::unordered_map<unsigned long, std::string> m_remote_file_transfers;
143 // All files up to this name have either been received from a
144 // remote server or failed on all remote servers, so those files
145 // don't need to be looked at again
146 // (use m_files.upper_bound(m_name_bound) to get an iterator)
147 std::string m_name_bound = "";
151 #endif // !CLIENTMEDIA_HEADER