Ton

Форк
0
/
dht-remote-node.cpp 
149 строк · 5.3 Кб
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 "dht.hpp"
20

21
#include "td/utils/tl_storers.h"
22
#include "td/utils/crypto.h"
23
#include "td/utils/Random.h"
24

25
#include "td/utils/format.h"
26

27
#include "auto/tl/ton_api.hpp"
28

29
#include "dht-remote-node.hpp"
30

31
namespace ton {
32

33
namespace dht {
34

35
static const double PING_INTERVAL_DEFAULT = 60.0;
36
static const double PING_INTERVAL_MULTIPLIER = 1.1;
37
static const double PING_INTERVAL_MAX = 3600.0 * 4;
38

39
DhtRemoteNode::DhtRemoteNode(DhtNode node, td::uint32 max_missed_pings, td::int32 our_network_id)
40
    : node_(std::move(node))
41
    , max_missed_pings_(max_missed_pings)
42
    , our_network_id_(our_network_id)
43
    , ping_interval_(PING_INTERVAL_DEFAULT) {
44
  failed_from_ = td::Time::now_cached();
45
  id_ = node_.get_key();
46
}
47

48
td::Status DhtRemoteNode::receive_ping(DhtNode node, td::actor::ActorId<adnl::Adnl> adnl,
49
                                       adnl::AdnlNodeIdShort self_id) {
50
  TRY_STATUS(update_value(std::move(node), adnl, self_id));
51
  receive_ping();
52
  return td::Status::OK();
53
}
54

55
void DhtRemoteNode::receive_ping() {
56
  missed_pings_ = 0;
57
  ping_interval_ = PING_INTERVAL_DEFAULT;
58
  if (ready_from_ == 0) {
59
    ready_from_ = td::Time::now_cached();
60
  }
61
}
62

63
td::Status DhtRemoteNode::update_value(DhtNode node, td::actor::ActorId<adnl::Adnl> adnl,
64
                                       adnl::AdnlNodeIdShort self_id) {
65
  if (node.adnl_id() != node_.adnl_id()) {
66
    return td::Status::Error("Wrong adnl id");
67
  }
68
  if (node.version() <= node_.version()) {
69
    return td::Status::OK();
70
  }
71
  TRY_STATUS(node.check_signature());
72

73
  node_ = std::move(node);
74
  td::actor::send_closure(adnl, &adnl::Adnl::add_peer, self_id, node_.adnl_id(), node_.addr_list());
75
  return td::Status::OK();
76
}
77

78
void DhtRemoteNode::send_ping(bool client_only, td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<DhtMember> node,
79
                              adnl::AdnlNodeIdShort src) {
80
  missed_pings_++;
81
  if (missed_pings_ > max_missed_pings_) {
82
    ping_interval_ = std::min(ping_interval_ * PING_INTERVAL_MULTIPLIER, PING_INTERVAL_MAX);
83
    if (ready_from_ > 0) {
84
      ready_from_ = 0;
85
      failed_from_ = td::Time::now_cached();
86
    }
87
  }
88

89
  last_ping_at_ = td::Time::now_cached();
90

91
  td::actor::send_closure(adnl, &adnl::Adnl::add_peer, src, node_.adnl_id(), node_.addr_list());
92

93
  auto P = td::PromiseCreator::lambda([key = id_, id = node_.adnl_id().compute_short_id(), client_only, node, src, adnl,
94
                                       our_network_id = our_network_id_](td::Result<DhtNode> R) mutable {
95
    if (R.is_error()) {
96
      LOG(ERROR) << "[dht]: failed to get self node";
97
      return;
98
    }
99
    auto P = td::PromiseCreator::lambda([key, node, adnl, our_network_id](td::Result<td::BufferSlice> R) {
100
      if (R.is_error()) {
101
        VLOG(DHT_INFO) << "[dht]: received error for query to " << key << ": " << R.move_as_error();
102
        return;
103
      }
104
      auto F = fetch_tl_object<ton_api::dht_node>(R.move_as_ok(), true);
105

106
      if (F.is_ok()) {
107
        auto N = DhtNode::create(F.move_as_ok(), our_network_id);
108
        if (N.is_ok()) {
109
          td::actor::send_closure(node, &DhtMember::receive_ping, key, N.move_as_ok());
110
        } else {
111
          VLOG(DHT_WARNING) << "[dht]: bad answer from " << key
112
                            << ": dropping bad getSignedAddressList() query answer: " << N.move_as_error();
113
        }
114
      } else {
115
        VLOG(DHT_WARNING) << "[dht]: bad answer from " << key
116
                          << ": dropping invalid getSignedAddressList() query answer: " << F.move_as_error();
117
      }
118
    });
119
    auto Q = create_serialize_tl_object<ton_api::dht_getSignedAddressList>();
120
    td::BufferSlice B;
121
    if (client_only) {
122
      B = std::move(Q);
123
    } else {
124
      B = create_serialize_tl_object_suffix<ton_api::dht_query>(Q.as_slice(), R.move_as_ok().tl());
125
    }
126
    td::actor::send_closure(adnl, &adnl::Adnl::send_query, src, id, "dht ping", std::move(P),
127
                            td::Timestamp::in(10.0 + td::Random::fast(0, 100) * 0.1), std::move(B));
128
  });
129

130
  td::actor::send_closure(node, &DhtMember::get_self_node, std::move(P));
131
}
132

133
adnl::AdnlAddressList DhtRemoteNode::get_addr_list() const {
134
  return node_.addr_list();
135
}
136

137
adnl::AdnlNodeIdFull DhtRemoteNode::get_full_id() const {
138
  return node_.adnl_id();
139
}
140

141
td::Result<std::unique_ptr<DhtRemoteNode>> DhtRemoteNode::create(DhtNode node, td::uint32 max_missed_pings,
142
                                                                 td::int32 our_network_id) {
143
  TRY_STATUS(node.check_signature());
144
  return std::make_unique<DhtRemoteNode>(std::move(node), max_missed_pings, our_network_id);
145
}
146

147
}  // namespace dht
148

149
}  // namespace ton
150

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

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

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

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