1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

emergency update

This commit is contained in:
ton 2020-03-24 03:32:16 +04:00
parent 5d846e0aaf
commit 9f351fc29f
87 changed files with 2486 additions and 655 deletions

View file

@ -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

View file

@ -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

View file

@ -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 {
@ -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;
@ -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();
}
@ -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--;
}
if (out_desc_[priority].size() == 0) {
VLOG(ADNL_WARNING) << this << ": dropping OUT message [" << src_id << "->" << dst_id << "]: no out desc";
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;
}
auto &dv = out_desc_[priority];
auto &v = dv[randseed % dv.size()];
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 &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);
}
}
}
}

View file

@ -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
@ -26,6 +26,8 @@
#include "adnl-node-id.hpp"
#include "adnl-proxy-types.h"
#include <bitset>
namespace td {
class UdpServer;
}
@ -36,6 +38,8 @@ namespace adnl {
class AdnlPeerTable;
using AdnlCategoryMask = std::bitset<256>;
class AdnlNetworkConnection : public td::actor::Actor {
public:
class Callback {
@ -56,7 +60,7 @@ 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);
@ -64,14 +68,16 @@ class AdnlNetworkManager : public td::actor::Actor {
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;

View file

@ -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
@ -25,6 +25,7 @@
#include "td/actor/PromiseFuture.h"
#include "adnl-network-manager.h"
#include "adnl-received-mask.h"
#include <map>
@ -41,16 +42,61 @@ class AdnlPeerTable;
class AdnlNetworkManagerImpl : public AdnlNetworkManager {
public:
struct OutDesc {
td::IPAddress addr;
td::uint16 port;
td::IPAddress proxy_addr;
std::shared_ptr<AdnlProxy> proxy;
size_t socket_idx;
td::int64 out_seqno{0};
AdnlCategoryMask cat_mask{0};
bool is_proxy() const {
return proxy != nullptr;
}
bool operator==(const OutDesc &with) const {
return addr == with.addr && is_proxy() == with.is_proxy();
if (port != with.port) {
return false;
}
if (!is_proxy()) {
return !with.is_proxy();
}
if (!with.is_proxy()) {
return false;
}
return proxy_addr == with.proxy_addr && proxy->id() == with.proxy->id();
}
};
struct InDesc {
td::uint16 port;
std::shared_ptr<AdnlProxy> proxy;
AdnlCategoryMask cat_mask;
AdnlReceivedMaskVersion received{};
OutDesc *out_desc = nullptr;
bool is_proxy() const {
return proxy != nullptr;
}
bool operator==(const InDesc &with) const {
if (port != with.port) {
return false;
}
if (!is_proxy()) {
return !with.is_proxy();
}
if (!with.is_proxy()) {
return false;
}
return proxy->id() == with.proxy->id();
}
};
struct UdpSocketDesc {
UdpSocketDesc(td::uint16 port, td::actor::ActorOwn<td::UdpServer> server) : port(port), server(std::move(server)) {
}
td::uint16 port;
td::actor::ActorOwn<td::UdpServer> server;
size_t in_desc{std::numeric_limits<size_t>::max()};
bool allow_proxy{false};
};
OutDesc *choose_out_iface(td::uint8 cat, td::uint32 priority);
AdnlNetworkManagerImpl(td::uint16 out_udp_port) : out_udp_port_(out_udp_port) {
}
@ -59,45 +105,60 @@ class AdnlNetworkManagerImpl : public AdnlNetworkManager {
callback_ = std::move(callback);
}
void add_self_addr(td::IPAddress addr, td::uint32 priority) override {
auto x = OutDesc{addr, nullptr};
auto &v = out_desc_[priority];
for (auto &y : v) {
if (x == y) {
void alarm() override;
void start_up() override {
alarm_timestamp() = td::Timestamp::in(60.0);
}
void add_in_addr(InDesc desc, size_t socket_idx) {
for (size_t idx = 0; idx < in_desc_.size(); idx++) {
if (in_desc_[idx] == desc) {
in_desc_[idx].cat_mask |= desc.cat_mask;
return;
}
}
out_desc_[priority].push_back(std::move(x));
add_listening_udp_port(static_cast<td::uint16>(addr.get_port()));
}
void add_proxy_addr(td::IPAddress addr, std::shared_ptr<AdnlProxy> proxy, td::uint32 priority) override {
auto x = OutDesc{addr, std::move(proxy)};
auto &v = out_desc_[priority];
for (auto &y : v) {
if (x == y) {
return;
}
}
out_desc_[priority].push_back(std::move(x));
if (!udp_servers_.count(out_udp_port_)) {
add_listening_udp_port(out_udp_port_);
if (desc.is_proxy()) {
udp_sockets_[socket_idx].allow_proxy = true;
proxy_addrs_[desc.proxy->id()] = in_desc_.size();
} else {
CHECK(udp_sockets_[socket_idx].in_desc == std::numeric_limits<size_t>::max());
udp_sockets_[socket_idx].in_desc = in_desc_.size();
}
in_desc_.push_back(std::move(desc));
}
void add_self_addr(td::IPAddress addr, AdnlCategoryMask cat_mask, td::uint32 priority) override;
void add_proxy_addr(td::IPAddress addr, td::uint16 local_port, std::shared_ptr<AdnlProxy> proxy,
AdnlCategoryMask cat_mask, td::uint32 priority) override;
void send_udp_packet(AdnlNodeIdShort src_id, AdnlNodeIdShort dst_id, td::IPAddress dst_addr, td::uint32 priority,
td::BufferSlice data) override;
void add_listening_udp_port(td::uint16 port);
void receive_udp_message(td::UdpMessage message);
void set_local_id_category(AdnlNodeIdShort id, td::uint8 cat) override {
if (cat == 255) {
adnl_id_2_cat_.erase(id);
} else {
adnl_id_2_cat_[id] = cat;
}
}
size_t add_listening_udp_port(td::uint16 port);
void receive_udp_message(td::UdpMessage message, size_t idx);
void proxy_register(OutDesc &desc);
private:
std::unique_ptr<Callback> callback_;
std::map<td::uint32, std::vector<OutDesc>> out_desc_;
std::vector<InDesc> in_desc_;
std::map<td::Bits256, size_t> proxy_addrs_;
td::uint64 received_messages_ = 0;
td::uint64 sent_messages_ = 0;
std::map<td::uint16, td::actor::ActorOwn<td::UdpServer>> udp_servers_;
std::vector<UdpSocketDesc> udp_sockets_;
std::map<td::uint16, size_t> port_2_socket_;
std::map<AdnlNodeIdShort, td::uint8> adnl_id_2_cat_;
td::uint16 out_udp_port_;
};

View file

@ -30,6 +30,7 @@
#include "utils.hpp"
#include "adnl-query.h"
#include "adnl-ext-client.h"
#include "adnl-tunnel.h"
namespace ton {
@ -49,7 +50,7 @@ td::actor::ActorOwn<Adnl> Adnl::create(std::string db, td::actor::ActorId<keyrin
return td::actor::ActorOwn<Adnl>(td::actor::create_actor<AdnlPeerTableImpl>("PeerTable", db, keyring));
}
void AdnlPeerTableImpl::receive_packet(td::IPAddress addr, td::BufferSlice data) {
void AdnlPeerTableImpl::receive_packet(td::IPAddress addr, AdnlCategoryMask cat_mask, td::BufferSlice data) {
if (data.size() < 32) {
VLOG(ADNL_WARNING) << this << ": dropping IN message [?->?]: message too short: len=" << data.size();
return;
@ -60,14 +61,22 @@ void AdnlPeerTableImpl::receive_packet(td::IPAddress addr, td::BufferSlice data)
auto it = local_ids_.find(dst);
if (it != local_ids_.end()) {
td::actor::send_closure(it->second.first, &AdnlLocalId::receive, addr, std::move(data));
if (!cat_mask.test(it->second.cat)) {
VLOG(ADNL_WARNING) << this << ": dropping IN message [?->" << dst << "]: category mismatch";
return;
}
td::actor::send_closure(it->second.local_id, &AdnlLocalId::receive, addr, std::move(data));
return;
}
AdnlChannelIdShort dst_chan_id{dst.pubkey_hash()};
auto it2 = channels_.find(dst_chan_id);
if (it2 != channels_.end()) {
td::actor::send_closure(it2->second, &AdnlChannel::receive, addr, std::move(data));
if (!cat_mask.test(it2->second.second)) {
VLOG(ADNL_WARNING) << this << ": dropping IN message to channel [?->" << dst << "]: category mismatch";
return;
}
td::actor::send_closure(it2->second.first, &AdnlChannel::receive, addr, std::move(data));
return;
}
@ -109,7 +118,7 @@ void AdnlPeerTableImpl::receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket
<< "]: unknown dst (but how did we decrypt message?)";
return;
}
td::actor::send_closure(it->second, &AdnlPeer::receive_packet, dst, it2->second.second, it2->second.first.get(),
td::actor::send_closure(it->second, &AdnlPeer::receive_packet, dst, it2->second.mode, it2->second.local_id.get(),
std::move(packet));
}
@ -127,8 +136,8 @@ void AdnlPeerTableImpl::add_peer(AdnlNodeIdShort local_id, AdnlNodeIdFull id, Ad
}
td::actor::send_closure(it->second, &AdnlPeer::update_id, std::move(id));
if (!addr_list.empty()) {
td::actor::send_closure(it->second, &AdnlPeer::update_addr_list, local_id, it2->second.second,
it2->second.first.get(), std::move(addr_list));
td::actor::send_closure(it->second, &AdnlPeer::update_addr_list, local_id, it2->second.mode,
it2->second.local_id.get(), std::move(addr_list));
}
}
@ -152,7 +161,7 @@ void AdnlPeerTableImpl::send_message_in(AdnlNodeIdShort src, AdnlNodeIdShort dst
return;
}
td::actor::send_closure(it->second, &AdnlPeer::send_one_message, src, it2->second.second, it2->second.first.get(),
td::actor::send_closure(it->second, &AdnlPeer::send_one_message, src, it2->second.mode, it2->second.local_id.get(),
OutboundAdnlMessage{std::move(message), flags});
}
@ -185,23 +194,32 @@ void AdnlPeerTableImpl::send_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, std
return;
}
td::actor::send_closure(it->second, &AdnlPeer::send_query, src, it2->second.second, it2->second.first.get(), name,
td::actor::send_closure(it->second, &AdnlPeer::send_query, src, it2->second.mode, it2->second.local_id.get(), name,
std::move(promise), timeout, std::move(data), 0);
}
void AdnlPeerTableImpl::add_id_ex(AdnlNodeIdFull id, AdnlAddressList addr_list, td::uint32 mode) {
void AdnlPeerTableImpl::add_id_ex(AdnlNodeIdFull id, AdnlAddressList addr_list, td::uint8 cat, td::uint32 mode) {
auto a = id.compute_short_id();
VLOG(ADNL_INFO) << "adnl: adding local id " << a;
auto it = local_ids_.find(a);
if (it != local_ids_.end()) {
td::actor::send_closure(it->second.first, &AdnlLocalId::update_address_list, std::move(addr_list));
if (it->second.cat != cat) {
it->second.cat = cat;
if (!network_manager_.empty()) {
td::actor::send_closure(network_manager_, &AdnlNetworkManager::set_local_id_category, a, cat);
}
}
td::actor::send_closure(it->second.local_id, &AdnlLocalId::update_address_list, std::move(addr_list));
} else {
local_ids_.emplace(
a, std::make_pair(td::actor::create_actor<AdnlLocalId>("localid", std::move(id), std::move(addr_list), mode,
actor_id(this), keyring_, dht_node_),
mode));
a, LocalIdInfo{td::actor::create_actor<AdnlLocalId>("localid", std::move(id), std::move(addr_list), mode,
actor_id(this), keyring_, dht_node_),
cat, mode});
if (!network_manager_.empty()) {
td::actor::send_closure(network_manager_, &AdnlNetworkManager::set_local_id_category, a, cat);
}
}
}
@ -215,14 +233,14 @@ void AdnlPeerTableImpl::subscribe(AdnlNodeIdShort dst, std::string prefix, std::
auto it = local_ids_.find(dst);
LOG_CHECK(it != local_ids_.end()) << "dst=" << dst;
td::actor::send_closure(it->second.first, &AdnlLocalId::subscribe, prefix, std::move(callback));
td::actor::send_closure(it->second.local_id, &AdnlLocalId::subscribe, prefix, std::move(callback));
}
void AdnlPeerTableImpl::unsubscribe(AdnlNodeIdShort dst, std::string prefix) {
auto it = local_ids_.find(dst);
if (it != local_ids_.end()) {
td::actor::send_closure(it->second.first, &AdnlLocalId::unsubscribe, prefix);
td::actor::send_closure(it->second.local_id, &AdnlLocalId::unsubscribe, prefix);
}
}
@ -233,7 +251,7 @@ void AdnlPeerTableImpl::register_dht_node(td::actor::ActorId<dht::Dht> dht_node)
td::actor::send_closure(peer.second, &AdnlPeer::update_dht_node, dht_node_);
}
for (auto &local_id : local_ids_) {
td::actor::send_closure(local_id.second.first, &AdnlLocalId::update_dht_node, dht_node_);
td::actor::send_closure(local_id.second.local_id, &AdnlLocalId::update_dht_node, dht_node_);
}
}
@ -242,8 +260,8 @@ void AdnlPeerTableImpl::register_network_manager(td::actor::ActorId<AdnlNetworkM
class Cb : public AdnlNetworkManager::Callback {
public:
void receive_packet(td::IPAddress addr, td::BufferSlice data) override {
td::actor::send_closure(id_, &AdnlPeerTableImpl::receive_packet, addr, std::move(data));
void receive_packet(td::IPAddress addr, AdnlCategoryMask cat_mask, td::BufferSlice data) override {
td::actor::send_closure(id_, &AdnlPeerTableImpl::receive_packet, addr, std::move(cat_mask), std::move(data));
}
Cb(td::actor::ActorId<AdnlPeerTableImpl> id) : id_(id) {
}
@ -254,6 +272,10 @@ void AdnlPeerTableImpl::register_network_manager(td::actor::ActorId<AdnlNetworkM
auto cb = std::make_unique<Cb>(actor_id(this));
td::actor::send_closure(network_manager_, &AdnlNetworkManager::install_callback, std::move(cb));
for (auto &id : local_ids_) {
td::actor::send_closure(network_manager_, &AdnlNetworkManager::set_local_id_category, id.first, id.second.cat);
}
}
void AdnlPeerTableImpl::get_addr_list(AdnlNodeIdShort id, td::Promise<AdnlAddressList> promise) {
@ -262,7 +284,7 @@ void AdnlPeerTableImpl::get_addr_list(AdnlNodeIdShort id, td::Promise<AdnlAddres
promise.set_error(td::Status::Error(ErrorCode::notready));
return;
}
td::actor::send_closure(it->second.first, &AdnlLocalId::get_addr_list_async, std::move(promise));
td::actor::send_closure(it->second.local_id, &AdnlLocalId::get_addr_list_async, std::move(promise));
}
void AdnlPeerTableImpl::get_self_node(AdnlNodeIdShort id, td::Promise<AdnlNode> promise) {
@ -271,11 +293,14 @@ void AdnlPeerTableImpl::get_self_node(AdnlNodeIdShort id, td::Promise<AdnlNode>
promise.set_error(td::Status::Error(ErrorCode::notready));
return;
}
td::actor::send_closure(it->second.first, &AdnlLocalId::get_self_node, std::move(promise));
td::actor::send_closure(it->second.local_id, &AdnlLocalId::get_self_node, std::move(promise));
}
void AdnlPeerTableImpl::register_channel(AdnlChannelIdShort id, td::actor::ActorId<AdnlChannel> channel) {
auto success = channels_.emplace(id, channel).second;
void AdnlPeerTableImpl::register_channel(AdnlChannelIdShort id, AdnlNodeIdShort local_id,
td::actor::ActorId<AdnlChannel> channel) {
auto it = local_ids_.find(local_id);
auto cat = (it != local_ids_.end()) ? it->second.cat : 255;
auto success = channels_.emplace(id, std::make_pair(channel, cat)).second;
CHECK(success);
}
@ -317,14 +342,14 @@ AdnlPeerTableImpl::AdnlPeerTableImpl(std::string db_root, td::actor::ActorId<key
void AdnlPeerTableImpl::deliver(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data) {
auto it = local_ids_.find(dst);
if (it != local_ids_.end()) {
td::actor::send_closure(it->second.first, &AdnlLocalId::deliver, src, std::move(data));
td::actor::send_closure(it->second.local_id, &AdnlLocalId::deliver, src, std::move(data));
}
}
void AdnlPeerTableImpl::deliver_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data,
td::Promise<td::BufferSlice> promise) {
auto it = local_ids_.find(dst);
if (it != local_ids_.end()) {
td::actor::send_closure(it->second.first, &AdnlLocalId::deliver_query, src, std::move(data), std::move(promise));
td::actor::send_closure(it->second.local_id, &AdnlLocalId::deliver_query, src, std::move(data), std::move(promise));
} else {
LOG(WARNING) << "deliver query: unknown dst " << dst;
promise.set_error(td::Status::Error(ErrorCode::notready, "cannot deliver: unknown DST"));
@ -335,7 +360,7 @@ void AdnlPeerTableImpl::decrypt_message(AdnlNodeIdShort dst, td::BufferSlice dat
td::Promise<td::BufferSlice> promise) {
auto it = local_ids_.find(dst);
if (it != local_ids_.end()) {
td::actor::send_closure(it->second.first, &AdnlLocalId::decrypt_message, std::move(data), std::move(promise));
td::actor::send_closure(it->second.local_id, &AdnlLocalId::decrypt_message, std::move(data), std::move(promise));
} else {
LOG(WARNING) << "decrypt message: unknown dst " << dst;
promise.set_error(td::Status::Error(ErrorCode::notready, "cannot decrypt: unknown DST"));
@ -347,6 +372,10 @@ void AdnlPeerTableImpl::create_ext_server(std::vector<AdnlNodeIdShort> ids, std:
promise.set_value(AdnlExtServerCreator::create(actor_id(this), std::move(ids), std::move(ports)));
}
void AdnlPeerTableImpl::create_tunnel(AdnlNodeIdShort dst, td::uint32 size,
td::Promise<std::pair<td::actor::ActorOwn<AdnlTunnel>, AdnlAddress>> promise) {
}
} // namespace adnl
} // namespace ton

View file

@ -89,11 +89,12 @@ class AdnlPeerTable : public Adnl {
virtual void answer_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlQueryId query_id, 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;
virtual void receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket packet) = 0;
virtual void send_message_in(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlMessage message, td::uint32 flags) = 0;
virtual void register_channel(AdnlChannelIdShort id, td::actor::ActorId<AdnlChannel> channel) = 0;
virtual void register_channel(AdnlChannelIdShort id, AdnlNodeIdShort local_id,
td::actor::ActorId<AdnlChannel> channel) = 0;
virtual void unregister_channel(AdnlChannelIdShort id) = 0;
virtual void add_static_node(AdnlNode node) = 0;

View file

@ -43,7 +43,7 @@ class AdnlPeerTableImpl : public AdnlPeerTable {
void add_peer(AdnlNodeIdShort local_id, AdnlNodeIdFull id, AdnlAddressList addr_list) override;
void add_static_nodes_from_config(AdnlNodesList nodes) override;
void receive_packet(td::IPAddress addr, td::BufferSlice data) override;
void receive_packet(td::IPAddress addr, AdnlCategoryMask cat_mask, td::BufferSlice data) override;
void receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket data) override;
void send_message_in(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlMessage message, td::uint32 flags) override;
void send_message(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data) override {
@ -64,7 +64,7 @@ class AdnlPeerTableImpl : public AdnlPeerTable {
td::Timestamp timeout, td::BufferSlice data, td::uint64 max_answer_size) override {
send_query(src, dst, name, std::move(promise), timeout, std::move(data));
}
void add_id_ex(AdnlNodeIdFull id, AdnlAddressList addr_list, td::uint32 mode) override;
void add_id_ex(AdnlNodeIdFull id, AdnlAddressList addr_list, td::uint8 cat, td::uint32 mode) override;
void del_id(AdnlNodeIdShort id, td::Promise<td::Unit> promise) override;
void subscribe(AdnlNodeIdShort dst, std::string prefix, std::unique_ptr<Callback> callback) override;
void unsubscribe(AdnlNodeIdShort dst, std::string prefix) override;
@ -73,7 +73,8 @@ class AdnlPeerTableImpl : public AdnlPeerTable {
void get_addr_list(AdnlNodeIdShort id, td::Promise<AdnlAddressList> promise) override;
void get_self_node(AdnlNodeIdShort id, td::Promise<AdnlNode> promise) override;
void start_up() override;
void register_channel(AdnlChannelIdShort id, td::actor::ActorId<AdnlChannel> channel) override;
void register_channel(AdnlChannelIdShort id, AdnlNodeIdShort local_id,
td::actor::ActorId<AdnlChannel> channel) override;
void unregister_channel(AdnlChannelIdShort id) override;
void write_new_addr_list_to_db(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id, AdnlDbItem node,
@ -99,12 +100,20 @@ class AdnlPeerTableImpl : public AdnlPeerTable {
void create_ext_server(std::vector<AdnlNodeIdShort> ids, std::vector<td::uint16> ports,
td::Promise<td::actor::ActorOwn<AdnlExtServer>> promise) override;
void create_tunnel(AdnlNodeIdShort dst, td::uint32 size,
td::Promise<std::pair<td::actor::ActorOwn<AdnlTunnel>, AdnlAddress>> promise) override;
struct PrintId {};
PrintId print_id() const {
return PrintId{};
}
private:
struct LocalIdInfo {
td::actor::ActorOwn<AdnlLocalId> local_id;
td::uint8 cat;
td::uint32 mode;
};
td::actor::ActorId<keyring::Keyring> keyring_;
td::actor::ActorId<AdnlNetworkManager> network_manager_;
@ -114,13 +123,14 @@ class AdnlPeerTableImpl : public AdnlPeerTable {
void deliver_one_message(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlMessage message);
std::map<AdnlNodeIdShort, td::actor::ActorOwn<AdnlPeer>> peers_;
std::map<AdnlNodeIdShort, std::pair<td::actor::ActorOwn<AdnlLocalId>, td::uint32>> local_ids_;
std::map<AdnlChannelIdShort, td::actor::ActorId<AdnlChannel>> channels_;
std::map<AdnlNodeIdShort, LocalIdInfo> local_ids_;
std::map<AdnlChannelIdShort, std::pair<td::actor::ActorId<AdnlChannel>, td::uint8>> channels_;
td::actor::ActorOwn<AdnlDb> db_;
td::actor::ActorOwn<AdnlExtServer> ext_server_;
AdnlNodeIdShort proxy_addr_;
//std::map<td::uint64, td::actor::ActorId<AdnlQuery>> out_queries_;
//td::uint64 last_query_id_ = 1;
};

View file

@ -482,7 +482,8 @@ void AdnlPeerPairImpl::create_channel(pubkeys::Ed25519 pub, td::uint32 date) {
channel_ = R.move_as_ok();
channel_inited_ = true;
td::actor::send_closure_later(peer_table_, &AdnlPeerTable::register_channel, channel_in_id_, channel_.get());
td::actor::send_closure_later(peer_table_, &AdnlPeerTable::register_channel, channel_in_id_, local_id_,
channel_.get());
} else {
VLOG(ADNL_WARNING) << this << ": failed to create channel: " << R.move_as_error();
}

View file

@ -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

View file

@ -23,7 +23,7 @@
exception statement from your version. If you delete this exception statement
from all source files in the program, then also delete it here.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#include "td/actor/actor.h"
#include "td/utils/buffer.h"
@ -170,7 +170,10 @@ int main(int argc, char *argv[]) {
network_manager = ton::adnl::AdnlNetworkManager::create(static_cast<td::uint16>(addr.get_port()));
td::actor::send_closure(network_manager, &ton::adnl::AdnlNetworkManager::add_self_addr, addr, 0);
ton::adnl::AdnlCategoryMask cat_mask;
cat_mask[0] = true;
td::actor::send_closure(network_manager, &ton::adnl::AdnlNetworkManager::add_self_addr, addr, std::move(cat_mask),
0);
auto tladdr = ton::create_tl_object<ton::ton_api::adnl_address_udp>(addr.get_ipv4(), addr.get_port());
auto addr_vec = std::vector<ton::tl_object_ptr<ton::ton_api::adnl_Address>>();
@ -179,7 +182,8 @@ int main(int argc, char *argv[]) {
std::move(addr_vec), ton::adnl::Adnl::adnl_start_time(), ton::adnl::Adnl::adnl_start_time(), 0, 2000000000);
auto addrlist = ton::adnl::AdnlAddressList::create(tladdrlist).move_as_ok();
td::actor::send_closure(adnl, &ton::adnl::Adnl::add_id, ton::adnl::AdnlNodeIdFull{pub}, std::move(addrlist));
td::actor::send_closure(adnl, &ton::adnl::Adnl::add_id, ton::adnl::AdnlNodeIdFull{pub}, std::move(addrlist),
static_cast<td::uint8>(0));
td::actor::send_closure(adnl, &ton::adnl::Adnl::subscribe, ton::adnl::AdnlNodeIdShort{pub.compute_short_id()},
ton::adnl::Adnl::int_to_bytestring(ton::ton_api::adnl_ping::ID),
std::make_unique<ton::adnl::Callback>());

View file

@ -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
*/
#include "adnl-proxy-types.hpp"
#include "tl-utils/tl-utils.hpp"
@ -27,59 +27,84 @@ namespace ton {
namespace adnl {
td::Result<AdnlProxy::Packet> AdnlProxyNone::decrypt(td::BufferSlice packet) const {
if (packet.size() < 32) {
return td::Status::Error(ErrorCode::protoviolation, "bad signature");
}
if (packet.as_slice().truncate(32) != id_.as_slice()) {
return td::Status::Error(ErrorCode::protoviolation, "bad proxy id");
}
Packet p{};
p.flags = 0;
p.ip = 0;
p.port = 0;
p.adnl_start_time = 0;
p.seqno = 0;
p.date = 0;
p.data = std::move(packet);
p.data.confirm_read(32);
return std::move(p);
}
td::BufferSlice AdnlProxyFast::encrypt(Packet packet) const {
auto date = static_cast<td::uint32>(td::Clocks::system());
auto signature = create_hash_tl_object<ton_api::adnl_proxyToFastHash>(
packet.ip, packet.port, date, sha256_bits256(packet.data.as_slice()), shared_secret_);
auto obj = create_serialize_tl_object<ton_api::adnl_proxyToFast>(packet.ip, packet.port, date, signature);
td::BufferSlice res{32 + obj.size() + packet.data.size()};
auto S = res.as_slice();
S.copy_from(td::Bits256::zero().as_slice());
if (!packet.date) {
packet.date = static_cast<td::int32>(td::Clocks::system());
packet.flags |= 8;
}
auto obj = create_tl_object<ton_api::adnl_proxyPacketHeader>(id_, packet.flags, packet.ip, packet.port,
packet.adnl_start_time, packet.seqno, packet.date,
td::sha256_bits256(packet.data.as_slice()));
char data[64];
td::MutableSlice S{data, 64};
S.copy_from(get_tl_object_sha256(obj).as_slice());
S.remove_prefix(32);
S.copy_from(obj.as_slice());
S.remove_prefix(obj.size());
S.copy_from(packet.data.as_slice());
S.copy_from(shared_secret_.as_slice());
return res;
obj->signature_ = td::sha256_bits256(td::Slice(data, 64));
return serialize_tl_object(obj, false, std::move(packet.data));
}
td::Result<AdnlProxy::Packet> AdnlProxyFast::decrypt(td::BufferSlice packet) const {
if (packet.size() < 36) {
return td::Status::Error(ErrorCode::protoviolation, "too short packet");
TRY_RESULT(obj, fetch_tl_prefix<ton_api::adnl_proxyPacketHeader>(packet, false));
if (obj->proxy_id_ != id_) {
return td::Status::Error(ErrorCode::protoviolation, "bad proxy id");
}
td::Bits256 v;
v.as_slice().copy_from(packet.as_slice().truncate(32));
if (!v.is_zero()) {
return td::Status::Error(ErrorCode::protoviolation, "non-zero DST");
}
packet.confirm_read(32);
auto signature = std::move(obj->signature_);
obj->signature_ = td::sha256_bits256(packet.as_slice());
TRY_RESULT(R, fetch_tl_prefix<ton_api::adnl_proxyToFast>(packet, true));
char data[64];
td::MutableSlice S{data, 64};
S.copy_from(get_tl_object_sha256(obj).as_slice());
S.remove_prefix(32);
S.copy_from(shared_secret_.as_slice());
if (R->date_ < td::Clocks::system() - 8) {
return td::Status::Error(ErrorCode::protoviolation, "too old date");
}
auto signature = create_hash_tl_object<ton_api::adnl_proxyToFastHash>(
R->ip_, R->port_, R->date_, sha256_bits256(packet.as_slice()), shared_secret_);
if (signature != R->signature_) {
if (td::sha256_bits256(td::Slice(data, 64)) != signature) {
return td::Status::Error(ErrorCode::protoviolation, "bad signature");
}
return Packet{static_cast<td::uint32>(R->ip_), static_cast<td::uint16>(R->port_), std::move(packet)};
Packet p;
p.flags = obj->flags_;
p.ip = (p.flags & 1) ? obj->ip_ : 0;
p.port = (p.flags & 1) ? static_cast<td::uint16>(obj->port_) : 0;
p.adnl_start_time = (p.flags & 2) ? obj->adnl_start_time_ : 0;
p.seqno = (p.flags & 4) ? obj->seqno_ : 0;
p.date = (p.flags & 8) ? obj->date_ : 0;
p.data = std::move(packet);
return std::move(p);
}
td::Result<std::shared_ptr<AdnlProxy>> AdnlProxy::create(const ton_api::adnl_Proxy &proxy_type) {
std::shared_ptr<AdnlProxy> R;
ton_api::downcast_call(
const_cast<ton_api::adnl_Proxy &>(proxy_type),
td::overloaded([&](const ton_api::adnl_proxy_none &x) { R = std::make_shared<AdnlProxyNone>(); },
td::overloaded([&](const ton_api::adnl_proxy_none &x) { R = std::make_shared<AdnlProxyNone>(x.id_); },
[&](const ton_api::adnl_proxy_fast &x) {
R = std::make_shared<AdnlProxyFast>(x.shared_secret_.as_slice());
R = std::make_shared<AdnlProxyFast>(x.id_, x.shared_secret_.as_slice());
}));
return R;
return std::move(R);
}
} // namespace adnl

View file

@ -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
@ -28,14 +28,19 @@ namespace adnl {
class AdnlProxy {
public:
struct Packet {
td::uint32 flags;
td::uint32 ip;
td::uint16 port;
td::int32 adnl_start_time;
td::int64 seqno;
td::int32 date{0};
td::BufferSlice data;
};
virtual ~AdnlProxy() = default;
virtual td::BufferSlice encrypt(Packet packet) const = 0;
virtual td::Result<Packet> decrypt(td::BufferSlice packet) const = 0;
virtual tl_object_ptr<ton_api::adnl_Proxy> tl() const = 0;
virtual const td::Bits256 &id() const = 0;
static td::Result<std::shared_ptr<AdnlProxy>> create(const ton_api::adnl_Proxy &proxy_type);
};

View file

@ -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
@ -28,31 +28,42 @@ namespace adnl {
class AdnlProxyNone : public AdnlProxy {
public:
AdnlProxyNone() {
AdnlProxyNone(td::Bits256 id) : id_(id) {
}
td::BufferSlice encrypt(Packet packet) const override {
return std::move(packet.data);
}
td::Result<Packet> decrypt(td::BufferSlice packet) const override {
return Packet{0, 0, std::move(packet)};
td::BufferSlice d{packet.data.size() + 32};
d.as_slice().copy_from(id_.as_slice());
d.as_slice().remove_prefix(32).copy_from(packet.data.as_slice());
return d;
}
td::Result<Packet> decrypt(td::BufferSlice packet) const override;
tl_object_ptr<ton_api::adnl_Proxy> tl() const override {
return create_tl_object<ton_api::adnl_proxy_none>();
return create_tl_object<ton_api::adnl_proxy_none>(id_);
}
const td::Bits256 &id() const override {
return id_;
}
private:
td::Bits256 id_;
};
class AdnlProxyFast : public AdnlProxy {
public:
AdnlProxyFast(td::Slice shared_secret)
: shared_secret_(sha256_bits256(shared_secret)), shared_secret_raw_(shared_secret) {
AdnlProxyFast(td::Bits256 id, td::Slice shared_secret)
: id_(id), shared_secret_(sha256_bits256(shared_secret)), shared_secret_raw_(shared_secret) {
}
td::BufferSlice encrypt(Packet packet) const override;
td::Result<Packet> decrypt(td::BufferSlice packet) const override;
tl_object_ptr<ton_api::adnl_Proxy> tl() const override {
return create_tl_object<ton_api::adnl_proxy_fast>(shared_secret_raw_.clone_as_buffer_slice());
return create_tl_object<ton_api::adnl_proxy_fast>(id_, shared_secret_raw_.clone_as_buffer_slice());
}
const td::Bits256 &id() const override {
return id_;
}
private:
td::Bits256 id_;
td::Bits256 shared_secret_;
td::SharedSlice shared_secret_raw_;
};

View file

@ -23,7 +23,7 @@
exception statement from your version. If you delete this exception statement
from all source files in the program, then also delete it here.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#include "td/actor/actor.h"
#include "td/utils/buffer.h"
@ -35,11 +35,13 @@
#include "td/utils/port/path.h"
#include "td/utils/port/user.h"
#include "td/utils/filesystem.h"
#include "td/utils/overloaded.h"
#include "common/checksum.h"
#include "common/errorcode.h"
#include "tl-utils/tl-utils.hpp"
#include "auto/tl/ton_api_json.h"
#include "adnl-proxy-types.h"
#include "adnl-received-mask.h"
#include <map>
#if TD_DARWIN || TD_LINUX
@ -50,12 +52,19 @@ namespace ton {
namespace adnl {
namespace {
td::int32 start_time() {
static td::int32 t = static_cast<td::int32>(td::Clocks::system());
return t;
}
} // namespace
class Receiver : public td::actor::Actor {
public:
void start_up() override;
void receive_common(td::BufferSlice data);
void receive_from_client(td::BufferSlice data);
void receive_to_client(td::BufferSlice data);
void receive_common(td::IPAddress addr, td::BufferSlice data);
void receive_from_client(td::IPAddress addr, td::BufferSlice data);
void receive_to_client(td::IPAddress addr, td::BufferSlice data);
Receiver(td::uint16 in_port, td::uint16 out_port, std::shared_ptr<AdnlProxy> proxy, td::IPAddress client_addr)
: in_port_(in_port), out_port_(out_port), proxy_(std::move(proxy)), addr_(client_addr) {
@ -68,6 +77,10 @@ class Receiver : public td::actor::Actor {
td::IPAddress addr_;
td::actor::ActorOwn<td::UdpServer> out_udp_server_;
td::actor::ActorOwn<td::UdpServer> in_udp_server_;
td::int32 client_start_time_{0};
td::uint64 out_seqno_{0};
AdnlReceivedMaskVersion received_;
};
void Receiver::start_up() {
@ -81,15 +94,18 @@ void Receiver::start_up() {
const td::uint32 mode_;
void on_udp_message(td::UdpMessage udp_message) override {
if (udp_message.error.is_error()) {
LOG(DEBUG) << udp_message.error;
LOG(INFO) << "receifed udp message with error: " << udp_message.error;
return;
}
if (mode_ == 0) {
td::actor::send_closure_later(manager_, &Receiver::receive_common, std::move(udp_message.data));
td::actor::send_closure_later(manager_, &Receiver::receive_common, udp_message.address,
std::move(udp_message.data));
} else if (mode_ == 1) {
td::actor::send_closure_later(manager_, &Receiver::receive_from_client, std::move(udp_message.data));
td::actor::send_closure_later(manager_, &Receiver::receive_from_client, udp_message.address,
std::move(udp_message.data));
} else {
td::actor::send_closure_later(manager_, &Receiver::receive_to_client, std::move(udp_message.data));
td::actor::send_closure_later(manager_, &Receiver::receive_to_client, udp_message.address,
std::move(udp_message.data));
}
}
};
@ -108,46 +124,152 @@ void Receiver::start_up() {
}
}
void Receiver::receive_common(td::BufferSlice data) {
void Receiver::receive_common(td::IPAddress addr, td::BufferSlice data) {
if (data.size() <= 32) {
LOG(INFO) << "dropping too short packet: size=" << data.size();
return;
}
td::Bits256 id;
id.as_slice().copy_from(data.as_slice().truncate(32));
if (id.is_zero()) {
receive_from_client(std::move(data));
if (proxy_->id().as_slice() == data.as_slice().truncate(32)) {
receive_from_client(addr, std::move(data));
} else {
receive_to_client(std::move(data));
receive_to_client(addr, std::move(data));
}
}
void Receiver::receive_from_client(td::BufferSlice data) {
void Receiver::receive_from_client(td::IPAddress addr, td::BufferSlice data) {
auto F = proxy_->decrypt(std::move(data));
if (F.is_error()) {
LOG(INFO) << "proxy: failed to decrypt message from client: " << F.move_as_error();
return;
}
auto f = F.move_as_ok();
if (f.flags & (1 << 16)) {
LOG(INFO) << "proxy: dropping message from client: flag 16 is set";
return;
}
if (f.date) {
if (f.date + 60.0 < td::Clocks::system() || f.date - 60.0 > td::Clocks::system()) {
LOG(INFO) << "proxy: dropping message from client: date mismatch";
return;
}
}
if ((f.flags & 6) == 6) {
if (received_.packet_is_delivered(f.adnl_start_time, f.seqno)) {
LOG(INFO) << "proxy: dropping message from client: duplicate packet (or old seqno/start_time)";
return;
}
received_.deliver_packet(f.adnl_start_time, f.seqno);
}
if (f.flags & (1 << 17)) {
auto F = fetch_tl_object<ton_api::adnl_ProxyControlPacket>(std::move(f.data), true);
if (F.is_error()) {
LOG(INFO) << this << ": dropping proxy packet: bad control packet: " << F.move_as_error();
return;
}
ton_api::downcast_call(*F.move_as_ok().get(),
td::overloaded(
[&](const ton_api::adnl_proxyControlPacketPing &f) {
auto data = create_serialize_tl_object<ton_api::adnl_proxyControlPacketPong>(f.id_);
AdnlProxy::Packet p;
p.flags = 6 | (1 << 16) | (1 << 17);
if (addr.is_valid() && addr.is_ipv4()) {
p.flags |= 1;
p.ip = addr.get_ipv4();
p.port = static_cast<td::uint16>(addr.get_port());
} else {
p.ip = 0;
p.port = 0;
}
p.data = std::move(data);
p.adnl_start_time = start_time();
p.seqno = out_seqno_;
p.data = std::move(data);
auto enc = proxy_->encrypt(std::move(p));
td::UdpMessage M;
M.address = addr;
M.data = std::move(enc);
td::actor::send_closure(
in_udp_server_.empty() ? out_udp_server_.get() : in_udp_server_.get(),
&td::UdpServer::send, std::move(M));
},
[&](const ton_api::adnl_proxyControlPacketPong &f) {},
[&](const ton_api::adnl_proxyControlPacketRegister &f) {
if (f.ip_ == 0 && f.port_ == 0) {
if (addr.is_valid() && addr.is_ipv4()) {
addr_ = addr;
}
} else {
td::IPAddress a;
auto S = a.init_host_port(td::IPAddress::ipv4_to_str(f.ip_), f.port_);
if (S.is_ok()) {
addr_ = a;
} else {
LOG(INFO) << "failed to init remote addr: " << S.move_as_error();
}
}
}));
return;
}
if (!(f.flags & 1)) {
LOG(INFO) << this << ": dropping proxy packet: no destination";
return;
}
td::IPAddress a;
if (a.init_ipv4_port(td::IPAddress::ipv4_to_str(f.ip), f.port).is_error()) {
LOG(INFO) << this << ": dropping proxy packet: invalid destination";
return;
}
if (!a.is_valid()) {
LOG(INFO) << this << ": dropping proxy packet: invalid destination";
return;
}
td::UdpMessage M;
M.address = a;
M.data = std::move(f.data);
LOG(DEBUG) << this << ": proxying DOWN packet of length " << M.data.size() << " to " << a;
td::actor::send_closure(out_udp_server_.empty() ? in_udp_server_.get() : out_udp_server_.get(), &td::UdpServer::send,
std::move(M));
}
void Receiver::receive_to_client(td::BufferSlice data) {
void Receiver::receive_to_client(td::IPAddress addr, td::BufferSlice data) {
LOG(DEBUG) << "proxying to " << addr_;
if (!addr_.is_valid() || !addr_.is_ipv4() || !addr_.get_ipv4()) {
LOG(INFO) << this << ": dropping external packet: client not inited";
return;
}
AdnlProxy::Packet p;
p.flags = (1 << 16);
if (addr.is_valid() && addr.is_ipv4()) {
p.flags |= 1;
p.ip = addr.get_ipv4();
p.port = static_cast<td::uint16>(addr.get_port());
} else {
p.ip = 0;
p.port = 0;
}
p.flags |= 2;
p.adnl_start_time = start_time();
p.flags |= 4;
p.seqno = ++out_seqno_;
p.data = std::move(data);
LOG(DEBUG) << this << ": proxying UP packet of length " << p.data.size() << " to " << addr_;
td::UdpMessage M;
M.address = addr_;
M.data = std::move(data);
M.data = proxy_->encrypt(std::move(p));
td::actor::send_closure(in_udp_server_.empty() ? out_udp_server_.get() : in_udp_server_.get(), &td::UdpServer::send,
std::move(M));
@ -204,7 +326,7 @@ int main(int argc, char *argv[]) {
});
p.add_option('l', "logname", "log to file", [&](td::Slice fname) {
auto F = std::make_unique<td::FileLog>();
TRY_STATUS(F->init(fname.str(), std::numeric_limits<td::uint64>::max(), true));
TRY_STATUS(F->init(fname.str(), std::numeric_limits<td::int64>::max(), true));
logger_ = std::move(F);
td::log_interface = logger_.get();
return td::Status::OK();
@ -248,7 +370,9 @@ int main(int argc, char *argv[]) {
}
TRY_RESULT(proxy, ton::adnl::AdnlProxy::create(*y->proxy_type_.get()));
td::IPAddress a;
a.init_ipv4_port(td::IPAddress::ipv4_to_str(y->dst_ip_), static_cast<td::uint16>(y->dst_port_)).ensure();
if (y->dst_ip_ || y->dst_port_) {
a.init_ipv4_port(td::IPAddress::ipv4_to_str(y->dst_ip_), static_cast<td::uint16>(y->dst_port_)).ensure();
}
scheduler.run_in_context([&] {
x.push_back(td::actor::create_actor<ton::adnl::Receiver>("adnl-proxy", in_port, out_port, std::move(proxy), a));

84
adnl/adnl-received-mask.h Normal file
View file

@ -0,0 +1,84 @@
#pragma once
#include "td/utils/int_types.h"
#include "td/utils/logging.h"
namespace ton {
namespace adnl {
class AdnlReceivedMask {
public:
void reset() {
seqno_ = 0;
mask_ = 0;
}
bool packet_is_delivered(td::int64 seqno) const {
if (seqno <= 0) {
return false;
}
if (seqno + 64 <= seqno_) {
return true;
}
if (seqno > seqno_) {
return false;
}
return mask_ & (1ull << (seqno_ - seqno));
}
void deliver_packet(td::int64 seqno) {
CHECK(!packet_is_delivered(seqno));
CHECK(seqno > 0);
if (seqno <= seqno_) {
mask_ |= (1ull << (seqno_ - seqno));
} else {
auto old = seqno_;
seqno_ = seqno;
if (seqno_ - old >= 64) {
mask_ = 1;
} else {
mask_ = mask_ << (seqno_ - old);
mask_ |= 1;
}
}
}
private:
td::int64 seqno_{0};
td::uint64 mask_{0};
};
class AdnlReceivedMaskVersion {
public:
bool packet_is_delivered(td::int32 utime, td::uint64 seqno) {
if (utime < utime_) {
return true;
} else if (utime == utime_) {
return mask_.packet_is_delivered(seqno);
} else {
return false;
}
}
void deliver_packet(td::int32 utime, td::uint64 seqno) {
CHECK(utime >= utime_);
if (utime == utime_) {
mask_.deliver_packet(seqno);
} else {
utime_ = utime;
mask_.reset();
mask_.deliver_packet(seqno);
}
}
void reset() {
mask_.reset();
utime_ = 0;
}
private:
AdnlReceivedMask mask_;
td::int32 utime_{0};
};
} // namespace adnl
} // namespace ton

View file

@ -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
@ -34,9 +34,10 @@ class TestLoopbackNetworkManager : public ton::adnl::AdnlNetworkManager {
callback_ = std::move(callback);
}
void add_self_addr(td::IPAddress addr, td::uint32 priority) override {
void add_self_addr(td::IPAddress addr, AdnlCategoryMask cat_mask, td::uint32 priority) override {
}
void add_proxy_addr(td::IPAddress addr, std::shared_ptr<AdnlProxy> proxy, td::uint32 priority) override {
void add_proxy_addr(td::IPAddress addr, td::uint16 local_port, std::shared_ptr<AdnlProxy> proxy,
AdnlCategoryMask cat_mask, td::uint32 priority) override {
}
void send_udp_packet(ton::adnl::AdnlNodeIdShort src_id, ton::adnl::AdnlNodeIdShort dst_id, td::IPAddress dst_addr,
td::uint32 priority, td::BufferSlice data) override {
@ -48,7 +49,9 @@ class TestLoopbackNetworkManager : public ton::adnl::AdnlNetworkManager {
return;
}
CHECK(callback_);
callback_->receive_packet(dst_addr, std::move(data));
AdnlCategoryMask m;
m[0] = true;
callback_->receive_packet(dst_addr, std::move(m), std::move(data));
}
void add_node_id(AdnlNodeIdShort id, bool allow_send, bool allow_receive) {
@ -68,6 +71,8 @@ class TestLoopbackNetworkManager : public ton::adnl::AdnlNetworkManager {
CHECK(p >= 0 && p <= 1);
loss_probability_ = p;
}
void set_local_id_category(AdnlNodeIdShort id, td::uint8 cat) override {
}
TestLoopbackNetworkManager() {
}

97
adnl/adnl-tunnel.cpp Normal file
View file

@ -0,0 +1,97 @@
#include "adnl-tunnel.h"
#include "adnl-peer-table.h"
namespace ton {
namespace adnl {
void AdnlInboundTunnelEndpoint::receive_packet(AdnlNodeIdShort src, td::IPAddress src_addr, td::BufferSlice datagram) {
receive_packet_cont(src, src_addr, std::move(datagram), 0);
}
void AdnlInboundTunnelEndpoint::receive_packet_cont(AdnlNodeIdShort src, td::IPAddress src_addr,
td::BufferSlice datagram, size_t idx) {
if (datagram.size() <= 32) {
VLOG(ADNL_INFO) << "dropping too short datagram";
return;
}
if (datagram.as_slice().truncate(32) != decrypt_via_[idx].as_slice()) {
VLOG(ADNL_INFO) << "invalid tunnel midpoint";
return;
}
datagram.confirm_read(32);
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), src, src_addr, idx](td::Result<td::BufferSlice> R) {
if (R.is_error()) {
VLOG(ADNL_INFO) << "dropping tunnel packet: failed to decrypt: " << R.move_as_error();
return;
} else {
td::actor::send_closure(SelfId, &AdnlInboundTunnelEndpoint::decrypted_packet, src, src_addr, R.move_as_ok(), idx);
}
});
td::actor::send_closure(keyring_, &keyring::Keyring::decrypt_message, decrypt_via_[idx], std::move(datagram),
std::move(P));
}
void AdnlInboundTunnelEndpoint::decrypted_packet(AdnlNodeIdShort src, td::IPAddress src_addr, td::BufferSlice data,
size_t idx) {
if (idx == decrypt_via_.size() - 1) {
td::actor::send_closure(adnl_, &AdnlPeerTable::receive_packet, src_addr, std::move(data));
return;
}
auto F = fetch_tl_object<ton_api::adnl_tunnelPacketContents>(std::move(data), true);
if (F.is_error()) {
VLOG(ADNL_INFO) << "dropping tunnel packet: failed to fetch: " << F.move_as_error();
return;
}
auto packet = F.move_as_ok();
td::IPAddress addr;
if (packet->flags_ & 1) {
addr.init_host_port(td::IPAddress::ipv4_to_str(packet->from_ip_), packet->from_port_).ignore();
}
if (packet->flags_ & 2) {
receive_packet_cont(src, addr, std::move(packet->message_), idx + 1);
}
}
void AdnlInboundTunnelMidpoint::start_up() {
encrypt_key_hash_ = encrypt_via_.compute_short_id();
auto R = encrypt_via_.create_encryptor();
if (R.is_error()) {
return;
}
encryptor_ = R.move_as_ok();
}
void AdnlInboundTunnelMidpoint::receive_packet(AdnlNodeIdShort src, td::IPAddress src_addr, td::BufferSlice datagram) {
if (!encryptor_) {
return;
}
auto obj = create_tl_object<ton_api::adnl_tunnelPacketContents>();
obj->flags_ = 2;
obj->message_ = std::move(datagram);
if (src_addr.is_valid() && src_addr.is_ipv4()) {
obj->flags_ |= 1;
obj->from_ip_ = src_addr.get_ipv4();
obj->from_port_ = src_addr.get_port();
}
auto packet = serialize_tl_object(std::move(obj), true);
auto dataR = encryptor_->encrypt(packet.as_slice());
if (dataR.is_error()) {
return;
}
auto data = dataR.move_as_ok();
td::BufferSlice enc{data.size() + 32};
auto S = enc.as_slice();
S.copy_from(encrypt_key_hash_.as_slice());
S.remove_prefix(32);
S.copy_from(data.as_slice());
td::actor::send_closure(adnl_, &Adnl::send_message_ex, proxy_as_, proxy_to_, std::move(enc),
Adnl::SendFlags::direct_only);
}
} // namespace adnl
} // namespace ton

73
adnl/adnl-tunnel.h Normal file
View file

@ -0,0 +1,73 @@
#pragma once
#include "adnl.h"
#include "adnl-peer-table.h"
#include "keys/encryptor.h"
#include <map>
namespace ton {
namespace adnl {
class AdnlInboundTunnelPoint : public AdnlTunnel {
public:
virtual ~AdnlInboundTunnelPoint() = default;
virtual void receive_packet(AdnlNodeIdShort src, td::IPAddress src_addr, td::BufferSlice datagram) = 0;
};
class AdnlInboundTunnelEndpoint : public AdnlInboundTunnelPoint {
public:
AdnlInboundTunnelEndpoint(PublicKeyHash pubkey_hash, std::vector<PublicKeyHash> decrypt_via, AdnlNodeIdShort proxy_to,
td::actor::ActorId<keyring::Keyring> keyring, td::actor::ActorId<AdnlPeerTable> adnl)
: pubkey_hash_(std::move(pubkey_hash))
, decrypt_via_(std::move(decrypt_via))
, proxy_to_(std::move(proxy_to))
, keyring_(std::move(keyring))
, adnl_(std::move(adnl)) {
}
void receive_packet(AdnlNodeIdShort src, td::IPAddress src_addr, td::BufferSlice datagram) override;
void receive_packet_cont(AdnlNodeIdShort src, td::IPAddress src_addr, td::BufferSlice datagram, size_t idx);
void decrypted_packet(AdnlNodeIdShort src, td::IPAddress src_addr, td::BufferSlice data, size_t idx);
private:
PublicKeyHash pubkey_hash_;
std::vector<PublicKeyHash> decrypt_via_;
AdnlNodeIdShort proxy_to_;
td::actor::ActorId<keyring::Keyring> keyring_;
td::actor::ActorId<AdnlPeerTable> adnl_;
};
class AdnlInboundTunnelMidpoint : public AdnlInboundTunnelPoint {
public:
AdnlInboundTunnelMidpoint(ton::PublicKey encrypt_via, AdnlNodeIdShort proxy_to, AdnlNodeIdShort proxy_as,
td::actor::ActorId<keyring::Keyring> keyring, td::actor::ActorId<AdnlPeerTable> adnl)
: encrypt_via_(std::move(encrypt_via)), proxy_to_(proxy_to), proxy_as_(proxy_as), keyring_(keyring), adnl_(adnl) {
}
void start_up() override;
void receive_packet(AdnlNodeIdShort src, td::IPAddress src_addr, td::BufferSlice datagram) override;
private:
ton::PublicKeyHash encrypt_key_hash_;
ton::PublicKey encrypt_via_;
std::unique_ptr<Encryptor> encryptor_;
AdnlNodeIdShort proxy_to_;
AdnlNodeIdShort proxy_as_;
td::actor::ActorId<keyring::Keyring> keyring_;
td::actor::ActorId<AdnlPeerTable> adnl_;
};
class AdnlProxyNode : public td::actor::Actor {
public:
void receive_message(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data);
void receive_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data,
td::Promise<td::BufferSlice> promise);
private:
std::map<PublicKeyHash, td::actor::ActorOwn<AdnlInboundTunnelMidpoint>> mid_;
};
} // namespace adnl
} // namespace ton

View file

@ -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
@ -58,6 +58,8 @@ class AdnlSenderInterface : public td::actor::Actor {
td::uint64 max_answer_size) = 0;
};
class AdnlTunnel : public td::actor::Actor {};
class Adnl : public AdnlSenderInterface {
public:
class Callback {
@ -88,10 +90,10 @@ class Adnl : public AdnlSenderInterface {
virtual void add_static_nodes_from_config(AdnlNodesList nodes) = 0;
// adds local id. After that you can send/receive messages from/to this id
void add_id(AdnlNodeIdFull id, AdnlAddressList addr_list) {
add_id_ex(std::move(id), std::move(addr_list), 0);
void add_id(AdnlNodeIdFull id, AdnlAddressList addr_list, td::uint8 cat) {
add_id_ex(std::move(id), std::move(addr_list), cat, 0);
}
virtual void add_id_ex(AdnlNodeIdFull id, AdnlAddressList addr_list, td::uint32 mode) = 0;
virtual void add_id_ex(AdnlNodeIdFull id, AdnlAddressList addr_list, td::uint8 cat, td::uint32 mode) = 0;
virtual void del_id(AdnlNodeIdShort id, td::Promise<td::Unit> promise) = 0;
// subscribe to (some) messages(+queries) to this local id
@ -113,6 +115,8 @@ class Adnl : public AdnlSenderInterface {
virtual void create_ext_server(std::vector<AdnlNodeIdShort> ids, std::vector<td::uint16> ports,
td::Promise<td::actor::ActorOwn<AdnlExtServer>> promise) = 0;
virtual void create_tunnel(AdnlNodeIdShort dst, td::uint32 size,
td::Promise<std::pair<td::actor::ActorOwn<AdnlTunnel>, AdnlAddress>> promise) = 0;
static td::actor::ActorOwn<Adnl> create(std::string db, td::actor::ActorId<keyring::Keyring> keyring);