From 8970512160117116ee3e2f1fdc37a7373c862a95 Mon Sep 17 00:00:00 2001 From: Green Sky Date: Sat, 14 Jan 2023 23:18:10 +0100 Subject: [PATCH] states + refactoring --- src/CMakeLists.txt | 5 +++ src/command_line.cpp | 67 ++++++++++++++++++++-------------- src/command_line.hpp | 15 ++++++-- src/main.cpp | 3 +- src/send_states/sha1_start.cpp | 48 ++++++++++++++++++++++++ src/send_states/sha1_start.hpp | 34 +++++++++++++++++ src/state.hpp | 34 +++++++++++++++++ src/tox_callbacks.cpp | 16 ++++---- src/tox_client.cpp | 35 +++++++++++++++--- src/tox_client.hpp | 21 ++++++++++- 10 files changed, 230 insertions(+), 48 deletions(-) create mode 100644 src/send_states/sha1_start.cpp create mode 100644 src/send_states/sha1_start.hpp create mode 100644 src/state.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e0a1374..d39a3eb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,6 +18,11 @@ add_executable(tox_ngc_ft1_tool ./tox_client.hpp ./tox_client.cpp + + ./state.hpp + + ./send_states/sha1_start.hpp + ./send_states/sha1_start.cpp ) target_compile_features(tox_ngc_ft1_tool PUBLIC cxx_std_17) diff --git a/src/command_line.cpp b/src/command_line.cpp index d4ed932..93b4ea0 100644 --- a/src/command_line.cpp +++ b/src/command_line.cpp @@ -11,6 +11,8 @@ CommandLine::CommandLine(int argc, char** argv) { for (int i = 1; i < argc; i++) { std::string_view arg_sv{argv[i]}; +#define PRINT_HELP_AND_BAIL printHelp(); _should_exit = true; return; + if (arg_sv == "-v") { version = true; _should_exit = true; @@ -22,59 +24,68 @@ CommandLine::CommandLine(int argc, char** argv) { _should_exit = true; } else if (arg_sv == "-G") { if (i+1 >= argc) { - std::cerr << "-G missing parameter!\n\n"; - printHelp(); - _should_exit = true; - return; + std::cerr << "ERROR: -G missing parameter!\n\n"; + PRINT_HELP_AND_BAIL; } chat_id = argv[++i]; } else if (arg_sv == "-F") { if (i+1 >= argc) { - std::cerr << "-F missing parameter!\n\n"; - printHelp(); - _should_exit = true; - return; + std::cerr << "ERROR: -F missing parameter!\n\n"; + PRINT_HELP_AND_BAIL; } profile_path = argv[++i]; } else if (arg_sv == "-N") { if (i+1 >= argc) { - std::cerr << "-N missing parameter!\n\n"; - printHelp(); - _should_exit = true; - return; + std::cerr << "ERROR: -N missing parameter!\n\n"; + PRINT_HELP_AND_BAIL; } self_name = argv[++i]; } else if (arg_sv == "-a") { + if (i+1 >= argc) { + std::cerr << "ERROR: -a missing parameter!\n\n"; + PRINT_HELP_AND_BAIL; + } + std::string_view tv_sv{argv[++i]}; + + if (tv_sv == "id1") { + transfer_variant = TransferE::ID; + } else if (tv_sv == "sha1_single") { + transfer_variant = TransferE::SHA1_SINGLE; + } else if (tv_sv == "sha1_info") { + transfer_variant = TransferE::SHA1_INFO; + } else { + std::cerr << "ERROR: invalid parameter!\n\n"; + PRINT_HELP_AND_BAIL; + } + } else if (arg_sv == "-f") { if (i+1 >= argc) { - std::cerr << "-f missing parameter!\n\n"; - printHelp(); - _should_exit = true; - return; + std::cerr << "ERROR: -f missing parameter!\n\n"; + PRINT_HELP_AND_BAIL; } send_path = argv[++i]; } else if (arg_sv == "-d") { if (i+1 >= argc) { - std::cerr << "-d missing parameter!\n\n"; - printHelp(); - _should_exit = true; - return; + std::cerr << "ERROR: -d missing parameter!\n\n"; + PRINT_HELP_AND_BAIL; } receive_dump_dir = argv[++i]; } else if (arg_sv == "-D") { if (i+1 >= argc) { - std::cerr << "-D missing parameter!\n\n"; - printHelp(); - _should_exit = true; - return; + std::cerr << "ERROR: -D missing parameter!\n\n"; + PRINT_HELP_AND_BAIL; } receive_id = argv[++i]; } else { - std::cerr << "unknown parameter '" << arg_sv << "' !\n\n"; - printHelp(); - _should_exit = true; + std::cerr << "ERROR: unknown parameter '" << arg_sv << "' !\n\n"; + PRINT_HELP_AND_BAIL; } } + + if (transfer_variant == TransferE::INVALID) { + std::cerr << "ERROR: transfer_variant not set!\n\n"; + PRINT_HELP_AND_BAIL; + } } void CommandLine::printHelp(void) { @@ -95,7 +106,7 @@ void CommandLine::printHelp(void) { << " if profile exists load, otherwise create new\n" << "\n" << " transfer variant:\n" - << " -a id1/sha128_single/sha128_info/sha256_single/sha256_info\n" + << " -a id1/sha1_single/sha1_info/sha2_single/sha2_info\n" << "\n" << " send:\n" << " -f send_this_file.zip\n" diff --git a/src/command_line.hpp b/src/command_line.hpp index 14ddce5..ebea48c 100644 --- a/src/command_line.hpp +++ b/src/command_line.hpp @@ -17,7 +17,7 @@ // if profile exists load, otherwise create new // // transfer variant: -// -a id1/sha128_single/sha128_info/sha256_single/sha256_info +// -a id1/sha1_single/sha1_info/sha2_single/sha2_info // // send: // -f send_this_file.zip @@ -26,6 +26,15 @@ // -d dump/everything/in/this/dir // -D (what to dl) +enum class TransferE { + INVALID, + + ID, + SHA1_SINGLE, // a single chunk (no filename is transfered) + SHA1_INFO, + //... +}; + struct CommandLine { std::string exe; @@ -46,8 +55,8 @@ struct CommandLine { std::string self_name {"tox_ngc_tf1_tool"}; // transfer variant: - // -a id1/sha128_single/sha128_info/sha256_single/sha256_info - // some enum? + // -a id1/sha1_single/sha1_info/sha2_single/sha2_info + TransferE transfer_variant {TransferE::INVALID}; // send: // -f send_this_file.zip diff --git a/src/main.cpp b/src/main.cpp index e25fc50..2af1147 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,8 +23,7 @@ int main(int argc, char** argv) { std::cout << "tox id: " << client.getOwnAddress() << "\n"; - while (true) { - client.iterate(); + while (client.iterate()) { std::this_thread::sleep_for(std::chrono::milliseconds(5)); } diff --git a/src/send_states/sha1_start.cpp b/src/send_states/sha1_start.cpp new file mode 100644 index 0000000..de6a590 --- /dev/null +++ b/src/send_states/sha1_start.cpp @@ -0,0 +1,48 @@ +#include "./sha1_start.hpp" + +#include "../tox_client.hpp" + +namespace SendStates { + +SHA1Start::SHA1Start(ToxClient& tcl, const CommandLine& cl) : StateI(tcl) { +} + +bool SHA1Start::iterate(void) { + _tcl._tox; + return false; +} + +std::unique_ptr SHA1Start::nextState(void) { + return nullptr; +} + +// sha1_info +void SHA1Start::onFT1ReceiveRequestSHA1Info(uint32_t, uint32_t, const uint8_t*, size_t) { +} + +bool SHA1Start::onFT1ReceiveInitSHA1Info(uint32_t, uint32_t, const uint8_t*, size_t, const uint8_t, const size_t) { + return false; +} + +void SHA1Start::onFT1ReceiveDataSHA1Info(uint32_t, uint32_t, uint8_t, size_t, const uint8_t*, size_t) { +} + +void SHA1Start::onFT1SendDataSHA1Info(uint32_t, uint32_t, uint8_t, size_t, uint8_t*, size_t) { +} + +// sha1_chunk +void SHA1Start::onFT1ReceiveRequestSHA1Chunk(uint32_t, uint32_t, const uint8_t*, size_t) { +} + +bool SHA1Start::onFT1ReceiveInitSHA1Chunk(uint32_t, uint32_t, const uint8_t*, size_t, const uint8_t, const size_t) { + return false; +} + +void SHA1Start::onFT1ReceiveDataSHA1Chunk(uint32_t, uint32_t, uint8_t, size_t, const uint8_t*, size_t) { +} + +void SHA1Start::onFT1SendDataSHA1Chunk(uint32_t, uint32_t, uint8_t, size_t, uint8_t*, size_t) { +} + +} // SendStates + diff --git a/src/send_states/sha1_start.hpp b/src/send_states/sha1_start.hpp new file mode 100644 index 0000000..3b99565 --- /dev/null +++ b/src/send_states/sha1_start.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "../state.hpp" + +#include "../command_line.hpp" + +namespace SendStates { + +// we are hashing the given file +// does not react to any ft events +struct SHA1Start final : public StateI { + public: // general interface + SHA1Start(ToxClient& tcl, const CommandLine& cl); + ~SHA1Start(void) override = default; + + bool iterate(void) override; + std::unique_ptr nextState(void) override; + + public: // callbacks + // sha1_info + void onFT1ReceiveRequestSHA1Info(uint32_t group_number, uint32_t peer_number, const uint8_t* file_id, size_t file_id_size) override; + 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) override; + 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) override; + 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) override; + + // sha1_chunk + void onFT1ReceiveRequestSHA1Chunk(uint32_t group_number, uint32_t peer_number, const uint8_t* file_id, size_t file_id_size) override; + 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) override; + 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; +}; + +} // SendStates + diff --git a/src/state.hpp b/src/state.hpp new file mode 100644 index 0000000..bf9d56f --- /dev/null +++ b/src/state.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include + +// fwd +struct ToxClient; + +struct StateI { + public: // general interface + StateI(ToxClient& tcl) : _tcl(tcl) {} + virtual ~StateI(void) = default; + + // returns true if we should call nextState() + virtual bool iterate(void) = 0; + // returns the new state (transition) + virtual std::unique_ptr nextState(void) = 0; + + public: // callbacks + // sha1_info + virtual void onFT1ReceiveRequestSHA1Info(uint32_t group_number, uint32_t peer_number, const uint8_t* file_id, size_t file_id_size) = 0; + virtual 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) = 0; + virtual 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) = 0; + virtual 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) = 0; + + // sha1_chunk + virtual void onFT1ReceiveRequestSHA1Chunk(uint32_t group_number, uint32_t peer_number, const uint8_t* file_id, size_t file_id_size) = 0; + virtual 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) = 0; + virtual 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) = 0; + virtual 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) = 0; + + protected: + ToxClient& _tcl; +}; + diff --git a/src/tox_callbacks.cpp b/src/tox_callbacks.cpp index 6ec94ac..59aabb1 100644 --- a/src/tox_callbacks.cpp +++ b/src/tox_callbacks.cpp @@ -48,36 +48,36 @@ void group_self_join_cb(Tox*, uint32_t group_number, void *user_data) { // ==================== sha1_info ==================== void ft1_recv_request_sha1_info_cb(Tox*, uint32_t group_number, uint32_t peer_number, const uint8_t* file_id, size_t file_id_size, void* user_data) { - static_cast(user_data)->onFT1ReceiveRequestSHA1Info(group_number, peer_number, file_id, file_id_size); + static_cast(user_data)->getState().onFT1ReceiveRequestSHA1Info(group_number, peer_number, file_id, file_id_size); } bool ft1_recv_init_sha1_info_cb(Tox*, 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* user_data) { - return static_cast(user_data)->onFT1ReceiveInitSHA1Info(group_number, peer_number, file_id, file_id_size, transfer_id, file_size); + return static_cast(user_data)->getState().onFT1ReceiveInitSHA1Info(group_number, peer_number, file_id, file_id_size, transfer_id, file_size); } void ft1_recv_data_sha1_info_cb(Tox*, 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* user_data) { - static_cast(user_data)->onFT1ReceiveDataSHA1Info(group_number, peer_number, transfer_id, data_offset, data, data_size); + static_cast(user_data)->getState().onFT1ReceiveDataSHA1Info(group_number, peer_number, transfer_id, data_offset, data, data_size); } void ft1_send_data_sha1_info_cb(Tox*, uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, uint8_t* data, size_t data_size, void* user_data) { - static_cast(user_data)->onFT1SendDataSHA1Info(group_number, peer_number, transfer_id, data_offset, data, data_size); + static_cast(user_data)->getState().onFT1SendDataSHA1Info(group_number, peer_number, transfer_id, data_offset, data, data_size); } // ==================== sha1_chunk ==================== void ft1_recv_request_sha1_chunk_cb(Tox*, uint32_t group_number, uint32_t peer_number, const uint8_t* file_id, size_t file_id_size, void* user_data) { - static_cast(user_data)->onFT1ReceiveRequestSHA1Chunk(group_number, peer_number, file_id, file_id_size); + static_cast(user_data)->getState().onFT1ReceiveRequestSHA1Chunk(group_number, peer_number, file_id, file_id_size); } bool ft1_recv_init_sha1_chunk_cb(Tox*, 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* user_data) { - return static_cast(user_data)->onFT1ReceiveInitSHA1Chunk(group_number, peer_number, file_id, file_id_size, transfer_id, file_size); + return static_cast(user_data)->getState().onFT1ReceiveInitSHA1Chunk(group_number, peer_number, file_id, file_id_size, transfer_id, file_size); } void ft1_recv_data_sha1_chunk_cb(Tox*, 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* user_data) { - static_cast(user_data)->onFT1ReceiveDataSHA1Chunk(group_number, peer_number, transfer_id, data_offset, data, data_size); + static_cast(user_data)->getState().onFT1ReceiveDataSHA1Chunk(group_number, peer_number, transfer_id, data_offset, data, data_size); } void ft1_send_data_sha1_chunk_cb(Tox*, uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, uint8_t* data, size_t data_size, void* user_data) { - static_cast(user_data)->onFT1SendDataSHA1Chunk(group_number, peer_number, transfer_id, data_offset, data, data_size); + static_cast(user_data)->getState().onFT1SendDataSHA1Chunk(group_number, peer_number, transfer_id, data_offset, data, data_size); } diff --git a/src/tox_client.cpp b/src/tox_client.cpp index c4bf33d..9fde51c 100644 --- a/src/tox_client.cpp +++ b/src/tox_client.cpp @@ -2,11 +2,9 @@ #include "./tox_utils.hpp" #include "./tox_callbacks.hpp" -#include "ngc_ext.h" -#include "ngc_ft1.h" - -#include +#include "send_states/sha1_start.hpp" +#include #include #include @@ -123,6 +121,14 @@ ToxClient::ToxClient(const CommandLine& cl) : NGC_FT1_register_callback_recv_data(_ft1_ctx, NGC_FT1_file_kind::HASH_SHA1_CHUNK, ft1_recv_data_sha1_chunk_cb, this); NGC_FT1_register_callback_send_data(_ft1_ctx, NGC_FT1_file_kind::HASH_SHA1_CHUNK, ft1_send_data_sha1_chunk_cb, this); + { // state factory // TODO: extract + // sender + if (!cl.send_path.empty()) { + _state = std::make_unique(*this, cl); + } else { // receiver + } + } + // dht bootstrap { struct DHT_node { @@ -163,13 +169,24 @@ ToxClient::~ToxClient(void) { tox_kill(_tox); } -void ToxClient::iterate(void) { +bool ToxClient::iterate(void) { tox_iterate(_tox, this); NGC_FT1_iterate(_tox, _ft1_ctx); + if (_state->iterate()) { + _state = _state->nextState(); + + if (!_state) { + // exit program + return false; + } + } + if (_tox_profile_dirty) { saveToxProfile(); } + + return true; } std::string ToxClient::getOwnAddress(void) const { @@ -230,6 +247,13 @@ void ToxClient::onToxGroupSelfJoin(uint32_t group_number) { _tox_profile_dirty = true; } + +StateI& ToxClient::getState(void) { + assert(_state.get()); + 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) { } @@ -257,6 +281,7 @@ void ToxClient::onFT1ReceiveDataSHA1Chunk(uint32_t group_number, uint32_t peer_n 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()) { diff --git a/src/tox_client.hpp b/src/tox_client.hpp index 771a323..e4117a9 100644 --- a/src/tox_client.hpp +++ b/src/tox_client.hpp @@ -2,19 +2,28 @@ #include "./command_line.hpp" -#include +#include "./state.hpp" + +#include #include #include #include #include +#include + +// fwd +namespace SendStates { + struct SHA1Start; +} struct ToxClient { public: ToxClient(const CommandLine& cl); ~ToxClient(void); - void iterate(void); + // returns false when we shoul stop the program + bool iterate(void); void setToxProfilePath(const std::string& new_path) { _tox_profile_path = new_path; } @@ -31,6 +40,8 @@ struct ToxClient { void onToxGroupSelfJoin(uint32_t group_number); 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); @@ -42,6 +53,7 @@ struct ToxClient { 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 private: void saveToxProfile(void); @@ -55,5 +67,10 @@ struct ToxClient { std::string _tox_profile_path; bool _tox_profile_dirty {false}; // set in callbacks + + std::unique_ptr _state; + + // TODO: this is a hack, make better? + friend SendStates::SHA1Start; };