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.h148
1 files changed, 148 insertions, 0 deletions
diff --git a/src/client/clientmedia.h b/src/client/clientmedia.h
new file mode 100644
index 000000000..b08b83e4d
--- /dev/null
+++ b/src/client/clientmedia.h
@@ -0,0 +1,148 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#pragma once
+
+#include "irrlichttypes.h"
+#include "filecache.h"
+#include <ostream>
+#include <map>
+#include <set>
+#include <vector>
+#include <unordered_map>
+
+class Client;
+struct HTTPFetchResult;
+
+#define MTHASHSET_FILE_SIGNATURE 0x4d544853 // 'MTHS'
+#define MTHASHSET_FILE_NAME "index.mth"
+
+class ClientMediaDownloader
+{
+public:
+ ClientMediaDownloader();
+ ~ClientMediaDownloader();
+
+ float getProgress() const {
+ if (m_uncached_count >= 1)
+ return 1.0f * m_uncached_received_count /
+ m_uncached_count;
+
+ return 0.0f;
+ }
+
+ bool isStarted() const {
+ return m_initial_step_done;
+ }
+
+ // If this returns true, the downloader is done and can be deleted
+ bool isDone() const {
+ 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);
+
+ // Add a remote server to the list; ignored if not built with cURL
+ void addRemoteServer(const std::string &baseurl);
+
+ // 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);
+
+ // Must be called for each file received through TOCLIENT_MEDIA
+ void conventionalTransferDone(
+ const std::string &name,
+ const std::string &data,
+ Client *client);
+
+private:
+ struct FileStatus {
+ bool received;
+ std::string sha1;
+ s32 current_remote;
+ std::vector<s32> available_remotes;
+ };
+
+ struct RemoteServerStatus {
+ std::string baseurl;
+ s32 active_count;
+ bool request_by_filename;
+ };
+
+ void initialStep(Client *client);
+ void remoteHashSetReceived(const HTTPFetchResult &fetch_result);
+ void remoteMediaReceived(const HTTPFetchResult &fetch_result,
+ Client *client);
+ s32 selectRemoteServer(FileStatus *filestatus);
+ 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);
+
+ // Maps filename to file status
+ std::map<std::string, FileStatus*> m_files;
+
+ // 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;
+
+ // Total number of media files to load
+ s32 m_uncached_count = 0;
+
+ // Number of media files that have been received
+ s32 m_uncached_received_count = 0;
+
+ // Status of remote transfers
+ unsigned long m_httpfetch_caller;
+ unsigned long m_httpfetch_next_id = 0;
+ long m_httpfetch_timeout = 0;
+ s32 m_httpfetch_active = 0;
+ s32 m_httpfetch_active_limit = 0;
+ s32 m_outstanding_hash_sets = 0;
+ std::unordered_map<unsigned long, std::string> m_remote_file_transfers;
+
+ // All files up to this name have either been received from a
+ // remote server or failed on all remote servers, so those files
+ // don't need to be looked at again
+ // (use m_files.upper_bound(m_name_bound) to get an iterator)
+ std::string m_name_bound = "";
+
+};