proper transfer obj handling (still no sending)
This commit is contained in:
parent
4e75bd64ae
commit
7e12cdfb23
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <solanaceae/contact/fwd.hpp>
|
||||
#include <solanaceae/object_store/meta_components_file.hpp> // contains the alias
|
||||
|
||||
#include <solanaceae/message3/registry_message_model.hpp>
|
||||
@ -36,6 +37,11 @@ namespace ObjectStore::Components {
|
||||
uint32_t transfer_number;
|
||||
};
|
||||
|
||||
// TODO: replace this with something generic
|
||||
struct ToxContact {
|
||||
ContactHandle4 c;
|
||||
};
|
||||
|
||||
// TODO: replace this with something generic
|
||||
struct ToxMessage {
|
||||
// the message, if the ft is visible as a message
|
||||
|
@ -25,7 +25,11 @@ namespace Components {
|
||||
|
||||
struct TFTFile2 {
|
||||
// the cached file2 for receiving/sending only
|
||||
// should be destroyed when no activity and recreated on demand
|
||||
std::unique_ptr<File2I> file;
|
||||
|
||||
// set to current time on init, read, write
|
||||
uint64_t last_activity_ts {};
|
||||
};
|
||||
|
||||
} // Components
|
||||
@ -78,6 +82,62 @@ ObjectHandle ToxTransferManager::toxFriendLookupReceiving(const uint32_t friend_
|
||||
}
|
||||
}
|
||||
|
||||
File2I* ToxTransferManager::objGetFile2Write(ObjectHandle o) {
|
||||
auto* file2_comp_ptr = o.try_get<Components::TFTFile2>();
|
||||
if (file2_comp_ptr == nullptr || !file2_comp_ptr->file || !file2_comp_ptr->file->can_write || !file2_comp_ptr->file->isGood()) {
|
||||
std::cout << "TTM: (re)opening object " << entt::to_integral(entt::to_entity(o.entity())) << " for writing\n";
|
||||
// (re)request file2 from backend
|
||||
auto* file_backend = o.get<ObjComp::Ephemeral::BackendFile2>().ptr;
|
||||
if (file_backend == nullptr) {
|
||||
std::cerr << "TTM error: object backend nullptr\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//auto new_file = _mfb.file2(o, StorageBackendIFile2::FILE2_WRITE);
|
||||
auto file2 = file_backend->file2(o, StorageBackendIFile2::FILE2_WRITE);
|
||||
if (!file2 || !file2->isGood() || !file2->can_write) {
|
||||
std::cerr << "TTM error: creating file2 from object via backendI\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
file2_comp_ptr = &o.emplace_or_replace<Components::TFTFile2>(std::move(file2), getTimeMS());
|
||||
}
|
||||
assert(file2_comp_ptr != nullptr);
|
||||
assert(static_cast<bool>(file2_comp_ptr->file));
|
||||
|
||||
file2_comp_ptr->last_activity_ts = getTimeMS();
|
||||
|
||||
return file2_comp_ptr->file.get();
|
||||
}
|
||||
|
||||
File2I* ToxTransferManager::objGetFile2Read(ObjectHandle o) {
|
||||
auto* file2_comp_ptr = o.try_get<Components::TFTFile2>();
|
||||
if (file2_comp_ptr == nullptr || !file2_comp_ptr->file || !file2_comp_ptr->file->can_read || !file2_comp_ptr->file->isGood()) {
|
||||
std::cout << "TTM: (re)opening object " << entt::to_integral(entt::to_entity(o.entity())) << " for reading\n";
|
||||
// (re)request file2 from backend
|
||||
auto* file_backend = o.get<ObjComp::Ephemeral::BackendFile2>().ptr;
|
||||
if (file_backend == nullptr) {
|
||||
std::cerr << "TTM error: object backend nullptr\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//auto new_file = _mfb.file2(o, StorageBackendIFile2::FILE2_READ);
|
||||
auto file2 = file_backend->file2(o, StorageBackendIFile2::FILE2_READ);
|
||||
if (!file2 || !file2->isGood() || !file2->can_read) {
|
||||
std::cerr << "TTM error: creating file2 from object via backendI\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
file2_comp_ptr = &o.emplace_or_replace<Components::TFTFile2>(std::move(file2), getTimeMS());
|
||||
}
|
||||
assert(file2_comp_ptr != nullptr);
|
||||
assert(static_cast<bool>(file2_comp_ptr->file));
|
||||
|
||||
file2_comp_ptr->last_activity_ts = getTimeMS();
|
||||
|
||||
return file2_comp_ptr->file.get();
|
||||
}
|
||||
|
||||
ToxTransferManager::ToxTransferManager(
|
||||
RegistryMessageModelI& rmm,
|
||||
ContactStore4I& cs,
|
||||
@ -119,11 +179,6 @@ Message3Handle ToxTransferManager::toxSendFilePath(const Contact4 c, uint32_t fi
|
||||
return {};
|
||||
}
|
||||
|
||||
auto* reg_ptr = _rmm.get(c);
|
||||
if (reg_ptr == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto file_impl = std::make_unique<File2RFile>(file_path);
|
||||
if (!file_impl->isGood()) {
|
||||
std::cerr << "TTM error: failed opening file '" << file_path << "'!\n";
|
||||
@ -149,6 +204,7 @@ Message3Handle ToxTransferManager::toxSendFilePath(const Contact4 c, uint32_t fi
|
||||
}
|
||||
|
||||
auto o = _ftb.newObject(ByteSpan{file_id}, false);
|
||||
//auto o = _os.objectHandle(_os.registry().create());
|
||||
|
||||
o.emplace<ObjComp::F::TagLocalHaveAll>();
|
||||
o.emplace<ObjComp::Tox::TagOutgoing>();
|
||||
@ -165,6 +221,11 @@ Message3Handle ToxTransferManager::toxSendFilePath(const Contact4 c, uint32_t fi
|
||||
// TODO: replace with better state tracking
|
||||
o.emplace<ObjComp::Ephemeral::File::TagTransferPaused>();
|
||||
|
||||
auto* reg_ptr = _rmm.get(c);
|
||||
if (reg_ptr == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
Message3Handle msg {*reg_ptr, reg_ptr->create()};
|
||||
msg.emplace<Message::Components::ContactTo>(c);
|
||||
msg.emplace<Message::Components::ContactFrom>(c_self);
|
||||
@ -355,6 +416,18 @@ bool ToxTransferManager::accept(ObjectHandle transfer, std::string_view file_pat
|
||||
return false;
|
||||
}
|
||||
|
||||
if (transfer.any_of<ObjComp::Ephemeral::BackendMeta, ObjComp::Ephemeral::BackendFile2>()) {
|
||||
std::cerr << "TTM error: accepted transfer " << entt::to_integral(transfer.entity()) << " already has backend, use obj instead\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
{ // HACK: backend has no attach() and we gonna remove this eitherway
|
||||
const auto& id_data = transfer.get<ObjComp::Tox::FileID>().id.data;
|
||||
transfer.emplace<ObjComp::ID>(std::vector<uint8_t>(id_data.cbegin(), id_data.cend()));
|
||||
transfer.emplace<ObjComp::Ephemeral::BackendMeta>(&_ftb);
|
||||
transfer.emplace<ObjComp::Ephemeral::BackendFile2>(&_ftb);
|
||||
}
|
||||
|
||||
if (transfer.any_of<Components::TFTFile2>()) {
|
||||
std::cerr << "TTM warning: overwriting existing file_impl " << entt::to_integral(transfer.entity()) << "\n";
|
||||
}
|
||||
@ -383,6 +456,39 @@ bool ToxTransferManager::accept(ObjectHandle transfer, std::string_view file_pat
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ToxTransferManager::acceptObj(ObjectHandle transfer) {
|
||||
if (!static_cast<bool>(transfer)) {
|
||||
std::cerr << "TTM error: accepted transfer " << entt::to_integral(transfer.entity()) << " is not a valid transfer\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!transfer.all_of<ObjComp::Tox::TagIncomming, ObjComp::Ephemeral::ToxTransferFriend>()) {
|
||||
std::cerr << "TTM error: accepted transfer " << entt::to_integral(transfer.entity()) << " is not a receiving transfer\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (transfer.any_of<Components::TFTFile2>()) {
|
||||
std::cerr << "TTM error: existing file_impl " << entt::to_integral(transfer.entity()) << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!transfer.all_of<ObjComp::Ephemeral::BackendFile2>()) {
|
||||
std::cerr << "TTM error: transfer " << entt::to_integral(transfer.entity()) << " missing BackendFile2\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!resume(transfer)) {
|
||||
std::cerr << "TTM error: accepted transfer " << entt::to_integral(transfer.entity()) << " failed to resume\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << "TTM info: accepted " << entt::to_integral(transfer.entity()) << "\n";
|
||||
|
||||
// resume() throws events (bad lol)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ToxTransferManager::sendFilePath(const Contact4 c, std::string_view file_name, std::string_view file_path) {
|
||||
const auto& cr = _cs.registry();
|
||||
if (
|
||||
@ -487,6 +593,7 @@ bool ToxTransferManager::onToxEvent(const Tox_Event_File_Recv* e) {
|
||||
});
|
||||
if (static_cast<bool>(o)) {
|
||||
std::cerr << "TTM error: existing file transfer frd:" << friend_number << " fnb:" << file_number << "\n";
|
||||
// TODO: hard error
|
||||
return false;
|
||||
}
|
||||
assert(!_friend_receiving_lookup.count((uint64_t(friend_number) << 32) | file_number));
|
||||
@ -497,7 +604,7 @@ bool ToxTransferManager::onToxEvent(const Tox_Event_File_Recv* e) {
|
||||
//assert(f_id_opt.has_value());
|
||||
if (!f_id_opt.has_value()) {
|
||||
// very unfortuante, toxcore already forgot about the transfer we are handling
|
||||
// TODO: make sure we exit cracefully here
|
||||
// TODO: make sure we exit gracefully here
|
||||
std::cerr << "TTM error: querying for fileid failed, toxcore already forgot. frd:" << friend_number << " fnb:" << file_number << "\n";
|
||||
return false;
|
||||
}
|
||||
@ -509,11 +616,14 @@ bool ToxTransferManager::onToxEvent(const Tox_Event_File_Recv* e) {
|
||||
|
||||
auto self_c = cr.get<Contact::Components::Self>(c).self;
|
||||
|
||||
o = _ftb.newObject(ByteSpan{f_id_opt.value()}, false);
|
||||
//o = _ftb.newObject(ByteSpan{f_id_opt.value()}, false);
|
||||
o = _os.objectHandle(_os.registry().create());
|
||||
//o.emplace<ObjComp::ID>(f_id_opt.value()); // actually no, the meta backend does this, once accepted
|
||||
|
||||
o.emplace<ObjComp::Tox::TagIncomming>();
|
||||
o.emplace<ObjComp::Ephemeral::File::TagTransferPaused>();
|
||||
o.emplace<ObjComp::Ephemeral::ToxTransferFriend>(friend_number, file_number);
|
||||
o.emplace<ObjComp::Ephemeral::ToxContact>(c);
|
||||
o.emplace<ObjComp::Tox::FileKind>(file_kind);
|
||||
|
||||
o.emplace<ObjComp::Tox::FileID>(f_id_opt.value());
|
||||
@ -525,23 +635,35 @@ bool ToxTransferManager::onToxEvent(const Tox_Event_File_Recv* e) {
|
||||
|
||||
toxFriendLookupAdd(o);
|
||||
|
||||
Message3Handle msg = {*reg_ptr, reg_ptr->create()};
|
||||
Message3Handle msg;
|
||||
if (file_kind == 0) {
|
||||
msg = {*reg_ptr, reg_ptr->create()};
|
||||
|
||||
msg.emplace<Message::Components::ContactTo>(self_c);
|
||||
msg.emplace<Message::Components::ContactFrom>(c);
|
||||
msg.emplace<Message::Components::Timestamp>(ts); // reactive?
|
||||
msg.emplace<Message::Components::TagUnread>();
|
||||
{
|
||||
auto& rb = msg.emplace<Message::Components::ReceivedBy>().ts;
|
||||
//rb.try_emplace(self_c, ts); // only on completion
|
||||
rb.try_emplace(c, ts);
|
||||
msg.emplace<Message::Components::ContactTo>(self_c);
|
||||
msg.emplace<Message::Components::ContactFrom>(c);
|
||||
msg.emplace<Message::Components::Timestamp>(ts); // reactive?
|
||||
msg.emplace<Message::Components::TagUnread>();
|
||||
{
|
||||
auto& rb = msg.emplace<Message::Components::ReceivedBy>().ts;
|
||||
//rb.try_emplace(self_c, ts); // only on completion
|
||||
rb.try_emplace(c, ts);
|
||||
}
|
||||
msg.emplace<Message::Components::MessageFileObject>(o);
|
||||
|
||||
o.emplace<ObjComp::Ephemeral::ToxMessage>(msg);
|
||||
}
|
||||
msg.emplace<Message::Components::MessageFileObject>(o);
|
||||
|
||||
o.emplace<ObjComp::Ephemeral::ToxMessage>(msg);
|
||||
// maybe system message otherwise? might get very spammy
|
||||
|
||||
_os.throwEventConstruct(o);
|
||||
_rmm.throwEventConstruct(msg);
|
||||
|
||||
// check accepted
|
||||
if (o.all_of<ObjComp::Ephemeral::BackendFile2>()) {
|
||||
acceptObj(o);
|
||||
}
|
||||
|
||||
if (file_kind == 0) {
|
||||
_rmm.throwEventConstruct(msg);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -638,24 +760,26 @@ bool ToxTransferManager::onToxEvent(const Tox_Event_File_Recv_Chunk* e) {
|
||||
|
||||
_rmm.throwEventUpdate(msg);
|
||||
}
|
||||
} else if (!o.all_of<Components::TFTFile2>() || !o.get<Components::TFTFile2>().file || !o.get<Components::TFTFile2>().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(o);
|
||||
|
||||
o.remove<
|
||||
ObjComp::Ephemeral::ToxTransferFriend,
|
||||
Components::TFTFile2
|
||||
>();
|
||||
|
||||
_os.throwEventUpdate(o);
|
||||
// update messages?
|
||||
} else {
|
||||
auto& file = o.get<Components::TFTFile2>().file;
|
||||
const auto res = file->write({data, data_size}, position);
|
||||
//o.get<Message::Components::Transfer::BytesReceived>().total += data_size;
|
||||
auto* file_ptr = objGetFile2Write(o);
|
||||
if (file_ptr == nullptr || !file_ptr->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(o);
|
||||
|
||||
o.remove<
|
||||
ObjComp::Ephemeral::ToxTransferFriend,
|
||||
Components::TFTFile2
|
||||
>();
|
||||
|
||||
_os.throwEventUpdate(o);
|
||||
// update messages?
|
||||
|
||||
return true;
|
||||
}
|
||||
const auto res = file_ptr->write({data, data_size}, position);
|
||||
o.get_or_emplace<ObjComp::Ephemeral::File::TransferStats>().total_down += data_size;
|
||||
|
||||
// queue?
|
||||
@ -691,25 +815,28 @@ bool ToxTransferManager::onToxEvent(const Tox_Event_File_Chunk_Request* e) {
|
||||
>();
|
||||
|
||||
// TODO: add tag finished?
|
||||
//_rmm.throwEventUpdate(o);
|
||||
_os.throwEventUpdate(o);
|
||||
} else if (!o.all_of<Components::TFTFile2>() || !o.get<Components::TFTFile2>().file || !o.get<Components::TFTFile2>().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(o);
|
||||
|
||||
o.remove<
|
||||
ObjComp::Ephemeral::ToxTransferFriend,
|
||||
Components::TFTFile2
|
||||
>();
|
||||
|
||||
//_rmm.throwEventUpdate(o);
|
||||
_os.throwEventUpdate(o);
|
||||
} else {
|
||||
auto& file = o.get<Components::TFTFile2>().file;
|
||||
const auto data = file->read(data_size, position);
|
||||
auto* file_ptr = objGetFile2Read(o);
|
||||
if (file_ptr == nullptr || !file_ptr->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(o);
|
||||
|
||||
o.remove<
|
||||
ObjComp::Ephemeral::ToxTransferFriend,
|
||||
Components::TFTFile2
|
||||
>();
|
||||
|
||||
//_rmm.throwEventUpdate(o);
|
||||
_os.throwEventUpdate(o);
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto data = file_ptr->read(data_size, position);
|
||||
if (data.empty()) {
|
||||
std::cerr << "TMM error: failed to read file!!\n";
|
||||
return true;
|
||||
|
@ -21,7 +21,7 @@ struct ToxI;
|
||||
|
||||
class ToxTransferManager : public RegistryMessageModelEventI, public ObjectStoreEventI, public ToxEventI {
|
||||
public:
|
||||
static constexpr const char* version {"3"};
|
||||
static constexpr const char* version {"4"};
|
||||
|
||||
protected:
|
||||
RegistryMessageModelI& _rmm;
|
||||
@ -32,6 +32,8 @@ class ToxTransferManager : public RegistryMessageModelEventI, public ObjectStore
|
||||
ToxEventProviderI::SubscriptionReference _tep_sr;
|
||||
ObjectStore2& _os;
|
||||
ObjectStore2::SubscriptionReference _os_sr;
|
||||
|
||||
// TODO: remove
|
||||
Backends::ToxFTFilesystem _ftb;
|
||||
|
||||
bool _in_obj_update_event {false};
|
||||
@ -46,6 +48,9 @@ class ToxTransferManager : public RegistryMessageModelEventI, public ObjectStore
|
||||
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;
|
||||
|
||||
File2I* objGetFile2Write(ObjectHandle o);
|
||||
File2I* objGetFile2Read(ObjectHandle o);
|
||||
|
||||
public:
|
||||
ToxTransferManager(
|
||||
RegistryMessageModelI& rmm,
|
||||
@ -71,6 +76,7 @@ class ToxTransferManager : public RegistryMessageModelEventI, public ObjectStore
|
||||
|
||||
// calls setFileI() and resume()
|
||||
bool accept(ObjectHandle transfer, std::string_view file_path, bool path_is_file);
|
||||
bool acceptObj(ObjectHandle transfer);
|
||||
|
||||
protected: // (r)mm
|
||||
bool sendFilePath(const Contact4 c, std::string_view file_name, std::string_view file_path) override;
|
||||
|
Loading…
x
Reference in New Issue
Block a user