diff --git a/solanaceae/tox_messages/obj_components_id.inl b/solanaceae/tox_messages/obj_components_id.inl index 8d93d7e..b8b8bac 100644 --- a/solanaceae/tox_messages/obj_components_id.inl +++ b/solanaceae/tox_messages/obj_components_id.inl @@ -26,6 +26,7 @@ DEFINE_COMP_ID(ObjComp::Tox::TagIncomming) DEFINE_COMP_ID(ObjComp::Tox::TagOutgoing) DEFINE_COMP_ID(ObjComp::Ephemeral::ToxTransferFriend) +DEFINE_COMP_ID(ObjComp::Ephemeral::ToxContact) DEFINE_COMP_ID(ObjComp::Ephemeral::ToxMessage) #undef DEFINE_COMP_ID diff --git a/solanaceae/tox_messages/tox_transfer_manager.cpp b/solanaceae/tox_messages/tox_transfer_manager.cpp index 1c844d5..7604d44 100644 --- a/solanaceae/tox_messages/tox_transfer_manager.cpp +++ b/solanaceae/tox_messages/tox_transfer_manager.cpp @@ -159,7 +159,10 @@ ToxTransferManager::ToxTransferManager( .subscribe(ObjectStore_Event::object_destroy) ; - _rmm_sr.subscribe(RegistryMessageModel_Event::send_file_path); + _rmm_sr + .subscribe(RegistryMessageModel_Event::send_file_path) + .subscribe(RegistryMessageModel_Event::send_file_obj) + ; } ToxTransferManager::~ToxTransferManager(void) { @@ -493,15 +496,128 @@ bool ToxTransferManager::sendFilePath(const Contact4 c, std::string_view file_na const auto& cr = _cs.registry(); if ( // TODO: add support of offline queuing - !cr.all_of(c) + !cr.all_of(c) || + !cr.all_of(c) ) { - // TODO: add support for persistant friend filesends + // TODO: add support for persistent friend filesends (messages only?) return false; } return static_cast(toxSendFilePath(c, 0, file_name, file_path)); } +bool ToxTransferManager::sendFileObj(const Contact4 c, ObjectHandle o) { + const auto& cr = _cs.registry(); + if ( + // TODO: add support of offline queuing + !cr.all_of(c) || + !cr.all_of(c) + ) { + // TODO: add support for persistent friend filesends (messages only?) + return false; + } + + // needs to have: + // - SingleInfo + // - LocalHaveAll (TODO: figure out streaming?) + // - Tox::FileID (defaults to obj id? rng?) + // - Tox::FileKind (defaults to 0(DATA) ) + // - StorageBackendIFile2 + if ( + !o.all_of< + ObjComp::F::SingleInfo, + ObjComp::F::TagLocalHaveAll, + //ObjComp::Tox::FileID, + //ObjComp::Tox::FileKind, + ObjComp::Ephemeral::BackendFile2 + >() + ) { + std::cerr << "TTM error: tried sending incomplete object\n"; + return false; + } + + // get current time unix epoch utc + uint64_t ts = getTimeMS(); + + const auto c_self = cr.get(c).self; + if (!cr.valid(c_self)) { + std::cerr << "TTM error: failed to get self!\n"; + return false; + } + + Message3Registry* msg_reg_ptr = nullptr; + // making sure before we mod o + if (!o.all_of() || o.get().kind == 0) { + msg_reg_ptr = _rmm.get(c); + if (msg_reg_ptr == nullptr) { + return false; + } + } + + o.emplace_or_replace(_cs.contactHandle(c)); + + if (!o.all_of()) { + // use id if set, otherwise random + if (o.all_of()) { + o.emplace( + o.get().v + ); + } else { + auto& file_id = o.emplace().id; + randombytes_buf(file_id.data.data(), file_id.data.size()); + o.emplace(std::vector{file_id.data.cbegin(), file_id.data.cend()}); + } + } + + if (!o.all_of()) { + // default to 0 (data) == file message (?) + o.emplace(); + } + + const auto& info = o.get(); + + o.emplace(); + o.emplace(); + + // TODO: replace with better state tracking + o.emplace(); + + Message3Handle msg; + if (o.get().kind == 0) { + msg = {*msg_reg_ptr, msg_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, + o.get().kind, + info.file_size, + {o.get().id.data.cbegin(), o.get().id.data.cend()}, + info.file_name + ); + if (err == TOX_ERR_FILE_SEND_OK) { + assert(transfer_id.has_value()); + o.emplace(friend_number, transfer_id.value()); + // TODO: add tag signifying init sent status? + + toxFriendLookupAdd(o); + } // else queue? + + _os.throwEventConstruct(o); + + if (static_cast(msg)) { + _rmm.throwEventConstruct(msg); + } + + return true; +} + bool ToxTransferManager::onEvent(const ObjectStore::Events::ObjectUpdate& e) { if (_in_obj_update_event) { return false; diff --git a/solanaceae/tox_messages/tox_transfer_manager.hpp b/solanaceae/tox_messages/tox_transfer_manager.hpp index aada12d..cd7ea39 100644 --- a/solanaceae/tox_messages/tox_transfer_manager.hpp +++ b/solanaceae/tox_messages/tox_transfer_manager.hpp @@ -81,6 +81,14 @@ class ToxTransferManager : public RegistryMessageModelEventI, public ObjectStore protected: // (r)mm bool sendFilePath(const Contact4 c, std::string_view file_name, std::string_view file_path) override; + // needs to have: + // - StorageBackendIFile2 + // - SingleInfo + // - LocalHaveAll (TODO: figure out streaming?) + // - Tox::FileID (defaults to obj id? rng?) + // - Tox::FileKind (defaults to 0(DATA) ) + bool sendFileObj(const Contact4 c, ObjectHandle o) override; + protected: // os //bool onEvent(const ObjectStore::Events::ObjectConstruct&) override; bool onEvent(const ObjectStore::Events::ObjectUpdate&) override;