Skip to content

Commit

Permalink
emergency update
Browse files Browse the repository at this point in the history
  • Loading branch information
ton committed Mar 23, 2020
1 parent 5d846e0 commit 9f351fc
Show file tree
Hide file tree
Showing 87 changed files with 2,473 additions and 642 deletions.
2 changes: 1 addition & 1 deletion adnl/adnl-address-list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once

Expand Down
2 changes: 1 addition & 1 deletion adnl/adnl-message.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once

Expand Down
239 changes: 212 additions & 27 deletions adnl/adnl-network-manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
#include "adnl-network-manager.hpp"
#include "adnl-peer-table.h"

#include "auto/tl/ton_api.hpp"

#include "td/utils/overloaded.h"

namespace ton {

namespace adnl {
Expand All @@ -27,25 +31,84 @@ td::actor::ActorOwn<AdnlNetworkManager> AdnlNetworkManager::create(td::uint16 po
return td::actor::create_actor<AdnlNetworkManagerImpl>("NetworkManager", port);
}

void AdnlNetworkManagerImpl::add_listening_udp_port(td::uint16 port) {
AdnlNetworkManagerImpl::OutDesc *AdnlNetworkManagerImpl::choose_out_iface(td::uint8 cat, td::uint32 priority) {
auto it = out_desc_.upper_bound(priority);
while (true) {
if (it == out_desc_.begin()) {
return nullptr;
}
it--;

auto &v = it->second;
for (auto &x : v) {
if (x.cat_mask.test(cat)) {
return &x;
}
}
}
}

size_t AdnlNetworkManagerImpl::add_listening_udp_port(td::uint16 port) {
auto it = port_2_socket_.find(port);
if (it != port_2_socket_.end()) {
return it->second;
}
class Callback : public td::UdpServer::Callback {
public:
Callback(td::actor::ActorShared<AdnlNetworkManagerImpl> manager) : manager_(std::move(manager)) {
Callback(td::actor::ActorShared<AdnlNetworkManagerImpl> manager, size_t idx)
: manager_(std::move(manager)), idx_(idx) {
}

private:
td::actor::ActorShared<AdnlNetworkManagerImpl> manager_;
size_t idx_;
void on_udp_message(td::UdpMessage udp_message) override {
td::actor::send_closure_later(manager_, &AdnlNetworkManagerImpl::receive_udp_message, std::move(udp_message));
td::actor::send_closure_later(manager_, &AdnlNetworkManagerImpl::receive_udp_message, std::move(udp_message),
idx_);
}
};

auto X = td::UdpServer::create("udp server", port, std::make_unique<Callback>(actor_shared(this)));
auto idx = udp_sockets_.size();
auto X = td::UdpServer::create("udp server", port, std::make_unique<Callback>(actor_shared(this), idx));
X.ensure();
udp_servers_.emplace(port, X.move_as_ok());
port_2_socket_[port] = idx;
udp_sockets_.push_back(UdpSocketDesc{port, X.move_as_ok()});
return idx;
}

void AdnlNetworkManagerImpl::receive_udp_message(td::UdpMessage message) {
void AdnlNetworkManagerImpl::add_self_addr(td::IPAddress addr, AdnlCategoryMask cat_mask, td::uint32 priority) {
auto port = td::narrow_cast<td::uint16>(addr.get_port());
size_t idx = add_listening_udp_port(port);
add_in_addr(InDesc{port, nullptr, cat_mask}, idx);
auto d = OutDesc{port, td::IPAddress{}, nullptr, idx};
for (auto &it : out_desc_[priority]) {
if (it == d) {
it.cat_mask |= cat_mask;
return;
}
}

d.cat_mask = cat_mask;
out_desc_[priority].push_back(std::move(d));
}

void AdnlNetworkManagerImpl::add_proxy_addr(td::IPAddress addr, td::uint16 local_port, std::shared_ptr<AdnlProxy> proxy,
AdnlCategoryMask cat_mask, td::uint32 priority) {
size_t idx = add_listening_udp_port(local_port);
add_in_addr(InDesc{local_port, proxy, cat_mask}, idx);
auto d = OutDesc{local_port, addr, proxy, idx};
for (auto &it : out_desc_[priority]) {
if (it == d) {
it.cat_mask |= cat_mask;
return;
}
}
d.cat_mask = cat_mask;
proxy_register(d);
out_desc_[priority].push_back(std::move(d));
}

void AdnlNetworkManagerImpl::receive_udp_message(td::UdpMessage message, size_t idx) {
if (!callback_) {
LOG(ERROR) << this << ": dropping IN message [?->?]: peer table unitialized";
return;
Expand All @@ -54,6 +117,96 @@ void AdnlNetworkManagerImpl::receive_udp_message(td::UdpMessage message) {
VLOG(ADNL_WARNING) << this << ": dropping ERROR message: " << message.error;
return;
}
if (message.data.size() < 32) {
VLOG(ADNL_WARNING) << this << ": received too small proxy packet of size " << message.data.size();
return;
}
if (message.data.size() >= get_mtu() + 128) {
VLOG(ADNL_NOTICE) << this << ": received huge packet of size " << message.data.size();
}
CHECK(idx < udp_sockets_.size());
auto &socket = udp_sockets_[idx];
AdnlCategoryMask cat_mask;
bool from_proxy = false;
if (socket.allow_proxy) {
td::Bits256 x;
x.as_slice().copy_from(message.data.as_slice().truncate(32));
auto it = proxy_addrs_.find(x);
if (it != proxy_addrs_.end()) {
from_proxy = true;
CHECK(it->second < in_desc_.size());
auto &proxy_iface = in_desc_[it->second];
CHECK(proxy_iface.is_proxy());
auto R = in_desc_[it->second].proxy->decrypt(std::move(message.data));
if (R.is_error()) {
VLOG(ADNL_WARNING) << this << ": failed to decrypt proxy mesage: " << R.move_as_error();
return;
}
auto packet = R.move_as_ok();
if (packet.flags & 1) {
message.address.init_host_port(td::IPAddress::ipv4_to_str(packet.ip), packet.port).ensure();
} else {
message.address = td::IPAddress{};
}
if ((packet.flags & 6) == 6) {
if (proxy_iface.received.packet_is_delivered(packet.adnl_start_time, packet.seqno)) {
VLOG(ADNL_WARNING) << this << ": dropping duplicate proxy packet";
return;
}
}
if (packet.flags & 8) {
if (packet.date < td::Clocks::system() - 60 || packet.date > td::Clocks::system() + 60) {
VLOG(ADNL_WARNING) << this << ": dropping proxy packet: bad time " << packet.date;
return;
}
}
if (!(packet.flags & (1 << 16))) {
VLOG(ADNL_WARNING) << this << ": dropping proxy packet: packet has outbound flag";
return;
}
if (packet.flags & (1 << 17)) {
auto F = fetch_tl_object<ton_api::adnl_ProxyControlPacket>(std::move(packet.data), true);
if (F.is_error()) {
VLOG(ADNL_WARNING) << this << ": dropping proxy packet: bad control packet";
return;
}
ton_api::downcast_call(*F.move_as_ok().get(),
td::overloaded(
[&](const ton_api::adnl_proxyControlPacketPing &f) {
auto &v = *proxy_iface.out_desc;
auto data =
create_serialize_tl_object<ton_api::adnl_proxyControlPacketPong>(f.id_);
AdnlProxy::Packet p;
p.flags = 6 | (1 << 17);
p.ip = 0;
p.port = 0;
p.data = std::move(data);
p.adnl_start_time = Adnl::adnl_start_time();
p.seqno = ++v.out_seqno;

auto enc = v.proxy->encrypt(std::move(p));

td::UdpMessage M;
M.address = v.proxy_addr;
M.data = std::move(enc);

td::actor::send_closure(socket.server, &td::UdpServer::send, std::move(M));
},
[&](const ton_api::adnl_proxyControlPacketPong &f) {},
[&](const ton_api::adnl_proxyControlPacketRegister &f) {}));
return;
}
message.data = std::move(packet.data);
cat_mask = in_desc_[it->second].cat_mask;
}
}
if (!from_proxy) {
if (socket.in_desc == std::numeric_limits<size_t>::max()) {
VLOG(ADNL_WARNING) << this << ": received bad packet to proxy-only listenung port";
return;
}
cat_mask = in_desc_[socket.in_desc].cat_mask;
}
if (message.data.size() >= get_mtu()) {
VLOG(ADNL_NOTICE) << this << ": received huge packet of size " << message.data.size();
}
Expand All @@ -63,49 +216,81 @@ void AdnlNetworkManagerImpl::receive_udp_message(td::UdpMessage message) {
}

VLOG(ADNL_EXTRA_DEBUG) << this << ": received message of size " << message.data.size();
callback_->receive_packet(message.address, std::move(message.data));
callback_->receive_packet(message.address, cat_mask, std::move(message.data));
}

void AdnlNetworkManagerImpl::send_udp_packet(AdnlNodeIdShort src_id, AdnlNodeIdShort dst_id, td::IPAddress dst_addr,
td::uint32 priority, td::BufferSlice data) {
auto randseed = 1; // use DST?
while (priority > 0) {
if (out_desc_[priority].size() > 0) {
break;
}
priority--;
auto it = adnl_id_2_cat_.find(src_id);
if (it == adnl_id_2_cat_.end()) {
VLOG(ADNL_WARNING) << this << ": dropping OUT message [" << src_id << "->" << dst_id << "]: unknown src";
return;
}
if (out_desc_[priority].size() == 0) {
VLOG(ADNL_WARNING) << this << ": dropping OUT message [" << src_id << "->" << dst_id << "]: no out desc";

auto out = choose_out_iface(it->second, priority);
if (!out) {
VLOG(ADNL_WARNING) << this << ": dropping OUT message [" << src_id << "->" << dst_id << "]: no out rules";
return;
}

auto &dv = out_desc_[priority];
auto &v = dv[randseed % dv.size()];
auto &v = *out;
auto &socket = udp_sockets_[v.socket_idx];

if (!v.is_proxy()) {
auto it = udp_servers_.find(static_cast<td::uint16>(v.addr.get_port()));
CHECK(it != udp_servers_.end());

td::UdpMessage M;
M.address = dst_addr;
M.data = std::move(data);

CHECK(M.data.size() <= get_mtu());

td::actor::send_closure(it->second, &td::UdpServer::send, std::move(M));
td::actor::send_closure(socket.server, &td::UdpServer::send, std::move(M));
} else {
auto it = udp_servers_.find(out_udp_port_);
CHECK(it != udp_servers_.end());
AdnlProxy::Packet p;
p.flags = 7;
p.ip = dst_addr.get_ipv4();
p.port = static_cast<td::uint16>(dst_addr.get_port());
p.data = std::move(data);
p.adnl_start_time = Adnl::adnl_start_time();
p.seqno = ++v.out_seqno;

auto enc = v.proxy->encrypt(
AdnlProxy::Packet{dst_addr.get_ipv4(), static_cast<td::uint16>(dst_addr.get_port()), std::move(data)});
auto enc = v.proxy->encrypt(std::move(p));

td::UdpMessage M;
M.address = v.addr;
M.address = v.proxy_addr;
M.data = std::move(enc);

td::actor::send_closure(it->second, &td::UdpServer::send, std::move(M));
td::actor::send_closure(socket.server, &td::UdpServer::send, std::move(M));
}
}

void AdnlNetworkManagerImpl::proxy_register(OutDesc &desc) {
auto data = create_serialize_tl_object<ton_api::adnl_proxyControlPacketRegister>(0, 0);
AdnlProxy::Packet p;
p.flags = 6 | (1 << 17);
p.ip = 0;
p.port = 0;
p.data = std::move(data);
p.adnl_start_time = Adnl::adnl_start_time();
p.seqno = ++desc.out_seqno;

auto enc = desc.proxy->encrypt(std::move(p));

td::UdpMessage M;
M.address = desc.proxy_addr;
M.data = std::move(enc);

auto &socket = udp_sockets_[desc.socket_idx];
td::actor::send_closure(socket.server, &td::UdpServer::send, std::move(M));
}

void AdnlNetworkManagerImpl::alarm() {
alarm_timestamp() = td::Timestamp::in(60.0);
for (auto &vec : out_desc_) {
for (auto &desc : vec.second) {
if (desc.is_proxy()) {
proxy_register(desc);
}
}
}
}

Expand Down
14 changes: 10 additions & 4 deletions adnl/adnl-network-manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once

Expand All @@ -26,6 +26,8 @@
#include "adnl-node-id.hpp"
#include "adnl-proxy-types.h"

#include <bitset>

namespace td {
class UdpServer;
}
Expand All @@ -36,6 +38,8 @@ namespace adnl {

class AdnlPeerTable;

using AdnlCategoryMask = std::bitset<256>;

class AdnlNetworkConnection : public td::actor::Actor {
public:
class Callback {
Expand All @@ -56,22 +60,24 @@ class AdnlNetworkManager : public td::actor::Actor {
public:
virtual ~Callback() = default;
//virtual void receive_packet(td::IPAddress addr, ConnHandle conn_handle, td::BufferSlice data) = 0;
virtual void receive_packet(td::IPAddress addr, td::BufferSlice data) = 0;
virtual void receive_packet(td::IPAddress addr, AdnlCategoryMask cat_mask, td::BufferSlice data) = 0;
};
static td::actor::ActorOwn<AdnlNetworkManager> create(td::uint16 out_port);

virtual ~AdnlNetworkManager() = default;

virtual void install_callback(std::unique_ptr<Callback> callback) = 0;

virtual void add_self_addr(td::IPAddress addr, td::uint32 priority) = 0;
virtual void add_proxy_addr(td::IPAddress addr, std::shared_ptr<AdnlProxy> proxy, td::uint32 priority) = 0;
virtual void add_self_addr(td::IPAddress addr, AdnlCategoryMask cat_mask, td::uint32 priority) = 0;
virtual void add_proxy_addr(td::IPAddress addr, td::uint16 local_port, std::shared_ptr<AdnlProxy> proxy,
AdnlCategoryMask cat_mask, td::uint32 priority) = 0;
virtual void send_udp_packet(AdnlNodeIdShort src_id, AdnlNodeIdShort dst_id, td::IPAddress dst_addr,
td::uint32 priority, td::BufferSlice data) = 0;
//virtual void send_tcp_packet(AdnlNodeIdShort src_id, AdnlNodeIdShort dst_id, td::IPAddress dst_addr,
// td::uint32 priority, td::BufferSlice data) = 0;
//virtual void send_answer_packet(AdnlNodeIdShort src_id, AdnlNodeIdShort dst_id, td::IPAddress dst_addr,
// ConnHandle conn_handle, td::uint32 priority, td::BufferSlice data) = 0;
virtual void set_local_id_category(AdnlNodeIdShort id, td::uint8 cat) = 0;

static constexpr td::uint32 get_mtu() {
return 1440;
Expand Down

0 comments on commit 9f351fc

Please sign in to comment.