Ton

Форк
0
/
adnl-peer-table.cpp 
390 строк · 14.6 Кб
1
/*
2
    This file is part of TON Blockchain Library.
3

4
    TON Blockchain Library is free software: you can redistribute it and/or modify
5
    it under the terms of the GNU Lesser General Public License as published by
6
    the Free Software Foundation, either version 2 of the License, or
7
    (at your option) any later version.
8

9
    TON Blockchain Library is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU Lesser General Public License for more details.
13

14
    You should have received a copy of the GNU Lesser General Public License
15
    along with TON Blockchain Library.  If not, see <http://www.gnu.org/licenses/>.
16

17
    Copyright 2017-2020 Telegram Systems LLP
18
*/
19
#include "adnl-peer-table.hpp"
20
#include "adnl-peer.h"
21
#include "adnl-channel.h"
22
#include "utils.hpp"
23

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"
29

30
#include "utils.hpp"
31
#include "adnl-query.h"
32
#include "adnl-ext-client.h"
33
#include "adnl-tunnel.h"
34

35
namespace ton {
36

37
namespace adnl {
38

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;
44
  }();
45
  return start_time;
46
}
47

48
td::actor::ActorOwn<Adnl> Adnl::create(std::string db, td::actor::ActorId<keyring::Keyring> keyring) {
49
  adnl_start_time();
50
  return td::actor::ActorOwn<Adnl>(td::actor::create_actor<AdnlPeerTableImpl>("PeerTable", db, keyring));
51
}
52

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();
56
    return;
57
  }
58

59
  AdnlNodeIdShort dst{data.as_slice().truncate(32)};
60
  data.confirm_read(32);
61

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";
66
      return;
67
    }
68
    td::actor::send_closure(it->second.local_id, &AdnlLocalId::receive, addr, std::move(data));
69
    return;
70
  }
71

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";
77
      return;
78
    }
79
    td::actor::send_closure(it2->second.first, &AdnlChannel::receive, addr, std::move(data));
80
    return;
81
  }
82

83
  VLOG(ADNL_DEBUG) << this << ": dropping IN message [?->" << dst << "]: unknown dst " << dst
84
                   << " (len=" << (data.size() + 32) << ")";
85
}
86

87
void AdnlPeerTableImpl::receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket packet) {
88
  packet.run_basic_checks().ensure();
89

90
  if (!packet.inited_from_short()) {
91
    VLOG(ADNL_INFO) << this << ": dropping IN message [?->" << dst << "]: destination not set";
92
    return;
93
  }
94

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";
100
      return;
101
    }
102
    if (network_manager_.empty()) {
103
      VLOG(ADNL_NOTICE) << this << ": dropping IN message [" << packet.from_short() << "->" << dst
104
                        << "]: unknown peer and network manager uninitialized";
105
      return;
106
    }
107

108
    it = peers_
109
             .emplace(packet.from_short(),
110
                      AdnlPeer::create(network_manager_, actor_id(this), dht_node_, packet.from_short()))
111
             .first;
112
    CHECK(it != peers_.end());
113
  }
114

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?)";
119
    return;
120
  }
121
  td::actor::send_closure(it->second, &AdnlPeer::receive_packet, dst, it2->second.mode, it2->second.local_id.get(),
122
                          std::move(packet));
123
}
124

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;
128

129
  auto it2 = local_ids_.find(local_id);
130
  CHECK(it2 != local_ids_.end());
131

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());
136
  }
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));
141
  }
142
}
143

144
void AdnlPeerTableImpl::add_static_nodes_from_config(AdnlNodesList nodes) {
145
  for (auto &it : nodes.nodes()) {
146
    add_static_node(it);
147
  }
148
}
149

150
void AdnlPeerTableImpl::send_message_in(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlMessage message,
151
                                        td::uint32 flags) {
152
  auto it = peers_.find(dst);
153

154
  if (it == peers_.end()) {
155
    it = peers_.emplace(dst, AdnlPeer::create(network_manager_, actor_id(this), dht_node_, dst)).first;
156
  }
157

158
  auto it2 = local_ids_.find(src);
159
  if (it2 == local_ids_.end()) {
160
    LOG(ERROR) << this << ": dropping OUT message [" << src << "->" << dst << "]: unknown src";
161
    return;
162
  }
163

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});
166
}
167

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();
173
    return;
174
  }
175
  send_message_in(src, dst, adnlmessage::AdnlMessageAnswer{query_id, std::move(data)}, 0);
176
}
177

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));
183
    return;
184
  }
185
  auto it = peers_.find(dst);
186

187
  if (it == peers_.end()) {
188
    it = peers_.emplace(dst, AdnlPeer::create(network_manager_, actor_id(this), dht_node_, dst)).first;
189
  }
190

191
  auto it2 = local_ids_.find(src);
192
  if (it2 == local_ids_.end()) {
193
    LOG(ERROR) << this << ": dropping OUT message [" << src << "->" << dst << "]: unknown src";
194
    return;
195
  }
196

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);
199
}
200

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;
204

205
  auto it = local_ids_.find(a);
206

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);
212
      }
213
    }
214
    td::actor::send_closure(it->second.local_id, &AdnlLocalId::update_address_list, std::move(addr_list));
215
  } else {
216
    local_ids_.emplace(
217
        a, LocalIdInfo{td::actor::create_actor<AdnlLocalId>("localid", std::move(id), std::move(addr_list), mode,
218
                                                            actor_id(this), keyring_, dht_node_),
219
                       cat, mode});
220
    if (!network_manager_.empty()) {
221
      td::actor::send_closure(network_manager_, &AdnlNetworkManager::set_local_id_category, a, cat);
222
    }
223
  }
224
}
225

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());
230
}
231

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;
235

236
  td::actor::send_closure(it->second.local_id, &AdnlLocalId::subscribe, prefix, std::move(callback));
237
}
238

239
void AdnlPeerTableImpl::unsubscribe(AdnlNodeIdShort dst, std::string prefix) {
240
  auto it = local_ids_.find(dst);
241

242
  if (it != local_ids_.end()) {
243
    td::actor::send_closure(it->second.local_id, &AdnlLocalId::unsubscribe, prefix);
244
  }
245
}
246

247
void AdnlPeerTableImpl::register_dht_node(td::actor::ActorId<dht::Dht> dht_node) {
248
  dht_node_ = dht_node;
249

250
  for (auto &peer : peers_) {
251
    td::actor::send_closure(peer.second, &AdnlPeer::update_dht_node, dht_node_);
252
  }
253
  for (auto &local_id : local_ids_) {
254
    td::actor::send_closure(local_id.second.local_id, &AdnlLocalId::update_dht_node, dht_node_);
255
  }
256
}
257

258
void AdnlPeerTableImpl::register_network_manager(td::actor::ActorId<AdnlNetworkManager> network_manager) {
259
  network_manager_ = std::move(network_manager);
260

261
  class Cb : public AdnlNetworkManager::Callback {
262
   public:
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));
265
    }
266
    Cb(td::actor::ActorId<AdnlPeerTableImpl> id) : id_(id) {
267
    }
268

269
   private:
270
    td::actor::ActorId<AdnlPeerTableImpl> id_;
271
  };
272

273
  auto cb = std::make_unique<Cb>(actor_id(this));
274
  td::actor::send_closure(network_manager_, &AdnlNetworkManager::install_callback, std::move(cb));
275

276
  for (auto &id : local_ids_) {
277
    td::actor::send_closure(network_manager_, &AdnlNetworkManager::set_local_id_category, id.first, id.second.cat);
278
  }
279
}
280

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));
285
    return;
286
  }
287
  td::actor::send_closure(it->second.local_id, &AdnlLocalId::get_addr_list_async, std::move(promise));
288
}
289

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));
294
    return;
295
  }
296
  td::actor::send_closure(it->second.local_id, &AdnlLocalId::get_self_node, std::move(promise));
297
}
298

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;
304
  CHECK(success);
305
}
306

307
void AdnlPeerTableImpl::unregister_channel(AdnlChannelIdShort id) {
308
  auto erased = channels_.erase(id);
309
  CHECK(erased == 1);
310
}
311

312
void AdnlPeerTableImpl::start_up() {
313
}
314

315
void AdnlPeerTableImpl::write_new_addr_list_to_db(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id, AdnlDbItem node,
316
                                                  td::Promise<td::Unit> promise) {
317
  if (db_.empty()) {
318
    promise.set_value(td::Unit());
319
    return;
320
  }
321
  td::actor::send_closure(db_, &AdnlDb::update, local_id, peer_id, std::move(node), std::move(promise));
322
}
323

324
void AdnlPeerTableImpl::get_addr_list_from_db(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id,
325
                                              td::Promise<AdnlDbItem> promise) {
326
  if (db_.empty()) {
327
    promise.set_error(td::Status::Error(ErrorCode::notready, "db not inited"));
328
    return;
329
  }
330
  td::actor::send_closure(db_, &AdnlDb::get, local_id, peer_id, std::move(promise));
331
}
332

333
AdnlPeerTableImpl::AdnlPeerTableImpl(std::string db_root, td::actor::ActorId<keyring::Keyring> keyring) {
334
  keyring_ = keyring;
335
  static_nodes_manager_ = AdnlStaticNodesManager::create();
336

337
  if (!db_root.empty()) {
338
    db_ = AdnlDb::create(db_root + "/adnl");
339
  }
340
}
341

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));
346
  }
347
}
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));
353
  } else {
354
    LOG(WARNING) << "deliver query: unknown dst " << dst;
355
    promise.set_error(td::Status::Error(ErrorCode::notready, "cannot deliver: unknown DST"));
356
  }
357
}
358

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));
364
  } else {
365
    LOG(WARNING) << "decrypt message: unknown dst " << dst;
366
    promise.set_error(td::Status::Error(ErrorCode::notready, "cannot decrypt: unknown DST"));
367
  }
368
}
369

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)));
373
}
374

375
void AdnlPeerTableImpl::create_tunnel(AdnlNodeIdShort dst, td::uint32 size,
376
                                      td::Promise<std::pair<td::actor::ActorOwn<AdnlTunnel>, AdnlAddress>> promise) {
377
}
378

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");
383
    return;
384
  }
385
  td::actor::send_closure(it->second, &AdnlPeer::get_conn_ip_str, l_id, std::move(promise));
386
}
387

388
}  // namespace adnl
389

390
}  // namespace ton
391

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.