Skip to content

Commit 1bef6df

Browse files
authored
Merge pull request #1156 from ton-blockchain/safe_features
Merge safe features branch
2 parents 0c21ce2 + 89e1cd9 commit 1bef6df

39 files changed

+1010
-207
lines changed

adnl/adnl-channel.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,16 @@ void AdnlChannelImpl::send_message(td::uint32 priority, td::actor::ActorId<AdnlN
112112
}
113113

114114
void AdnlChannelImpl::receive(td::IPAddress addr, td::BufferSlice data) {
115-
auto P = td::PromiseCreator::lambda(
116-
[peer = peer_pair_, channel_id = channel_in_id_, addr, id = print_id()](td::Result<AdnlPacket> R) {
117-
if (R.is_error()) {
118-
VLOG(ADNL_WARNING) << id << ": dropping IN message: can not decrypt: " << R.move_as_error();
119-
} else {
120-
auto packet = R.move_as_ok();
121-
packet.set_remote_addr(addr);
122-
td::actor::send_closure(peer, &AdnlPeerPair::receive_packet_from_channel, channel_id, std::move(packet));
123-
}
124-
});
115+
auto P = td::PromiseCreator::lambda([peer = peer_pair_, channel_id = channel_in_id_, addr, id = print_id(),
116+
size = data.size()](td::Result<AdnlPacket> R) {
117+
if (R.is_error()) {
118+
VLOG(ADNL_WARNING) << id << ": dropping IN message: can not decrypt: " << R.move_as_error();
119+
} else {
120+
auto packet = R.move_as_ok();
121+
packet.set_remote_addr(addr);
122+
td::actor::send_closure(peer, &AdnlPeerPair::receive_packet_from_channel, channel_id, std::move(packet), size);
123+
}
124+
});
125125

126126
decrypt(std::move(data), std::move(P));
127127
}

adnl/adnl-local-id.cpp

Lines changed: 86 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,34 @@ AdnlAddressList AdnlLocalId::get_addr_list() const {
4141
}
4242

4343
void AdnlLocalId::receive(td::IPAddress addr, td::BufferSlice data) {
44-
auto P = td::PromiseCreator::lambda(
45-
[peer_table = peer_table_, dst = short_id_, addr, id = print_id()](td::Result<AdnlPacket> R) {
46-
if (R.is_error()) {
47-
VLOG(ADNL_WARNING) << id << ": dropping IN message: cannot decrypt: " << R.move_as_error();
48-
} else {
49-
auto packet = R.move_as_ok();
50-
packet.set_remote_addr(addr);
51-
td::actor::send_closure(peer_table, &AdnlPeerTable::receive_decrypted_packet, dst, std::move(packet));
52-
}
53-
});
54-
44+
InboundRateLimiter& rate_limiter = inbound_rate_limiter_[addr];
45+
if (!rate_limiter.rate_limiter.take()) {
46+
VLOG(ADNL_NOTICE) << this << ": dropping IN message: rate limit exceeded";
47+
add_dropped_packet_stats(addr);
48+
return;
49+
}
50+
++rate_limiter.currently_decrypting_packets;
51+
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), peer_table = peer_table_, dst = short_id_, addr,
52+
id = print_id(), size = data.size()](td::Result<AdnlPacket> R) {
53+
td::actor::send_closure(SelfId, &AdnlLocalId::decrypt_packet_done, addr);
54+
if (R.is_error()) {
55+
VLOG(ADNL_WARNING) << id << ": dropping IN message: cannot decrypt: " << R.move_as_error();
56+
} else {
57+
auto packet = R.move_as_ok();
58+
packet.set_remote_addr(addr);
59+
td::actor::send_closure(peer_table, &AdnlPeerTable::receive_decrypted_packet, dst, std::move(packet), size);
60+
}
61+
});
5562
decrypt(std::move(data), std::move(P));
5663
}
5764

65+
void AdnlLocalId::decrypt_packet_done(td::IPAddress addr) {
66+
auto it = inbound_rate_limiter_.find(addr);
67+
CHECK(it != inbound_rate_limiter_.end());
68+
--it->second.currently_decrypting_packets;
69+
add_decrypted_packet_stats(addr);
70+
}
71+
5872
void AdnlLocalId::deliver(AdnlNodeIdShort src, td::BufferSlice data) {
5973
auto s = std::move(data);
6074
for (auto &cb : cb_) {
@@ -292,6 +306,67 @@ void AdnlLocalId::update_packet(AdnlPacket packet, bool update_id, bool sign, td
292306
}
293307
}
294308

309+
void AdnlLocalId::get_stats(td::Promise<tl_object_ptr<ton_api::adnl_stats_localId>> promise) {
310+
auto stats = create_tl_object<ton_api::adnl_stats_localId>();
311+
stats->short_id_ = short_id_.bits256_value();
312+
for (auto &[ip, x] : inbound_rate_limiter_) {
313+
if (x.currently_decrypting_packets != 0) {
314+
stats->current_decrypt_.push_back(create_tl_object<ton_api::adnl_stats_ipPackets>(
315+
ip.is_valid() ? PSTRING() << ip.get_ip_str() << ":" << ip.get_port() : "", x.currently_decrypting_packets));
316+
}
317+
}
318+
prepare_packet_stats();
319+
stats->packets_recent_ = packet_stats_prev_.tl();
320+
stats->packets_total_ = packet_stats_total_.tl();
321+
stats->packets_total_->ts_start_ = (double)Adnl::adnl_start_time();
322+
stats->packets_total_->ts_end_ = td::Clocks::system();
323+
promise.set_result(std::move(stats));
324+
}
325+
326+
void AdnlLocalId::add_decrypted_packet_stats(td::IPAddress addr) {
327+
prepare_packet_stats();
328+
++packet_stats_cur_.decrypted_packets[addr];
329+
++packet_stats_total_.decrypted_packets[addr];
330+
}
331+
332+
void AdnlLocalId::add_dropped_packet_stats(td::IPAddress addr) {
333+
prepare_packet_stats();
334+
++packet_stats_cur_.dropped_packets[addr];
335+
++packet_stats_total_.dropped_packets[addr];
336+
}
337+
338+
void AdnlLocalId::prepare_packet_stats() {
339+
double now = td::Clocks::system();
340+
if (now >= packet_stats_cur_.ts_end) {
341+
packet_stats_prev_ = std::move(packet_stats_cur_);
342+
packet_stats_cur_ = {};
343+
auto now_int = (int)td::Clocks::system();
344+
packet_stats_cur_.ts_start = (double)(now_int / 60 * 60);
345+
packet_stats_cur_.ts_end = packet_stats_cur_.ts_start + 60.0;
346+
if (packet_stats_prev_.ts_end < now - 60.0) {
347+
packet_stats_prev_ = {};
348+
packet_stats_prev_.ts_end = packet_stats_cur_.ts_start;
349+
packet_stats_prev_.ts_start = packet_stats_prev_.ts_end - 60.0;
350+
}
351+
}
352+
}
353+
354+
tl_object_ptr<ton_api::adnl_stats_localIdPackets> AdnlLocalId::PacketStats::tl() const {
355+
auto obj = create_tl_object<ton_api::adnl_stats_localIdPackets>();
356+
obj->ts_start_ = ts_start;
357+
obj->ts_end_ = ts_end;
358+
for (const auto &[ip, packets] : decrypted_packets) {
359+
obj->decrypted_packets_.push_back(create_tl_object<ton_api::adnl_stats_ipPackets>(
360+
ip.is_valid() ? PSTRING() << ip.get_ip_str() << ":" << ip.get_port() : "", packets));
361+
}
362+
for (const auto &[ip, packets] : dropped_packets) {
363+
obj->dropped_packets_.push_back(create_tl_object<ton_api::adnl_stats_ipPackets>(
364+
ip.is_valid() ? PSTRING() << ip.get_ip_str() << ":" << ip.get_port() : "", packets));
365+
}
366+
return obj;
367+
}
368+
369+
295370
} // namespace adnl
296371

297372
} // namespace ton

adnl/adnl-local-id.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class AdnlLocalId : public td::actor::Actor {
5555
void deliver(AdnlNodeIdShort src, td::BufferSlice data);
5656
void deliver_query(AdnlNodeIdShort src, td::BufferSlice data, td::Promise<td::BufferSlice> promise);
5757
void receive(td::IPAddress addr, td::BufferSlice data);
58+
void decrypt_packet_done(td::IPAddress addr);
5859

5960
void subscribe(std::string prefix, std::unique_ptr<AdnlPeerTable::Callback> callback);
6061
void unsubscribe(std::string prefix);
@@ -77,6 +78,8 @@ class AdnlLocalId : public td::actor::Actor {
7778
void update_packet(AdnlPacket packet, bool update_id, bool sign, td::int32 update_addr_list_if,
7879
td::int32 update_priority_addr_list_if, td::Promise<AdnlPacket> promise);
7980

81+
void get_stats(td::Promise<tl_object_ptr<ton_api::adnl_stats_localId>> promise);
82+
8083
td::uint32 get_mode() {
8184
return mode_;
8285
}
@@ -101,6 +104,22 @@ class AdnlLocalId : public td::actor::Actor {
101104

102105
td::uint32 mode_;
103106

107+
struct InboundRateLimiter {
108+
RateLimiter rate_limiter = RateLimiter(75, 0.33);
109+
td::uint64 currently_decrypting_packets = 0;
110+
};
111+
std::map<td::IPAddress, InboundRateLimiter> inbound_rate_limiter_;
112+
struct PacketStats {
113+
double ts_start = 0.0, ts_end = 0.0;
114+
std::map<td::IPAddress, td::uint64> decrypted_packets;
115+
std::map<td::IPAddress, td::uint64> dropped_packets;
116+
117+
tl_object_ptr<ton_api::adnl_stats_localIdPackets> tl() const;
118+
} packet_stats_cur_, packet_stats_prev_, packet_stats_total_;
119+
void add_decrypted_packet_stats(td::IPAddress addr);
120+
void add_dropped_packet_stats(td::IPAddress addr);
121+
void prepare_packet_stats();
122+
104123
void publish_address_list();
105124
};
106125

adnl/adnl-peer-table.cpp

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ void AdnlPeerTableImpl::receive_packet(td::IPAddress addr, AdnlCategoryMask cat_
8484
<< " (len=" << (data.size() + 32) << ")";
8585
}
8686

87-
void AdnlPeerTableImpl::receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket packet) {
87+
void AdnlPeerTableImpl::receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket packet, td::uint64 serialized_size) {
8888
packet.run_basic_checks().ensure();
8989

9090
if (!packet.inited_from_short()) {
@@ -119,7 +119,7 @@ void AdnlPeerTableImpl::receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket
119119
return;
120120
}
121121
td::actor::send_closure(it->second, &AdnlPeer::receive_packet, dst, it2->second.mode, it2->second.local_id.get(),
122-
std::move(packet));
122+
std::move(packet), serialized_size);
123123
}
124124

125125
void AdnlPeerTableImpl::add_peer(AdnlNodeIdShort local_id, AdnlNodeIdFull id, AdnlAddressList addr_list) {
@@ -385,6 +385,88 @@ void AdnlPeerTableImpl::get_conn_ip_str(AdnlNodeIdShort l_id, AdnlNodeIdShort p_
385385
td::actor::send_closure(it->second, &AdnlPeer::get_conn_ip_str, l_id, std::move(promise));
386386
}
387387

388+
void AdnlPeerTableImpl::get_stats(td::Promise<tl_object_ptr<ton_api::adnl_stats>> promise) {
389+
class Cb : public td::actor::Actor {
390+
public:
391+
explicit Cb(td::Promise<tl_object_ptr<ton_api::adnl_stats>> promise) : promise_(std::move(promise)) {
392+
}
393+
394+
void got_local_id_stats(tl_object_ptr<ton_api::adnl_stats_localId> local_id) {
395+
auto &local_id_stats = local_id_stats_[local_id->short_id_];
396+
if (local_id_stats) {
397+
local_id->peers_ = std::move(local_id_stats->peers_);
398+
}
399+
local_id_stats = std::move(local_id);
400+
dec_pending();
401+
}
402+
403+
void got_peer_stats(std::vector<tl_object_ptr<ton_api::adnl_stats_peerPair>> peer_pairs) {
404+
for (auto &peer_pair : peer_pairs) {
405+
auto &local_id_stats = local_id_stats_[peer_pair->local_id_];
406+
if (local_id_stats == nullptr) {
407+
local_id_stats = create_tl_object<ton_api::adnl_stats_localId>();
408+
local_id_stats->short_id_ = peer_pair->local_id_;
409+
}
410+
local_id_stats->peers_.push_back(std::move(peer_pair));
411+
}
412+
dec_pending();
413+
}
414+
415+
void inc_pending() {
416+
++pending_;
417+
}
418+
419+
void dec_pending() {
420+
CHECK(pending_ > 0);
421+
--pending_;
422+
if (pending_ == 0) {
423+
auto stats = create_tl_object<ton_api::adnl_stats>();
424+
stats->timestamp_ = td::Clocks::system();
425+
for (auto &[id, local_id_stats] : local_id_stats_) {
426+
stats->local_ids_.push_back(std::move(local_id_stats));
427+
}
428+
promise_.set_result(std::move(stats));
429+
stop();
430+
}
431+
}
432+
433+
private:
434+
td::Promise<tl_object_ptr<ton_api::adnl_stats>> promise_;
435+
size_t pending_ = 1;
436+
437+
std::map<td::Bits256, tl_object_ptr<ton_api::adnl_stats_localId>> local_id_stats_;
438+
};
439+
auto callback = td::actor::create_actor<Cb>("adnlstats", std::move(promise)).release();
440+
441+
for (auto &[id, local_id] : local_ids_) {
442+
td::actor::send_closure(callback, &Cb::inc_pending);
443+
td::actor::send_closure(local_id.local_id, &AdnlLocalId::get_stats,
444+
[id = id, callback](td::Result<tl_object_ptr<ton_api::adnl_stats_localId>> R) {
445+
if (R.is_error()) {
446+
VLOG(ADNL_NOTICE)
447+
<< "failed to get stats for local id " << id << " : " << R.move_as_error();
448+
td::actor::send_closure(callback, &Cb::dec_pending);
449+
} else {
450+
td::actor::send_closure(callback, &Cb::got_local_id_stats, R.move_as_ok());
451+
}
452+
});
453+
}
454+
for (auto &[id, peer] : peers_) {
455+
td::actor::send_closure(callback, &Cb::inc_pending);
456+
td::actor::send_closure(
457+
peer, &AdnlPeer::get_stats,
458+
[id = id, callback](td::Result<std::vector<tl_object_ptr<ton_api::adnl_stats_peerPair>>> R) {
459+
if (R.is_error()) {
460+
VLOG(ADNL_NOTICE) << "failed to get stats for peer " << id << " : " << R.move_as_error();
461+
td::actor::send_closure(callback, &Cb::dec_pending);
462+
} else {
463+
td::actor::send_closure(callback, &Cb::got_peer_stats, R.move_as_ok());
464+
}
465+
});
466+
}
467+
td::actor::send_closure(callback, &Cb::dec_pending);
468+
}
469+
388470
} // namespace adnl
389471

390472
} // namespace ton

adnl/adnl-peer-table.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ class AdnlPeerTable : public Adnl {
9090
virtual void answer_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlQueryId query_id, td::BufferSlice data) = 0;
9191

9292
virtual void receive_packet(td::IPAddress addr, AdnlCategoryMask cat_mask, td::BufferSlice data) = 0;
93-
virtual void receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket packet) = 0;
93+
virtual void receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket packet, td::uint64 serialized_size) = 0;
9494
virtual void send_message_in(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlMessage message, td::uint32 flags) = 0;
9595

9696
virtual void register_channel(AdnlChannelIdShort id, AdnlNodeIdShort local_id,

adnl/adnl-peer-table.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class AdnlPeerTableImpl : public AdnlPeerTable {
4444
void add_static_nodes_from_config(AdnlNodesList nodes) override;
4545

4646
void receive_packet(td::IPAddress addr, AdnlCategoryMask cat_mask, td::BufferSlice data) override;
47-
void receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket data) override;
47+
void receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket data, td::uint64 serialized_size) override;
4848
void send_message_in(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlMessage message, td::uint32 flags) override;
4949
void send_message(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data) override {
5050
send_message_ex(src, dst, std::move(data), 0);
@@ -108,6 +108,8 @@ class AdnlPeerTableImpl : public AdnlPeerTable {
108108
td::Promise<std::pair<td::actor::ActorOwn<AdnlTunnel>, AdnlAddress>> promise) override;
109109
void get_conn_ip_str(AdnlNodeIdShort l_id, AdnlNodeIdShort p_id, td::Promise<td::string> promise) override;
110110

111+
void get_stats(td::Promise<tl_object_ptr<ton_api::adnl_stats>> promise) override;
112+
111113
struct PrintId {};
112114
PrintId print_id() const {
113115
return PrintId{};

0 commit comments

Comments
 (0)