#pragma once // solanaceae port of sha1 fts for NGCFT1 #include #include #include #include #include #include "./ft1_sha1_info.hpp" #include #include #include #include #include #include #include #include class SHA1_NGCFT1 : public ToxEventI, public RegistryMessageModelEventI, public NGCFT1EventI, public NGCEXTEventI { ObjectStore2& _os; // TODO: backend abstraction Contact3Registry& _cr; RegistryMessageModel& _rmm; NGCFT1& _nft; ToxContactModel2& _tcm; ToxEventProviderI& _tep; NGCEXTEventProvider& _neep; std::minstd_rand _rng {1337*11}; // limit this to each group? entt::dense_map _info_to_content; // sha1 chunk index // TODO: optimize lookup // TODO: multiple contents. hashes might be unique, but data is not entt::dense_map _chunks; // group_number, peer_number, content, chunk_hash, timer std::deque> _queue_requested_chunk; //void queueUpRequestInfo(uint32_t group_number, uint32_t peer_number, const SHA1Digest& hash); void queueUpRequestChunk(uint32_t group_number, uint32_t peer_number, ObjectHandle content, const SHA1Digest& hash); struct SendingTransfer { struct Info { // copy of info data // too large? std::vector info_data; }; struct Chunk { ObjectHandle content; size_t chunk_index; // <.< remove offset_into_file //uint64_t offset_into_file; // or data? // if memmapped, this would be just a pointer }; std::variant v; float time_since_activity {0.f}; }; // key is groupid + peerid entt::dense_map> _sending_transfers; struct ReceivingTransfer { struct Info { ObjectHandle content; // copy of info data // too large? std::vector info_data; }; struct Chunk { ObjectHandle content; std::vector chunk_indices; // or data? // if memmapped, this would be just a pointer }; std::variant v; float time_since_activity {0.f}; }; // key is groupid + peerid entt::dense_map> _receiving_transfers; // makes request rotate around open content std::deque _queue_content_want_info; std::deque _queue_content_want_chunk; std::atomic_bool _info_builder_dirty {false}; std::mutex _info_builder_queue_mutex; //struct InfoBuilderEntry { //// called on completion on the iterate thread //// (owning) //std::function fn; //}; using InfoBuilderEntry = std::function; std::list _info_builder_queue; static uint64_t combineIds(const uint32_t group_number, const uint32_t peer_number); void updateMessages(ObjectHandle ce); static bool addParticipation(Contact3Handle c, ObjectHandle o); static void removeParticipation(Contact3Handle c, ObjectHandle o); std::optional> selectPeerForRequest(ObjectHandle ce); public: // TODO: config bool _udp_only {false}; size_t _max_concurrent_in {6}; size_t _max_concurrent_out {8}; // TODO: probably also includes running transfers rn (meh) size_t _max_pending_requests {32}; // per content public: SHA1_NGCFT1( ObjectStore2& os, Contact3Registry& cr, RegistryMessageModel& rmm, NGCFT1& nft, ToxContactModel2& tcm, ToxEventProviderI& tep, NGCEXTEventProvider& neep ); void iterate(float delta); protected: // rmm events (actions) bool onEvent(const Message::Events::MessageUpdated&) override; protected: // events bool onEvent(const Events::NGCFT1_recv_request&) override; bool onEvent(const Events::NGCFT1_recv_init&) override; bool onEvent(const Events::NGCFT1_recv_data&) override; bool onEvent(const Events::NGCFT1_send_data&) override; // const? bool onEvent(const Events::NGCFT1_recv_done&) override; bool onEvent(const Events::NGCFT1_send_done&) override; bool onEvent(const Events::NGCFT1_recv_message&) override; bool sendFilePath(const Contact3 c, std::string_view file_name, std::string_view file_path) override; bool onToxEvent(const Tox_Event_Group_Peer_Exit* e) override; bool onEvent(const Events::NGCEXT_ft1_have&) override; bool onEvent(const Events::NGCEXT_ft1_bitset&) override; bool onEvent(const Events::NGCEXT_pc1_announce&) override; };