From 3e0100efdf33e4fe54c0ad1ea02b8d43ba15512b Mon Sep 17 00:00:00 2001 From: Green Sky Date: Sun, 15 Jan 2023 20:15:48 +0100 Subject: [PATCH] refactoring + sha1_info should be requestable --- src/state.hpp | 2 +- src/states/send_start_sha1.cpp | 2 +- src/states/send_start_sha1.hpp | 2 +- src/states/sha1.cpp | 86 +++++++++++++++++++++++++++++++++- src/states/sha1.hpp | 18 +++++-- src/tox_client.cpp | 40 +++++----------- src/tox_client.hpp | 14 +----- 7 files changed, 115 insertions(+), 49 deletions(-) diff --git a/src/state.hpp b/src/state.hpp index bf9d56f..b84a474 100644 --- a/src/state.hpp +++ b/src/state.hpp @@ -11,7 +11,7 @@ struct StateI { virtual ~StateI(void) = default; // returns true if we should call nextState() - virtual bool iterate(void) = 0; + virtual bool iterate(float delta) = 0; // returns the new state (transition) virtual std::unique_ptr nextState(void) = 0; diff --git a/src/states/send_start_sha1.cpp b/src/states/send_start_sha1.cpp index e106c33..cb17499 100644 --- a/src/states/send_start_sha1.cpp +++ b/src/states/send_start_sha1.cpp @@ -56,7 +56,7 @@ SendStartSHA1::SendStartSHA1(ToxClient& tcl, const CommandLine& cl) : StateI(tcl std::cout << "SendStartSHA1 sha1_info_hash: " << bin2hex(_sha1_info_hash) << "\n"; } -bool SendStartSHA1::iterate(void) { +bool SendStartSHA1::iterate(float) { return true; // TODO: change hashing to async } diff --git a/src/states/send_start_sha1.hpp b/src/states/send_start_sha1.hpp index de29f06..18e5370 100644 --- a/src/states/send_start_sha1.hpp +++ b/src/states/send_start_sha1.hpp @@ -16,7 +16,7 @@ struct SendStartSHA1 final : public StateI { SendStartSHA1(ToxClient& tcl, const CommandLine& cl); ~SendStartSHA1(void) override = default; - bool iterate(void) override; + bool iterate(float delta) override; std::unique_ptr nextState(void) override; public: // callbacks diff --git a/src/states/sha1.cpp b/src/states/sha1.cpp index 841eac5..b9fa5ff 100644 --- a/src/states/sha1.cpp +++ b/src/states/sha1.cpp @@ -1,5 +1,7 @@ #include "./sha1.hpp" +#include "../tox_client.hpp" + #include namespace States { @@ -28,7 +30,52 @@ SHA1::SHA1( } } -bool SHA1::iterate(void) { +bool SHA1::iterate(float delta) { + // do ongoing transfers, send data?, timeout + // info + for (auto it = _transfers_requested_info.begin(); it != _transfers_requested_info.end();) { + float& time_since_remove_activity = std::get(*it); + time_since_remove_activity += delta; + + // if we have not heard for 10sec, timeout + if (time_since_remove_activity >= 10.f) { + std::cerr << "SHA1 info tansfer timed out " << std::get<0>(*it) << ":" << std::get<1>(*it) << "." << std::get<2>(*it) << "\n"; + it = _transfers_requested_info.erase(it); + } else { + it++; + } + } + + // if we have not reached the total cap for transfers + if (true) { + // for each peer? transfer cap per peer? + + // first check requests for info + if (!_queue_requested_info.empty()) { + // send init to _queue_requested_info + const auto [group_number, peer_number] = _queue_requested_info.front(); + + uint8_t transfer_id {0}; + + _tcl.sendFT1InitPrivate( + group_number, peer_number, + NGC_FT1_file_kind::HASH_SHA1_INFO, + _sha1_info_hash.data.data(), _sha1_info_hash.size(), // id (info hash) + _sha1_info_data.size(), // "file_size" + transfer_id + ); + + _transfers_requested_info.push_back({ + group_number, peer_number, + transfer_id, + 0.f + }); + + _queue_requested_info.pop_front(); + } else if (false) { // then check for chunk requests + } + } + // TODO: unmap and remap the file every couple of minutes to keep ram usage down? // TODO: when to stop? return false; @@ -54,6 +101,9 @@ void SHA1::onFT1ReceiveRequestSHA1Info(uint32_t group_number, uint32_t peer_numb // same hash, should respond // prio higher then chunks? + + // add to requested queue + queueUpRequestInfo(group_number, peer_number); } bool SHA1::onFT1ReceiveInitSHA1Info(uint32_t, uint32_t, const uint8_t*, size_t, const uint8_t, const size_t) { @@ -63,6 +113,7 @@ bool SHA1::onFT1ReceiveInitSHA1Info(uint32_t, uint32_t, const uint8_t*, size_t, void SHA1::onFT1ReceiveDataSHA1Info(uint32_t, uint32_t, uint8_t, size_t, const uint8_t*, size_t) { // no, in this state we have init + assert(false && "ft should have said dropped this for us!"); } void SHA1::onFT1SendDataSHA1Info(uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, uint8_t* data, size_t data_size) { @@ -74,7 +125,18 @@ void SHA1::onFT1SendDataSHA1Info(uint32_t group_number, uint32_t peer_number, ui for (size_t i = 0; i < data_size; i++) { data[i] = _sha1_info_data.at(data_offset+i); } - // knowing when to end might be important + + // if last data block + if (data_offset + data_size == _sha1_info_data.size()) { + // this transfer is "done" (ft still could have to retransfer) + for (auto it = _transfers_requested_info.cbegin(); it != _transfers_requested_info.cend(); it++) { + if (std::get<0>(*it) == group_number && std::get<1>(*it) == peer_number && std::get<2>(*it) == transfer_id) { + std::cout << "SHA1 info tansfer finished " << std::get<0>(*it) << ":" << std::get<1>(*it) << "." << std::get<2>(*it) << "\n"; + _transfers_requested_info.erase(it); + break; + } + } + } } // sha1_chunk @@ -99,5 +161,25 @@ void SHA1::onFT1ReceiveDataSHA1Chunk(uint32_t group_number, uint32_t peer_number void SHA1::onFT1SendDataSHA1Chunk(uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, uint8_t* data, size_t data_size) { } +void SHA1::queueUpRequestInfo(uint32_t group_number, uint32_t peer_number) { + // check ongoing transfers for dup + for (const auto& it : _transfers_requested_info) { + // if allready in queue + if (std::get<0>(it) == group_number && std::get<1>(it) == peer_number) { + return; + } + } + + for (auto& [i_g, i_p] : _queue_requested_info) { + // if allready in queue + if (i_g == group_number && i_p == peer_number) { + return; + } + } + + // not in queue yet + _queue_requested_info.push_back(std::make_pair(group_number, peer_number)); +} + } // States diff --git a/src/states/sha1.hpp b/src/states/sha1.hpp index 29a768b..9d79224 100644 --- a/src/states/sha1.hpp +++ b/src/states/sha1.hpp @@ -5,7 +5,9 @@ #include "../ft_sha1_info.hpp" #include -#include + +#include +#include namespace States { @@ -19,11 +21,11 @@ struct SHA1 final : public StateI { const FTInfoSHA1&& sha1_info, const std::vector&& sha1_info_data, const std::vector&& sha1_info_hash, - std::vector&& have_chunk = {} + std::vector&& have_chunk ); ~SHA1(void) override = default; - bool iterate(void) override; + bool iterate(float delta) override; std::unique_ptr nextState(void) override; public: // callbacks @@ -39,6 +41,11 @@ struct SHA1 final : public StateI { void onFT1ReceiveDataSHA1Chunk(uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, const uint8_t* data, size_t data_size) override; void onFT1SendDataSHA1Chunk(uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, uint8_t* data, size_t data_size) override; + private: + // avoids duplicates + // clears timer if exists + void queueUpRequestInfo(uint32_t group_number, uint32_t peer_number); + private: mio::mmap_source _file_map; const FTInfoSHA1 _sha1_info; @@ -48,6 +55,11 @@ struct SHA1 final : public StateI { // index is the same as for info std::vector _have_chunk; bool _have_all {false}; + + // group_number, peer_number + std::deque> _queue_requested_info; + // group_number, peer_number, transfer_id, second since (remote) activity + std::vector> _transfers_requested_info; }; } // States diff --git a/src/tox_client.cpp b/src/tox_client.cpp index 8e83da8..a5c3e93 100644 --- a/src/tox_client.cpp +++ b/src/tox_client.cpp @@ -174,7 +174,8 @@ bool ToxClient::iterate(void) { tox_iterate(_tox, this); NGC_FT1_iterate(_tox, _ft1_ctx); - if (_state->iterate()) { + // HACK: hardcoded 5ms sleep in main + if (_state->iterate(0.005f)) { _state = _state->nextState(); if (!_state) { @@ -254,36 +255,17 @@ StateI& ToxClient::getState(void) { return *_state.get(); } -#if 0 -// sha1_info -void ToxClient::onFT1ReceiveRequestSHA1Info(uint32_t group_number, uint32_t peer_number, const uint8_t* file_id, size_t file_id_size) { +bool ToxClient::sendFT1InitPrivate(uint32_t group_number, uint32_t peer_number, NGC_FT1_file_kind file_kind, const uint8_t* file_id, size_t file_id_size, uint64_t file_size, uint8_t& transfer_id) { + return NGC_FT1_send_init_private( + _tox, _ft1_ctx, + group_number, peer_number, + file_kind, + file_id, file_id_size, + file_size, + &transfer_id + ); } -bool ToxClient::onFT1ReceiveInitSHA1Info(uint32_t group_number, uint32_t peer_number, const uint8_t* file_id, size_t file_id_size, const uint8_t transfer_id, const size_t file_size) { - return false; // deny -} - -void ToxClient::onFT1ReceiveDataSHA1Info(uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, const uint8_t* data, size_t data_size) { -} - -void ToxClient::onFT1SendDataSHA1Info(uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, uint8_t* data, size_t data_size) { -} - -// sha1_chunk -void ToxClient::onFT1ReceiveRequestSHA1Chunk(uint32_t group_number, uint32_t peer_number, const uint8_t* file_id, size_t file_id_size) { -} - -bool ToxClient::onFT1ReceiveInitSHA1Chunk(uint32_t group_number, uint32_t peer_number, const uint8_t* file_id, size_t file_id_size, const uint8_t transfer_id, const size_t file_size) { - return false; // deny -} - -void ToxClient::onFT1ReceiveDataSHA1Chunk(uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, const uint8_t* data, size_t data_size) { -} - -void ToxClient::onFT1SendDataSHA1Chunk(uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, uint8_t* data, size_t data_size) { -} -#endif - void ToxClient::saveToxProfile(void) { if (_tox_profile_path.empty()) { return; diff --git a/src/tox_client.hpp b/src/tox_client.hpp index e927fdb..8bcd5b1 100644 --- a/src/tox_client.hpp +++ b/src/tox_client.hpp @@ -41,19 +41,9 @@ struct ToxClient { public: // FT1 callbacks StateI& getState(void); // public accessor for callbacks -#if 0 - // sha1_info - void onFT1ReceiveRequestSHA1Info(uint32_t group_number, uint32_t peer_number, const uint8_t* file_id, size_t file_id_size); - bool onFT1ReceiveInitSHA1Info(uint32_t group_number, uint32_t peer_number, const uint8_t* file_id, size_t file_id_size, const uint8_t transfer_id, const size_t file_size); - void onFT1ReceiveDataSHA1Info(uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, const uint8_t* data, size_t data_size); - void onFT1SendDataSHA1Info(uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, uint8_t* data, size_t data_size); - // sha1_chunk - void onFT1ReceiveRequestSHA1Chunk(uint32_t group_number, uint32_t peer_number, const uint8_t* file_id, size_t file_id_size); - bool onFT1ReceiveInitSHA1Chunk(uint32_t group_number, uint32_t peer_number, const uint8_t* file_id, size_t file_id_size, const uint8_t transfer_id, const size_t file_size); - void onFT1ReceiveDataSHA1Chunk(uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, const uint8_t* data, size_t data_size); - void onFT1SendDataSHA1Chunk(uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, uint8_t* data, size_t data_size); -#endif + public: // FT1 sends + bool sendFT1InitPrivate(uint32_t group_number, uint32_t peer_number, NGC_FT1_file_kind file_kind, const uint8_t* file_id, size_t file_id_size, uint64_t file_size, uint8_t& transfer_id); private: void saveToxProfile(void);