2023-07-24 13:20:53 +02:00
|
|
|
#include "./tox_transfer_manager.hpp"
|
|
|
|
|
|
|
|
#include <solanaceae/toxcore/tox_interface.hpp>
|
|
|
|
|
2024-05-26 18:57:36 +02:00
|
|
|
#include <solanaceae/file/file2_std.hpp>
|
2023-07-24 13:20:53 +02:00
|
|
|
|
|
|
|
#include <solanaceae/contact/components.hpp>
|
|
|
|
#include <solanaceae/tox_contacts/components.hpp>
|
|
|
|
#include <solanaceae/message3/components.hpp>
|
2024-07-29 20:03:24 +02:00
|
|
|
#include "./msg_components.hpp"
|
|
|
|
#include "./obj_components.hpp"
|
2023-07-24 13:20:53 +02:00
|
|
|
|
|
|
|
#include <sodium.h>
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
#include <filesystem>
|
2023-07-24 13:20:53 +02:00
|
|
|
#include <cassert>
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
// https://youtu.be/4XsL5iYHS6c
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
namespace Components {
|
|
|
|
|
|
|
|
struct TFTFile2 {
|
|
|
|
// the cached file2 for receiving/sending only
|
|
|
|
std::unique_ptr<File2I> file;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // Components
|
|
|
|
|
|
|
|
void ToxTransferManager::toxFriendLookupAdd(ObjectHandle o) {
|
|
|
|
const auto& comp = o.get<ObjComp::Ephemeral::ToxTransferFriend>();
|
2023-07-24 13:20:53 +02:00
|
|
|
const uint64_t key {(uint64_t(comp.friend_number) << 32) | comp.transfer_number};
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
if (o.all_of<ObjComp::Tox::TagOutgoing>()) {
|
2023-07-24 13:20:53 +02:00
|
|
|
assert(!_friend_sending_lookup.count(key));
|
2024-07-29 20:03:24 +02:00
|
|
|
_friend_sending_lookup[key] = o;
|
2023-07-24 13:20:53 +02:00
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
if (o.all_of<ObjComp::Tox::TagIncomming>()) {
|
2023-07-24 13:20:53 +02:00
|
|
|
assert(!_friend_receiving_lookup.count(key));
|
2024-07-29 20:03:24 +02:00
|
|
|
_friend_receiving_lookup[key] = o;
|
2023-07-24 13:20:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
void ToxTransferManager::toxFriendLookupRemove(ObjectHandle o) {
|
|
|
|
const auto& comp = o.get<ObjComp::Ephemeral::ToxTransferFriend>();
|
2023-07-24 13:20:53 +02:00
|
|
|
const uint64_t key {(uint64_t(comp.friend_number) << 32) | comp.transfer_number};
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
if (o.all_of<ObjComp::Tox::TagOutgoing>()) {
|
2023-07-24 13:20:53 +02:00
|
|
|
assert(_friend_sending_lookup.count(key));
|
|
|
|
_friend_sending_lookup.erase(key);
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
if (o.all_of<ObjComp::Tox::TagIncomming>()) {
|
2023-07-24 13:20:53 +02:00
|
|
|
assert(_friend_receiving_lookup.count(key));
|
|
|
|
_friend_receiving_lookup.erase(key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
ObjectHandle ToxTransferManager::toxFriendLookupSending(const uint32_t friend_number, const uint32_t file_number) const {
|
2023-07-24 13:20:53 +02:00
|
|
|
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;
|
|
|
|
} else {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
ObjectHandle ToxTransferManager::toxFriendLookupReceiving(const uint32_t friend_number, const uint32_t file_number) const {
|
2023-07-24 13:20:53 +02:00
|
|
|
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;
|
|
|
|
} else {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
ToxTransferManager::ToxTransferManager(
|
2024-10-06 11:14:54 +02:00
|
|
|
RegistryMessageModelI& rmm,
|
2024-07-29 20:03:24 +02:00
|
|
|
Contact3Registry& cr,
|
|
|
|
ToxContactModel2& tcm,
|
|
|
|
ToxI& t,
|
|
|
|
ToxEventProviderI& tep,
|
|
|
|
ObjectStore2& os
|
2024-10-24 15:55:44 +02:00
|
|
|
) : _rmm(rmm), _rmm_sr(_rmm.newSubRef(this)), _cr(cr), _tcm(tcm), _t(t), _tep_sr(tep.newSubRef(this)), _os(os), _os_sr(_os.newSubRef(this)), _ftb(os) {
|
|
|
|
_tep_sr
|
|
|
|
.subscribe(Tox_Event_Type::TOX_EVENT_FRIEND_CONNECTION_STATUS)
|
|
|
|
.subscribe(Tox_Event_Type::TOX_EVENT_FILE_RECV)
|
|
|
|
.subscribe(Tox_Event_Type::TOX_EVENT_FILE_RECV_CONTROL)
|
|
|
|
.subscribe(Tox_Event_Type::TOX_EVENT_FILE_RECV_CHUNK)
|
|
|
|
.subscribe(Tox_Event_Type::TOX_EVENT_FILE_CHUNK_REQUEST)
|
|
|
|
;
|
|
|
|
|
|
|
|
_os_sr
|
|
|
|
.subscribe(ObjectStore_Event::object_update)
|
|
|
|
.subscribe(ObjectStore_Event::object_destroy)
|
|
|
|
;
|
|
|
|
|
|
|
|
_rmm_sr.subscribe(RegistryMessageModel_Event::send_file_path);
|
2023-07-24 13:20:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ToxTransferManager::~ToxTransferManager(void) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void ToxTransferManager::iterate(void) {
|
|
|
|
// TODO: time out transfers
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
Message3Handle ToxTransferManager::toxSendFilePath(const Contact3 c, uint32_t file_kind, std::string_view file_name, std::string_view file_path, std::vector<uint8_t> file_id) {
|
2023-07-24 13:20:53 +02:00
|
|
|
if (
|
|
|
|
// TODO: add support of offline queuing
|
|
|
|
!_cr.all_of<Contact::Components::ToxFriendEphemeral>(c)
|
|
|
|
) {
|
|
|
|
std::cerr << "TTM error: unsupported contact type\n";
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
auto* reg_ptr = _rmm.get(c);
|
|
|
|
if (reg_ptr == nullptr) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2024-05-26 18:57:36 +02:00
|
|
|
auto file_impl = std::make_unique<File2RFile>(file_path);
|
2023-07-24 13:20:53 +02:00
|
|
|
if (!file_impl->isGood()) {
|
|
|
|
std::cerr << "TTM error: failed opening file '" << file_path << "'!\n";
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
// get current time unix epoch utc
|
2024-07-29 20:03:24 +02:00
|
|
|
uint64_t ts = Message::getTimeMS();
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
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);
|
2023-07-24 13:20:53 +02:00
|
|
|
|
|
|
|
const auto c_self = _cr.get<Contact::Components::Self>(c).self;
|
|
|
|
if (!_cr.valid(c_self)) {
|
|
|
|
std::cerr << "TTM error: failed to get self!\n";
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
// TODO: move this to backend
|
|
|
|
ObjectHandle o {_os.registry(), _os.registry().create()};
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
o.emplace<ObjComp::F::TagLocalHaveAll>();
|
|
|
|
o.emplace<ObjComp::Tox::TagOutgoing>();
|
|
|
|
o.emplace<ObjComp::Tox::FileKind>(file_kind);
|
|
|
|
o.emplace<ObjComp::Tox::FileID>(file_id);
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-30 11:00:36 +02:00
|
|
|
// file info
|
|
|
|
o.emplace<ObjComp::F::SingleInfo>(std::string{file_name}, file_impl->_file_size);
|
|
|
|
o.emplace<ObjComp::F::SingleInfoLocal>(std::string{file_path});
|
|
|
|
o.emplace<ObjComp::Ephemeral::FilePath>(std::string{file_path}); // ?
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-30 11:00:36 +02:00
|
|
|
o.emplace<ObjComp::Ephemeral::Backend>(&_ftb);
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
o.emplace<ObjComp::Ephemeral::File::TransferStats>();
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-30 11:00:36 +02:00
|
|
|
// TODO: replace with better state tracking
|
2024-07-29 20:03:24 +02:00
|
|
|
o.emplace<ObjComp::Ephemeral::File::TagTransferPaused>();
|
|
|
|
|
|
|
|
Message3Handle msg {*reg_ptr, reg_ptr->create()};
|
|
|
|
msg.emplace<Message::Components::ContactTo>(c);
|
|
|
|
msg.emplace<Message::Components::ContactFrom>(c_self);
|
|
|
|
msg.emplace<Message::Components::Timestamp>(ts); // reactive?
|
|
|
|
msg.emplace<Message::Components::Read>(ts);
|
|
|
|
msg.emplace<Message::Components::ReceivedBy>().ts.try_emplace(c_self, ts);
|
|
|
|
msg.emplace<Message::Components::MessageFileObject>(o);
|
2023-07-24 13:20:53 +02:00
|
|
|
|
|
|
|
const auto friend_number = _cr.get<Contact::Components::ToxFriendEphemeral>(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) {
|
2024-07-29 20:03:24 +02:00
|
|
|
assert(transfer_id.has_value());
|
|
|
|
o.emplace<ObjComp::Ephemeral::ToxTransferFriend>(friend_number, transfer_id.value());
|
|
|
|
o.emplace<Components::TFTFile2>(std::move(file_impl));
|
2023-07-24 13:20:53 +02:00
|
|
|
// TODO: add tag signifying init sent status?
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
toxFriendLookupAdd(o);
|
2023-07-24 13:20:53 +02:00
|
|
|
} // else queue?
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
_os.throwEventConstruct(o);
|
|
|
|
_rmm.throwEventConstruct(msg);
|
|
|
|
return msg;
|
2023-07-24 13:20:53 +02:00
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
bool ToxTransferManager::resume(ObjectHandle transfer) {
|
2023-07-24 13:20:53 +02:00
|
|
|
if (!static_cast<bool>(transfer)) {
|
|
|
|
std::cerr << "TTM error: resume() transfer " << entt::to_integral(transfer.entity()) << " is not a valid transfer\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: test for paused?
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
if (!transfer.all_of<ObjComp::Ephemeral::ToxTransferFriend>()) {
|
2023-07-24 13:20:53 +02:00
|
|
|
std::cerr << "TTM error: resume() transfer " << entt::to_integral(transfer.entity()) << " ent does not have toxtransfer info\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
const auto [friend_number, transfer_number] = transfer.get<ObjComp::Ephemeral::ToxTransferFriend>();
|
2023-07-24 13:20:53 +02:00
|
|
|
|
|
|
|
const auto err = _t.toxFileControl(friend_number, transfer_number, TOX_FILE_CONTROL_RESUME);
|
|
|
|
if (err != TOX_ERR_FILE_CONTROL_OK) {
|
|
|
|
std::cerr << "TTM error: resume() transfer " << entt::to_integral(transfer.entity()) << " tox file control error " << err << "\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
transfer.remove<ObjComp::Ephemeral::File::TagTransferPaused>();
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
_os.throwEventUpdate(transfer);
|
2023-07-24 13:20:53 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
bool ToxTransferManager::pause(ObjectHandle transfer) {
|
2023-07-24 13:20:53 +02:00
|
|
|
if (!static_cast<bool>(transfer)) {
|
|
|
|
std::cerr << "TTM error: pause() transfer " << entt::to_integral(transfer.entity()) << " is not a valid transfer\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: test for paused?
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
if (!transfer.all_of<ObjComp::Ephemeral::ToxTransferFriend>()) {
|
2023-07-24 13:20:53 +02:00
|
|
|
std::cerr << "TTM error: pause() transfer " << entt::to_integral(transfer.entity()) << " ent does not have toxtransfer info\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
const auto [friend_number, transfer_number] = transfer.get<ObjComp::Ephemeral::ToxTransferFriend>();
|
2023-07-24 13:20:53 +02:00
|
|
|
|
|
|
|
const auto err = _t.toxFileControl(friend_number, transfer_number, TOX_FILE_CONTROL_PAUSE);
|
|
|
|
if (err != TOX_ERR_FILE_CONTROL_OK) {
|
|
|
|
std::cerr << "TTM error: pause() transfer " << entt::to_integral(transfer.entity()) << " tox file control error " << err << "\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
transfer.emplace_or_replace<ObjComp::Ephemeral::File::TagTransferPaused>();
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
_os.throwEventUpdate(transfer);
|
2023-07-24 13:20:53 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
bool ToxTransferManager::setFileI(ObjectHandle transfer, std::unique_ptr<File2I>&& new_file) {
|
2023-07-24 13:20:53 +02:00
|
|
|
if (!static_cast<bool>(transfer)) {
|
|
|
|
std::cerr << "TTM error: setFileI() transfer " << entt::to_integral(transfer.entity()) << " is not a valid transfer\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!new_file->isGood()) {
|
|
|
|
std::cerr << "TTM error: failed setting new_file_impl!\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
transfer.emplace_or_replace<Components::TFTFile2>(std::move(new_file));
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
_os.throwEventUpdate(transfer);
|
2023-07-24 13:20:53 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
bool ToxTransferManager::setFilePath(ObjectHandle transfer, std::string_view file_path) {
|
2023-10-13 20:39:40 +02:00
|
|
|
if (!static_cast<bool>(transfer)) {
|
|
|
|
std::cerr << "TTM error: setFilePath() transfer " << entt::to_integral(transfer.entity()) << " is not a valid transfer\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t file_size {0};
|
|
|
|
std::filesystem::path full_file_path{file_path};
|
2023-10-14 01:01:40 +02:00
|
|
|
if (auto parent_path = full_file_path.parent_path(); !parent_path.empty()) {
|
|
|
|
std::filesystem::create_directories(parent_path);
|
|
|
|
}
|
2023-10-13 20:39:40 +02:00
|
|
|
|
|
|
|
// TODO: read file name(s) from comp
|
2024-07-29 20:03:24 +02:00
|
|
|
if (transfer.all_of<ObjComp::F::SingleInfo>()) {
|
|
|
|
const auto& file_info = transfer.get<ObjComp::F::SingleInfo>();
|
|
|
|
file_size = file_info.file_size;
|
2023-10-13 20:39:40 +02:00
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
transfer.emplace_or_replace<ObjComp::F::SingleInfoLocal>(full_file_path.u8string());
|
|
|
|
transfer.emplace_or_replace<ObjComp::Ephemeral::FilePath>(full_file_path.u8string()); // ?
|
2023-10-13 20:39:40 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
// huh? we also set file2i ?
|
2024-05-26 18:57:36 +02:00
|
|
|
auto file_impl = std::make_unique<File2RWFile>(full_file_path.u8string(), file_size, true);
|
2023-10-13 20:39:40 +02:00
|
|
|
if (!file_impl->isGood()) {
|
|
|
|
std::cerr << "TTM error: failed opening file '" << file_path << "'!\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
transfer.emplace_or_replace<Components::TFTFile2>(std::move(file_impl));
|
2023-10-13 20:39:40 +02:00
|
|
|
|
|
|
|
// TODO: is this a good idea????
|
2024-07-29 20:03:24 +02:00
|
|
|
_os.throwEventUpdate(transfer);
|
2023-10-13 20:39:40 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
bool ToxTransferManager::setFilePathDir(ObjectHandle transfer, std::string_view file_path) {
|
2023-07-24 13:20:53 +02:00
|
|
|
if (!static_cast<bool>(transfer)) {
|
|
|
|
std::cerr << "TTM error: setFilePathDir() transfer " << entt::to_integral(transfer.entity()) << " is not a valid transfer\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t file_size {0};
|
|
|
|
std::string full_file_path{file_path};
|
|
|
|
// TODO: replace with filesystem or something
|
|
|
|
// TODO: ensure dir exists
|
|
|
|
if (full_file_path.back() != '/') {
|
|
|
|
full_file_path += "/";
|
|
|
|
}
|
|
|
|
|
2023-08-03 13:32:17 +02:00
|
|
|
std::filesystem::create_directories(full_file_path);
|
|
|
|
|
2023-07-24 13:20:53 +02:00
|
|
|
// TODO: read file name(s) from comp
|
2024-07-29 20:03:24 +02:00
|
|
|
if (transfer.all_of<ObjComp::F::SingleInfo>()) {
|
|
|
|
const auto& file_info = transfer.get<ObjComp::F::SingleInfo>();
|
|
|
|
file_size = file_info.file_size;
|
|
|
|
full_file_path += file_info.file_name;
|
2023-07-24 13:20:53 +02:00
|
|
|
|
|
|
|
} else {
|
|
|
|
std::cerr << "TTM warning: no FileInfo on transfer, using default\n";
|
|
|
|
full_file_path += "file_recv.bin";
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
transfer.emplace_or_replace<ObjComp::F::SingleInfoLocal>(full_file_path);
|
|
|
|
transfer.emplace_or_replace<ObjComp::Ephemeral::FilePath>(full_file_path); // ?
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
// huh? we also set file2i ?
|
2024-05-26 18:57:36 +02:00
|
|
|
auto file_impl = std::make_unique<File2RWFile>(full_file_path, file_size, true);
|
2023-07-24 13:20:53 +02:00
|
|
|
if (!file_impl->isGood()) {
|
|
|
|
std::cerr << "TTM error: failed opening file '" << file_path << "'!\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
transfer.emplace_or_replace<Components::TFTFile2>(std::move(file_impl));
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
// TODO: is this a good idea???? - no lol, it was not
|
|
|
|
_os.throwEventUpdate(transfer);
|
2023-07-24 13:20:53 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
bool ToxTransferManager::accept(ObjectHandle transfer, std::string_view file_path, bool path_is_file) {
|
2023-07-24 13:20:53 +02:00
|
|
|
if (!static_cast<bool>(transfer)) {
|
|
|
|
std::cerr << "TTM error: accepted transfer " << entt::to_integral(transfer.entity()) << " is not a valid transfer\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
if (!transfer.all_of<ObjComp::Tox::TagIncomming, ObjComp::Ephemeral::ToxTransferFriend>()) {
|
2023-07-24 13:20:53 +02:00
|
|
|
std::cerr << "TTM error: accepted transfer " << entt::to_integral(transfer.entity()) << " is not a receiving transfer\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
if (transfer.any_of<Components::TFTFile2>()) {
|
2023-07-24 13:20:53 +02:00
|
|
|
std::cerr << "TTM warning: overwriting existing file_impl " << entt::to_integral(transfer.entity()) << "\n";
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
if (path_is_file) {
|
2023-10-13 20:39:40 +02:00
|
|
|
if (!setFilePath(transfer, file_path)) {
|
|
|
|
std::cerr << "TTM error: accepted transfer " << entt::to_integral(transfer.entity()) << " failed setting path\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!setFilePathDir(transfer, file_path)) {
|
|
|
|
std::cerr << "TTM error: accepted transfer " << entt::to_integral(transfer.entity()) << " failed setting path dir\n";
|
|
|
|
return false;
|
|
|
|
}
|
2023-07-24 13:20:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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()) << ", saving to " << file_path << "\n";
|
|
|
|
|
|
|
|
// setFilePathDir() and resume() throw events
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
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<Contact::Components::ToxFriendEphemeral>(c)
|
|
|
|
) {
|
|
|
|
// TODO: add support for persistant friend filesends
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return static_cast<bool>(toxSendFilePath(c, 0, file_name, file_path));
|
2023-07-24 13:20:53 +02:00
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
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<ObjComp::Ephemeral::File::ActionTransferAccept, ObjComp::Ephemeral::ToxTransferFriend>()) {
|
2023-10-13 20:39:40 +02:00
|
|
|
accept(
|
|
|
|
e.e,
|
2024-07-29 20:03:24 +02:00
|
|
|
e.e.get<ObjComp::Ephemeral::File::ActionTransferAccept>().save_to_path,
|
|
|
|
e.e.get<ObjComp::Ephemeral::File::ActionTransferAccept>().path_is_file
|
2023-10-13 20:39:40 +02:00
|
|
|
);
|
2023-07-24 13:20:53 +02:00
|
|
|
|
|
|
|
// should?
|
2024-07-29 20:03:24 +02:00
|
|
|
e.e.remove<ObjComp::Ephemeral::File::ActionTransferAccept>();
|
2023-07-24 13:20:53 +02:00
|
|
|
|
|
|
|
// TODO: recursion??
|
|
|
|
// oh no, accept calls it 2x
|
|
|
|
//_rmm.throwEventUpdate(
|
|
|
|
}
|
2024-07-29 20:03:24 +02:00
|
|
|
_in_obj_update_event = false;
|
2023-07-24 13:20:53 +02:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
bool ToxTransferManager::onEvent(const ObjectStore::Events::ObjectDestory& e) {
|
|
|
|
if (e.e.all_of<ObjComp::Ephemeral::ToxTransferFriend>()) {
|
2023-07-24 13:20:53 +02:00
|
|
|
toxFriendLookupRemove(e.e);
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ToxTransferManager::onToxEvent(const Tox_Event_Friend_Connection_Status* e) {
|
|
|
|
const auto friend_number = tox_event_friend_connection_status_get_friend_number(e);
|
|
|
|
const auto connection_status = tox_event_friend_connection_status_get_connection_status(e);
|
|
|
|
|
|
|
|
if (connection_status == TOX_CONNECTION_NONE) {
|
|
|
|
auto c = _tcm.getContactFriend(friend_number);
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
std::vector<Object> to_destory;
|
|
|
|
_os.registry().view<ObjComp::Ephemeral::ToxTransferFriend>().each([&](const Object ov, const auto& ttf) {
|
2024-07-30 10:29:31 +02:00
|
|
|
if (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";
|
|
|
|
}
|
2023-07-24 13:20:53 +02:00
|
|
|
});
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
for (const auto ov : to_destory) {
|
|
|
|
ObjectHandle o {_os.registry(), ov};
|
|
|
|
|
2023-07-24 13:20:53 +02:00
|
|
|
// update lookup table
|
2024-07-29 20:03:24 +02:00
|
|
|
toxFriendLookupRemove(o);
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
o.remove<ObjComp::Ephemeral::ToxTransferFriend, Components::TFTFile2>();
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
o.emplace_or_replace<ObjComp::Ephemeral::File::TagTransferPaused>();
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
//_rmm.throwEventUpdate(*reg_ptr, ent);
|
|
|
|
_os.throwEventUpdate(ov);
|
2023-07-24 13:20:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false; // always continue
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ToxTransferManager::onToxEvent(const Tox_Event_File_Recv* e) {
|
|
|
|
const auto friend_number = tox_event_file_recv_get_friend_number(e);
|
|
|
|
const std::string_view file_name {
|
|
|
|
reinterpret_cast<const char*>(tox_event_file_recv_get_filename(e)),
|
|
|
|
tox_event_file_recv_get_filename_length(e)
|
|
|
|
};
|
|
|
|
const auto file_number = tox_event_file_recv_get_file_number(e);
|
|
|
|
const auto file_size = tox_event_file_recv_get_file_size(e);
|
|
|
|
const auto file_kind = tox_event_file_recv_get_kind(e);
|
|
|
|
|
|
|
|
auto c = _tcm.getContactFriend(friend_number);
|
|
|
|
auto* reg_ptr = _rmm.get(c);
|
|
|
|
if (reg_ptr == nullptr) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// making sure, we dont have a dup
|
2024-07-29 20:03:24 +02:00
|
|
|
ObjectHandle o {};
|
|
|
|
_os.registry().view<ObjComp::Tox::TagIncomming, ObjComp::Ephemeral::ToxTransferFriend>().each([&](Object ov, const ObjComp::Ephemeral::ToxTransferFriend& ttf) {
|
2023-07-24 13:20:53 +02:00
|
|
|
if (ttf.friend_number == friend_number && ttf.transfer_number == file_number) {
|
2024-07-29 20:03:24 +02:00
|
|
|
o = {_os.registry(), ov};
|
2023-07-24 13:20:53 +02:00
|
|
|
}
|
|
|
|
});
|
2024-07-29 20:03:24 +02:00
|
|
|
if (static_cast<bool>(o)) {
|
2023-07-24 13:20:53 +02:00
|
|
|
std::cerr << "TTM error: existing file transfer frd:" << friend_number << " fnb:" << file_number << "\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
assert(!_friend_receiving_lookup.count((uint64_t(friend_number) << 32) | file_number));
|
|
|
|
|
|
|
|
// TODO: also check for file id
|
|
|
|
|
2023-10-06 12:50:53 +02:00
|
|
|
auto [f_id_opt, _] = _t.toxFileGetFileID(friend_number, file_number);
|
|
|
|
//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
|
|
|
|
std::cerr << "TTM error: querying for fileid failed, toxcore already forgot. frd:" << friend_number << " fnb:" << file_number << "\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-07-24 13:20:53 +02:00
|
|
|
// get current time unix epoch utc
|
2024-07-29 20:03:24 +02:00
|
|
|
uint64_t ts = Message::getTimeMS();
|
2023-07-24 13:20:53 +02:00
|
|
|
|
|
|
|
auto self_c = _cr.get<Contact::Components::Self>(c).self;
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
o = {_os.registry(), _os.registry().create()};
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
o.emplace<ObjComp::Tox::TagIncomming>();
|
|
|
|
o.emplace<ObjComp::Ephemeral::File::TagTransferPaused>();
|
|
|
|
o.emplace<ObjComp::Ephemeral::ToxTransferFriend>(friend_number, file_number);
|
|
|
|
o.emplace<ObjComp::Tox::FileKind>(file_kind);
|
2024-04-20 13:47:54 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
o.emplace<ObjComp::Tox::FileID>(f_id_opt.value());
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
// file info
|
|
|
|
o.emplace<ObjComp::F::SingleInfo>(std::string{file_name}, file_size);
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
o.emplace<ObjComp::Ephemeral::File::TransferStats>();
|
|
|
|
|
2024-07-30 11:00:36 +02:00
|
|
|
o.emplace<ObjComp::Ephemeral::Backend>(&_ftb);
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
toxFriendLookupAdd(o);
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
Message3Handle msg = {*reg_ptr, reg_ptr->create()};
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
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);
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-10-06 19:58:44 +02:00
|
|
|
o.emplace<ObjComp::Ephemeral::ToxMessage>(msg);
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
_os.throwEventConstruct(o);
|
|
|
|
_rmm.throwEventConstruct(msg);
|
2023-07-24 13:20:53 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ToxTransferManager::onToxEvent(const Tox_Event_File_Recv_Control* e) {
|
|
|
|
const auto friend_number = tox_event_file_recv_control_get_friend_number(e);
|
|
|
|
const auto file_number = tox_event_file_recv_control_get_file_number(e);
|
|
|
|
const auto control = tox_event_file_recv_control_get_control(e);
|
|
|
|
|
|
|
|
// first try sending
|
2024-07-29 20:03:24 +02:00
|
|
|
ObjectHandle o = toxFriendLookupSending(friend_number, file_number);
|
|
|
|
if (!static_cast<bool>(o)) {
|
2023-07-24 13:20:53 +02:00
|
|
|
// then receiving
|
2024-07-29 20:03:24 +02:00
|
|
|
o = toxFriendLookupReceiving(friend_number, file_number);
|
2023-07-24 13:20:53 +02:00
|
|
|
}
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
if (!static_cast<bool>(o)) {
|
2023-07-24 13:20:53 +02:00
|
|
|
std::cerr << "TMM waring: control for unk ft\n";
|
|
|
|
return false; // shrug, we don't know about it, might be someone else's
|
|
|
|
}
|
|
|
|
|
|
|
|
if (control == TOX_FILE_CONTROL_CANCEL) {
|
|
|
|
std::cerr << "TTM: friend transfer canceled frd:" << friend_number << " fnb:" << file_number << "\n";
|
|
|
|
|
|
|
|
// update lookup table
|
2024-07-29 20:03:24 +02:00
|
|
|
toxFriendLookupRemove(o);
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
o.remove<
|
|
|
|
ObjComp::Ephemeral::ToxTransferFriend,
|
|
|
|
Components::TFTFile2
|
2023-07-24 13:20:53 +02:00
|
|
|
>();
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
//_rmm.throwEventUpdate(transfer);
|
|
|
|
_os.throwEventUpdate(o);
|
2023-07-24 13:20:53 +02:00
|
|
|
} 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
|
2024-07-29 20:03:24 +02:00
|
|
|
o.emplace_or_replace<ObjComp::Ephemeral::File::TagTransferPaused>();
|
|
|
|
//_rmm.throwEventUpdate(transfer);
|
|
|
|
_os.throwEventUpdate(o);
|
2023-07-24 13:20:53 +02:00
|
|
|
} else if (control == TOX_FILE_CONTROL_RESUME) {
|
|
|
|
std::cerr << "TTM: friend transfer resumed frd:" << friend_number << " fnb:" << file_number << "\n";
|
2024-07-29 20:03:24 +02:00
|
|
|
o.remove<ObjComp::Ephemeral::File::TagTransferPaused>();
|
|
|
|
//_rmm.throwEventUpdate(transfer);
|
|
|
|
_os.throwEventUpdate(o);
|
2023-07-24 13:20:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ToxTransferManager::onToxEvent(const Tox_Event_File_Recv_Chunk* e) {
|
|
|
|
const auto friend_number = tox_event_file_recv_chunk_get_friend_number(e);
|
|
|
|
const auto file_number = tox_event_file_recv_chunk_get_file_number(e);
|
|
|
|
const uint8_t* data = tox_event_file_recv_chunk_get_data(e);
|
2023-12-26 21:03:49 +01:00
|
|
|
const auto data_size = tox_event_file_recv_chunk_get_data_length(e);
|
2023-07-24 13:20:53 +02:00
|
|
|
const auto position = tox_event_file_recv_chunk_get_position(e);
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
ObjectHandle o = toxFriendLookupReceiving(friend_number, file_number);
|
|
|
|
if (!static_cast<bool>(o)) {
|
2023-07-24 13:20:53 +02:00
|
|
|
return false; // shrug, we don't know about it, might be someone else's
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data_size == 0) {
|
2024-07-29 20:03:24 +02:00
|
|
|
uint64_t ts = Message::getTimeMS();
|
2024-04-20 13:47:54 +02:00
|
|
|
|
2023-07-24 13:20:53 +02:00
|
|
|
std::cout << "TTM finished friend " << friend_number << " transfer " << file_number << ", closing\n";
|
|
|
|
|
|
|
|
// update lookup table
|
2024-07-29 20:03:24 +02:00
|
|
|
toxFriendLookupRemove(o);
|
2023-09-29 18:13:45 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
o.remove<
|
|
|
|
ObjComp::Ephemeral::ToxTransferFriend,
|
|
|
|
Components::TFTFile2
|
2023-07-24 13:20:53 +02:00
|
|
|
>();
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
o.emplace_or_replace<ObjComp::F::TagLocalHaveAll>();
|
|
|
|
|
2024-10-06 19:58:44 +02:00
|
|
|
_os.throwEventUpdate(o);
|
2024-07-29 20:03:24 +02:00
|
|
|
|
2024-10-06 19:58:44 +02:00
|
|
|
// TODO: move out generic? do we want to update on EVERY chunk?
|
|
|
|
if (const auto* msg_ptr = o.try_get<ObjComp::Ephemeral::ToxMessage>(); msg_ptr != nullptr && static_cast<bool>(msg_ptr->m)) {
|
|
|
|
const auto& msg = msg_ptr->m;
|
2024-04-20 13:47:54 +02:00
|
|
|
|
2024-10-06 19:58:44 +02:00
|
|
|
// re-unread a finished transfer
|
|
|
|
msg.emplace_or_replace<Message::Components::TagUnread>();
|
|
|
|
msg.remove<Message::Components::Read>();
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-10-06 19:58:44 +02:00
|
|
|
auto c = _tcm.getContactFriend(friend_number);
|
|
|
|
if (static_cast<bool>(c)) {
|
|
|
|
auto self_c = _cr.get<Contact::Components::Self>(c).self;
|
|
|
|
auto& rb = msg.get_or_emplace<Message::Components::ReceivedBy>().ts;
|
|
|
|
rb.try_emplace(self_c, ts); // on completion
|
|
|
|
}
|
|
|
|
|
|
|
|
_rmm.throwEventUpdate(msg);
|
|
|
|
}
|
2024-07-29 20:03:24 +02:00
|
|
|
} else if (!o.all_of<Components::TFTFile2>() || !o.get<Components::TFTFile2>().file || !o.get<Components::TFTFile2>().file->isGood()) {
|
2023-07-24 13:20:53 +02:00
|
|
|
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
|
2024-07-29 20:03:24 +02:00
|
|
|
toxFriendLookupRemove(o);
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
o.remove<
|
|
|
|
ObjComp::Ephemeral::ToxTransferFriend,
|
|
|
|
Components::TFTFile2
|
2023-07-24 13:20:53 +02:00
|
|
|
>();
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
_os.throwEventUpdate(o);
|
|
|
|
// update messages?
|
2023-07-24 13:20:53 +02:00
|
|
|
} else {
|
2024-07-29 20:03:24 +02:00
|
|
|
auto& file = o.get<Components::TFTFile2>().file;
|
2024-05-26 18:57:36 +02:00
|
|
|
const auto res = file->write({data, data_size}, position);
|
2024-07-29 20:03:24 +02:00
|
|
|
//o.get<Message::Components::Transfer::BytesReceived>().total += data_size;
|
|
|
|
o.get_or_emplace<ObjComp::Ephemeral::File::TransferStats>().total_down += data_size;
|
2023-07-24 13:20:53 +02:00
|
|
|
|
|
|
|
// queue?
|
2024-07-29 20:03:24 +02:00
|
|
|
_os.throwEventUpdate(o);
|
|
|
|
//_rmm.throwEventUpdate(msg);
|
2023-07-24 13:20:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ToxTransferManager::onToxEvent(const Tox_Event_File_Chunk_Request* e) {
|
|
|
|
const auto friend_number = tox_event_file_chunk_request_get_friend_number(e);
|
|
|
|
const auto file_number = tox_event_file_chunk_request_get_file_number(e);
|
|
|
|
const auto position = tox_event_file_chunk_request_get_position(e);
|
|
|
|
const auto data_size = tox_event_file_chunk_request_get_length(e);
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
ObjectHandle o = toxFriendLookupSending(friend_number, file_number);
|
|
|
|
if (!static_cast<bool>(o)) {
|
2023-07-24 13:20:53 +02:00
|
|
|
std::cerr << "TTM warning: chunk request for unk ft\n";
|
|
|
|
return false; // shrug, we don't know about it, might be someone else's
|
|
|
|
}
|
|
|
|
|
|
|
|
// tox wants us to end the transmission
|
|
|
|
if (data_size == 0) {
|
|
|
|
std::cout << "TTM finished friend " << friend_number << " transfer " << file_number << ", closing\n";
|
|
|
|
|
|
|
|
// update lookup table
|
2024-07-29 20:03:24 +02:00
|
|
|
toxFriendLookupRemove(o);
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
o.remove<
|
|
|
|
ObjComp::Ephemeral::ToxTransferFriend,
|
|
|
|
Components::TFTFile2
|
2023-07-24 13:20:53 +02:00
|
|
|
>();
|
|
|
|
|
|
|
|
// TODO: add tag finished?
|
2024-07-29 20:03:24 +02:00
|
|
|
//_rmm.throwEventUpdate(o);
|
|
|
|
_os.throwEventUpdate(o);
|
|
|
|
} else if (!o.all_of<Components::TFTFile2>() || !o.get<Components::TFTFile2>().file || !o.get<Components::TFTFile2>().file->isGood()) {
|
2023-07-24 13:20:53 +02:00
|
|
|
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
|
2024-07-29 20:03:24 +02:00
|
|
|
toxFriendLookupRemove(o);
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
o.remove<
|
|
|
|
ObjComp::Ephemeral::ToxTransferFriend,
|
|
|
|
Components::TFTFile2
|
2023-07-24 13:20:53 +02:00
|
|
|
>();
|
|
|
|
|
2024-07-29 20:03:24 +02:00
|
|
|
//_rmm.throwEventUpdate(o);
|
|
|
|
_os.throwEventUpdate(o);
|
2023-07-24 13:20:53 +02:00
|
|
|
} else {
|
2024-07-29 20:03:24 +02:00
|
|
|
auto& file = o.get<Components::TFTFile2>().file;
|
2024-05-26 18:57:36 +02:00
|
|
|
const auto data = file->read(data_size, position);
|
2024-05-26 21:34:45 +02:00
|
|
|
if (data.empty()) {
|
2024-05-26 18:57:36 +02:00
|
|
|
std::cerr << "TMM error: failed to read file!!\n";
|
|
|
|
return true;
|
|
|
|
}
|
2023-07-24 13:20:53 +02:00
|
|
|
|
2024-05-26 18:57:36 +02:00
|
|
|
// TODO: get rid of the data cast and support spans in the tox api
|
2024-05-26 21:34:45 +02:00
|
|
|
const auto err = _t.toxFileSendChunk(friend_number, file_number, position, static_cast<std::vector<uint8_t>>(data));
|
2023-07-24 13:20:53 +02:00
|
|
|
// TODO: investigate if i need to retry if sendq full
|
|
|
|
if (err == TOX_ERR_FILE_SEND_CHUNK_OK) {
|
2024-07-29 20:03:24 +02:00
|
|
|
o.get_or_emplace<ObjComp::Ephemeral::File::TransferStats>().total_up += data_size;
|
|
|
|
_os.throwEventUpdate(o);
|
2023-07-24 13:20:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|