/* 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-2020 Telegram Systems LLP */ #pragma once #include "LoadSpeed.h" #include "PartsHelper.h" #include "PeerActor.h" #include "Torrent.h" #include "td/utils/Random.h" #include namespace ton { class NodeActor : public td::actor::Actor { public: class Callback { public: virtual ~Callback() { } virtual td::actor::ActorOwn create_peer(PeerId self_id, PeerId peer_id, td::SharedState state) = 0; virtual void get_peers(td::Promise> peers) = 0; virtual void register_self(td::actor::ActorId self) = 0; //TODO: proper callbacks virtual void on_completed() = 0; virtual void on_closed(ton::Torrent torrent) = 0; }; NodeActor(PeerId self_id, ton::Torrent torrent, td::unique_ptr callback, bool should_download = true); void start_peer(PeerId peer_id, td::Promise> promise); ton::Torrent *with_torrent() { return &torrent_; } std::string get_stats_str(); void set_file_priority(size_t i, td::uint8 priority); void set_should_download(bool should_download); private: PeerId self_id_; ton::Torrent torrent_; std::vector file_priority_; td::unique_ptr callback_; bool should_download_{false}; class Notifier : public td::actor::Actor { public: Notifier(td::actor::ActorId node, PeerId peer_id) : node_(std::move(node)), peer_id_(peer_id) { } void wake_up() override { send_closure(node_, &NodeActor::on_signal_from_peer, peer_id_); } private: td::actor::ActorId node_; PeerId peer_id_; }; struct Peer { td::actor::ActorOwn actor; td::actor::ActorOwn notifier; td::SharedState state; PartsHelper::PeerToken peer_token; }; std::map peers_; struct QueryId { PeerId peer; PartId part; auto key() const { return std::tie(peer, part); } bool operator<(const QueryId &other) const { return key() < other.key(); } }; struct PartsSet { struct Info { td::optional query_to_peer; bool ready{false}; }; size_t total_queries{0}; std::vector parts; }; PartsSet parts_; PartsHelper parts_helper_; std::vector ready_parts_; LoadSpeed download_; td::Timestamp next_get_peers_at_; bool has_get_peers_{false}; static constexpr double GET_PEER_RETRY_TIMEOUT = 5; static constexpr double GET_PEER_EACH = 5; bool is_completed_{false}; td::Timestamp will_upload_at_; void on_signal_from_peer(PeerId peer_id); void start_up() override; void loop() override; void tear_down() override; void loop_start_stop_peers(); static constexpr size_t MAX_TOTAL_QUERIES = 20; static constexpr size_t MAX_PEER_TOTAL_QUERIES = 5; void loop_queries(); bool try_send_query(); bool try_send_part(PartId part_id); void loop_get_peers(); void got_peers(td::Result> r_peers); void loop_peer(const PeerId &peer_id, Peer &peer); void on_part_ready(PartId part_id); void loop_will_upload(); }; } // namespace ton