/* This file is part of TON Blockchain Library. TON Blockchain Library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. TON Blockchain Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with TON Blockchain Library. If not, see . Copyright 2017-2019 Telegram Systems LLP */ #pragma once #include #include #include #include #include "overlay.h" #include "overlay-manager.h" #include "overlay-fec.hpp" #include "overlay-broadcast.hpp" #include "overlay-fec-broadcast.hpp" #include "overlay-id.hpp" #include "td/utils/DecTree.h" #include "td/utils/List.h" #include "td/utils/overloaded.h" #include "fec/fec.h" #include "adnl/utils.hpp" #include "keys/encryptor.h" #include "auto/tl/ton_api.h" #include "auto/tl/ton_api.hpp" namespace ton { namespace overlay { //using OverlayNode = tl_object_ptr; //using OverlayNodesList = tl_object_ptr; class OverlayImpl; class OverlayPeer { public: adnl::AdnlNodeIdShort get_id() const { return id_; } adnl::AdnlNodeIdFull get_full_id() const { return node_.adnl_id_full(); } OverlayNode get() const { return node_.clone(); } void update(OverlayNode node) { CHECK(get_id() == node.adnl_id_short()); if (node.version() > node_.version()) { node_ = std::move(node); } } OverlayPeer(OverlayNode node) : node_(std::move(node)) { id_ = node_.adnl_id_short(); } bool is_neighbour() const { return is_neighbour_; } void set_neighbour(bool value) { is_neighbour_ = value; } td::int32 get_version() const { return node_.version(); } private: OverlayNode node_; adnl::AdnlNodeIdShort id_; bool is_neighbour_ = false; }; class OverlayImpl : public Overlay { public: OverlayImpl(td::actor::ActorId keyring, td::actor::ActorId adnl, td::actor::ActorId manager, td::actor::ActorId dht_node, adnl::AdnlNodeIdShort local_id, OverlayIdFull overlay_id, bool pub, std::vector nodes, std::unique_ptr callback, OverlayPrivacyRules rules); void update_dht_node(td::actor::ActorId dht) override { dht_node_ = dht; } void receive_message(adnl::AdnlNodeIdShort src, td::BufferSlice data) override; void receive_query(adnl::AdnlNodeIdShort src, td::BufferSlice data, td::Promise promise) override; void send_message_to_neighbours(td::BufferSlice data) override; void send_broadcast(PublicKeyHash send_as, td::uint32 flags, td::BufferSlice data) override; void send_broadcast_fec(PublicKeyHash send_as, td::uint32 flags, td::BufferSlice data) override; void receive_nodes_from_db(tl_object_ptr nodes) override; void get_self_node(td::Promise promise); void alarm() override; void start_up() override { if (public_) { update_db_at_ = td::Timestamp::in(60.0); } alarm_timestamp() = td::Timestamp::in(1); } void receive_random_peers(adnl::AdnlNodeIdShort src, td::BufferSlice data); void send_random_peers(adnl::AdnlNodeIdShort dst, td::Promise promise); void send_random_peers_cont(adnl::AdnlNodeIdShort dst, OverlayNode node, td::Promise promise); void get_overlay_random_peers(td::uint32 max_peers, td::Promise> promise) override; void set_privacy_rules(OverlayPrivacyRules rules) override; void add_certificate(PublicKeyHash key, std::shared_ptr cert) override { certs_[key] = std::move(cert); } void receive_dht_nodes(td::Result res, bool dummy); void update_dht_nodes(OverlayNode node); void update_neighbours(td::uint32 nodes_to_change); void finish_fec_bcast(BroadcastHash id) { out_fec_bcasts_.erase(id); } struct PrintId { OverlayIdShort overlay_id; adnl::AdnlNodeIdShort local_id; }; PrintId print_id() const { return PrintId{overlay_id_, local_id_}; } void print(td::StringBuilder &sb) override; td::Status check_date(td::uint32 date); td::Status check_source_eligible(PublicKey source, const Certificate *cert, td::uint32 size); td::Status check_delivered(BroadcastHash hash); BroadcastFec *get_fec_broadcast(BroadcastHash hash); void register_fec_broadcast(std::unique_ptr bcast); void register_simple_broadcast(std::unique_ptr bcast); void created_simple_broadcast(std::unique_ptr bcast); void failed_to_create_simple_broadcast(td::Status reason); void created_fec_broadcast(PublicKeyHash local_id, std::unique_ptr bcast); void failed_to_create_fec_broadcast(td::Status reason); void deliver_broadcast(PublicKeyHash source, td::BufferSlice data); void send_new_fec_broadcast_part(PublicKeyHash local_id, Overlay::BroadcastDataHash data_hash, td::uint32 size, td::uint32 flags, td::BufferSlice part, td::uint32 seqno, fec::FecType fec_type, td::uint32 date); std::vector get_neighbours(td::uint32 max_size = 0) const { if (max_size == 0 || max_size >= neighbours_.size()) { return neighbours_; } else { std::vector vec; for (td::uint32 i = 0; i < max_size; i++) { vec.push_back(neighbours_[td::Random::fast(0, static_cast(neighbours_.size()))]); } return vec; } } td::actor::ActorId overlay_manager() const { return manager_; } td::actor::ActorId adnl() const { return adnl_; } td::actor::ActorId keyring() const { return keyring_; } adnl::AdnlNodeIdShort local_id() const { return local_id_; } OverlayIdShort overlay_id() const { return overlay_id_; } std::shared_ptr get_certificate(PublicKeyHash local_id); td::Result get_encryptor(PublicKey source); private: template void process_query(adnl::AdnlNodeIdShort src, T &query, td::Promise promise) { callback_->receive_query(src, overlay_id_, serialize_tl_object(&query, true), std::move(promise)); } void process_query(adnl::AdnlNodeIdShort src, ton_api::overlay_getRandomPeers &query, td::Promise promise); void process_query(adnl::AdnlNodeIdShort src, ton_api::overlay_getBroadcast &query, td::Promise promise); void process_query(adnl::AdnlNodeIdShort src, ton_api::overlay_getBroadcastList &query, td::Promise promise); //void process_query(adnl::AdnlNodeIdShort src, adnl::AdnlQueryId query_id, ton_api::overlay_customQuery &query); td::Status process_broadcast(adnl::AdnlNodeIdShort message_from, tl_object_ptr bcast); td::Status process_broadcast(adnl::AdnlNodeIdShort message_from, tl_object_ptr bcast); td::Status process_broadcast(adnl::AdnlNodeIdShort message_from, tl_object_ptr bcast); td::Status process_broadcast(adnl::AdnlNodeIdShort message_from, tl_object_ptr bcast); td::Status process_broadcast(adnl::AdnlNodeIdShort message_from, tl_object_ptr msg); td::Status process_broadcast(adnl::AdnlNodeIdShort message_from, tl_object_ptr msg); td::Status process_broadcast(adnl::AdnlNodeIdShort message_from, tl_object_ptr msg); void do_add_peer(OverlayNode node); void add_peer_in_cont(OverlayNode node); void add_peer_in(OverlayNode node); void add_peer(OverlayNode node); void add_peers(std::vector nodes); void del_some_peers(); void del_peer(adnl::AdnlNodeIdShort id); OverlayPeer *get_random_peer(); td::actor::ActorId keyring_; td::actor::ActorId adnl_; td::actor::ActorId manager_; td::actor::ActorId dht_node_; adnl::AdnlNodeIdShort local_id_; OverlayIdFull id_full_; OverlayIdShort overlay_id_; td::DecTree peers_; td::Timestamp next_dht_query_ = td::Timestamp::in(1.0); td::Timestamp update_db_at_; std::unique_ptr callback_; std::map> broadcasts_; std::map> fec_broadcasts_; std::set delivered_broadcasts_; std::vector neighbours_; td::ListNode bcast_data_lru_; td::ListNode bcast_fec_lru_; std::queue bcast_lru_; std::map> out_fec_bcasts_; void bcast_gc(); static td::uint32 max_data_bcasts() { return 100; } static td::uint32 max_bcasts() { return 1000; } static td::uint32 max_fec_bcasts() { return 20; } static td::uint32 max_sources() { return 10; } static td::uint32 max_neighbours() { return 5; } static td::uint32 max_encryptors() { return 16; } static td::uint32 max_peers() { return 20; } static td::uint32 nodes_to_send() { return 4; } static BroadcastHash get_broadcast_hash(adnl::AdnlNodeIdShort &src, td::Bits256 &data_hash) { td::uint8 buf[64]; td::MutableSlice m{buf, 64}; m.copy_from(src.as_slice()); m.remove_prefix(32); m.copy_from(data_hash.as_slice()); return td::sha256_bits256(td::Slice(buf, 64)); } bool public_; bool semi_public_ = false; OverlayPrivacyRules rules_; std::map> certs_; class CachedEncryptor : public td::ListNode { public: Encryptor *get() { return encryptor_.get(); } auto id() const { return id_; } CachedEncryptor(PublicKeyHash id, std::unique_ptr encryptor) : id_(id), encryptor_(std::move(encryptor)) { } static CachedEncryptor *from_list_node(td::ListNode *node) { return static_cast(node); } private: PublicKeyHash id_; std::unique_ptr encryptor_; }; td::ListNode encryptor_lru_; std::map> encryptor_map_; }; } // namespace overlay } // namespace ton namespace td { inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::overlay::OverlayImpl::PrintId &id) { sb << "[overlay " << id.overlay_id << "@" << id.local_id << "]"; return sb; } inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::overlay::OverlayImpl &overlay) { sb << overlay.print_id(); return sb; } inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::overlay::OverlayImpl *overlay) { sb << overlay->print_id(); return sb; } } // namespace td