create sha1_info

This commit is contained in:
Green Sky 2023-01-15 01:44:48 +01:00
parent e251a3ce51
commit 1dee83b01f
No known key found for this signature in database
9 changed files with 221 additions and 60 deletions

View File

@ -13,6 +13,9 @@ add_executable(tox_ngc_ft1_tool
./tox_utils.hpp ./tox_utils.hpp
./tox_utils.cpp ./tox_utils.cpp
./hash_utils.hpp
./hash_utils.cpp
./tox_callbacks.hpp ./tox_callbacks.hpp
./tox_callbacks.cpp ./tox_callbacks.cpp
@ -21,8 +24,8 @@ add_executable(tox_ngc_ft1_tool
./state.hpp ./state.hpp
./send_states/sha1_start.hpp ./states/state_send_start_sha1.hpp
./send_states/sha1_start.cpp ./states/state_send_start_sha1.cpp
) )
target_compile_features(tox_ngc_ft1_tool PUBLIC cxx_std_17) target_compile_features(tox_ngc_ft1_tool PUBLIC cxx_std_17)
@ -31,5 +34,8 @@ target_link_libraries(tox_ngc_ft1_tool
toxcore toxcore
tox_ngc_ext tox_ngc_ext
tox_ngc_ft1 tox_ngc_ft1
mio::mio
sha1::sha1
) )

64
src/ft_sha1_info.hpp Normal file
View File

@ -0,0 +1,64 @@
#pragma once
#include <cstdint>
#include <array>
#include <vector>
#include <cassert>
#include <string>
struct SHA1Digest {
std::array<uint8_t, 20> data;
SHA1Digest(const std::vector<uint8_t>& 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<SHA1Digest> chunks;
std::vector<uint8_t> toBuffer(void) const {
std::vector<uint8_t> 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;
}
};

26
src/hash_utils.cpp Normal file
View File

@ -0,0 +1,26 @@
#include "./hash_utils.hpp"
#include <sha1.h>
// returns the 20bytes sha1 hash
std::vector<uint8_t> 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<const uint8_t*>(data) + i, hash_block_size);
}
if (i < size) {
SHA1Update(&ctx, reinterpret_cast<const uint8_t*>(data) + i, size - i);
}
}
std::vector<uint8_t> sha1_hash(20);
SHA1Final(sha1_hash.data(), &ctx);
return sha1_hash;
}

10
src/hash_utils.hpp Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include <cstdint>
#include <vector>
// returns the 20bytes sha1 hash
std::vector<uint8_t> hash_sha1(const uint8_t* data, size_t size);
inline std::vector<uint8_t> hash_sha1(const char* data, size_t size) { return hash_sha1(reinterpret_cast<const uint8_t*>(data), size); }

View File

@ -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<StateI> 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

View File

@ -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 <mio/mio.hpp>
#include <iostream>
#include <cassert>
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<StateI> 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

View File

@ -3,15 +3,18 @@
#include "../state.hpp" #include "../state.hpp"
#include "../command_line.hpp" #include "../command_line.hpp"
#include "../ft_sha1_info.hpp"
namespace SendStates { #include <mio/mio.hpp>
namespace States {
// we are hashing the given file // we are hashing the given file
// does not react to any ft events // does not react to any ft events
struct SHA1Start final : public StateI { struct SendStartSHA1 final : public StateI {
public: // general interface public: // general interface
SHA1Start(ToxClient& tcl, const CommandLine& cl); SendStartSHA1(ToxClient& tcl, const CommandLine& cl);
~SHA1Start(void) override = default; ~SendStartSHA1(void) override = default;
bool iterate(void) override; bool iterate(void) override;
std::unique_ptr<StateI> nextState(void) override; std::unique_ptr<StateI> 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; 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 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; 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<uint8_t> _sha1_info_data;
std::vector<uint8_t> _sha1_info_hash;
}; };
} // SendStates } // States

View File

@ -2,7 +2,8 @@
#include "./tox_utils.hpp" #include "./tox_utils.hpp"
#include "./tox_callbacks.hpp" #include "./tox_callbacks.hpp"
#include "send_states/sha1_start.hpp"
#include "./states/state_send_start_sha1.hpp"
#include <memory> #include <memory>
#include <sodium.h> #include <sodium.h>
@ -124,7 +125,7 @@ ToxClient::ToxClient(const CommandLine& cl) :
{ // state factory // TODO: extract { // state factory // TODO: extract
// sender // sender
if (!cl.send_path.empty()) { if (!cl.send_path.empty()) {
_state = std::make_unique<SendStates::SHA1Start>(*this, cl); _state = std::make_unique<States::SendStartSHA1>(*this, cl);
} else { // receiver } else { // receiver
} }
} }

View File

@ -13,8 +13,8 @@
#include <string_view> #include <string_view>
// fwd // fwd
namespace SendStates { namespace States {
struct SHA1Start; struct SendStartSHA1;
} }
struct ToxClient { struct ToxClient {
@ -71,6 +71,6 @@ struct ToxClient {
std::unique_ptr<StateI> _state; std::unique_ptr<StateI> _state;
// TODO: this is a hack, make better? // TODO: this is a hack, make better?
friend SendStates::SHA1Start; friend States::SendStartSHA1;
}; };