From e2c9880a159201061f49193ccdc395048991ace1 Mon Sep 17 00:00:00 2001 From: Green Sky Date: Mon, 29 Jul 2024 20:03:24 +0200 Subject: [PATCH] major msg -> obj file transfer refactor mostly done, some things are hacky or not done --- CMakeLists.txt | 12 +- .../tox_contacts/tox_contact_model2.cpp | 2 +- .../backends/tox_ft_filesystem.cpp | 77 +++ .../backends/tox_ft_filesystem.hpp | 19 + solanaceae/tox_messages/components.hpp | 47 -- solanaceae/tox_messages/msg_components.hpp | 21 + ...omponents_id.inl => msg_components_id.inl} | 7 +- .../nj/tox_message_components.hpp | 2 +- solanaceae/tox_messages/obj_components.hpp | 42 ++ solanaceae/tox_messages/obj_components_id.inl | 31 ++ .../tox_messages/tox_message_manager.cpp | 2 +- .../tox_messages/tox_transfer_manager.cpp | 461 ++++++++++-------- .../tox_messages/tox_transfer_manager.hpp | 62 ++- 13 files changed, 500 insertions(+), 285 deletions(-) create mode 100644 solanaceae/tox_messages/backends/tox_ft_filesystem.cpp create mode 100644 solanaceae/tox_messages/backends/tox_ft_filesystem.hpp delete mode 100644 solanaceae/tox_messages/components.hpp create mode 100644 solanaceae/tox_messages/msg_components.hpp rename solanaceae/tox_messages/{components_id.inl => msg_components_id.inl} (70%) create mode 100644 solanaceae/tox_messages/obj_components.hpp create mode 100644 solanaceae/tox_messages/obj_components_id.inl diff --git a/CMakeLists.txt b/CMakeLists.txt index 498923e..4d2d1b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,13 +21,20 @@ target_link_libraries(solanaceae_tox_contacts PUBLIC ) add_library(solanaceae_tox_messages - ./solanaceae/tox_messages/components.hpp - ./solanaceae/tox_messages/components_id.inl + ./solanaceae/tox_messages/msg_components.hpp + ./solanaceae/tox_messages/msg_components_id.inl ./solanaceae/tox_messages/tox_message_manager.hpp ./solanaceae/tox_messages/tox_message_manager.cpp # TODO: seperate tf? + + ./solanaceae/tox_messages/obj_components.hpp + ./solanaceae/tox_messages/obj_components_id.inl + + ./solanaceae/tox_messages/backends/tox_ft_filesystem.hpp + ./solanaceae/tox_messages/backends/tox_ft_filesystem.cpp + ./solanaceae/tox_messages/tox_transfer_manager.hpp ./solanaceae/tox_messages/tox_transfer_manager.cpp ) @@ -38,5 +45,6 @@ target_link_libraries(solanaceae_tox_messages PUBLIC solanaceae_tox_contacts solanaceae_message3 solanaceae_file2 + solanaceae_object_store ) diff --git a/solanaceae/tox_contacts/tox_contact_model2.cpp b/solanaceae/tox_contacts/tox_contact_model2.cpp index 892c978..2445b6c 100644 --- a/solanaceae/tox_contacts/tox_contact_model2.cpp +++ b/solanaceae/tox_contacts/tox_contact_model2.cpp @@ -6,7 +6,7 @@ // TODO: move #include #include -#include +#include #include "./components.hpp" diff --git a/solanaceae/tox_messages/backends/tox_ft_filesystem.cpp b/solanaceae/tox_messages/backends/tox_ft_filesystem.cpp new file mode 100644 index 0000000..f31d4d6 --- /dev/null +++ b/solanaceae/tox_messages/backends/tox_ft_filesystem.cpp @@ -0,0 +1,77 @@ +#include "./tox_ft_filesystem.hpp" + +#include +#include + +#include + +#include + +namespace Backends { + +ToxFTFilesystem::ToxFTFilesystem( + ObjectStore2& os +) : StorageBackendI::StorageBackendI(os) { +} + +ToxFTFilesystem::~ToxFTFilesystem(void) { +} + +ObjectHandle ToxFTFilesystem::newObject(ByteSpan id) { + ObjectHandle o{_os.registry(), _os.registry().create()}; + + o.emplace(this); + o.emplace(std::vector{id}); + //o.emplace(object_file_path.generic_u8string()); + + _os.throwEventConstruct(o); + + return o; +} + +std::unique_ptr ToxFTFilesystem::file2(Object ov, FILE2_FLAGS flags) { + if (flags & FILE2_RAW) { + std::cerr << "TFTF error: does not support raw modes\n"; + return nullptr; + } + + if (flags == FILE2_NONE) { + std::cerr << "TFTF error: no file mode set\n"; + assert(false); + return nullptr; + } + + if (flags & FILE2_WRITE) { + std::cerr << "TFTF error: opening file in write mode not supported\n"; + } + + ObjectHandle o{_os.registry(), ov}; + + if (!static_cast(o)) { + return nullptr; + } + + // will this do if we go and support enc? + // use ObjComp::Ephemeral::FilePath instead?? + if (!o.all_of()) { + return nullptr; + } + + const auto& file_path = o.get().file_path; + if (file_path.empty()) { + return nullptr; + } + + // read only + auto res = std::make_unique(file_path); + + if (!res || !res->isGood()) { + std::cerr << "TFTF error: failed constructing file '" << file_path << "'\n"; + return nullptr; + } + + return res; +} + +} // Backends + diff --git a/solanaceae/tox_messages/backends/tox_ft_filesystem.hpp b/solanaceae/tox_messages/backends/tox_ft_filesystem.hpp new file mode 100644 index 0000000..9723880 --- /dev/null +++ b/solanaceae/tox_messages/backends/tox_ft_filesystem.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include + +namespace Backends { + +struct ToxFTFilesystem : public StorageBackendI { + ToxFTFilesystem( + ObjectStore2& os + ); + ~ToxFTFilesystem(void); + + ObjectHandle newObject(ByteSpan id) override; + + std::unique_ptr file2(Object o, FILE2_FLAGS flags) override; +}; + +} // Backends + diff --git a/solanaceae/tox_messages/components.hpp b/solanaceae/tox_messages/components.hpp deleted file mode 100644 index 3bb5ca5..0000000 --- a/solanaceae/tox_messages/components.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include - -#include - -#include -#include - -namespace Message::Components { - -struct ToxFriendMessageID { - // only exposed for the read reciept event - uint32_t id = 0u; -}; - -struct ToxGroupMessageID { - uint32_t id = 0u; -}; - -// TODO: move all those comps - -namespace Transfer { - - struct ToxTransferFriend { - uint32_t friend_number; - uint32_t transfer_number; - }; - - struct FileID { - // persistent ID - // sometimes called file_id or hash - ToxKey id; - // TODO: variable length - }; - - struct FileKind { - // TODO: use tox file kind - uint64_t kind {0}; - }; - -} // Transfer - -} // Message::Components - -#include "./components_id.inl" - diff --git a/solanaceae/tox_messages/msg_components.hpp b/solanaceae/tox_messages/msg_components.hpp new file mode 100644 index 0000000..69044e7 --- /dev/null +++ b/solanaceae/tox_messages/msg_components.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include + +#include + +namespace Message::Components { + +struct ToxFriendMessageID { + // only exposed for the read reciept event + uint32_t id = 0u; +}; + +struct ToxGroupMessageID { + uint32_t id = 0u; +}; + +} // Message::Components + +#include "./msg_components_id.inl" + diff --git a/solanaceae/tox_messages/components_id.inl b/solanaceae/tox_messages/msg_components_id.inl similarity index 70% rename from solanaceae/tox_messages/components_id.inl rename to solanaceae/tox_messages/msg_components_id.inl index bb0174f..5b08856 100644 --- a/solanaceae/tox_messages/components_id.inl +++ b/solanaceae/tox_messages/msg_components_id.inl @@ -1,4 +1,6 @@ -#include "./components.hpp" +#pragma once + +#include "./msg_components.hpp" #include @@ -18,9 +20,6 @@ constexpr std::string_view entt::type_name::value() noexcept { \ DEFINE_COMP_ID(Message::Components::ToxFriendMessageID) DEFINE_COMP_ID(Message::Components::ToxGroupMessageID) -DEFINE_COMP_ID(Message::Components::Transfer::ToxTransferFriend) -DEFINE_COMP_ID(Message::Components::Transfer::FileID) -DEFINE_COMP_ID(Message::Components::Transfer::FileKind) #undef DEFINE_COMP_ID diff --git a/solanaceae/tox_messages/nj/tox_message_components.hpp b/solanaceae/tox_messages/nj/tox_message_components.hpp index cdf9827..ed4bbaa 100644 --- a/solanaceae/tox_messages/nj/tox_message_components.hpp +++ b/solanaceae/tox_messages/nj/tox_message_components.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include diff --git a/solanaceae/tox_messages/obj_components.hpp b/solanaceae/tox_messages/obj_components.hpp new file mode 100644 index 0000000..9148375 --- /dev/null +++ b/solanaceae/tox_messages/obj_components.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include // contains the alias + +#include + +namespace ObjectStore::Components { + + namespace Tox { + + struct FileID { + // persistent ID + // sometimes called file_id or hash + ToxKey id; + // TODO: variable length + }; + + struct FileKind { + // TODO: use tox file kind + uint64_t kind {0}; + }; + + // temporary replacement for Sending/Receiving + // TODO: something generic in os ????? + struct TagIncomming {}; + struct TagOutgoing {}; + + } // Tox + + namespace Ephemeral { + + struct ToxTransferFriend { + uint32_t friend_number; + uint32_t transfer_number; + }; + + } // Ephemeral + +} // ObjectStore::Components + +#include "./obj_components_id.inl" + diff --git a/solanaceae/tox_messages/obj_components_id.inl b/solanaceae/tox_messages/obj_components_id.inl new file mode 100644 index 0000000..c084c1b --- /dev/null +++ b/solanaceae/tox_messages/obj_components_id.inl @@ -0,0 +1,31 @@ +#pragma once + +#include "./obj_components.hpp" + +#include + +// TODO: move more central +#define DEFINE_COMP_ID(x) \ +template<> \ +constexpr entt::id_type entt::type_hash::value() noexcept { \ + using namespace entt::literals; \ + return #x##_hs; \ +} \ +template<> \ +constexpr std::string_view entt::type_name::value() noexcept { \ + return #x; \ +} + +// cross compile(r) stable ids + +DEFINE_COMP_ID(ObjComp::Tox::FileID) +DEFINE_COMP_ID(ObjComp::Tox::FileKind) + +// tmp +DEFINE_COMP_ID(ObjComp::Tox::TagIncomming) +DEFINE_COMP_ID(ObjComp::Tox::TagOutgoing) + +DEFINE_COMP_ID(ObjComp::Ephemeral::ToxTransferFriend) + +#undef DEFINE_COMP_ID + diff --git a/solanaceae/tox_messages/tox_message_manager.cpp b/solanaceae/tox_messages/tox_message_manager.cpp index e6b81bd..644de0e 100644 --- a/solanaceae/tox_messages/tox_message_manager.cpp +++ b/solanaceae/tox_messages/tox_message_manager.cpp @@ -5,7 +5,7 @@ #include #include #include -#include "./components.hpp" +#include "./msg_components.hpp" #include diff --git a/solanaceae/tox_messages/tox_transfer_manager.cpp b/solanaceae/tox_messages/tox_transfer_manager.cpp index b61d4f9..261c0d9 100644 --- a/solanaceae/tox_messages/tox_transfer_manager.cpp +++ b/solanaceae/tox_messages/tox_transfer_manager.cpp @@ -1,6 +1,5 @@ #include "./tox_transfer_manager.hpp" -#include #include #include @@ -8,47 +7,57 @@ #include #include #include -#include "./components.hpp" +#include "./msg_components.hpp" +#include "./obj_components.hpp" #include -#include +#include #include #include // https://youtu.be/4XsL5iYHS6c -void ToxTransferManager::toxFriendLookupAdd(Message3Handle h) { - const auto& comp = h.get(); +namespace Components { + + struct TFTFile2 { + // the cached file2 for receiving/sending only + std::unique_ptr file; + }; + +} // Components + +void ToxTransferManager::toxFriendLookupAdd(ObjectHandle o) { + const auto& comp = o.get(); const uint64_t key {(uint64_t(comp.friend_number) << 32) | comp.transfer_number}; - if (h.all_of()) { + if (o.all_of()) { assert(!_friend_sending_lookup.count(key)); - _friend_sending_lookup[key] = h; + _friend_sending_lookup[key] = o; } - if (h.all_of()) { + if (o.all_of()) { assert(!_friend_receiving_lookup.count(key)); - _friend_receiving_lookup[key] = h; + _friend_receiving_lookup[key] = o; } } -void ToxTransferManager::toxFriendLookupRemove(Message3Handle h) { - const auto& comp = h.get(); +void ToxTransferManager::toxFriendLookupRemove(ObjectHandle o) { + const auto& comp = o.get(); const uint64_t key {(uint64_t(comp.friend_number) << 32) | comp.transfer_number}; - if (h.all_of()) { + if (o.all_of()) { assert(_friend_sending_lookup.count(key)); _friend_sending_lookup.erase(key); } - if (h.all_of()) { + if (o.all_of()) { assert(_friend_receiving_lookup.count(key)); _friend_receiving_lookup.erase(key); } } -Message3Handle ToxTransferManager::toxFriendLookupSending(const uint32_t friend_number, const uint32_t file_number) const { +ObjectHandle ToxTransferManager::toxFriendLookupSending(const uint32_t friend_number, const uint32_t file_number) const { const auto lookup_it = _friend_sending_lookup.find((uint64_t(friend_number) << 32) | file_number); if (lookup_it != _friend_sending_lookup.end()) { return lookup_it->second; @@ -57,7 +66,7 @@ Message3Handle ToxTransferManager::toxFriendLookupSending(const uint32_t friend_ } } -Message3Handle ToxTransferManager::toxFriendLookupReceiving(const uint32_t friend_number, const uint32_t file_number) const { +ObjectHandle ToxTransferManager::toxFriendLookupReceiving(const uint32_t friend_number, const uint32_t file_number) const { const auto lookup_it = _friend_receiving_lookup.find((uint64_t(friend_number) << 32) | file_number); if (lookup_it != _friend_receiving_lookup.end()) { return lookup_it->second; @@ -66,16 +75,22 @@ Message3Handle ToxTransferManager::toxFriendLookupReceiving(const uint32_t frien } } -ToxTransferManager::ToxTransferManager(RegistryMessageModel& rmm, Contact3Registry& cr, ToxContactModel2& tcm, ToxI& t, ToxEventProviderI& tep) : _rmm(rmm), _cr(cr), _tcm(tcm), _t(t) { +ToxTransferManager::ToxTransferManager( + RegistryMessageModel& rmm, + Contact3Registry& cr, + ToxContactModel2& tcm, + ToxI& t, + ToxEventProviderI& tep, + ObjectStore2& os +) : _rmm(rmm), _cr(cr), _tcm(tcm), _t(t), _os(os), _ftb(os) { tep.subscribe(this, Tox_Event_Type::TOX_EVENT_FRIEND_CONNECTION_STATUS); tep.subscribe(this, Tox_Event_Type::TOX_EVENT_FILE_RECV); tep.subscribe(this, Tox_Event_Type::TOX_EVENT_FILE_RECV_CONTROL); tep.subscribe(this, Tox_Event_Type::TOX_EVENT_FILE_RECV_CHUNK); tep.subscribe(this, Tox_Event_Type::TOX_EVENT_FILE_CHUNK_REQUEST); - _rmm.subscribe(this, RegistryMessageModel_Event::message_construct); - _rmm.subscribe(this, RegistryMessageModel_Event::message_updated); - _rmm.subscribe(this, RegistryMessageModel_Event::message_destroy); + _os.subscribe(this, ObjectStore_Event::object_update); + _os.subscribe(this, ObjectStore_Event::object_destroy); _rmm.subscribe(this, RegistryMessageModel_Event::send_file_path); } @@ -87,7 +102,7 @@ void ToxTransferManager::iterate(void) { // TODO: time out transfers } -Message3Handle ToxTransferManager::toxSendFilePath(const Contact3 c, uint32_t file_kind, std::string_view file_name, std::string_view file_path) { +Message3Handle ToxTransferManager::toxSendFilePath(const Contact3 c, uint32_t file_kind, std::string_view file_name, std::string_view file_path, std::vector file_id) { if ( // TODO: add support of offline queuing !_cr.all_of(c) @@ -108,11 +123,16 @@ Message3Handle ToxTransferManager::toxSendFilePath(const Contact3 c, uint32_t fi } // get current time unix epoch utc - uint64_t ts = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + uint64_t ts = Message::getTimeMS(); - // TODO: expose file id - std::vector file_id(32); assert(file_id.size() == 32); - randombytes_buf(file_id.data(), file_id.size()); + if (file_id.empty()) { + file_id.resize(32); + randombytes_buf(file_id.data(), file_id.size()); + } else if (file_id.size() != 32) { + // trunc or pad with zero + file_id.resize(32); + } + assert(file_id.size() == 32); const auto c_self = _cr.get(c).self; if (!_cr.valid(c_self)) { @@ -120,46 +140,67 @@ Message3Handle ToxTransferManager::toxSendFilePath(const Contact3 c, uint32_t fi return {}; } - const auto e = reg_ptr->create(); - reg_ptr->emplace(e, c); - reg_ptr->emplace(e, c_self); - reg_ptr->emplace(e, ts); // reactive? - reg_ptr->emplace(e, ts); - reg_ptr->emplace(e).ts.try_emplace(c_self, ts); + // TODO: move this to backend + ObjectHandle o {_os.registry(), _os.registry().create()}; - reg_ptr->emplace(e); - reg_ptr->emplace(e); - reg_ptr->emplace(e, file_kind); - reg_ptr->emplace(e, file_id); + //reg_ptr->emplace(e); + o.emplace(); + //reg_ptr->emplace(e); + o.emplace(); + //reg_ptr->emplace(e, file_kind); + o.emplace(file_kind); + //reg_ptr->emplace(e, file_id); + o.emplace(file_id); { // file info - auto& file_info = reg_ptr->emplace(e); - file_info.file_list.emplace_back() = {std::string{file_name}, file_impl->_file_size}; - file_info.total_size = file_impl->_file_size; + //auto& file_info = reg_ptr->emplace(e); + //file_info.file_list.emplace_back() = {std::string{file_name}, file_impl->_file_size}; + //file_info.total_size = file_impl->_file_size; + o.emplace(std::string{file_name}, file_impl->_file_size); - reg_ptr->emplace(e, std::vector{std::string{file_path}}); + //reg_ptr->emplace(e, std::vector{std::string{file_path}}); + o.emplace(std::string{file_path}); + o.emplace(std::string{file_path}); // ? } - reg_ptr->emplace(e); + //reg_ptr->emplace(e); + o.emplace(); // TODO: determine if this is true - reg_ptr->emplace(e); + //reg_ptr->emplace(e); + o.emplace(); + + Message3Handle msg {*reg_ptr, reg_ptr->create()}; + msg.emplace(c); + msg.emplace(c_self); + msg.emplace(ts); // reactive? + msg.emplace(ts); + msg.emplace().ts.try_emplace(c_self, ts); + msg.emplace(o); const auto friend_number = _cr.get(c).friend_number; const auto&& [transfer_id, err] = _t.toxFileSend(friend_number, file_kind, file_impl->_file_size, file_id, file_name); if (err == TOX_ERR_FILE_SEND_OK) { - reg_ptr->emplace(e, friend_number, transfer_id.value()); - reg_ptr->emplace(e, std::move(file_impl)); + assert(transfer_id.has_value()); + //reg_ptr->emplace(e, friend_number, transfer_id.value()); + o.emplace(friend_number, transfer_id.value()); + //reg_ptr->emplace(e, std::move(file_impl)); + o.emplace(std::move(file_impl)); // TODO: add tag signifying init sent status? - toxFriendLookupAdd({*reg_ptr, e}); + //toxFriendLookupAdd({*reg_ptr, e}); + toxFriendLookupAdd(o); } // else queue? - _rmm.throwEventConstruct(*reg_ptr, e); - return {*reg_ptr, e}; + _os.throwEventConstruct(o); + + //_rmm.throwEventConstruct(*reg_ptr, e); + _rmm.throwEventConstruct(msg); + //return {*reg_ptr, e}; + return msg; } -bool ToxTransferManager::resume(Message3Handle transfer) { +bool ToxTransferManager::resume(ObjectHandle transfer) { if (!static_cast(transfer)) { std::cerr << "TTM error: resume() transfer " << entt::to_integral(transfer.entity()) << " is not a valid transfer\n"; return false; @@ -167,12 +208,12 @@ bool ToxTransferManager::resume(Message3Handle transfer) { // TODO: test for paused? - if (!transfer.all_of()) { + if (!transfer.all_of()) { std::cerr << "TTM error: resume() transfer " << entt::to_integral(transfer.entity()) << " ent does not have toxtransfer info\n"; return false; } - const auto [friend_number, transfer_number] = transfer.get(); + const auto [friend_number, transfer_number] = transfer.get(); const auto err = _t.toxFileControl(friend_number, transfer_number, TOX_FILE_CONTROL_RESUME); if (err != TOX_ERR_FILE_CONTROL_OK) { @@ -180,14 +221,14 @@ bool ToxTransferManager::resume(Message3Handle transfer) { return false; } - transfer.remove(); + transfer.remove(); - _rmm.throwEventUpdate(transfer); + _os.throwEventUpdate(transfer); return true; } -bool ToxTransferManager::pause(Message3Handle transfer) { +bool ToxTransferManager::pause(ObjectHandle transfer) { if (!static_cast(transfer)) { std::cerr << "TTM error: pause() transfer " << entt::to_integral(transfer.entity()) << " is not a valid transfer\n"; return false; @@ -195,12 +236,12 @@ bool ToxTransferManager::pause(Message3Handle transfer) { // TODO: test for paused? - if (!transfer.all_of()) { + if (!transfer.all_of()) { std::cerr << "TTM error: pause() transfer " << entt::to_integral(transfer.entity()) << " ent does not have toxtransfer info\n"; return false; } - const auto [friend_number, transfer_number] = transfer.get(); + const auto [friend_number, transfer_number] = transfer.get(); const auto err = _t.toxFileControl(friend_number, transfer_number, TOX_FILE_CONTROL_PAUSE); if (err != TOX_ERR_FILE_CONTROL_OK) { @@ -208,14 +249,14 @@ bool ToxTransferManager::pause(Message3Handle transfer) { return false; } - transfer.emplace_or_replace(); + transfer.emplace_or_replace(); - _rmm.throwEventUpdate(transfer); + _os.throwEventUpdate(transfer); return true; } -bool ToxTransferManager::setFileI(Message3Handle transfer, std::unique_ptr&& new_file) { +bool ToxTransferManager::setFileI(ObjectHandle transfer, std::unique_ptr&& new_file) { if (!static_cast(transfer)) { std::cerr << "TTM error: setFileI() transfer " << entt::to_integral(transfer.entity()) << " is not a valid transfer\n"; return false; @@ -226,14 +267,14 @@ bool ToxTransferManager::setFileI(Message3Handle transfer, std::unique_ptr(std::move(new_file)); + transfer.emplace_or_replace(std::move(new_file)); - _rmm.throwEventUpdate(transfer); + _os.throwEventUpdate(transfer); return true; } -bool ToxTransferManager::setFilePath(Message3Handle transfer, std::string_view file_path) { +bool ToxTransferManager::setFilePath(ObjectHandle transfer, std::string_view file_path) { if (!static_cast(transfer)) { std::cerr << "TTM error: setFilePath() transfer " << entt::to_integral(transfer.entity()) << " is not a valid transfer\n"; return false; @@ -246,30 +287,30 @@ bool ToxTransferManager::setFilePath(Message3Handle transfer, std::string_view f } // TODO: read file name(s) from comp - if (transfer.all_of()) { - const auto& file_info = transfer.get(); - file_size = file_info.total_size; // hack - // HACK: use fist enty - assert(file_info.file_list.size() == 1); + if (transfer.all_of()) { + const auto& file_info = transfer.get(); + file_size = file_info.file_size; } - transfer.emplace(std::vector{full_file_path.u8string()}); + transfer.emplace_or_replace(full_file_path.u8string()); + transfer.emplace_or_replace(full_file_path.u8string()); // ? + // huh? we also set file2i ? auto file_impl = std::make_unique(full_file_path.u8string(), file_size, true); if (!file_impl->isGood()) { std::cerr << "TTM error: failed opening file '" << file_path << "'!\n"; return false; } - transfer.emplace_or_replace(std::move(file_impl)); + transfer.emplace_or_replace(std::move(file_impl)); // TODO: is this a good idea???? - _rmm.throwEventUpdate(transfer); + _os.throwEventUpdate(transfer); return true; } -bool ToxTransferManager::setFilePathDir(Message3Handle transfer, std::string_view file_path) { +bool ToxTransferManager::setFilePathDir(ObjectHandle transfer, std::string_view file_path) { if (!static_cast(transfer)) { std::cerr << "TTM error: setFilePathDir() transfer " << entt::to_integral(transfer.entity()) << " is not a valid transfer\n"; return false; @@ -286,50 +327,50 @@ bool ToxTransferManager::setFilePathDir(Message3Handle transfer, std::string_vie std::filesystem::create_directories(full_file_path); // TODO: read file name(s) from comp - if (transfer.all_of()) { - const auto& file_info = transfer.get(); - file_size = file_info.total_size; // hack - // HACK: use fist enty - assert(file_info.file_list.size() == 1); - full_file_path += file_info.file_list.front().file_name; + if (transfer.all_of()) { + const auto& file_info = transfer.get(); + file_size = file_info.file_size; + full_file_path += file_info.file_name; } else { std::cerr << "TTM warning: no FileInfo on transfer, using default\n"; full_file_path += "file_recv.bin"; } - transfer.emplace(std::vector{full_file_path}); + transfer.emplace_or_replace(full_file_path); + transfer.emplace_or_replace(full_file_path); // ? + // huh? we also set file2i ? auto file_impl = std::make_unique(full_file_path, file_size, true); if (!file_impl->isGood()) { std::cerr << "TTM error: failed opening file '" << file_path << "'!\n"; return false; } - transfer.emplace_or_replace(std::move(file_impl)); + transfer.emplace_or_replace(std::move(file_impl)); - // TODO: is this a good idea???? - _rmm.throwEventUpdate(transfer); + // TODO: is this a good idea???? - no lol, it was not + _os.throwEventUpdate(transfer); return true; } -bool ToxTransferManager::accept(Message3Handle transfer, std::string_view file_path, bool is_file_path) { +bool ToxTransferManager::accept(ObjectHandle transfer, std::string_view file_path, bool path_is_file) { if (!static_cast(transfer)) { std::cerr << "TTM error: accepted transfer " << entt::to_integral(transfer.entity()) << " is not a valid transfer\n"; return false; } - if (!transfer.all_of()) { + if (!transfer.all_of()) { std::cerr << "TTM error: accepted transfer " << entt::to_integral(transfer.entity()) << " is not a receiving transfer\n"; return false; } - if (transfer.any_of()) { + if (transfer.any_of()) { std::cerr << "TTM warning: overwriting existing file_impl " << entt::to_integral(transfer.entity()) << "\n"; } - if (is_file_path) { + if (path_is_file) { if (!setFilePath(transfer, file_path)) { std::cerr << "TTM error: accepted transfer " << entt::to_integral(transfer.entity()) << " failed setting path\n"; return false; @@ -353,31 +394,45 @@ bool ToxTransferManager::accept(Message3Handle transfer, std::string_view file_p return true; } -bool ToxTransferManager::onEvent(const Message::Events::MessageConstruct&) { - return false; +bool ToxTransferManager::sendFilePath(const Contact3 c, std::string_view file_name, std::string_view file_path) { + if ( + // TODO: add support of offline queuing + !_cr.all_of(c) + ) { + // TODO: add support for persistant friend filesends + return false; + } + + return static_cast(toxSendFilePath(c, 0, file_name, file_path)); } -bool ToxTransferManager::onEvent(const Message::Events::MessageUpdated& e) { - if (e.e.all_of()) { +bool ToxTransferManager::onEvent(const ObjectStore::Events::ObjectUpdate& e) { + if (_in_obj_update_event) { + return false; + } + + _in_obj_update_event = true; + if (e.e.all_of()) { accept( e.e, - e.e.get().save_to_path, - e.e.get().path_is_file + e.e.get().save_to_path, + e.e.get().path_is_file ); // should? - e.e.remove(); + e.e.remove(); // TODO: recursion?? // oh no, accept calls it 2x //_rmm.throwEventUpdate( } + _in_obj_update_event = false; return false; } -bool ToxTransferManager::onEvent(const Message::Events::MessageDestory& e) { - if (e.e.all_of()) { +bool ToxTransferManager::onEvent(const ObjectStore::Events::ObjectDestory& e) { + if (e.e.all_of()) { toxFriendLookupRemove(e.e); } @@ -390,29 +445,26 @@ bool ToxTransferManager::onToxEvent(const Tox_Event_Friend_Connection_Status* e) if (connection_status == TOX_CONNECTION_NONE) { auto c = _tcm.getContactFriend(friend_number); - auto* reg_ptr = _rmm.get(c); - if (reg_ptr == nullptr) { - return false; - } - std::vector to_destory; - reg_ptr->view().each([&](const Message3 ent, const auto& ttfs) { - assert(ttfs.friend_number == friend_number); - //if (ttfs.friend_number == friend_number) { - to_destory.push_back(ent); - std::cerr << "TTM warning: friend disconnected, forcefully removing e:" << entt::to_integral(ent) << " frd:" << friend_number << " fnb:" << ttfs.transfer_number << "\n"; + std::vector to_destory; + _os.registry().view().each([&](const Object ov, const auto& ttf) { + assert(ttf.friend_number == friend_number); + to_destory.push_back(ov); + std::cerr << "TTM warning: friend disconnected, forcefully removing e:" << entt::to_integral(ov) << " frd:" << friend_number << " fnb:" << ttf.transfer_number << "\n"; }); - for (const auto ent : to_destory) { + for (const auto ov : to_destory) { + ObjectHandle o {_os.registry(), ov}; + // update lookup table - toxFriendLookupRemove({*reg_ptr, ent}); + toxFriendLookupRemove(o); - // TODO: removing file a good idea? - reg_ptr->remove(ent); + o.remove(); - reg_ptr->emplace_or_replace(ent); + o.emplace_or_replace(); - _rmm.throwEventUpdate(*reg_ptr, ent); + //_rmm.throwEventUpdate(*reg_ptr, ent); + _os.throwEventUpdate(ov); } } @@ -436,13 +488,13 @@ bool ToxTransferManager::onToxEvent(const Tox_Event_File_Recv* e) { } // making sure, we dont have a dup - Message3Handle transfer {}; - reg_ptr->view().each([&](Message3 ent, const Message::Components::Transfer::ToxTransferFriend& ttf) { + ObjectHandle o {}; + _os.registry().view().each([&](Object ov, const ObjComp::Ephemeral::ToxTransferFriend& ttf) { if (ttf.friend_number == friend_number && ttf.transfer_number == file_number) { - transfer = {*reg_ptr, ent}; + o = {_os.registry(), ov}; } }); - if (static_cast(transfer)) { + if (static_cast(o)) { std::cerr << "TTM error: existing file transfer frd:" << friend_number << " fnb:" << file_number << "\n"; return false; } @@ -460,42 +512,41 @@ bool ToxTransferManager::onToxEvent(const Tox_Event_File_Recv* e) { } // get current time unix epoch utc - uint64_t ts = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); - - // create ent - transfer = {*reg_ptr, reg_ptr->create()}; + uint64_t ts = Message::getTimeMS(); auto self_c = _cr.get(c).self; - transfer.emplace(self_c); - transfer.emplace(c); - transfer.emplace(ts); // reactive? - transfer.emplace(); + o = {_os.registry(), _os.registry().create()}; + o.emplace(); + o.emplace(); + o.emplace(friend_number, file_number); + o.emplace(file_kind); + + o.emplace(f_id_opt.value()); + + // file info + o.emplace(std::string{file_name}, file_size); + + o.emplace(); + + toxFriendLookupAdd(o); + + Message3Handle msg = {*reg_ptr, reg_ptr->create()}; + + msg.emplace(self_c); + msg.emplace(c); + msg.emplace(ts); // reactive? + msg.emplace(); { - auto& rb = transfer.emplace().ts; + auto& rb = msg.emplace().ts; //rb.try_emplace(self_c, ts); // only on completion rb.try_emplace(c, ts); } + msg.emplace(o); - transfer.emplace(); - transfer.emplace(); - transfer.emplace(friend_number, file_number); - transfer.emplace(file_kind); - - transfer.emplace(f_id_opt.value()); - - { // file info - auto& file_info = transfer.emplace(); - file_info.file_list.push_back({std::string{file_name}, file_size}); - file_info.total_size = file_size; - } - - transfer.emplace(); - - toxFriendLookupAdd(transfer); - - _rmm.throwEventConstruct(transfer); + _os.throwEventConstruct(o); + _rmm.throwEventConstruct(msg); return true; } @@ -506,13 +557,13 @@ bool ToxTransferManager::onToxEvent(const Tox_Event_File_Recv_Control* e) { const auto control = tox_event_file_recv_control_get_control(e); // first try sending - Message3Handle transfer = toxFriendLookupSending(friend_number, file_number); - if (!static_cast(transfer)) { + ObjectHandle o = toxFriendLookupSending(friend_number, file_number); + if (!static_cast(o)) { // then receiving - transfer = toxFriendLookupReceiving(friend_number, file_number); + o = toxFriendLookupReceiving(friend_number, file_number); } - if (!static_cast(transfer)) { + if (!static_cast(o)) { std::cerr << "TMM waring: control for unk ft\n"; return false; // shrug, we don't know about it, might be someone else's } @@ -521,24 +572,26 @@ bool ToxTransferManager::onToxEvent(const Tox_Event_File_Recv_Control* e) { std::cerr << "TTM: friend transfer canceled frd:" << friend_number << " fnb:" << file_number << "\n"; // update lookup table - toxFriendLookupRemove(transfer); + toxFriendLookupRemove(o); - transfer.remove< - Message::Components::Transfer::ToxTransferFriend, - // TODO: removing file a good idea? - Message::Components::Transfer::File + o.remove< + ObjComp::Ephemeral::ToxTransferFriend, + Components::TFTFile2 >(); - _rmm.throwEventUpdate(transfer); + //_rmm.throwEventUpdate(transfer); + _os.throwEventUpdate(o); } else if (control == TOX_FILE_CONTROL_PAUSE) { std::cerr << "TTM: friend transfer paused frd:" << friend_number << " fnb:" << file_number << "\n"; // TODO: add distinction between local and remote pause - transfer.emplace_or_replace(); - _rmm.throwEventUpdate(transfer); + o.emplace_or_replace(); + //_rmm.throwEventUpdate(transfer); + _os.throwEventUpdate(o); } else if (control == TOX_FILE_CONTROL_RESUME) { std::cerr << "TTM: friend transfer resumed frd:" << friend_number << " fnb:" << file_number << "\n"; - transfer.remove(); - _rmm.throwEventUpdate(transfer); + o.remove(); + //_rmm.throwEventUpdate(transfer); + _os.throwEventUpdate(o); } return true; @@ -551,61 +604,65 @@ bool ToxTransferManager::onToxEvent(const Tox_Event_File_Recv_Chunk* e) { const auto data_size = tox_event_file_recv_chunk_get_data_length(e); const auto position = tox_event_file_recv_chunk_get_position(e); - Message3Handle transfer = toxFriendLookupReceiving(friend_number, file_number); - if (!static_cast(transfer)) { + ObjectHandle o = toxFriendLookupReceiving(friend_number, file_number); + if (!static_cast(o)) { return false; // shrug, we don't know about it, might be someone else's } if (data_size == 0) { - uint64_t ts = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + uint64_t ts = Message::getTimeMS(); std::cout << "TTM finished friend " << friend_number << " transfer " << file_number << ", closing\n"; // update lookup table - toxFriendLookupRemove(transfer); + toxFriendLookupRemove(o); - transfer.remove< - Message::Components::Transfer::ToxTransferFriend, - // TODO: removing file a good idea? - Message::Components::Transfer::File, - - Message::Components::Read + o.remove< + ObjComp::Ephemeral::ToxTransferFriend, + Components::TFTFile2 >(); + o.emplace_or_replace(); + +#if 0 // TODO: track back msg + // re-unread a finished transfer + msg.emplace_or_replace(); + msg.remove(); + auto c = _tcm.getContactFriend(friend_number); if (static_cast(c)) { auto self_c = _cr.get(c).self; - auto& rb = transfer.get_or_emplace().ts; + auto& rb = msg.get_or_emplace().ts; rb.try_emplace(self_c, ts); // on completion } +#endif - transfer.emplace(); + _os.throwEventUpdate(o); - // re-unread a finished transfer - transfer.emplace_or_replace(); - - _rmm.throwEventUpdate(transfer); - } else if (!transfer.all_of() || !transfer.get()->isGood()) { + //_rmm.throwEventUpdate(msg); + } else if (!o.all_of() || !o.get().file || !o.get().file->isGood()) { std::cerr << "TTM error: file not good f" << friend_number << " t" << file_number << ", closing\n"; _t.toxFileControl(friend_number, file_number, Tox_File_Control::TOX_FILE_CONTROL_CANCEL); // update lookup table - toxFriendLookupRemove(transfer); + toxFriendLookupRemove(o); - transfer.remove< - Message::Components::Transfer::ToxTransferFriend, - // TODO: removing file a good idea? - Message::Components::Transfer::File + o.remove< + ObjComp::Ephemeral::ToxTransferFriend, + Components::TFTFile2 >(); - _rmm.throwEventUpdate(transfer); + _os.throwEventUpdate(o); + // update messages? } else { - auto* file = transfer.get().get(); + auto& file = o.get().file; const auto res = file->write({data, data_size}, position); - transfer.get().total += data_size; + //o.get().total += data_size; + o.get_or_emplace().total_down += data_size; // queue? - _rmm.throwEventUpdate(transfer); + _os.throwEventUpdate(o); + //_rmm.throwEventUpdate(msg); } return true; @@ -617,8 +674,8 @@ bool ToxTransferManager::onToxEvent(const Tox_Event_File_Chunk_Request* e) { const auto position = tox_event_file_chunk_request_get_position(e); const auto data_size = tox_event_file_chunk_request_get_length(e); - Message3Handle transfer = toxFriendLookupSending(friend_number, file_number); - if (!static_cast(transfer)) { + ObjectHandle o = toxFriendLookupSending(friend_number, file_number); + if (!static_cast(o)) { std::cerr << "TTM warning: chunk request for unk ft\n"; return false; // shrug, we don't know about it, might be someone else's } @@ -628,32 +685,32 @@ bool ToxTransferManager::onToxEvent(const Tox_Event_File_Chunk_Request* e) { std::cout << "TTM finished friend " << friend_number << " transfer " << file_number << ", closing\n"; // update lookup table - toxFriendLookupRemove(transfer); + toxFriendLookupRemove(o); - transfer.remove< - Message::Components::Transfer::ToxTransferFriend, - // TODO: removing file a good idea? - Message::Components::Transfer::File + o.remove< + ObjComp::Ephemeral::ToxTransferFriend, + Components::TFTFile2 >(); // TODO: add tag finished? - _rmm.throwEventUpdate(transfer); - } else if (!transfer.all_of() || !transfer.get()->isGood()) { + //_rmm.throwEventUpdate(o); + _os.throwEventUpdate(o); + } else if (!o.all_of() || !o.get().file || !o.get().file->isGood()) { std::cerr << "TTM error: file not good f" << friend_number << " t" << file_number << ", closing\n"; _t.toxFileControl(friend_number, file_number, Tox_File_Control::TOX_FILE_CONTROL_CANCEL); // update lookup table - toxFriendLookupRemove(transfer); + toxFriendLookupRemove(o); - transfer.remove< - Message::Components::Transfer::ToxTransferFriend, - // TODO: removing file a good idea? - Message::Components::Transfer::File + o.remove< + ObjComp::Ephemeral::ToxTransferFriend, + Components::TFTFile2 >(); - _rmm.throwEventUpdate(transfer); + //_rmm.throwEventUpdate(o); + _os.throwEventUpdate(o); } else { - auto* file = transfer.get().get(); + auto& file = o.get().file; const auto data = file->read(data_size, position); if (data.empty()) { std::cerr << "TMM error: failed to read file!!\n"; @@ -664,23 +721,11 @@ bool ToxTransferManager::onToxEvent(const Tox_Event_File_Chunk_Request* e) { const auto err = _t.toxFileSendChunk(friend_number, file_number, position, static_cast>(data)); // TODO: investigate if i need to retry if sendq full if (err == TOX_ERR_FILE_SEND_CHUNK_OK) { - transfer.get().total += data.size; - _rmm.throwEventUpdate(transfer); + o.get_or_emplace().total_up += data_size; + _os.throwEventUpdate(o); } } return true; } -bool ToxTransferManager::sendFilePath(const Contact3 c, std::string_view file_name, std::string_view file_path) { - if ( - // TODO: add support of offline queuing - !_cr.all_of(c) - ) { - // TODO: add support for persistant friend filesends - return false; - } - - return static_cast(toxSendFilePath(c, 0, file_name, file_path)); -} - diff --git a/solanaceae/tox_messages/tox_transfer_manager.hpp b/solanaceae/tox_messages/tox_transfer_manager.hpp index 3aa71b5..9d0a25c 100644 --- a/solanaceae/tox_messages/tox_transfer_manager.hpp +++ b/solanaceae/tox_messages/tox_transfer_manager.hpp @@ -1,9 +1,13 @@ #pragma once #include +#include #include #include +#include "./backends/tox_ft_filesystem.hpp" + +// switch to fwd or remove #include #include @@ -14,45 +18,63 @@ // fwd struct ToxI; -class ToxTransferManager : public RegistryMessageModelEventI, public ToxEventI { +class ToxTransferManager : public RegistryMessageModelEventI, public ObjectStoreEventI, public ToxEventI { + public: + static constexpr const char* version {"2"}; + protected: RegistryMessageModel& _rmm; Contact3Registry& _cr; ToxContactModel2& _tcm; ToxI& _t; + ObjectStore2& _os; + Backends::ToxFTFilesystem _ftb; - entt::dense_map _friend_sending_lookup; - entt::dense_map _friend_receiving_lookup; + bool _in_obj_update_event {false}; + + entt::dense_map _friend_sending_lookup; + entt::dense_map _friend_receiving_lookup; protected: - void toxFriendLookupAdd(Message3Handle h); - void toxFriendLookupRemove(Message3Handle h); + void toxFriendLookupAdd(ObjectHandle o); + void toxFriendLookupRemove(ObjectHandle o); - Message3Handle toxFriendLookupSending(const uint32_t friend_number, const uint32_t file_number) const; - Message3Handle toxFriendLookupReceiving(const uint32_t friend_number, const uint32_t file_number) const; + ObjectHandle toxFriendLookupSending(const uint32_t friend_number, const uint32_t file_number) const; + ObjectHandle toxFriendLookupReceiving(const uint32_t friend_number, const uint32_t file_number) const; public: - ToxTransferManager(RegistryMessageModel& rmm, Contact3Registry& cr, ToxContactModel2& tcm, ToxI& t, ToxEventProviderI& tep); + ToxTransferManager( + RegistryMessageModel& rmm, + Contact3Registry& cr, + ToxContactModel2& tcm, + ToxI& t, + ToxEventProviderI& tep, + ObjectStore2& os + ); virtual ~ToxTransferManager(void); virtual void iterate(void); public: // TODO: private? - Message3Handle toxSendFilePath(const Contact3 c, uint32_t file_kind, std::string_view file_name, std::string_view file_path); + Message3Handle toxSendFilePath(const Contact3 c, uint32_t file_kind, std::string_view file_name, std::string_view file_path, std::vector file_id = {}); - bool resume(Message3Handle transfer); - bool pause(Message3Handle transfer); - bool setFileI(Message3Handle transfer, std::unique_ptr&& new_file); // note, does not emplace FileInfoLocal - bool setFilePath(Message3Handle transfer, std::string_view file_path); - bool setFilePathDir(Message3Handle transfer, std::string_view file_path); + bool resume(ObjectHandle transfer); + bool pause(ObjectHandle transfer); + // move to "file" backend? + bool setFileI(ObjectHandle transfer, std::unique_ptr&& new_file); // note, does not emplace FileInfoLocal + bool setFilePath(ObjectHandle transfer, std::string_view file_path); + bool setFilePathDir(ObjectHandle transfer, std::string_view file_path); // calls setFileI() and resume() - bool accept(Message3Handle transfer, std::string_view file_path, bool is_file_path); + bool accept(ObjectHandle transfer, std::string_view file_path, bool path_is_file); - protected: - bool onEvent(const Message::Events::MessageConstruct&) override; - bool onEvent(const Message::Events::MessageUpdated&) override; - bool onEvent(const Message::Events::MessageDestory&) override; + protected: // (r)mm + bool sendFilePath(const Contact3 c, std::string_view file_name, std::string_view file_path) override; + + protected: // os + //bool onEvent(const ObjectStore::Events::ObjectConstruct&) override; + bool onEvent(const ObjectStore::Events::ObjectUpdate&) override; + bool onEvent(const ObjectStore::Events::ObjectDestory&) override; protected: // events virtual bool onToxEvent(const Tox_Event_Friend_Connection_Status* e) override; @@ -60,7 +82,5 @@ class ToxTransferManager : public RegistryMessageModelEventI, public ToxEventI { virtual bool onToxEvent(const Tox_Event_File_Recv_Control* e) override; virtual bool onToxEvent(const Tox_Event_File_Recv_Chunk* e) override; virtual bool onToxEvent(const Tox_Event_File_Chunk_Request* e) override; - - bool sendFilePath(const Contact3 c, std::string_view file_name, std::string_view file_path) override; };