Line data Source code
1 : /*
2 : Minetest
3 : Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4 :
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.
9 :
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.
14 :
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.
18 : */
19 :
20 : #ifndef CLIENTMEDIA_HEADER
21 : #define CLIENTMEDIA_HEADER
22 :
23 : #include "irrlichttypes.h"
24 : #include "filecache.h"
25 : #include <ostream>
26 : #include <map>
27 : #include <set>
28 : #include <vector>
29 :
30 : class Client;
31 : struct HTTPFetchResult;
32 :
33 : #define MTHASHSET_FILE_SIGNATURE 0x4d544853 // 'MTHS'
34 : #define MTHASHSET_FILE_NAME "index.mth"
35 :
36 : class ClientMediaDownloader
37 : {
38 : public:
39 : ClientMediaDownloader();
40 : ~ClientMediaDownloader();
41 :
42 1 : float getProgress() const {
43 1 : if (m_uncached_count >= 1)
44 0 : return 1.0 * m_uncached_received_count /
45 0 : m_uncached_count;
46 : else
47 1 : return 0.0;
48 : }
49 :
50 21 : bool isStarted() const {
51 21 : return m_initial_step_done;
52 : }
53 :
54 : // If this returns true, the downloader is done and can be deleted
55 1 : bool isDone() const {
56 2 : return m_initial_step_done &&
57 2 : m_uncached_received_count == m_uncached_count;
58 : }
59 :
60 : // Add a file to the list of required file (but don't fetch it yet)
61 : void addFile(std::string name, std::string sha1);
62 :
63 : // Add a remote server to the list; ignored if not built with cURL
64 : void addRemoteServer(std::string baseurl);
65 :
66 : // Steps the media downloader:
67 : // - May load media into client by calling client->loadMedia()
68 : // - May check media cache for files
69 : // - May add files to media cache
70 : // - May start remote transfers by calling httpfetch_async
71 : // - May check for completion of current remote transfers
72 : // - May start conventional transfers by calling client->request_media()
73 : // - May inform server that all media has been loaded
74 : // by calling client->received_media()
75 : // After step has been called once, don't call addFile/addRemoteServer.
76 : void step(Client *client);
77 :
78 : // Must be called for each file received through TOCLIENT_MEDIA
79 : void conventionalTransferDone(
80 : const std::string &name,
81 : const std::string &data,
82 : Client *client);
83 :
84 : private:
85 5270 : struct FileStatus {
86 : bool received;
87 : std::string sha1;
88 : s32 current_remote;
89 : std::vector<s32> available_remotes;
90 : };
91 :
92 0 : struct RemoteServerStatus {
93 : std::string baseurl;
94 : s32 active_count;
95 : bool request_by_filename;
96 : };
97 :
98 : void initialStep(Client *client);
99 : void remoteHashSetReceived(const HTTPFetchResult &fetch_result);
100 : void remoteMediaReceived(const HTTPFetchResult &fetch_result,
101 : Client *client);
102 : s32 selectRemoteServer(FileStatus *filestatus);
103 : void startRemoteMediaTransfers();
104 : void startConventionalTransfers(Client *client);
105 :
106 : bool checkAndLoad(const std::string &name, const std::string &sha1,
107 : const std::string &data, bool is_from_cache,
108 : Client *client);
109 :
110 : std::string serializeRequiredHashSet();
111 : static void deSerializeHashSet(const std::string &data,
112 : std::set<std::string> &result);
113 :
114 : // Maps filename to file status
115 : std::map<std::string, FileStatus*> m_files;
116 :
117 : // Array of remote media servers
118 : std::vector<RemoteServerStatus*> m_remotes;
119 :
120 : // Filesystem-based media cache
121 : FileCache m_media_cache;
122 :
123 : // Has an attempt been made to load media files from the file cache?
124 : // Have hash sets been requested from remote servers?
125 : bool m_initial_step_done;
126 :
127 : // Total number of media files to load
128 : s32 m_uncached_count;
129 :
130 : // Number of media files that have been received
131 : s32 m_uncached_received_count;
132 :
133 : // Status of remote transfers
134 : unsigned long m_httpfetch_caller;
135 : unsigned long m_httpfetch_next_id;
136 : long m_httpfetch_timeout;
137 : s32 m_httpfetch_active;
138 : s32 m_httpfetch_active_limit;
139 : s32 m_outstanding_hash_sets;
140 : std::map<unsigned long, std::string> m_remote_file_transfers;
141 :
142 : // All files up to this name have either been received from a
143 : // remote server or failed on all remote servers, so those files
144 : // don't need to be looked at again
145 : // (use m_files.upper_bound(m_name_bound) to get an iterator)
146 : std::string m_name_bound;
147 :
148 : };
149 :
150 : #endif // !CLIENTMEDIA_HEADER
|