mirror of
				https://github.com/ton-blockchain/ton
				synced 2025-03-09 15:40:10 +00:00 
			
		
		
		
	* Improve DHT store/load, pinging overlay peers * Fix speed limits in storage * Use keyStoreTypeDirectory in rldp-http-proxy and storage-daemon Mainly for caching synced block in tonlib. --------- Co-authored-by: SpyCheese <mikle98@yandex.ru>
		
			
				
	
	
		
			277 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			277 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|     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 <http://www.gnu.org/licenses/>.
 | |
| */
 | |
| 
 | |
| #include "rldp2/rldp.h"
 | |
| #include "td/actor/actor.h"
 | |
| #include "overlay/overlay.h"
 | |
| #include "NodeActor.h"
 | |
| 
 | |
| namespace ton_rldp = ton::rldp2;
 | |
| 
 | |
| class PeerManager : public td::actor::Actor {
 | |
|  public:
 | |
|   PeerManager(ton::adnl::AdnlNodeIdShort adnl_id, ton::overlay::OverlayIdFull overlay_id, bool client_mode,
 | |
|               td::actor::ActorId<ton::overlay::Overlays> overlays, td::actor::ActorId<ton::adnl::Adnl> adnl,
 | |
|               td::actor::ActorId<ton_rldp::Rldp> rldp)
 | |
|       : overlay_id_(std::move(overlay_id))
 | |
|       , client_mode_(client_mode)
 | |
|       , overlays_(std::move(overlays))
 | |
|       , adnl_(std::move(adnl))
 | |
|       , rldp_(std::move(rldp)) {
 | |
|     CHECK(register_adnl_id(adnl_id) == 1);
 | |
|   }
 | |
|   void start_up() override {
 | |
|   }
 | |
|   void tear_down() override {
 | |
|     for (const auto& p : subscribed_peers_) {
 | |
|       if (p.second > 0) {
 | |
|         auto adnl_id = peer_to_andl(p.first);
 | |
|         if (adnl_id.is_ok()) {
 | |
|           send_closure(overlays_, &ton::overlay::Overlays::delete_overlay, adnl_id.move_as_ok(),
 | |
|                        overlay_id_.compute_short_id());
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   void send_query(ton::PeerId src, ton::PeerId dst, td::BufferSlice query, td::Promise<td::BufferSlice> promise) {
 | |
|     TRY_RESULT_PROMISE(promise, src_id, peer_to_andl(src));
 | |
|     TRY_RESULT_PROMISE(promise, dst_id, peer_to_andl(dst));
 | |
|     send_closure(overlays_, &ton::overlay::Overlays::send_query_via, dst_id, src_id, overlay_id_.compute_short_id(), "",
 | |
|                  std::move(promise), td::Timestamp::in(10), std::move(query), 1 << 25, rldp_);
 | |
|   }
 | |
| 
 | |
|   void execute_query(ton::adnl::AdnlNodeIdShort src, ton::adnl::AdnlNodeIdShort dst, td::BufferSlice data,
 | |
|                      td::Promise<td::BufferSlice> promise) {
 | |
|     auto src_id = register_adnl_id(src);
 | |
|     auto dst_id = register_adnl_id(dst);
 | |
|     auto it = peers_.find(std::make_pair(dst_id, src_id));
 | |
|     if (it == peers_.end()) {
 | |
|       auto node_it = nodes_.find(dst_id);
 | |
|       if (node_it == nodes_.end()) {
 | |
|         LOG(ERROR) << "Unknown query destination";
 | |
|         promise.set_error(td::Status::Error("Unknown query destination"));
 | |
|         return;
 | |
|       }
 | |
|       if (!node_it->second.is_alive()) {
 | |
|         LOG(ERROR) << "Expired query destination";
 | |
|         promise.set_error(td::Status::Error("Unknown query destination"));
 | |
|         return;
 | |
|       }
 | |
|       send_closure(node_it->second, &ton::NodeActor::start_peer, src_id,
 | |
|                    [promise = std::move(promise),
 | |
|                     data = std::move(data)](td::Result<td::actor::ActorId<ton::PeerActor>> r_peer) mutable {
 | |
|                      TRY_RESULT_PROMISE(promise, peer, std::move(r_peer));
 | |
|                      send_closure(peer, &ton::PeerActor::execute_query, std::move(data), std::move(promise));
 | |
|                    });
 | |
|       return;
 | |
|     }
 | |
|     send_closure(it->second, &ton::PeerActor::execute_query, std::move(data), std::move(promise));
 | |
|   }
 | |
| 
 | |
|   void register_peer(ton::PeerId src, ton::PeerId dst, td::actor::ActorId<ton::PeerActor> peer) {
 | |
|     peers_[std::make_pair(src, dst)] = std::move(peer);
 | |
|     register_src(src, [](td::Result<td::Unit> res) { res.ensure(); });
 | |
|   }
 | |
| 
 | |
|   void register_node(ton::PeerId src, td::actor::ActorId<ton::NodeActor> node) {
 | |
|     nodes_[src] = std::move(node);
 | |
|     register_src(src, [](td::Result<td::Unit> res) { res.ensure(); });
 | |
|   }
 | |
| 
 | |
|   void unregister_node(ton::PeerId src, td::actor::ActorId<ton::NodeActor> node) {
 | |
|     auto it = nodes_.find(src);
 | |
|     CHECK(it != nodes_.end());
 | |
|     if (it->second == node) {
 | |
|       nodes_.erase(it);
 | |
|     }
 | |
|     unregister_src(src, [](td::Result<td::Unit> res) { res.ensure(); });
 | |
|   }
 | |
| 
 | |
|   void unregister_peer(ton::PeerId src, ton::PeerId dst, td::actor::ActorId<ton::PeerActor> peer) {
 | |
|     auto it = peers_.find(std::make_pair(src, dst));
 | |
|     CHECK(it != peers_.end());
 | |
|     if (it->second == peer) {
 | |
|       peers_.erase(it);
 | |
|     }
 | |
|     unregister_src(src, [](td::Result<td::Unit> res) { res.ensure(); });
 | |
|   }
 | |
| 
 | |
|   void unregister_src(ton::PeerId src, td::Promise<td::Unit> promise) {
 | |
|     TRY_RESULT_PROMISE(promise, src_id, peer_to_andl(src));
 | |
|     if (--subscribed_peers_[src] == 0) {
 | |
|       subscribed_peers_.erase(src);
 | |
|       send_closure(overlays_, &ton::overlay::Overlays::delete_overlay, src_id, overlay_id_.compute_short_id());
 | |
|     }
 | |
|     promise.set_value({});
 | |
|   }
 | |
|   void register_src(ton::PeerId src, td::Promise<td::Unit> promise) {
 | |
|     TRY_RESULT_PROMISE(promise, src_id, peer_to_andl(src));
 | |
|     if (subscribed_peers_[src]++ == 0) {
 | |
|       auto rules = ton::overlay::OverlayPrivacyRules{};
 | |
|       class Callback : public ton::overlay::Overlays::Callback {
 | |
|        public:
 | |
|         explicit Callback(td::actor::ActorId<PeerManager> peer_manager, ton::adnl::AdnlNodeIdShort dst)
 | |
|             : peer_manager_(std::move(peer_manager)), dst_(dst) {
 | |
|         }
 | |
|         void receive_message(ton::adnl::AdnlNodeIdShort src, ton::overlay::OverlayIdShort overlay_id,
 | |
|                              td::BufferSlice data) override {
 | |
|         }
 | |
|         void receive_query(ton::adnl::AdnlNodeIdShort src, ton::overlay::OverlayIdShort overlay_id,
 | |
|                            td::BufferSlice data, td::Promise<td::BufferSlice> promise) override {
 | |
|           td::actor::send_closure(peer_manager_, &PeerManager::execute_query, src, dst_, std::move(data),
 | |
|                                   std::move(promise));
 | |
|         }
 | |
|         void receive_broadcast(ton::PublicKeyHash src, ton::overlay::OverlayIdShort overlay_id,
 | |
|                                td::BufferSlice data) override {
 | |
|         }
 | |
| 
 | |
|        private:
 | |
|         td::actor::ActorId<PeerManager> peer_manager_;
 | |
|         ton::adnl::AdnlNodeIdShort dst_;
 | |
|       };
 | |
|       ton::overlay::OverlayOptions opts;
 | |
|       opts.announce_self_ = !client_mode_;
 | |
|       opts.frequent_dht_lookup_ = true;
 | |
|       send_closure(overlays_, &ton::overlay::Overlays::create_public_overlay_ex, src_id, overlay_id_.clone(),
 | |
|                    std::make_unique<Callback>(actor_id(this), src_id), rules, R"({ "type": "storage" })", opts);
 | |
|     }
 | |
|     promise.set_value({});
 | |
|   }
 | |
| 
 | |
|   td::Result<ton::adnl::AdnlNodeIdShort> peer_to_andl(ton::PeerId id) {
 | |
|     if (id <= 0 || id > adnl_ids_.size()) {
 | |
|       return td::Status::Error(PSLICE() << "Invalid peer id " << id);
 | |
|     }
 | |
|     return adnl_ids_[id - 1];
 | |
|   }
 | |
| 
 | |
|   ton::PeerId register_adnl_id(ton::adnl::AdnlNodeIdShort id) {
 | |
|     auto it = adnl_to_peer_id_.emplace(id, next_peer_id_);
 | |
|     if (it.second) {
 | |
|       adnl_ids_.push_back(id);
 | |
|       next_peer_id_++;
 | |
|     }
 | |
|     return it.first->second;
 | |
|   }
 | |
| 
 | |
|   void get_peers(ton::PeerId src, td::Promise<std::vector<ton::PeerId>> promise) {
 | |
|     TRY_RESULT_PROMISE(promise, src_id, peer_to_andl(src));
 | |
|     send_closure(overlays_, &ton::overlay::Overlays::get_overlay_random_peers, src_id, overlay_id_.compute_short_id(),
 | |
|                  30, promise.send_closure(actor_id(this), &PeerManager::got_overlay_random_peers));
 | |
|   }
 | |
| 
 | |
|   void get_peer_info(ton::PeerId src, ton::PeerId peer, td::Promise<std::pair<td::Bits256, std::string>> promise) {
 | |
|     TRY_RESULT_PROMISE(promise, src_id, peer_to_andl(src));
 | |
|     TRY_RESULT_PROMISE(promise, peer_id, peer_to_andl(peer));
 | |
|     td::actor::send_closure(
 | |
|         adnl_, &ton::adnl::Adnl::get_conn_ip_str, src_id, peer_id,
 | |
|         promise.wrap([peer_id](std::string s) { return std::make_pair(peer_id.bits256_value(), std::move(s)); }));
 | |
|   }
 | |
| 
 | |
|   static td::unique_ptr<ton::NodeActor::NodeCallback> create_callback(td::actor::ActorId<PeerManager> peer_manager) {
 | |
|     class Context : public ton::NodeActor::NodeCallback {
 | |
|      public:
 | |
|       Context(td::actor::ActorId<PeerManager> peer_manager) : peer_manager_(peer_manager) {
 | |
|       }
 | |
|       void get_peers(ton::PeerId src, td::Promise<std::vector<ton::PeerId>> promise) override {
 | |
|         send_closure(peer_manager_, &PeerManager::get_peers, src, std::move(promise));
 | |
|       }
 | |
|       void register_self(td::actor::ActorId<ton::NodeActor> self) override {
 | |
|         CHECK(self_.empty());
 | |
|         self_ = self;
 | |
|         send_closure(peer_manager_, &PeerManager::register_node, 1, self_);
 | |
|       }
 | |
|       ~Context() override {
 | |
|         if (!self_.empty()) {
 | |
|           send_closure(peer_manager_, &PeerManager::unregister_node, 1, self_);
 | |
|         }
 | |
|       }
 | |
|       td::actor::ActorOwn<ton::PeerActor> create_peer(ton::PeerId self_id, ton::PeerId peer_id,
 | |
|                                                       std::shared_ptr<ton::PeerState> state) override {
 | |
|         CHECK(self_id == 1);
 | |
|         class PeerCallback : public ton::PeerActor::Callback {
 | |
|          public:
 | |
|           PeerCallback(ton::PeerId self_id, ton::PeerId peer_id, td::actor::ActorId<PeerManager> peer_manager)
 | |
|               : self_id_(self_id), peer_id_(peer_id), peer_manager_(std::move(peer_manager)) {
 | |
|           }
 | |
|           void register_self(td::actor::ActorId<ton::PeerActor> self) override {
 | |
|             CHECK(self_.empty());
 | |
|             self_ = std::move(self);
 | |
|             send_closure(peer_manager_, &PeerManager::register_peer, self_id_, peer_id_, self_);
 | |
|           }
 | |
|           void send_query(td::uint64 query_id, td::BufferSlice query) override {
 | |
|             send_closure(peer_manager_, &PeerManager::send_query, self_id_, peer_id_, std::move(query),
 | |
|                          promise_send_closure(self_, &ton::PeerActor::on_query_result, query_id));
 | |
|           }
 | |
| 
 | |
|           ~PeerCallback() {
 | |
|             if (!self_.empty()) {
 | |
|               send_closure(peer_manager_, &PeerManager::unregister_peer, self_id_, peer_id_, self_);
 | |
|             }
 | |
|           }
 | |
| 
 | |
|          private:
 | |
|           td::actor::ActorId<ton::PeerActor> self_;
 | |
|           ton::PeerId self_id_;
 | |
|           ton::PeerId peer_id_;
 | |
|           td::actor::ActorId<PeerManager> peer_manager_;
 | |
|         };
 | |
|         return td::actor::create_actor<ton::PeerActor>(PSLICE() << "PeerActor " << peer_id,
 | |
|                                                        td::make_unique<PeerCallback>(self_id, peer_id, peer_manager_),
 | |
|                                                        std::move(state));
 | |
|       }
 | |
| 
 | |
|       void get_peer_info(ton::PeerId src, ton::PeerId peer,
 | |
|                          td::Promise<std::pair<td::Bits256, std::string>> promise) override {
 | |
|         td::actor::send_closure(peer_manager_, &PeerManager::get_peer_info, src, peer, std::move(promise));
 | |
|       }
 | |
| 
 | |
|      private:
 | |
|       td::actor::ActorId<PeerManager> peer_manager_;
 | |
|       std::vector<ton::PeerId> peers_;
 | |
|       td::actor::ActorId<ton::NodeActor> self_;
 | |
|     };
 | |
|     return td::make_unique<Context>(std::move(peer_manager));
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   ton::overlay::OverlayIdFull overlay_id_;
 | |
|   bool client_mode_ = false;
 | |
|   td::actor::ActorId<ton::overlay::Overlays> overlays_;
 | |
|   td::actor::ActorId<ton::adnl::Adnl> adnl_;
 | |
|   td::actor::ActorId<ton_rldp::Rldp> rldp_;
 | |
| 
 | |
|   std::map<std::pair<ton::PeerId, ton::PeerId>, td::actor::ActorId<ton::PeerActor>> peers_;
 | |
|   std::map<ton::PeerId, td::actor::ActorId<ton::NodeActor>> nodes_;
 | |
|   ton::PeerId next_peer_id_{1};
 | |
|   std::map<ton::adnl::AdnlNodeIdShort, ton::PeerId> adnl_to_peer_id_;
 | |
|   std::vector<ton::adnl::AdnlNodeIdShort> adnl_ids_;
 | |
| 
 | |
|   std::map<ton::PeerId, td::uint32> subscribed_peers_;
 | |
| 
 | |
|   void got_overlay_random_peers(td::Result<std::vector<ton::adnl::AdnlNodeIdShort>> r_peers,
 | |
|                                 td::Promise<std::vector<ton::PeerId>> promise) {
 | |
|     TRY_RESULT_PROMISE(promise, peers, std::move(r_peers));
 | |
| 
 | |
|     std::vector<ton::PeerId> res;
 | |
|     for (auto peer : peers) {
 | |
|       res.push_back(register_adnl_id(peer));
 | |
|     }
 | |
| 
 | |
|     promise.set_value(std::move(res));
 | |
|   }
 | |
| };
 |