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