diff --git a/src/ngcext.cpp b/src/ngcext.cpp index e443f44..c94612b 100644 --- a/src/ngcext.cpp +++ b/src/ngcext.cpp @@ -186,6 +186,44 @@ bool NGCEXTEventProvider::parse_ft1_data_ack( ); } +bool NGCEXTEventProvider::parse_ft1_message( + uint32_t group_number, uint32_t peer_number, + const uint8_t* data, size_t data_size, + bool _private +) { + if (_private) { + std::cerr << "NGCEXT: ft1_message cant be private (yet)\n"; + return false; + } + + Events::NGCEXT_ft1_message e; + e.group_number = group_number; + e.peer_number = peer_number; + size_t curser = 0; + + // - 4 byte (message_id) + e.message_id = 0u; + _DATA_HAVE(sizeof(e.message_id), std::cerr << "NGCEXT: packet too small, missing message_id\n"; return false) + for (size_t i = 0; i < sizeof(e.message_id); i++, curser++) { + e.message_id |= uint32_t(data[curser]) << (i*8); + } + + // - 4 byte (file_kind) + e.file_kind = 0u; + _DATA_HAVE(sizeof(e.file_kind), std::cerr << "NGCEXT: packet too small, missing file_kind\n"; return false) + for (size_t i = 0; i < sizeof(e.file_kind); i++, curser++) { + e.file_kind |= uint32_t(data[curser]) << (i*8); + } + + // - X bytes (file_kind dependent id, differnt sizes) + e.file_id = {data+curser, data+curser+(data_size-curser)}; + + return dispatch( + NGCEXT_Event::FT1_MESSAGE, + e + ); +} + bool NGCEXTEventProvider::handlePacket( const uint32_t group_number, const uint32_t peer_number, @@ -214,6 +252,8 @@ bool NGCEXTEventProvider::handlePacket( return parse_ft1_data(group_number, peer_number, data+1, data_size-1, _private); case NGCEXT_Event::FT1_DATA_ACK: return parse_ft1_data_ack(group_number, peer_number, data+1, data_size-1, _private); + case NGCEXT_Event::FT1_MESSAGE: + return parse_ft1_message(group_number, peer_number, data+1, data_size-1, _private); default: return false; } diff --git a/src/ngcext.hpp b/src/ngcext.hpp index aa160ff..4932dcf 100644 --- a/src/ngcext.hpp +++ b/src/ngcext.hpp @@ -113,6 +113,21 @@ namespace Events { std::vector sequence_ids; }; + struct NGCEXT_ft1_message { + uint32_t group_number; + uint32_t peer_number; + + // - 4 byte (message_id) + uint32_t message_id; + + // request the other side to initiate a FT + // - 4 byte (file_kind) + uint32_t file_kind; + + // - X bytes (file_kind dependent id, differnt sizes) + std::vector file_id; + }; + } // Events enum class NGCEXT_Event : uint8_t { @@ -131,7 +146,7 @@ enum class NGCEXT_Event : uint8_t { HS1_RESPONSE_LAST_IDS, // request the other side to initiate a FT - // - 1 byte (file_kind) + // - 4 byte (file_kind) // - X bytes (file_kind dependent id, differnt sizes) FT1_REQUEST = 0x80 | 8u, @@ -139,7 +154,7 @@ enum class NGCEXT_Event : uint8_t { // tell the other side you want to start a FT // TODO: might use id layer instead. with it, it would look similar to friends_ft - // - 1 byte (file_kind) + // - 4 byte (file_kind) // - 8 bytes (data size, can be 0 if unknown, BUT files have to be atleast 1 byte) // - 1 byte (temporary_file_tf_id, for this peer only, technically just a prefix to distinguish between simultainious fts) // - X bytes (file_kind dependent id, differnt sizes) @@ -168,6 +183,14 @@ enum class NGCEXT_Event : uint8_t { // - ] FT1_DATA_ACK, + // send file as message + // basically the opposite of request + // contains file_kind and file_id (and timestamp?) + // - 4 byte (message_id) + // - 4 byte (file_kind) + // - X bytes (file_kind dependent id, differnt sizes) + FT1_MESSAGE, + MAX }; @@ -180,6 +203,7 @@ struct NGCEXTEventI { virtual bool onEvent(const Events::NGCEXT_ft1_init_ack&) { return false; } virtual bool onEvent(const Events::NGCEXT_ft1_data&) { return false; } virtual bool onEvent(const Events::NGCEXT_ft1_data_ack&) { return false; } + virtual bool onEvent(const Events::NGCEXT_ft1_message&) { return false; } }; using NGCEXTEventProviderI = EventProviderI; @@ -233,6 +257,12 @@ class NGCEXTEventProvider : public ToxEventI, public NGCEXTEventProviderI { bool _private ); + bool parse_ft1_message( + uint32_t group_number, uint32_t peer_number, + const uint8_t* data, size_t data_size, + bool _private + ); + bool handlePacket( const uint32_t group_number, const uint32_t peer_number, diff --git a/src/ngcft1.cpp b/src/ngcft1.cpp index b0a7643..9c3feae 100644 --- a/src/ngcft1.cpp +++ b/src/ngcft1.cpp @@ -2,6 +2,8 @@ #include +#include + #include #include #include @@ -118,6 +120,29 @@ bool NGCFT1::sendPKG_FT1_DATA_ACK( return _t.toxGroupSendCustomPrivatePacket(group_number, peer_number, false, pkg) == TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_OK; } +bool NGCFT1::sendPKG_FT1_MESSAGE( + uint32_t group_number, + uint32_t message_id, + uint32_t file_kind, + const uint8_t* file_id, size_t file_id_size +) { + std::vector pkg; + pkg.push_back(static_cast(NGCEXT_Event::FT1_MESSAGE)); + + for (size_t i = 0; i < sizeof(message_id); i++) { + pkg.push_back((message_id>>(i*8)) & 0xff); + } + for (size_t i = 0; i < sizeof(file_kind); i++) { + pkg.push_back((file_kind>>(i*8)) & 0xff); + } + for (size_t i = 0; i < file_id_size; i++) { + pkg.push_back(file_id[i]); + } + + // lossless + return _t.toxGroupSendCustomPacket(group_number, true, pkg) == TOX_ERR_GROUP_SEND_CUSTOM_PACKET_OK; +} + void NGCFT1::updateSendTransfer(float time_delta, uint32_t group_number, uint32_t peer_number, Group::Peer& peer, size_t idx, std::set& timeouts_set) { auto& tf_opt = peer.send_transfers.at(idx); assert(tf_opt.has_value()); @@ -306,6 +331,7 @@ NGCFT1::NGCFT1( _neep.subscribe(this, NGCEXT_Event::FT1_INIT_ACK); _neep.subscribe(this, NGCEXT_Event::FT1_DATA); _neep.subscribe(this, NGCEXT_Event::FT1_DATA_ACK); + _neep.subscribe(this, NGCEXT_Event::FT1_MESSAGE); } void NGCFT1::iterate(float time_delta) { @@ -383,6 +409,19 @@ bool NGCFT1::NGC_FT1_send_init_private( return true; } +bool NGCFT1::NGC_FT1_send_message_public( + uint32_t group_number, + uint32_t& message_id, + uint32_t file_kind, + const uint8_t* file_id, size_t file_id_size +) { + // create msg_id + message_id = randombytes_random(); + + // TODO: check return value + return sendPKG_FT1_MESSAGE(group_number, message_id, file_kind, file_id, file_id_size); +} + bool NGCFT1::onEvent(const Events::NGCEXT_ft1_request& e) { std::cout << "NGCFT1: FT1_REQUEST fk:" << e.file_kind << " [" << bin2hex(e.file_id) << "]\n"; @@ -577,3 +616,19 @@ bool NGCFT1::onEvent(const Events::NGCEXT_ft1_data_ack& e) { return true; } +bool NGCFT1::onEvent(const Events::NGCEXT_ft1_message& e) { + std::cout << "NGCFT1: FT1_MESSAGE mid:" << e.message_id << " fk:" << e.file_kind << " [" << bin2hex(e.file_id) << "]\n"; + + // .... just rethrow?? + // TODO: dont + return dispatch( + NGCFT1_Event::recv_message, + Events::NGCFT1_recv_message{ + e.group_number, e.peer_number, + e.message_id, + static_cast(e.file_kind), + e.file_id.data(), e.file_id.size() + } + ); +} + diff --git a/src/ngcft1.hpp b/src/ngcft1.hpp index 360a827..1cc6cd6 100644 --- a/src/ngcft1.hpp +++ b/src/ngcft1.hpp @@ -83,6 +83,18 @@ namespace Events { // TODO: reason }; + struct NGCFT1_recv_message { + uint32_t group_number; + uint32_t peer_number; + + uint32_t message_id; + + NGCFT1_file_kind file_kind; + + const uint8_t* file_id; + size_t file_id_size; + }; + } // Events enum class NGCFT1_Event : uint8_t { @@ -95,6 +107,8 @@ enum class NGCFT1_Event : uint8_t { recv_done, send_done, + recv_message, + MAX }; @@ -106,6 +120,7 @@ struct NGCFT1EventI { virtual bool onEvent(const Events::NGCFT1_send_data&) { return false; } // const? virtual bool onEvent(const Events::NGCFT1_recv_done&) { return false; } virtual bool onEvent(const Events::NGCFT1_send_done&) { return false; } + virtual bool onEvent(const Events::NGCFT1_recv_message&) { return false; } }; using NGCFT1EventProviderI = EventProviderI; @@ -181,6 +196,7 @@ class NGCFT1 : public ToxEventI, public NGCEXTEventI, public NGCFT1EventProvider bool sendPKG_FT1_INIT_ACK(uint32_t group_number, uint32_t peer_number, uint8_t transfer_id); bool sendPKG_FT1_DATA(uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, uint16_t sequence_id, const uint8_t* data, size_t data_size); bool sendPKG_FT1_DATA_ACK(uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, const uint16_t* seq_ids, size_t seq_ids_size); + bool sendPKG_FT1_MESSAGE(uint32_t group_number, uint32_t message_id, uint32_t file_kind, const uint8_t* file_id, size_t file_id_size); void updateSendTransfer(float time_delta, uint32_t group_number, uint32_t peer_number, Group::Peer& peer, size_t idx, std::set& timeouts_set); void iteratePeer(float time_delta, uint32_t group_number, uint32_t peer_number, Group::Peer& peer); @@ -211,12 +227,21 @@ class NGCFT1 : public ToxEventI, public NGCEXTEventI, public NGCFT1EventProvider uint8_t* transfer_id ); + // sends the message and fills in message_id + bool NGC_FT1_send_message_public( + uint32_t group_number, + uint32_t& message_id, + uint32_t file_kind, + const uint8_t* file_id, size_t file_id_size + ); + protected: bool onEvent(const Events::NGCEXT_ft1_request&) override; bool onEvent(const Events::NGCEXT_ft1_init&) override; bool onEvent(const Events::NGCEXT_ft1_init_ack&) override; bool onEvent(const Events::NGCEXT_ft1_data&) override; bool onEvent(const Events::NGCEXT_ft1_data_ack&) override; + bool onEvent(const Events::NGCEXT_ft1_message&) override; protected: //bool onToxEvent(const Tox_Event_Group_Custom_Packet* e) override; diff --git a/src/sha1_ngcft1.cpp b/src/sha1_ngcft1.cpp index dff90d3..2360969 100644 --- a/src/sha1_ngcft1.cpp +++ b/src/sha1_ngcft1.cpp @@ -5,12 +5,15 @@ #include #include #include +#include #include #include "./ft1_sha1_info.hpp" #include "./hash_utils.hpp" +#include + #include #include @@ -116,7 +119,7 @@ SHA1_NGCFT1::SHA1_NGCFT1( void SHA1_NGCFT1::iterate(float delta) { { // timers - // chunk sending + // sending transfers for (auto peer_it = _sending_transfers.begin(); peer_it != _sending_transfers.end();) { for (auto it = peer_it->second.begin(); it != peer_it->second.end();) { it->second.time_since_activity += delta; @@ -492,6 +495,30 @@ bool SHA1_NGCFT1::sendFilePath(const Contact3 c, std::string_view file_name, std } // else queue? #endif + if (_cr.any_of(c)) { + const uint32_t group_number = _cr.get(c).group_number; + uint32_t message_id = 0; + + // TODO: check return + _nft.NGC_FT1_send_message_public(group_number, message_id, static_cast(NGCFT1_file_kind::HASH_SHA1_INFO), sha1_info_hash.data(), sha1_info_hash.size()); + reg_ptr->emplace(e, message_id); + + // TODO: generalize? + auto& synced_by = reg_ptr->emplace(e).list; + synced_by.emplace(c_self); + } else if ( + // non online group + _cr.any_of(c) + ) { + // create msg_id + const uint32_t message_id = randombytes_random(); + reg_ptr->emplace(e, message_id); + + // TODO: generalize? + auto& synced_by = reg_ptr->emplace(e).list; + synced_by.emplace(c_self); + } + _rmm.throwEventConstruct(*reg_ptr, e); return true;