diff options
Diffstat (limited to 'src/client/clientmedia.h')
-rw-r--r-- | src/client/clientmedia.h | 159 |
1 files changed, 129 insertions, 30 deletions
diff --git a/src/client/clientmedia.h b/src/client/clientmedia.h index e97a0f24b..aa7b0f398 100644 --- a/src/client/clientmedia.h +++ b/src/client/clientmedia.h @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes.h" #include "filecache.h" +#include "util/basic_macros.h" #include <ostream> #include <map> #include <set> @@ -38,7 +39,62 @@ struct HTTPFetchResult; bool clientMediaUpdateCache(const std::string &raw_hash, const std::string &filedata); -class ClientMediaDownloader +// more of a base class than an interface but this name was most convenient... +class IClientMediaDownloader +{ +public: + DISABLE_CLASS_COPY(IClientMediaDownloader) + + virtual bool isStarted() const = 0; + + // If this returns true, the downloader is done and can be deleted + virtual bool isDone() const = 0; + + // Add a file to the list of required file (but don't fetch it yet) + virtual void addFile(const std::string &name, const std::string &sha1) = 0; + + // Add a remote server to the list; ignored if not built with cURL + virtual void addRemoteServer(const std::string &baseurl) = 0; + + // Steps the media downloader: + // - May load media into client by calling client->loadMedia() + // - May check media cache for files + // - May add files to media cache + // - May start remote transfers by calling httpfetch_async + // - May check for completion of current remote transfers + // - May start conventional transfers by calling client->request_media() + // - May inform server that all media has been loaded + // by calling client->received_media() + // After step has been called once, don't call addFile/addRemoteServer. + virtual void step(Client *client) = 0; + + // Must be called for each file received through TOCLIENT_MEDIA + // returns true if this file belongs to this downloader + virtual bool conventionalTransferDone(const std::string &name, + const std::string &data, Client *client) = 0; + +protected: + IClientMediaDownloader(); + virtual ~IClientMediaDownloader() = default; + + // Forwards the call to the appropriate Client method + virtual bool loadMedia(Client *client, const std::string &data, + const std::string &name) = 0; + + void createCacheDirs(); + + bool tryLoadFromCache(const std::string &name, const std::string &sha1, + Client *client); + + bool checkAndLoad(const std::string &name, const std::string &sha1, + const std::string &data, bool is_from_cache, Client *client); + + // Filesystem-based media cache + FileCache m_media_cache; + bool m_write_to_cache; +}; + +class ClientMediaDownloader : public IClientMediaDownloader { public: ClientMediaDownloader(); @@ -52,39 +108,29 @@ public: return 0.0f; } - bool isStarted() const { + bool isStarted() const override { return m_initial_step_done; } - // If this returns true, the downloader is done and can be deleted - bool isDone() const { + bool isDone() const override { return m_initial_step_done && m_uncached_received_count == m_uncached_count; } - // Add a file to the list of required file (but don't fetch it yet) - void addFile(const std::string &name, const std::string &sha1); + void addFile(const std::string &name, const std::string &sha1) override; - // Add a remote server to the list; ignored if not built with cURL - void addRemoteServer(const std::string &baseurl); + void addRemoteServer(const std::string &baseurl) override; - // Steps the media downloader: - // - May load media into client by calling client->loadMedia() - // - May check media cache for files - // - May add files to media cache - // - May start remote transfers by calling httpfetch_async - // - May check for completion of current remote transfers - // - May start conventional transfers by calling client->request_media() - // - May inform server that all media has been loaded - // by calling client->received_media() - // After step has been called once, don't call addFile/addRemoteServer. - void step(Client *client); + void step(Client *client) override; - // Must be called for each file received through TOCLIENT_MEDIA - void conventionalTransferDone( + bool conventionalTransferDone( const std::string &name, const std::string &data, - Client *client); + Client *client) override; + +protected: + bool loadMedia(Client *client, const std::string &data, + const std::string &name) override; private: struct FileStatus { @@ -107,13 +153,9 @@ private: void startRemoteMediaTransfers(); void startConventionalTransfers(Client *client); - bool checkAndLoad(const std::string &name, const std::string &sha1, - const std::string &data, bool is_from_cache, - Client *client); - - std::string serializeRequiredHashSet(); static void deSerializeHashSet(const std::string &data, std::set<std::string> &result); + std::string serializeRequiredHashSet(); // Maps filename to file status std::map<std::string, FileStatus*> m_files; @@ -121,9 +163,6 @@ private: // Array of remote media servers std::vector<RemoteServerStatus*> m_remotes; - // Filesystem-based media cache - FileCache m_media_cache; - // Has an attempt been made to load media files from the file cache? // Have hash sets been requested from remote servers? bool m_initial_step_done = false; @@ -149,3 +188,63 @@ private: std::string m_name_bound = ""; }; + +// A media downloader that only downloads a single file. +// It does/doesn't do several things the normal downloader does: +// - won't fetch hash sets from remote servers +// - will mark loaded media as coming from file push +// - writing to file cache is optional +class SingleMediaDownloader : public IClientMediaDownloader +{ +public: + SingleMediaDownloader(bool write_to_cache); + ~SingleMediaDownloader(); + + bool isStarted() const override { + return m_stage > STAGE_INIT; + } + + bool isDone() const override { + return m_stage >= STAGE_DONE; + } + + void addFile(const std::string &name, const std::string &sha1) override; + + void addRemoteServer(const std::string &baseurl) override; + + void step(Client *client) override; + + bool conventionalTransferDone(const std::string &name, + const std::string &data, Client *client) override; + +protected: + bool loadMedia(Client *client, const std::string &data, + const std::string &name) override; + +private: + void initialStep(Client *client); + void remoteMediaReceived(const HTTPFetchResult &fetch_result, Client *client); + void startRemoteMediaTransfer(); + void startConventionalTransfer(Client *client); + + enum Stage { + STAGE_INIT, + STAGE_CACHE_CHECKED, // we have tried to load the file from cache + STAGE_DONE + }; + + // Information about the one file we want to fetch + std::string m_file_name; + std::string m_file_sha1; + s32 m_current_remote; + + // Array of remote media servers + std::vector<std::string> m_remotes; + + enum Stage m_stage = STAGE_INIT; + + // Status of remote transfers + unsigned long m_httpfetch_caller; + unsigned long m_httpfetch_next_id = 0; + +}; |