1
0
mirror of https://github.com/danog/ton.git synced 2024-11-30 04:29:19 +01:00
ton/adnl/adnl-peer.hpp
2019-09-07 14:33:36 +04:00

319 lines
10 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/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include <vector>
#include <map>
#include "adnl-peer.h"
#include "adnl-peer-table.h"
#include "adnl-network-manager.h"
#include "keys/encryptor.h"
#include "adnl-channel.h"
#include "adnl-query.h"
#include "crypto/Ed25519.h"
#include "td/utils/DecTree.h"
#include "utils.hpp"
namespace ton {
namespace adnl {
using AdnlConnectionIdShort = AdnlAddressImpl::Hash;
class AdnlPeerPairImpl : public AdnlPeerPair {
public:
static constexpr td::uint32 packet_header_max_size() {
return 272;
}
static constexpr td::uint32 channel_packet_header_max_size() {
return 128;
}
static constexpr td::uint32 addr_list_max_size() {
return 128;
}
static constexpr td::uint32 get_mtu() {
return Adnl::get_mtu() + 128;
}
static constexpr td::uint32 huge_packet_max_size() {
return Adnl::huge_packet_max_size() + 128;
}
AdnlPeerPairImpl(td::actor::ActorId<AdnlNetworkManager> network_manager, td::actor::ActorId<AdnlPeerTable> peer_table,
td::actor::ActorId<AdnlLocalId> local_actor, td::actor::ActorId<AdnlPeer> peer,
td::actor::ActorId<dht::Dht> dht_node, AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id);
void start_up() override;
void alarm() override;
void discover();
void receive_packet_from_channel(AdnlChannelIdShort id, AdnlPacket packet) override;
void receive_packet_checked(AdnlPacket packet) override;
void receive_packet(AdnlPacket packet) override;
void deliver_message(AdnlMessage message);
void send_messages_in(std::vector<AdnlMessage> messages, bool allow_postpone);
void send_messages(std::vector<AdnlMessage> messages) override;
void send_packet_continue(AdnlPacket packet, td::actor::ActorId<AdnlNetworkConnection> conn, bool via_channel);
void send_query(std::string name, td::Promise<td::BufferSlice> promise, td::Timestamp timeout,
td::BufferSlice data) override;
void alarm_query(AdnlQueryId id) override;
void discover_query_result(td::Result<dht::DhtValue> B, bool dummy);
void update_dht_node(td::actor::ActorId<dht::Dht> dht_node) override {
dht_node_ = dht_node;
}
void update_addr_list(AdnlAddressList addr_list) override;
void update_peer_id(AdnlNodeIdFull id) override;
void got_data_from_db(td::Result<AdnlDbItem> R);
void got_data_from_static_nodes(td::Result<AdnlNode> R);
void got_data_from_dht(td::Result<AdnlNode> R);
//void conn_ready(AdnlConnectionIdShort id, td::Result<td::actor::ActorOwn<AdnlNetworkConnection>> R);
void process_message(const adnlmessage::AdnlMessageCreateChannel &message);
void process_message(const adnlmessage::AdnlMessageConfirmChannel &message);
void process_message(const adnlmessage::AdnlMessageCustom &message);
void process_message(const adnlmessage::AdnlMessageNop &message);
void process_message(const adnlmessage::AdnlMessageReinit &message);
void process_message(const adnlmessage::AdnlMessageQuery &message);
void process_message(const adnlmessage::AdnlMessageAnswer &message);
void process_message(const adnlmessage::AdnlMessagePart &message);
void process_message(const AdnlMessage::Empty &message) {
UNREACHABLE();
}
void conn_change_state(AdnlConnectionIdShort conn_id, bool ready);
void delete_query(AdnlQueryId id);
struct PrintId {
AdnlNodeIdShort peer_id;
AdnlNodeIdShort local_id;
};
PrintId print_id() const {
return PrintId{peer_id_short_, local_id_};
}
private:
void reinit(td::int32 date);
td::Result<td::actor::ActorId<AdnlNetworkConnection>> get_conn();
void create_channel(pubkeys::Ed25519 pub, td::uint32 date);
bool received_packet(td::uint32 seqno) const {
CHECK(seqno > 0);
if (seqno + 64 <= in_seqno_) {
return true;
}
if (seqno > in_seqno_) {
return false;
}
return recv_seqno_mask_ & (1ull << (in_seqno_ - seqno));
}
void add_received_packet(td::uint32 seqno) {
CHECK(!received_packet(seqno));
if (seqno <= in_seqno_) {
recv_seqno_mask_ |= (1ull << (in_seqno_ - seqno));
} else {
auto old = in_seqno_;
in_seqno_ = seqno;
if (in_seqno_ - old >= 64) {
recv_seqno_mask_ = 1;
} else {
recv_seqno_mask_ = recv_seqno_mask_ << (in_seqno_ - old);
recv_seqno_mask_ |= 1;
}
}
}
struct Conn {
class ConnCallback : public AdnlNetworkConnection::Callback {
public:
void on_change_state(bool ready) override {
td::actor::send_closure(root_, &AdnlPeerPairImpl::conn_change_state, conn_id_, ready);
}
ConnCallback(td::actor::ActorId<AdnlPeerPairImpl> root, AdnlConnectionIdShort conn_id)
: root_(root), conn_id_(conn_id) {
}
private:
td::actor::ActorId<AdnlPeerPairImpl> root_;
AdnlConnectionIdShort conn_id_;
};
AdnlAddress addr;
td::actor::ActorOwn<AdnlNetworkConnection> conn;
Conn(AdnlAddress addr, td::actor::ActorId<AdnlPeerPairImpl> peer,
td::actor::ActorId<AdnlNetworkManager> network_manager)
: addr(std::move(addr)) {
create_conn(peer, network_manager);
}
Conn() {
}
bool ready() {
return !conn.empty() && conn.get_actor_unsafe().is_active();
}
void create_conn(td::actor::ActorId<AdnlPeerPairImpl> peer, td::actor::ActorId<AdnlNetworkManager> network_manager);
};
std::vector<AdnlMessage> pending_messages_;
td::actor::ActorId<AdnlNetworkManager> network_manager_;
td::actor::ActorId<AdnlPeerTable> peer_table_;
td::actor::ActorId<AdnlLocalId> local_actor_;
td::actor::ActorId<AdnlPeer> peer_;
td::actor::ActorId<dht::Dht> dht_node_;
td::uint32 priority_ = 0;
td::int32 reinit_date_ = 0;
bool channel_ready_ = false;
bool channel_inited_ = false;
AdnlChannelIdShort channel_in_id_;
AdnlChannelIdShort channel_out_id_;
privkeys::Ed25519 channel_pk_;
pubkeys::Ed25519 channel_pub_;
td::int32 channel_pk_date_;
td::actor::ActorOwn<AdnlChannel> channel_;
td::uint64 in_seqno_ = 0;
td::uint64 out_seqno_ = 0;
td::uint64 ack_seqno_ = 0;
td::uint64 recv_seqno_mask_ = 0;
td::uint32 peer_channel_date_ = 0;
pubkeys::Ed25519 peer_channel_pub_;
td::int32 peer_recv_addr_list_version_ = -1;
td::int32 peer_recv_priority_addr_list_version_ = -1;
td::Bits256 huge_message_hash_ = td::Bits256::zero();
td::BufferSlice huge_message_;
td::uint32 huge_message_offset_ = 0;
AdnlAddressList addr_list_;
AdnlAddressList priority_addr_list_;
std::vector<Conn> conns_;
std::vector<Conn> priority_conns_;
AdnlNodeIdFull peer_id_;
AdnlNodeIdShort peer_id_short_;
AdnlNodeIdShort local_id_;
std::unique_ptr<Encryptor> encryptor_;
std::map<AdnlQueryId, td::actor::ActorId<AdnlQuery>> out_queries_;
td::uint32 received_messages_ = 0;
bool received_from_db_ = false;
bool received_from_static_nodes_ = false;
bool dht_query_active_ = false;
td::Timestamp next_dht_query_at_ = td::Timestamp::never();
td::Timestamp next_db_update_at_ = td::Timestamp::never();
td::Timestamp retry_send_at_ = td::Timestamp::never();
};
class AdnlPeerImpl : public AdnlPeer {
public:
void receive_packet(AdnlNodeIdShort dst, td::actor::ActorId<AdnlLocalId> dst_actor, AdnlPacket packet) override;
void send_messages(AdnlNodeIdShort src, td::actor::ActorId<AdnlLocalId> src_actor,
std::vector<AdnlMessage> messages) override;
void send_query(AdnlNodeIdShort src, td::actor::ActorId<AdnlLocalId> src_actor, std::string name,
td::Promise<td::BufferSlice> promise, td::Timestamp timeout, td::BufferSlice data) override;
void del_local_id(AdnlNodeIdShort local_id) override;
void update_id(AdnlNodeIdFull id) override;
void update_addr_list(AdnlNodeIdShort local_id, td::actor::ActorId<AdnlLocalId> local_actor,
AdnlAddressList addr_list) override;
void update_dht_node(td::actor::ActorId<dht::Dht> dht_node) override;
//void check_signature(td::BufferSlice data, td::BufferSlice signature, td::Promise<td::Unit> promise) override;
AdnlPeerImpl(td::actor::ActorId<AdnlNetworkManager> network_manager, td::actor::ActorId<AdnlPeerTable> peer_table,
td::actor::ActorId<dht::Dht> dht_node, AdnlNodeIdShort peer_id)
: peer_id_short_(peer_id), dht_node_(dht_node), peer_table_(peer_table), network_manager_(network_manager) {
}
struct PrintId {
AdnlNodeIdShort peer_id;
};
PrintId print_id() const {
return PrintId{peer_id_short_};
}
private:
AdnlNodeIdShort peer_id_short_;
AdnlNodeIdFull peer_id_;
std::map<AdnlNodeIdShort, td::actor::ActorOwn<AdnlPeerPair>> peer_pairs_;
td::actor::ActorId<dht::Dht> dht_node_;
td::actor::ActorId<AdnlPeerTable> peer_table_;
td::actor::ActorId<AdnlNetworkManager> network_manager_;
};
} // namespace adnl
} // namespace ton
namespace td {
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlPeerImpl::PrintId &id) {
sb << "[peer " << id.peer_id << "]";
return sb;
}
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlPeerImpl &peer) {
sb << peer.print_id();
return sb;
}
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlPeerImpl *peer) {
sb << peer->print_id();
return sb;
}
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlPeerPairImpl::PrintId &id) {
sb << "[peerpair " << id.peer_id << "-" << id.local_id << "]";
return sb;
}
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlPeerPairImpl &peer) {
sb << peer.print_id();
return sb;
}
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlPeerPairImpl *peer) {
sb << peer->print_id();
return sb;
}
} // namespace td