28
#include "adnl/adnl-network-manager.h"
30
#include "adnl/utils.hpp"
31
#include "keys/encryptor.h"
32
#include "td/utils/Time.h"
33
#include "td/utils/format.h"
34
#include "td/utils/OptionParser.h"
35
#include "td/utils/filesystem.h"
37
#include "auto/tl/ton_api_json.h"
38
#include "common/delay.h"
39
#include "td/utils/Random.h"
40
#include "terminal/terminal.h"
44
class AdnlNode : public td::actor::Actor {
46
td::actor::ActorOwn<ton::adnl::AdnlNetworkManager> network_manager_;
47
td::actor::ActorOwn<ton::adnl::Adnl> adnl_;
48
td::actor::ActorOwn<ton::keyring::Keyring> keyring_;
49
ton::adnl::AdnlNodeIdShort local_id_;
51
std::string host_ = "127.0.0.1";
52
td::uint16 port_ = 2380;
54
std::string global_config_ = "ton-global.config";
57
ton::adnl::AdnlNodeIdShort id;
58
td::uint32 sent = 0, received = 0;
59
double sum_time = 0.0;
60
explicit NodeInfo(ton::adnl::AdnlNodeIdShort id) : id(id) {
63
std::vector<NodeInfo> nodes_;
65
td::uint32 pings_remaining_ = 4;
66
td::uint32 pending_ = 1;
69
void set_global_config(std::string str) {
72
void listen_udp(td::uint16 port) {
80
network_manager_ = ton::adnl::AdnlNetworkManager::create(port_);
81
keyring_ = ton::keyring::Keyring::create("");
82
adnl_ = ton::adnl::Adnl::create("", keyring_.get());
83
td::actor::send_closure(adnl_, &ton::adnl::Adnl::register_network_manager, network_manager_.get());
86
addr.init_host_port(host_, port_).ensure();
87
ton::adnl::AdnlCategoryMask mask;
89
td::actor::send_closure(network_manager_, &ton::adnl::AdnlNetworkManager::add_self_addr, addr, mask, 0);
90
auto pk = ton::privkeys::Ed25519::random();
91
td::actor::send_closure(keyring_, &ton::keyring::Keyring::add_key, pk, true, [](td::Result<td::Unit>) {});
92
ton::adnl::AdnlNodeIdFull local_id_full(pk.pub());
93
ton::adnl::AdnlAddressList addr_list;
94
addr_list.set_version(static_cast<td::int32>(td::Clocks::system()));
95
addr_list.set_reinit_date(ton::adnl::Adnl::adnl_start_time());
96
td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_id, local_id_full, std::move(addr_list), (td::uint8)0);
97
local_id_ = local_id_full.compute_short_id();
99
auto r_dht = get_dht_config();
100
if (r_dht.is_error()) {
101
LOG(FATAL) << "Cannot get dht config: " << r_dht.move_as_error();
103
auto dht = r_dht.move_as_ok();
104
ton::adnl::AdnlNodesList static_nodes;
105
for (const auto &node : dht->nodes().list()) {
106
LOG(INFO) << "Node #" << nodes_.size() << " : " << node.adnl_id().compute_short_id();
107
nodes_.emplace_back(node.adnl_id().compute_short_id());
108
static_nodes.push(ton::adnl::AdnlNode(node.adnl_id(), node.addr_list()));
110
td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_static_nodes_from_config, std::move(static_nodes));
112
ton::delay_action([SelfId = actor_id(this)]() { td::actor::send_closure(SelfId, &AdnlNode::send_pings); },
113
td::Timestamp::in(1.0));
116
td::Result<std::shared_ptr<ton::dht::DhtGlobalConfig>> get_dht_config() {
117
TRY_RESULT_PREFIX(conf_data, td::read_file(global_config_), "failed to read: ");
118
TRY_RESULT_PREFIX(conf_json, td::json_decode(conf_data.as_slice()), "failed to parse json: ");
119
ton::ton_api::config_global conf;
120
TRY_STATUS_PREFIX(ton::ton_api::from_json(conf, conf_json.get_object()), "json does not fit TL scheme: ");
122
return td::Status::Error(ton::ErrorCode::error, "does not contain [dht] section");
124
TRY_RESULT_PREFIX(dht, ton::dht::Dht::create_global_config(std::move(conf.dht_)), "bad [dht] section: ");
125
return std::move(dht);
129
CHECK(pings_remaining_);
131
for (size_t i = 0; i < nodes_.size(); ++i) {
132
auto id = nodes_[i].id;
133
LOG(INFO) << "Sending ping to " << id;
135
td::actor::send_closure(
136
adnl_, &ton::adnl::Adnl::send_query, local_id_, id, "ping",
137
[SelfId = actor_id(this), i, timer = td::Timer()](td::Result<td::BufferSlice> R) {
138
td::actor::send_closure(SelfId, &AdnlNode::on_pong, i, timer.elapsed(), R.is_ok());
139
}, td::Timestamp::in(5.0),
140
ton::create_serialize_tl_object<ton::ton_api::dht_ping>(td::Random::fast_uint64()));
143
if (pings_remaining_ == 0) {
147
ton::delay_action([SelfId = actor_id(this)]() { td::actor::send_closure(SelfId, &AdnlNode::send_pings); },
148
td::Timestamp::in(1.0));
152
void on_pong(size_t i, double time, bool success) {
153
auto &node = nodes_[i];
157
node.sum_time += time;
158
LOG(INFO) << "Pong from " << node.id << " in " << time << "s";
160
LOG(INFO) << "Pong from " << node.id << " : timeout";
170
td::TerminalIO::out() << "Pinged " << nodes_.size() << " nodes:\n";
171
for (const auto& node : nodes_) {
172
td::TerminalIO::out() << node.id << " : " << node.received << "/" << node.sent;
173
if (node.received > 0) {
174
td::TerminalIO::out() << " (avg. time = " << node.sum_time / node.received << ")";
176
td::TerminalIO::out() << "\n";
182
int main(int argc, char *argv[]) {
183
td::actor::ActorOwn<AdnlNode> x;
186
p.set_description("ping dht servers from config");
187
p.add_option('h', "help", "print help", [&]() {
189
td::StringBuilder sb(td::MutableSlice{b, 10000});
191
std::cout << sb.as_cslice().c_str();
194
p.add_option('p', "port", "set udp port", [&](td::Slice port) {
195
td::actor::send_closure(x, &AdnlNode::listen_udp, static_cast<td::uint16>(std::stoi(port.str())));
197
p.add_option('C', "global-config", "file to read global config from",
198
[&](td::Slice fname) { td::actor::send_closure(x, &AdnlNode::set_global_config, fname.str()); });
199
p.add_option('v', "verbosity", "set verbosity", [&](td::Slice arg) {
200
int v = VERBOSITY_NAME(FATAL) + (td::to_integer<int>(arg));
201
SET_VERBOSITY_LEVEL(v);
204
td::actor::Scheduler scheduler({2});
206
scheduler.run_in_context([&] { x = td::actor::create_actor<AdnlNode>("AdnlNode"); });
208
scheduler.run_in_context([&] { p.run(argc, argv).ensure(); });
209
scheduler.run_in_context([&] { td::actor::send_closure(x, &AdnlNode::run); });