19
#include "adnl-peer-table.hpp"
21
#include "adnl-channel.h"
24
#include "td/utils/tl_storers.h"
25
#include "td/utils/crypto.h"
26
#include "td/utils/tl_parsers.h"
27
#include "td/utils/Random.h"
28
#include "td/db/RocksDb.h"
31
#include "adnl-query.h"
32
#include "adnl-ext-client.h"
33
#include "adnl-tunnel.h"
39
td::int32 Adnl::adnl_start_time() {
40
static td::int32 start_time = [] {
41
auto init_start_time = static_cast<td::int32>(td::Clocks::system());
42
CHECK(init_start_time > 0);
43
return init_start_time;
48
td::actor::ActorOwn<Adnl> Adnl::create(std::string db, td::actor::ActorId<keyring::Keyring> keyring) {
50
return td::actor::ActorOwn<Adnl>(td::actor::create_actor<AdnlPeerTableImpl>("PeerTable", db, keyring));
53
void AdnlPeerTableImpl::receive_packet(td::IPAddress addr, AdnlCategoryMask cat_mask, td::BufferSlice data) {
54
if (data.size() < 32) {
55
VLOG(ADNL_WARNING) << this << ": dropping IN message [?->?]: message too short: len=" << data.size();
59
AdnlNodeIdShort dst{data.as_slice().truncate(32)};
60
data.confirm_read(32);
62
auto it = local_ids_.find(dst);
63
if (it != local_ids_.end()) {
64
if (!cat_mask.test(it->second.cat)) {
65
VLOG(ADNL_WARNING) << this << ": dropping IN message [?->" << dst << "]: category mismatch";
68
td::actor::send_closure(it->second.local_id, &AdnlLocalId::receive, addr, std::move(data));
72
AdnlChannelIdShort dst_chan_id{dst.pubkey_hash()};
73
auto it2 = channels_.find(dst_chan_id);
74
if (it2 != channels_.end()) {
75
if (!cat_mask.test(it2->second.second)) {
76
VLOG(ADNL_WARNING) << this << ": dropping IN message to channel [?->" << dst << "]: category mismatch";
79
td::actor::send_closure(it2->second.first, &AdnlChannel::receive, addr, std::move(data));
83
VLOG(ADNL_DEBUG) << this << ": dropping IN message [?->" << dst << "]: unknown dst " << dst
84
<< " (len=" << (data.size() + 32) << ")";
87
void AdnlPeerTableImpl::receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket packet) {
88
packet.run_basic_checks().ensure();
90
if (!packet.inited_from_short()) {
91
VLOG(ADNL_INFO) << this << ": dropping IN message [?->" << dst << "]: destination not set";
95
auto it = peers_.find(packet.from_short());
96
if (it == peers_.end()) {
97
if (!packet.inited_from()) {
98
VLOG(ADNL_NOTICE) << this << ": dropping IN message [" << packet.from_short() << "->" << dst
99
<< "]: unknown peer and no full src in packet";
102
if (network_manager_.empty()) {
103
VLOG(ADNL_NOTICE) << this << ": dropping IN message [" << packet.from_short() << "->" << dst
104
<< "]: unknown peer and network manager uninitialized";
109
.emplace(packet.from_short(),
110
AdnlPeer::create(network_manager_, actor_id(this), dht_node_, packet.from_short()))
112
CHECK(it != peers_.end());
115
auto it2 = local_ids_.find(dst);
116
if (it2 == local_ids_.end()) {
117
VLOG(ADNL_ERROR) << this << ": dropping IN message [" << packet.from_short() << "->" << dst
118
<< "]: unknown dst (but how did we decrypt message?)";
121
td::actor::send_closure(it->second, &AdnlPeer::receive_packet, dst, it2->second.mode, it2->second.local_id.get(),
125
void AdnlPeerTableImpl::add_peer(AdnlNodeIdShort local_id, AdnlNodeIdFull id, AdnlAddressList addr_list) {
126
auto id_short = id.compute_short_id();
127
VLOG(ADNL_DEBUG) << this << ": adding peer " << id_short << " for local id " << local_id;
129
auto it2 = local_ids_.find(local_id);
130
CHECK(it2 != local_ids_.end());
132
auto it = peers_.find(id_short);
133
if (it == peers_.end()) {
134
it = peers_.emplace(id_short, AdnlPeer::create(network_manager_, actor_id(this), dht_node_, id_short)).first;
135
CHECK(it != peers_.end());
137
td::actor::send_closure(it->second, &AdnlPeer::update_id, std::move(id));
138
if (!addr_list.empty()) {
139
td::actor::send_closure(it->second, &AdnlPeer::update_addr_list, local_id, it2->second.mode,
140
it2->second.local_id.get(), std::move(addr_list));
144
void AdnlPeerTableImpl::add_static_nodes_from_config(AdnlNodesList nodes) {
145
for (auto &it : nodes.nodes()) {
150
void AdnlPeerTableImpl::send_message_in(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlMessage message,
152
auto it = peers_.find(dst);
154
if (it == peers_.end()) {
155
it = peers_.emplace(dst, AdnlPeer::create(network_manager_, actor_id(this), dht_node_, dst)).first;
158
auto it2 = local_ids_.find(src);
159
if (it2 == local_ids_.end()) {
160
LOG(ERROR) << this << ": dropping OUT message [" << src << "->" << dst << "]: unknown src";
164
td::actor::send_closure(it->second, &AdnlPeer::send_one_message, src, it2->second.mode, it2->second.local_id.get(),
165
OutboundAdnlMessage{std::move(message), flags});
168
void AdnlPeerTableImpl::answer_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlQueryId query_id,
169
td::BufferSlice data) {
170
if (data.size() > get_mtu()) {
171
LOG(ERROR) << this << ": dropping OUT message [" << src << "->" << dst
172
<< "]: message too big: size=" << data.size();
175
send_message_in(src, dst, adnlmessage::AdnlMessageAnswer{query_id, std::move(data)}, 0);
178
void AdnlPeerTableImpl::send_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, std::string name,
179
td::Promise<td::BufferSlice> promise, td::Timestamp timeout, td::BufferSlice data) {
180
if (data.size() > huge_packet_max_size()) {
181
VLOG(ADNL_WARNING) << "dropping too big packet [" << src << "->" << dst << "]: size=" << data.size();
182
VLOG(ADNL_WARNING) << "DUMP: " << td::buffer_to_hex(data.as_slice().truncate(128));
185
auto it = peers_.find(dst);
187
if (it == peers_.end()) {
188
it = peers_.emplace(dst, AdnlPeer::create(network_manager_, actor_id(this), dht_node_, dst)).first;
191
auto it2 = local_ids_.find(src);
192
if (it2 == local_ids_.end()) {
193
LOG(ERROR) << this << ": dropping OUT message [" << src << "->" << dst << "]: unknown src";
197
td::actor::send_closure(it->second, &AdnlPeer::send_query, src, it2->second.mode, it2->second.local_id.get(), name,
198
std::move(promise), timeout, std::move(data), 0);
201
void AdnlPeerTableImpl::add_id_ex(AdnlNodeIdFull id, AdnlAddressList addr_list, td::uint8 cat, td::uint32 mode) {
202
auto a = id.compute_short_id();
203
VLOG(ADNL_INFO) << "adnl: adding local id " << a;
205
auto it = local_ids_.find(a);
207
if (it != local_ids_.end()) {
208
if (it->second.cat != cat) {
209
it->second.cat = cat;
210
if (!network_manager_.empty()) {
211
td::actor::send_closure(network_manager_, &AdnlNetworkManager::set_local_id_category, a, cat);
214
td::actor::send_closure(it->second.local_id, &AdnlLocalId::update_address_list, std::move(addr_list));
217
a, LocalIdInfo{td::actor::create_actor<AdnlLocalId>("localid", std::move(id), std::move(addr_list), mode,
218
actor_id(this), keyring_, dht_node_),
220
if (!network_manager_.empty()) {
221
td::actor::send_closure(network_manager_, &AdnlNetworkManager::set_local_id_category, a, cat);
226
void AdnlPeerTableImpl::del_id(AdnlNodeIdShort id, td::Promise<td::Unit> promise) {
227
VLOG(ADNL_INFO) << "adnl: deleting local id " << id;
228
local_ids_.erase(id);
229
promise.set_value(td::Unit());
232
void AdnlPeerTableImpl::subscribe(AdnlNodeIdShort dst, std::string prefix, std::unique_ptr<Callback> callback) {
233
auto it = local_ids_.find(dst);
234
LOG_CHECK(it != local_ids_.end()) << "dst=" << dst;
236
td::actor::send_closure(it->second.local_id, &AdnlLocalId::subscribe, prefix, std::move(callback));
239
void AdnlPeerTableImpl::unsubscribe(AdnlNodeIdShort dst, std::string prefix) {
240
auto it = local_ids_.find(dst);
242
if (it != local_ids_.end()) {
243
td::actor::send_closure(it->second.local_id, &AdnlLocalId::unsubscribe, prefix);
247
void AdnlPeerTableImpl::register_dht_node(td::actor::ActorId<dht::Dht> dht_node) {
248
dht_node_ = dht_node;
250
for (auto &peer : peers_) {
251
td::actor::send_closure(peer.second, &AdnlPeer::update_dht_node, dht_node_);
253
for (auto &local_id : local_ids_) {
254
td::actor::send_closure(local_id.second.local_id, &AdnlLocalId::update_dht_node, dht_node_);
258
void AdnlPeerTableImpl::register_network_manager(td::actor::ActorId<AdnlNetworkManager> network_manager) {
259
network_manager_ = std::move(network_manager);
261
class Cb : public AdnlNetworkManager::Callback {
263
void receive_packet(td::IPAddress addr, AdnlCategoryMask cat_mask, td::BufferSlice data) override {
264
td::actor::send_closure(id_, &AdnlPeerTableImpl::receive_packet, addr, std::move(cat_mask), std::move(data));
266
Cb(td::actor::ActorId<AdnlPeerTableImpl> id) : id_(id) {
270
td::actor::ActorId<AdnlPeerTableImpl> id_;
273
auto cb = std::make_unique<Cb>(actor_id(this));
274
td::actor::send_closure(network_manager_, &AdnlNetworkManager::install_callback, std::move(cb));
276
for (auto &id : local_ids_) {
277
td::actor::send_closure(network_manager_, &AdnlNetworkManager::set_local_id_category, id.first, id.second.cat);
281
void AdnlPeerTableImpl::get_addr_list(AdnlNodeIdShort id, td::Promise<AdnlAddressList> promise) {
282
auto it = local_ids_.find(id);
283
if (it == local_ids_.end()) {
284
promise.set_error(td::Status::Error(ErrorCode::notready));
287
td::actor::send_closure(it->second.local_id, &AdnlLocalId::get_addr_list_async, std::move(promise));
290
void AdnlPeerTableImpl::get_self_node(AdnlNodeIdShort id, td::Promise<AdnlNode> promise) {
291
auto it = local_ids_.find(id);
292
if (it == local_ids_.end()) {
293
promise.set_error(td::Status::Error(ErrorCode::notready));
296
td::actor::send_closure(it->second.local_id, &AdnlLocalId::get_self_node, std::move(promise));
299
void AdnlPeerTableImpl::register_channel(AdnlChannelIdShort id, AdnlNodeIdShort local_id,
300
td::actor::ActorId<AdnlChannel> channel) {
301
auto it = local_ids_.find(local_id);
302
auto cat = (it != local_ids_.end()) ? it->second.cat : 255;
303
auto success = channels_.emplace(id, std::make_pair(channel, cat)).second;
307
void AdnlPeerTableImpl::unregister_channel(AdnlChannelIdShort id) {
308
auto erased = channels_.erase(id);
312
void AdnlPeerTableImpl::start_up() {
315
void AdnlPeerTableImpl::write_new_addr_list_to_db(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id, AdnlDbItem node,
316
td::Promise<td::Unit> promise) {
318
promise.set_value(td::Unit());
321
td::actor::send_closure(db_, &AdnlDb::update, local_id, peer_id, std::move(node), std::move(promise));
324
void AdnlPeerTableImpl::get_addr_list_from_db(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id,
325
td::Promise<AdnlDbItem> promise) {
327
promise.set_error(td::Status::Error(ErrorCode::notready, "db not inited"));
330
td::actor::send_closure(db_, &AdnlDb::get, local_id, peer_id, std::move(promise));
333
AdnlPeerTableImpl::AdnlPeerTableImpl(std::string db_root, td::actor::ActorId<keyring::Keyring> keyring) {
335
static_nodes_manager_ = AdnlStaticNodesManager::create();
337
if (!db_root.empty()) {
338
db_ = AdnlDb::create(db_root + "/adnl");
342
void AdnlPeerTableImpl::deliver(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data) {
343
auto it = local_ids_.find(dst);
344
if (it != local_ids_.end()) {
345
td::actor::send_closure(it->second.local_id, &AdnlLocalId::deliver, src, std::move(data));
348
void AdnlPeerTableImpl::deliver_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data,
349
td::Promise<td::BufferSlice> promise) {
350
auto it = local_ids_.find(dst);
351
if (it != local_ids_.end()) {
352
td::actor::send_closure(it->second.local_id, &AdnlLocalId::deliver_query, src, std::move(data), std::move(promise));
354
LOG(WARNING) << "deliver query: unknown dst " << dst;
355
promise.set_error(td::Status::Error(ErrorCode::notready, "cannot deliver: unknown DST"));
359
void AdnlPeerTableImpl::decrypt_message(AdnlNodeIdShort dst, td::BufferSlice data,
360
td::Promise<td::BufferSlice> promise) {
361
auto it = local_ids_.find(dst);
362
if (it != local_ids_.end()) {
363
td::actor::send_closure(it->second.local_id, &AdnlLocalId::decrypt_message, std::move(data), std::move(promise));
365
LOG(WARNING) << "decrypt message: unknown dst " << dst;
366
promise.set_error(td::Status::Error(ErrorCode::notready, "cannot decrypt: unknown DST"));
370
void AdnlPeerTableImpl::create_ext_server(std::vector<AdnlNodeIdShort> ids, std::vector<td::uint16> ports,
371
td::Promise<td::actor::ActorOwn<AdnlExtServer>> promise) {
372
promise.set_value(AdnlExtServerCreator::create(actor_id(this), std::move(ids), std::move(ports)));
375
void AdnlPeerTableImpl::create_tunnel(AdnlNodeIdShort dst, td::uint32 size,
376
td::Promise<std::pair<td::actor::ActorOwn<AdnlTunnel>, AdnlAddress>> promise) {
379
void AdnlPeerTableImpl::get_conn_ip_str(AdnlNodeIdShort l_id, AdnlNodeIdShort p_id, td::Promise<td::string> promise) {
380
auto it = peers_.find(p_id);
381
if (it == peers_.end()) {
382
promise.set_value("undefined");
385
td::actor::send_closure(it->second, &AdnlPeer::get_conn_ip_str, l_id, std::move(promise));