From 1dee83b01f34c4ea5df62c7c5c88fd06f4bdcf23 Mon Sep 17 00:00:00 2001 From: Green Sky Date: Sun, 15 Jan 2023 01:44:48 +0100 Subject: [PATCH] create sha1_info --- src/CMakeLists.txt | 10 +- src/ft_sha1_info.hpp | 64 +++++++++++++ src/hash_utils.cpp | 26 ++++++ src/hash_utils.hpp | 10 ++ src/send_states/sha1_start.cpp | 48 ---------- src/states/state_send_start_sha1.cpp | 93 +++++++++++++++++++ .../state_send_start_sha1.hpp} | 19 +++- src/tox_client.cpp | 5 +- src/tox_client.hpp | 6 +- 9 files changed, 221 insertions(+), 60 deletions(-) create mode 100644 src/ft_sha1_info.hpp create mode 100644 src/hash_utils.cpp create mode 100644 src/hash_utils.hpp delete mode 100644 src/send_states/sha1_start.cpp create mode 100644 src/states/state_send_start_sha1.cpp rename src/{send_states/sha1_start.hpp => states/state_send_start_sha1.hpp} (81%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d39a3eb..c35fd70 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,6 +13,9 @@ add_executable(tox_ngc_ft1_tool ./tox_utils.hpp ./tox_utils.cpp + ./hash_utils.hpp + ./hash_utils.cpp + ./tox_callbacks.hpp ./tox_callbacks.cpp @@ -21,8 +24,8 @@ add_executable(tox_ngc_ft1_tool ./state.hpp - ./send_states/sha1_start.hpp - ./send_states/sha1_start.cpp + ./states/state_send_start_sha1.hpp + ./states/state_send_start_sha1.cpp ) target_compile_features(tox_ngc_ft1_tool PUBLIC cxx_std_17) @@ -31,5 +34,8 @@ target_link_libraries(tox_ngc_ft1_tool toxcore tox_ngc_ext tox_ngc_ft1 + + mio::mio + sha1::sha1 ) diff --git a/src/ft_sha1_info.hpp b/src/ft_sha1_info.hpp new file mode 100644 index 0000000..67ec05c --- /dev/null +++ b/src/ft_sha1_info.hpp @@ -0,0 +1,64 @@ +#pragma once + +#include +#include +#include +#include +#include + +struct SHA1Digest { + std::array data; + + SHA1Digest(const std::vector& v) { + assert(v.size() == data.size()); + for (size_t i = 0; i < data.size(); i++) { + data[i] = v[i]; + } + } +}; + +struct FTInfoSHA1 { + std::string file_name; + uint64_t file_size {0}; + static constexpr size_t chunk_size {4*1024}; // 4KiB for now + std::vector chunks; + + std::vector toBuffer(void) const { + std::vector buffer; + + assert(!file_name.empty()); + // TODO: optimize + for (size_t i = 0; i < 256; i++) { + if (i < file_name.size()) { + buffer.push_back(file_name.at(i)); + } else { + buffer.push_back(0); + } + } + assert(buffer.size() == 256); + + { // HACK: endianess + buffer.push_back((file_size>>(0*8)) & 0xff); + buffer.push_back((file_size>>(1*8)) & 0xff); + buffer.push_back((file_size>>(2*8)) & 0xff); + buffer.push_back((file_size>>(3*8)) & 0xff); + buffer.push_back((file_size>>(4*8)) & 0xff); + buffer.push_back((file_size>>(5*8)) & 0xff); + buffer.push_back((file_size>>(6*8)) & 0xff); + buffer.push_back((file_size>>(7*8)) & 0xff); + } + assert(buffer.size() == 256+8); + + // chunk size? + + for (const auto& chunk : chunks) { + for (size_t i = 0; i < chunk.data.size(); i++) { + buffer.push_back(chunk.data[i]); + } + } + assert(buffer.size() == 256+8+20*chunks.size()); + + return buffer; + } +}; + diff --git a/src/hash_utils.cpp b/src/hash_utils.cpp new file mode 100644 index 0000000..9039447 --- /dev/null +++ b/src/hash_utils.cpp @@ -0,0 +1,26 @@ +#include "./hash_utils.hpp" + +#include + +// returns the 20bytes sha1 hash +std::vector hash_sha1(const uint8_t* data, size_t size) { + SHA1_CTX ctx; + SHA1Init(&ctx); + + { // lib only takes uint32_t sizes, so chunk it + constexpr size_t hash_block_size {0xffffffff}; + size_t i = 0; + for (; i + hash_block_size < size; i += hash_block_size) { + SHA1Update(&ctx, reinterpret_cast(data) + i, hash_block_size); + } + + if (i < size) { + SHA1Update(&ctx, reinterpret_cast(data) + i, size - i); + } + } + + std::vector sha1_hash(20); + SHA1Final(sha1_hash.data(), &ctx); + return sha1_hash; +} + diff --git a/src/hash_utils.hpp b/src/hash_utils.hpp new file mode 100644 index 0000000..4de52ec --- /dev/null +++ b/src/hash_utils.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include +#include + +// returns the 20bytes sha1 hash +std::vector hash_sha1(const uint8_t* data, size_t size); + +inline std::vector hash_sha1(const char* data, size_t size) { return hash_sha1(reinterpret_cast(data), size); } + diff --git a/src/send_states/sha1_start.cpp b/src/send_states/sha1_start.cpp deleted file mode 100644 index de6a590..0000000 --- a/src/send_states/sha1_start.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#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/states/state_send_start_sha1.cpp b/src/states/state_send_start_sha1.cpp new file mode 100644 index 0000000..101d33a --- /dev/null +++ b/src/states/state_send_start_sha1.cpp @@ -0,0 +1,93 @@ +#include "./state_send_start_sha1.hpp" + +#include "../tox_client.hpp" +#include "../tox_utils.hpp" +#include "../hash_utils.hpp" +#include "../ft_sha1_info.hpp" + +#include + +#include +#include + +namespace States { + +SendStartSHA1::SendStartSHA1(ToxClient& tcl, const CommandLine& cl) : StateI(tcl) { + std::cout << "SendStartSHA1 start building sha1_info\n"; + std::error_code err; + _file_map = mio::make_mmap_source(cl.send_path, 0, mio::map_entire_file, err); + + // TODO: propper error checking + + assert(!_file_map.empty()); + + // build info + _sha1_info.file_name = "testfile.bin"; + _sha1_info.file_size = _file_map.length(); + + { // build chunks + size_t i = 0; + for (; i + FTInfoSHA1::chunk_size < _file_map.length(); i += FTInfoSHA1::chunk_size) { + _sha1_info.chunks.push_back(hash_sha1(_file_map.data()+i, FTInfoSHA1::chunk_size)); + } + + if (i < _file_map.length()) { + _sha1_info.chunks.push_back(hash_sha1(_file_map.data()+i, _file_map.length()-i)); + } + } + + { // unload file and remap (for when the file was large) + _file_map.unmap(); + _file_map = mio::make_mmap_source(cl.send_path, 0, mio::map_entire_file, err); + } + + std::cout << "SHA1Start chunks: " << _sha1_info.chunks.size() << "\n"; + + _sha1_info_data = _sha1_info.toBuffer(); + + std::cout << "SHA1Start sha1_info size: " << _sha1_info_data.size() << "\n"; + + _sha1_info_hash = hash_sha1(_sha1_info_data.data(), _sha1_info_data.size()); + + std::cout << "SHA1Start sha1_info_hash: " << bin2hex(_sha1_info_hash) << "\n"; +} + +bool SendStartSHA1::iterate(void) { + (void)_tcl._tox; + return false; +} + +std::unique_ptr SendStartSHA1::nextState(void) { + return nullptr; +} + +// sha1_info +void SendStartSHA1::onFT1ReceiveRequestSHA1Info(uint32_t, uint32_t, const uint8_t*, size_t) { +} + +bool SendStartSHA1::onFT1ReceiveInitSHA1Info(uint32_t, uint32_t, const uint8_t*, size_t, const uint8_t, const size_t) { + return false; +} + +void SendStartSHA1::onFT1ReceiveDataSHA1Info(uint32_t, uint32_t, uint8_t, size_t, const uint8_t*, size_t) { +} + +void SendStartSHA1::onFT1SendDataSHA1Info(uint32_t, uint32_t, uint8_t, size_t, uint8_t*, size_t) { +} + +// sha1_chunk +void SendStartSHA1::onFT1ReceiveRequestSHA1Chunk(uint32_t, uint32_t, const uint8_t*, size_t) { +} + +bool SendStartSHA1::onFT1ReceiveInitSHA1Chunk(uint32_t, uint32_t, const uint8_t*, size_t, const uint8_t, const size_t) { + return false; +} + +void SendStartSHA1::onFT1ReceiveDataSHA1Chunk(uint32_t, uint32_t, uint8_t, size_t, const uint8_t*, size_t) { +} + +void SendStartSHA1::onFT1SendDataSHA1Chunk(uint32_t, uint32_t, uint8_t, size_t, uint8_t*, size_t) { +} + +} // States + diff --git a/src/send_states/sha1_start.hpp b/src/states/state_send_start_sha1.hpp similarity index 81% rename from src/send_states/sha1_start.hpp rename to src/states/state_send_start_sha1.hpp index 3b99565..de29f06 100644 --- a/src/send_states/sha1_start.hpp +++ b/src/states/state_send_start_sha1.hpp @@ -3,15 +3,18 @@ #include "../state.hpp" #include "../command_line.hpp" +#include "../ft_sha1_info.hpp" -namespace SendStates { +#include + +namespace States { // we are hashing the given file // does not react to any ft events -struct SHA1Start final : public StateI { +struct SendStartSHA1 final : public StateI { public: // general interface - SHA1Start(ToxClient& tcl, const CommandLine& cl); - ~SHA1Start(void) override = default; + SendStartSHA1(ToxClient& tcl, const CommandLine& cl); + ~SendStartSHA1(void) override = default; bool iterate(void) override; std::unique_ptr nextState(void) override; @@ -28,7 +31,13 @@ struct SHA1Start final : public StateI { 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; + + private: + mio::mmap_source _file_map; + FTInfoSHA1 _sha1_info; + std::vector _sha1_info_data; + std::vector _sha1_info_hash; }; -} // SendStates +} // States diff --git a/src/tox_client.cpp b/src/tox_client.cpp index 9fde51c..405a79a 100644 --- a/src/tox_client.cpp +++ b/src/tox_client.cpp @@ -2,7 +2,8 @@ #include "./tox_utils.hpp" #include "./tox_callbacks.hpp" -#include "send_states/sha1_start.hpp" + +#include "./states/state_send_start_sha1.hpp" #include #include @@ -124,7 +125,7 @@ ToxClient::ToxClient(const CommandLine& cl) : { // state factory // TODO: extract // sender if (!cl.send_path.empty()) { - _state = std::make_unique(*this, cl); + _state = std::make_unique(*this, cl); } else { // receiver } } diff --git a/src/tox_client.hpp b/src/tox_client.hpp index e4117a9..e927fdb 100644 --- a/src/tox_client.hpp +++ b/src/tox_client.hpp @@ -13,8 +13,8 @@ #include // fwd -namespace SendStates { - struct SHA1Start; +namespace States { + struct SendStartSHA1; } struct ToxClient { @@ -71,6 +71,6 @@ struct ToxClient { std::unique_ptr _state; // TODO: this is a hack, make better? - friend SendStates::SHA1Start; + friend States::SendStartSHA1; };