aboutsummaryrefslogtreecommitdiff
path: root/src/client/clientmedia.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/clientmedia.h')
-rw-r--r--src/client/clientmedia.h159
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;
+
+};