mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
initial commit
This commit is contained in:
commit
c2da007f40
1610 changed files with 398047 additions and 0 deletions
98
adnl/CMakeLists.txt
Normal file
98
adnl/CMakeLists.txt
Normal file
|
@ -0,0 +1,98 @@
|
|||
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
|
||||
|
||||
#BEGIN internal
|
||||
set(ADNL_HEADERS
|
||||
adnl-address-list.h
|
||||
adnl-address-list.hpp
|
||||
adnl-db.h
|
||||
adnl-db.hpp
|
||||
adnl-channel.h
|
||||
adnl-channel.hpp
|
||||
adnl-ext-client.h
|
||||
adnl-ext-client.hpp
|
||||
adnl-ext-connection.hpp
|
||||
adnl-ext-server.h
|
||||
adnl-ext-server.hpp
|
||||
adnl-local-id.h
|
||||
adnl-message.h
|
||||
adnl-network-manager.h
|
||||
adnl-network-manager.hpp
|
||||
adnl-node.h
|
||||
adnl-packet.h
|
||||
adnl-peer-table.h
|
||||
adnl-peer-table.hpp
|
||||
adnl-peer.h
|
||||
adnl-peer.hpp
|
||||
adnl-query.h
|
||||
adnl-static-nodes.h
|
||||
adnl-static-nodes.hpp
|
||||
adnl-proxy-types.h
|
||||
adnl-proxy-types.hpp
|
||||
adnl.h
|
||||
utils.hpp
|
||||
)
|
||||
set(ADNL_SOURCE
|
||||
adnl-address-list.cpp
|
||||
adnl-db.cpp
|
||||
adnl-ext-client.cpp
|
||||
adnl-ext-server.cpp
|
||||
adnl-ext-connection.cpp
|
||||
adnl-local-id.cpp
|
||||
adnl-message.cpp
|
||||
adnl-network-manager.cpp
|
||||
adnl-node.cpp
|
||||
adnl-packet.cpp
|
||||
adnl-peer-table.cpp
|
||||
adnl-peer.cpp
|
||||
adnl-query.cpp
|
||||
adnl-channel.cpp
|
||||
adnl-static-nodes.cpp
|
||||
adnl-proxy-types.cpp
|
||||
utils.cpp
|
||||
${ADNL_HEADERS}
|
||||
)
|
||||
|
||||
set(ADNL_TEST_SOURCE
|
||||
adnl-test-loopback-implementation.h
|
||||
adnl-test-loopback-implementation.cpp
|
||||
)
|
||||
|
||||
set(ADNL_PROXY_SOURCE
|
||||
adnl-proxy.cpp
|
||||
adnl-proxy-types.h
|
||||
adnl-proxy-types.hpp
|
||||
adnl-proxy-types.cpp
|
||||
)
|
||||
|
||||
#FIXME
|
||||
set(ADNL_LITE_HEADERS ${ADNL_HEADERS})
|
||||
#END internal
|
||||
|
||||
set(ADNL_LITE_SOURCE
|
||||
adnl-ext-client.cpp
|
||||
adnl-ext-connection.cpp
|
||||
adnl-query.cpp
|
||||
|
||||
${ADNL_LITE_HEADERS}
|
||||
)
|
||||
|
||||
#BEGIN internal
|
||||
add_library(adnl STATIC ${ADNL_SOURCE})
|
||||
|
||||
target_include_directories(adnl PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
|
||||
target_link_libraries(adnl PUBLIC tdactor ton_crypto tl_api tdnet tddb keys keyring )
|
||||
|
||||
add_executable(adnl-proxy ${ADNL_PROXY_SOURCE})
|
||||
target_include_directories(adnl-proxy PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
|
||||
target_link_libraries(adnl-proxy PUBLIC tdactor ton_crypto tl_api tdnet common
|
||||
tl-utils)
|
||||
|
||||
add_library(adnltest STATIC ${ADNL_TEST_SOURCE})
|
||||
target_include_directories(adnltest PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
|
||||
target_link_libraries(adnltest PUBLIC adnl )
|
||||
#END internal
|
||||
|
||||
add_library(adnllite STATIC ${ADNL_LITE_SOURCE})
|
||||
|
||||
target_include_directories(adnllite PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
|
||||
target_link_libraries(adnllite PUBLIC tdactor ton_crypto tl_lite_api tdnet keys )
|
160
adnl/adnl-address-list.cpp
Normal file
160
adnl/adnl-address-list.cpp
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "adnl-address-list.hpp"
|
||||
#include "adnl-peer-table.h"
|
||||
#include "auto/tl/ton_api.hpp"
|
||||
#include "td/utils/overloaded.h"
|
||||
#include "td/net/UdpServer.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlNetworkConnectionUdp : public AdnlNetworkConnection {
|
||||
public:
|
||||
void send(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::uint32 priority, td::BufferSlice message) override;
|
||||
bool is_alive() const override {
|
||||
return true;
|
||||
}
|
||||
bool is_active() const override {
|
||||
return true;
|
||||
}
|
||||
void start_up() override {
|
||||
callback_->on_change_state(true);
|
||||
}
|
||||
|
||||
AdnlNetworkConnectionUdp(td::actor::ActorId<AdnlNetworkManager> network_manager, td::uint32 ip, td::uint16 port,
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback);
|
||||
AdnlNetworkConnectionUdp(td::actor::ActorId<AdnlNetworkManager> network_manager, td::Bits128 ip, td::uint16 port,
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback);
|
||||
|
||||
private:
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager_;
|
||||
td::IPAddress addr_;
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback_;
|
||||
};
|
||||
|
||||
void AdnlNetworkConnectionUdp::send(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::uint32 priority,
|
||||
td::BufferSlice message) {
|
||||
LOG_CHECK(message.size() <= AdnlNetworkManager::get_mtu()) << "dst=" << addr_ << " size=" << message.size();
|
||||
td::actor::send_closure(network_manager_, &AdnlNetworkManager::send_udp_packet, src, dst, addr_, priority,
|
||||
std::move(message));
|
||||
}
|
||||
|
||||
AdnlNetworkConnectionUdp::AdnlNetworkConnectionUdp(td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
td::uint32 ip, td::uint16 port,
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback)
|
||||
: network_manager_(network_manager), callback_(std::move(callback)) {
|
||||
addr_.init_host_port(td::IPAddress::ipv4_to_str(ip), port).ensure();
|
||||
}
|
||||
|
||||
AdnlNetworkConnectionUdp::AdnlNetworkConnectionUdp(td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
td::Bits128 ip, td::uint16 port,
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback)
|
||||
: network_manager_(network_manager), callback_(std::move(callback)) {
|
||||
addr_.init_host_port(td::IPAddress::ipv6_to_str(ip.as_slice()), port).ensure();
|
||||
}
|
||||
|
||||
AdnlAddressImpl::Hash AdnlAddressImpl::get_hash() const {
|
||||
return get_tl_object_sha_bits256(tl());
|
||||
}
|
||||
|
||||
td::actor::ActorOwn<AdnlNetworkConnection> AdnlAddressUdp::create_connection(
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback) const {
|
||||
return td::actor::create_actor<AdnlNetworkConnectionUdp>("udpconn", network_manager, ip_, port_, std::move(callback));
|
||||
}
|
||||
|
||||
AdnlAddressUdp::AdnlAddressUdp(const ton_api::adnl_address_udp &obj) {
|
||||
ip_ = obj.ip_;
|
||||
port_ = static_cast<td::uint16>(obj.port_);
|
||||
}
|
||||
|
||||
td::actor::ActorOwn<AdnlNetworkConnection> AdnlAddressUdp6::create_connection(
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback) const {
|
||||
return td::actor::create_actor<AdnlNetworkConnectionUdp>("udpconn", network_manager, ip_, port_, std::move(callback));
|
||||
}
|
||||
|
||||
AdnlAddressUdp6::AdnlAddressUdp6(const ton_api::adnl_address_udp6 &obj) {
|
||||
ip_ = obj.ip_;
|
||||
port_ = static_cast<td::uint16>(obj.port_);
|
||||
}
|
||||
|
||||
td::Ref<AdnlAddressImpl> AdnlAddressImpl::create(const tl_object_ptr<ton_api::adnl_Address> &addr) {
|
||||
td::Ref<AdnlAddressImpl> res = td::Ref<AdnlAddressImpl>{};
|
||||
ton_api::downcast_call(*const_cast<ton_api::adnl_Address *>(addr.get()),
|
||||
td::overloaded(
|
||||
[&](const ton_api::adnl_address_udp &obj) {
|
||||
res = td::Ref<AdnlAddressUdp>{true, obj};
|
||||
},
|
||||
[&](const ton_api::adnl_address_udp6 &obj) {
|
||||
res = td::Ref<AdnlAddressUdp6>{true, obj};
|
||||
}));
|
||||
return res;
|
||||
}
|
||||
|
||||
bool AdnlAddressList::public_only() const {
|
||||
for (auto &addr : addrs_) {
|
||||
if (!addr->is_public()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
AdnlAddressList::AdnlAddressList(const tl_object_ptr<ton_api::adnl_addressList> &addrs) {
|
||||
version_ = static_cast<td::uint32>(addrs->version_);
|
||||
std::vector<td::Ref<AdnlAddressImpl>> vec;
|
||||
for (auto &addr : addrs->addrs_) {
|
||||
vec.push_back(AdnlAddressImpl::create(addr));
|
||||
}
|
||||
addrs_ = std::move(vec);
|
||||
reinit_date_ = addrs->reinit_date_;
|
||||
priority_ = addrs->priority_;
|
||||
expire_at_ = addrs->expire_at_;
|
||||
}
|
||||
|
||||
tl_object_ptr<ton_api::adnl_addressList> AdnlAddressList::tl() const {
|
||||
std::vector<tl_object_ptr<ton_api::adnl_Address>> addrs;
|
||||
for (auto &v : addrs_) {
|
||||
addrs.emplace_back(v->tl());
|
||||
}
|
||||
return create_tl_object<ton_api::adnl_addressList>(std::move(addrs), version_, reinit_date_, priority_, expire_at_);
|
||||
}
|
||||
|
||||
td::uint32 AdnlAddressList::serialized_size() const {
|
||||
td::uint32 res = 24;
|
||||
for (auto &addr : addrs_) {
|
||||
res += addr->serialized_size();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
td::Result<AdnlAddressList> AdnlAddressList::create(const tl_object_ptr<ton_api::adnl_addressList> &addr_list) {
|
||||
auto A = AdnlAddressList{addr_list};
|
||||
if (A.serialized_size() > max_serialized_size()) {
|
||||
return td::Status::Error(ErrorCode::protoviolation, PSTRING() << "too big addr list: size=" << A.serialized_size());
|
||||
}
|
||||
return A;
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
105
adnl/adnl-address-list.h
Normal file
105
adnl/adnl-address-list.h
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "adnl-network-manager.h"
|
||||
#include "crypto/common/refcnt.hpp"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlAddressImpl : public td::CntObject {
|
||||
public:
|
||||
using Hash = td::Bits256;
|
||||
virtual ~AdnlAddressImpl() = default;
|
||||
|
||||
virtual Hash get_hash() const;
|
||||
virtual bool is_public() const = 0;
|
||||
virtual td::uint32 serialized_size() const = 0;
|
||||
virtual tl_object_ptr<ton_api::adnl_Address> tl() const = 0;
|
||||
virtual td::actor::ActorOwn<AdnlNetworkConnection> create_connection(
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback) const = 0;
|
||||
|
||||
static td::Ref<AdnlAddressImpl> create(const tl_object_ptr<ton_api::adnl_Address> &addr);
|
||||
};
|
||||
|
||||
using AdnlAddress = td::Ref<AdnlAddressImpl>;
|
||||
|
||||
class AdnlAddressList {
|
||||
private:
|
||||
AdnlAddressList(const tl_object_ptr<ton_api::adnl_addressList> &addrs);
|
||||
|
||||
td::int32 version_;
|
||||
td::int32 reinit_date_;
|
||||
td::int32 priority_;
|
||||
td::int32 expire_at_;
|
||||
std::vector<AdnlAddress> addrs_;
|
||||
|
||||
public:
|
||||
static constexpr td::uint32 max_serialized_size() {
|
||||
return 128;
|
||||
}
|
||||
|
||||
const auto &addrs() const {
|
||||
return addrs_;
|
||||
}
|
||||
auto version() const {
|
||||
return version_;
|
||||
}
|
||||
auto reinit_date() const {
|
||||
return reinit_date_;
|
||||
}
|
||||
auto priority() const {
|
||||
return priority_;
|
||||
}
|
||||
auto expire_at() const {
|
||||
return expire_at_;
|
||||
}
|
||||
void set_version(td::uint32 version) {
|
||||
version_ = version;
|
||||
}
|
||||
void set_reinit_date(td::int32 date) {
|
||||
reinit_date_ = date;
|
||||
}
|
||||
void set_expire_at(td::int32 date) {
|
||||
expire_at_ = date;
|
||||
}
|
||||
bool empty() const {
|
||||
return version_ == -1;
|
||||
}
|
||||
void add_addr(AdnlAddress addr) {
|
||||
addrs_.push_back(addr);
|
||||
}
|
||||
bool public_only() const;
|
||||
td::uint32 size() const {
|
||||
return static_cast<td::uint32>(addrs_.size());
|
||||
}
|
||||
td::uint32 serialized_size() const;
|
||||
tl_object_ptr<ton_api::adnl_addressList> tl() const;
|
||||
AdnlAddressList() : version_{-1}, reinit_date_{0}, priority_{0}, expire_at_{0} {
|
||||
}
|
||||
|
||||
static td::Result<AdnlAddressList> create(const tl_object_ptr<ton_api::adnl_addressList> &addr_list);
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
90
adnl/adnl-address-list.hpp
Normal file
90
adnl/adnl-address-list.hpp
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "adnl-node-id.hpp"
|
||||
#include "adnl-address-list.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlAddressUdp : public AdnlAddressImpl {
|
||||
private:
|
||||
td::uint32 ip_;
|
||||
td::uint16 port_;
|
||||
|
||||
public:
|
||||
explicit AdnlAddressUdp(const ton_api::adnl_address_udp &obj);
|
||||
|
||||
AdnlAddressUdp(td::uint32 ip, td::uint16 port) : ip_(ip), port_(port) {
|
||||
}
|
||||
|
||||
AdnlAddressUdp *make_copy() const override {
|
||||
return new AdnlAddressUdp{ip_, port_};
|
||||
}
|
||||
|
||||
bool is_public() const override {
|
||||
return true;
|
||||
}
|
||||
td::uint32 serialized_size() const override {
|
||||
return 12;
|
||||
}
|
||||
|
||||
tl_object_ptr<ton_api::adnl_Address> tl() const override {
|
||||
return create_tl_object<ton_api::adnl_address_udp>(ip_, port_);
|
||||
}
|
||||
td::actor::ActorOwn<AdnlNetworkConnection> create_connection(
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback) const override;
|
||||
};
|
||||
|
||||
class AdnlAddressUdp6 : public AdnlAddressImpl {
|
||||
private:
|
||||
td::Bits128 ip_;
|
||||
td::uint16 port_;
|
||||
|
||||
public:
|
||||
explicit AdnlAddressUdp6(const ton_api::adnl_address_udp6 &obj);
|
||||
|
||||
AdnlAddressUdp6(td::Bits128 ip, td::uint16 port) : ip_(ip), port_(port) {
|
||||
}
|
||||
|
||||
AdnlAddressUdp6 *make_copy() const override {
|
||||
return new AdnlAddressUdp6{ip_, port_};
|
||||
}
|
||||
|
||||
bool is_public() const override {
|
||||
return true;
|
||||
}
|
||||
td::uint32 serialized_size() const override {
|
||||
return 12;
|
||||
}
|
||||
|
||||
tl_object_ptr<ton_api::adnl_Address> tl() const override {
|
||||
return create_tl_object<ton_api::adnl_address_udp6>(ip_, port_);
|
||||
}
|
||||
td::actor::ActorOwn<AdnlNetworkConnection> create_connection(
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback) const override;
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
129
adnl/adnl-channel.cpp
Normal file
129
adnl/adnl-channel.cpp
Normal file
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "adnl-channel.hpp"
|
||||
#include "adnl-peer.h"
|
||||
#include "adnl-peer-table.h"
|
||||
|
||||
#include "td/utils/crypto.h"
|
||||
#include "crypto/Ed25519.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
td::Result<td::actor::ActorOwn<AdnlChannel>> AdnlChannel::create(privkeys::Ed25519 pk_data, pubkeys::Ed25519 pub_data,
|
||||
AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id,
|
||||
AdnlChannelIdShort &out_id, AdnlChannelIdShort &in_id,
|
||||
td::actor::ActorId<AdnlPeerPair> peer_pair) {
|
||||
td::Ed25519::PublicKey pub_k = pub_data.export_key();
|
||||
td::Ed25519::PrivateKey priv_k = pk_data.export_key();
|
||||
|
||||
TRY_RESULT_PREFIX(shared_secret, td::Ed25519::compute_shared_secret(pub_k, priv_k),
|
||||
"failed to compute channel shared secret: ");
|
||||
CHECK(shared_secret.length() == 32);
|
||||
|
||||
td::SecureString rev_secret{32};
|
||||
for (td::uint32 i = 0; i < 32; i++) {
|
||||
rev_secret.as_mutable_slice()[i] = shared_secret[31 - i];
|
||||
}
|
||||
|
||||
auto R = [&]() -> std::pair<PrivateKey, PublicKey> {
|
||||
if (local_id < peer_id) {
|
||||
return {privkeys::AES{std::move(shared_secret)}, pubkeys::AES{std::move(rev_secret)}};
|
||||
} else if (peer_id < local_id) {
|
||||
return {privkeys::AES{std::move(rev_secret)}, pubkeys::AES{std::move(shared_secret)}};
|
||||
} else {
|
||||
auto c = shared_secret.copy();
|
||||
return {privkeys::AES{std::move(c)}, pubkeys::AES{std::move(shared_secret)}};
|
||||
}
|
||||
}();
|
||||
|
||||
in_id = AdnlChannelIdShort{R.first.compute_short_id()};
|
||||
out_id = AdnlChannelIdShort{R.second.compute_short_id()};
|
||||
|
||||
TRY_RESULT_PREFIX(encryptor, R.second.create_encryptor(), "failed to init channel encryptor: ");
|
||||
TRY_RESULT_PREFIX(decryptor, R.first.create_decryptor(), "failed to init channel decryptor: ");
|
||||
|
||||
return td::actor::create_actor<AdnlChannelImpl>("channel", local_id, peer_id, peer_pair, in_id, out_id,
|
||||
std::move(encryptor), std::move(decryptor));
|
||||
}
|
||||
|
||||
AdnlChannelImpl::AdnlChannelImpl(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id,
|
||||
td::actor::ActorId<AdnlPeerPair> peer_pair, AdnlChannelIdShort in_id,
|
||||
AdnlChannelIdShort out_id, std::unique_ptr<Encryptor> encryptor,
|
||||
std::unique_ptr<Decryptor> decryptor) {
|
||||
local_id_ = local_id;
|
||||
peer_id_ = peer_id;
|
||||
|
||||
encryptor_ = std::move(encryptor);
|
||||
decryptor_ = std::move(decryptor);
|
||||
|
||||
channel_in_id_ = in_id;
|
||||
channel_out_id_ = out_id;
|
||||
|
||||
peer_pair_ = peer_pair;
|
||||
|
||||
VLOG(ADNL_INFO) << this << ": created";
|
||||
}
|
||||
|
||||
void AdnlChannelImpl::decrypt(td::BufferSlice raw_data, td::Promise<AdnlPacket> promise) {
|
||||
TRY_RESULT_PROMISE_PREFIX(promise, data, decryptor_->decrypt(raw_data.as_slice()),
|
||||
"failed to decrypt channel message: ");
|
||||
TRY_RESULT_PROMISE_PREFIX(promise, tl_packet, fetch_tl_object<ton_api::adnl_packetContents>(std::move(data), true),
|
||||
"decrypted channel packet contains invalid TL scheme: ");
|
||||
TRY_RESULT_PROMISE_PREFIX(promise, packet, AdnlPacket::create(std::move(tl_packet)), "received bad packet: ");
|
||||
if (packet.inited_from_short() && packet.from_short() != peer_id_) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::protoviolation, "bad channel packet destination"));
|
||||
return;
|
||||
}
|
||||
promise.set_value(std::move(packet));
|
||||
}
|
||||
|
||||
void AdnlChannelImpl::send_message(td::uint32 priority, td::actor::ActorId<AdnlNetworkConnection> conn,
|
||||
td::BufferSlice data) {
|
||||
auto E = encryptor_->encrypt(data.as_slice());
|
||||
if (E.is_error()) {
|
||||
VLOG(ADNL_ERROR) << this << ": dropping OUT message: can not encrypt: " << E.move_as_error();
|
||||
return;
|
||||
}
|
||||
auto enc = E.move_as_ok();
|
||||
auto B = td::BufferSlice(enc.size() + 32);
|
||||
td::MutableSlice S = B.as_slice();
|
||||
S.copy_from(channel_out_id_.as_slice());
|
||||
S.remove_prefix(32);
|
||||
S.copy_from(enc.as_slice());
|
||||
td::actor::send_closure(conn, &AdnlNetworkConnection::send, local_id_, peer_id_, priority, std::move(B));
|
||||
}
|
||||
|
||||
void AdnlChannelImpl::receive(td::BufferSlice data) {
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[peer = peer_pair_, channel_id = channel_in_id_, id = print_id()](td::Result<AdnlPacket> R) {
|
||||
if (R.is_error()) {
|
||||
VLOG(ADNL_WARNING) << id << ": dropping IN message: can not decrypt: " << R.move_as_error();
|
||||
} else {
|
||||
td::actor::send_closure(peer, &AdnlPeerPair::receive_packet_from_channel, channel_id, R.move_as_ok());
|
||||
}
|
||||
});
|
||||
|
||||
decrypt(std::move(data), std::move(P));
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
46
adnl/adnl-channel.h
Normal file
46
adnl/adnl-channel.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "adnl-local-id.h"
|
||||
#include "adnl-peer.h"
|
||||
#include "adnl-peer-table.h"
|
||||
#include "adnl-network-manager.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlPeerPair;
|
||||
|
||||
class AdnlChannel : public td::actor::Actor {
|
||||
public:
|
||||
static td::Result<td::actor::ActorOwn<AdnlChannel>> create(privkeys::Ed25519 pk, pubkeys::Ed25519 pub,
|
||||
AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id,
|
||||
AdnlChannelIdShort &out_id, AdnlChannelIdShort &in_id,
|
||||
td::actor::ActorId<AdnlPeerPair> peer_pair);
|
||||
virtual void receive(td::BufferSlice data) = 0;
|
||||
virtual void send_message(td::uint32 priority, td::actor::ActorId<AdnlNetworkConnection> conn,
|
||||
td::BufferSlice data) = 0;
|
||||
virtual ~AdnlChannel() = default;
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
82
adnl/adnl-channel.hpp
Normal file
82
adnl/adnl-channel.hpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "adnl-channel.h"
|
||||
#include "keys/encryptor.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlPeerPair;
|
||||
|
||||
class AdnlChannelImpl : public AdnlChannel {
|
||||
public:
|
||||
AdnlChannelImpl(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id, td::actor::ActorId<AdnlPeerPair> peer_pair,
|
||||
AdnlChannelIdShort in_id, AdnlChannelIdShort out_id, std::unique_ptr<Encryptor> encryptor,
|
||||
std::unique_ptr<Decryptor> decryptor);
|
||||
void decrypt(td::BufferSlice data, td::Promise<AdnlPacket> promise);
|
||||
void receive(td::BufferSlice data) override;
|
||||
void send_message(td::uint32 priority, td::actor::ActorId<AdnlNetworkConnection> conn, td::BufferSlice data) override;
|
||||
|
||||
struct AdnlChannelPrintId {
|
||||
AdnlChannelIdShort channel_out_id_;
|
||||
AdnlChannelIdShort channel_in_id_;
|
||||
AdnlNodeIdShort local_id_;
|
||||
AdnlNodeIdShort peer_id_;
|
||||
};
|
||||
|
||||
AdnlChannelPrintId print_id() const {
|
||||
return AdnlChannelPrintId{channel_out_id_, channel_in_id_, local_id_, peer_id_};
|
||||
}
|
||||
|
||||
private:
|
||||
AdnlChannelIdShort channel_out_id_;
|
||||
AdnlChannelIdShort channel_in_id_;
|
||||
AdnlNodeIdShort local_id_;
|
||||
AdnlNodeIdShort peer_id_;
|
||||
std::unique_ptr<Encryptor> encryptor_;
|
||||
std::unique_ptr<Decryptor> decryptor_;
|
||||
td::actor::ActorId<AdnlPeerPair> peer_pair_;
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
||||
|
||||
namespace td {
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlChannelImpl::AdnlChannelPrintId &id) {
|
||||
sb << "[channel " << id.peer_id_ << "-" << id.local_id_ << " " << id.channel_out_id_ << "-" << id.channel_in_id_
|
||||
<< "]";
|
||||
return sb;
|
||||
}
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlChannelImpl &channel) {
|
||||
sb << channel.print_id();
|
||||
return sb;
|
||||
}
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlChannelImpl *channel) {
|
||||
sb << channel->print_id();
|
||||
return sb;
|
||||
}
|
||||
|
||||
} // namespace td
|
82
adnl/adnl-db.cpp
Normal file
82
adnl/adnl-db.cpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "adnl-db.hpp"
|
||||
#include "td/db/RocksDb.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
void AdnlDbImpl::update(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id, AdnlDbItem item,
|
||||
td::Promise<td::Unit> promise) {
|
||||
td::BufferSlice b{64};
|
||||
auto S = b.as_slice();
|
||||
S.copy_from(local_id.as_slice());
|
||||
S.remove_prefix(32);
|
||||
S.copy_from(peer_id.as_slice());
|
||||
|
||||
auto obj = create_tl_object<ton_api::adnl_db_node_value>(static_cast<td::int32>(td::Clocks::system()), item.id.tl(),
|
||||
item.addr_list.tl(), item.priority_addr_list.tl());
|
||||
|
||||
kv_->begin_transaction().ensure();
|
||||
kv_->set(b.as_slice(), serialize_tl_object(obj, true).as_slice()).ensure();
|
||||
kv_->commit_transaction().ensure();
|
||||
}
|
||||
|
||||
void AdnlDbImpl::get(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id, td::Promise<AdnlDbItem> promise) {
|
||||
td::BufferSlice b{64};
|
||||
auto S = b.as_slice();
|
||||
S.copy_from(local_id.as_slice());
|
||||
S.remove_prefix(32);
|
||||
S.copy_from(peer_id.as_slice());
|
||||
|
||||
std::string value;
|
||||
auto R = kv_->get(b.as_slice(), value);
|
||||
R.ensure();
|
||||
if (R.move_as_ok() == td::KeyValue::GetStatus::NotFound) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::notready, "not in db"));
|
||||
return;
|
||||
}
|
||||
auto F = fetch_tl_object<ton_api::adnl_db_node_value>(td::BufferSlice{value}, true);
|
||||
F.ensure();
|
||||
auto f = F.move_as_ok();
|
||||
AdnlDbItem n;
|
||||
auto id = AdnlNodeIdFull::create(f->id_);
|
||||
id.ensure();
|
||||
n.id = id.move_as_ok();
|
||||
auto addr_list = AdnlAddressList::create(std::move(f->addr_list_));
|
||||
addr_list.ensure();
|
||||
n.addr_list = addr_list.move_as_ok();
|
||||
auto priority_addr_list = AdnlAddressList::create(std::move(f->priority_addr_list_));
|
||||
priority_addr_list.ensure();
|
||||
n.priority_addr_list = priority_addr_list.move_as_ok();
|
||||
promise.set_value(std::move(n));
|
||||
}
|
||||
|
||||
void AdnlDbImpl::start_up() {
|
||||
kv_ = std::make_shared<td::RocksDb>(td::RocksDb::open(path_).move_as_ok());
|
||||
}
|
||||
|
||||
td::actor::ActorOwn<AdnlDb> AdnlDb::create(std::string path) {
|
||||
return td::actor::create_actor<AdnlDbImpl>("adnldb", path);
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
47
adnl/adnl-db.h
Normal file
47
adnl/adnl-db.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
|
||||
#include "adnl.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
struct AdnlDbItem {
|
||||
AdnlNodeIdFull id;
|
||||
AdnlAddressList addr_list;
|
||||
AdnlAddressList priority_addr_list;
|
||||
};
|
||||
|
||||
class AdnlDb : public td::actor::Actor {
|
||||
public:
|
||||
virtual ~AdnlDb() = default;
|
||||
virtual void update(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id, AdnlDbItem item,
|
||||
td::Promise<td::Unit> promise) = 0;
|
||||
virtual void get(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id, td::Promise<AdnlDbItem> promise) = 0;
|
||||
|
||||
static td::actor::ActorOwn<AdnlDb> create(std::string path);
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
47
adnl/adnl-db.hpp
Normal file
47
adnl/adnl-db.hpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "adnl-db.h"
|
||||
#include "td/db/KeyValue.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlDbImpl : public AdnlDb {
|
||||
public:
|
||||
void update(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id, AdnlDbItem item,
|
||||
td::Promise<td::Unit> promise) override;
|
||||
void get(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id, td::Promise<AdnlDbItem> promise) override;
|
||||
|
||||
void start_up() override;
|
||||
|
||||
AdnlDbImpl(std::string path) : path_(path) {
|
||||
}
|
||||
|
||||
private:
|
||||
std::string path_;
|
||||
|
||||
std::shared_ptr<td::KeyValue> kv_;
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
181
adnl/adnl-ext-client.cpp
Normal file
181
adnl/adnl-ext-client.cpp
Normal file
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "adnl-ext-client.hpp"
|
||||
#include "adnl-ext-client.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
void AdnlExtClientImpl::alarm() {
|
||||
if (is_closing_) {
|
||||
return;
|
||||
}
|
||||
if (conn_.empty() || !conn_.is_alive()) {
|
||||
next_create_at_ = td::Timestamp::in(10.0);
|
||||
alarm_timestamp() = next_create_at_;
|
||||
|
||||
auto fd = td::SocketFd::open(dst_addr_);
|
||||
if (fd.is_error()) {
|
||||
LOG(INFO) << "failed to connect to " << dst_addr_ << ": " << fd.move_as_error();
|
||||
return;
|
||||
}
|
||||
|
||||
class Cb : public AdnlExtConnection::Callback {
|
||||
private:
|
||||
td::actor::ActorId<AdnlExtClientImpl> id_;
|
||||
|
||||
public:
|
||||
void on_ready(td::actor::ActorId<AdnlExtConnection> conn) {
|
||||
td::actor::send_closure(id_, &AdnlExtClientImpl::conn_ready, conn);
|
||||
}
|
||||
void on_close(td::actor::ActorId<AdnlExtConnection> conn) {
|
||||
td::actor::send_closure(id_, &AdnlExtClientImpl::conn_stopped, conn);
|
||||
}
|
||||
Cb(td::actor::ActorId<AdnlExtClientImpl> id) : id_(id) {
|
||||
}
|
||||
};
|
||||
|
||||
conn_ = td::actor::create_actor<AdnlOutboundConnection>(td::actor::ActorOptions().with_name("outconn").with_poll(),
|
||||
fd.move_as_ok(), std::make_unique<Cb>(actor_id(this)), dst_,
|
||||
local_id_, actor_id(this));
|
||||
}
|
||||
}
|
||||
|
||||
void AdnlExtClientImpl::hangup() {
|
||||
conn_ = {};
|
||||
is_closing_ = true;
|
||||
ref_cnt_--;
|
||||
try_stop();
|
||||
}
|
||||
|
||||
void AdnlExtClientImpl::try_stop() {
|
||||
if (is_closing_ && ref_cnt_ == 0 && out_queries_.empty()) {
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
td::Status AdnlOutboundConnection::process_custom_packet(td::BufferSlice &data, bool &processed) {
|
||||
if (data.size() == 12) {
|
||||
auto F = fetch_tl_object<ton_api::tcp_pong>(data.clone(), true);
|
||||
if (F.is_ok()) {
|
||||
processed = true;
|
||||
return td::Status::OK();
|
||||
}
|
||||
}
|
||||
if (!local_id_.empty() && nonce_.size() != 0) {
|
||||
auto F = fetch_tl_object<ton_api::tcp_authentificationNonce>(data.clone(), true);
|
||||
if (F.is_ok()) {
|
||||
auto f = F.move_as_ok();
|
||||
if (f->nonce_.size() == 0 || f->nonce_.size() > 512) {
|
||||
return td::Status::Error(ErrorCode::protoviolation, "bad nonce size");
|
||||
}
|
||||
td::SecureString ss{nonce_.size() + f->nonce_.size()};
|
||||
ss.as_mutable_slice().copy_from(nonce_.as_slice());
|
||||
ss.as_mutable_slice().remove_prefix(nonce_.size()).copy_from(f->nonce_.as_slice());
|
||||
|
||||
TRY_RESULT(dec, local_id_.create_decryptor());
|
||||
TRY_RESULT(B, dec->sign(ss.as_slice()));
|
||||
|
||||
auto obj =
|
||||
create_tl_object<ton_api::tcp_authentificationComplete>(local_id_.compute_public_key().tl(), std::move(B));
|
||||
send(serialize_tl_object(obj, true));
|
||||
|
||||
nonce_.clear();
|
||||
|
||||
processed = true;
|
||||
authorization_complete_ = true;
|
||||
return td::Status::OK();
|
||||
}
|
||||
}
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
void AdnlOutboundConnection::start_up() {
|
||||
AdnlExtConnection::start_up();
|
||||
auto X = dst_.pubkey().create_encryptor();
|
||||
if (X.is_error()) {
|
||||
LOG(ERROR) << "failed to init encryptor: " << X.move_as_error();
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
auto enc = X.move_as_ok();
|
||||
|
||||
td::BufferSlice d{256};
|
||||
auto id = dst_.compute_short_id();
|
||||
auto S = d.as_slice();
|
||||
S.copy_from(id.as_slice());
|
||||
S.remove_prefix(32);
|
||||
S.truncate(256 - 64 - 32);
|
||||
td::Random::secure_bytes(S);
|
||||
init_crypto(S);
|
||||
|
||||
auto R = enc->encrypt(S);
|
||||
if (R.is_error()) {
|
||||
LOG(ERROR) << "failed to encrypt: " << R.move_as_error();
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
auto data = R.move_as_ok();
|
||||
LOG_CHECK(data.size() == 256 - 32) << "size=" << data.size();
|
||||
S = d.as_slice();
|
||||
S.remove_prefix(32);
|
||||
CHECK(S.size() == data.size());
|
||||
S.copy_from(data.as_slice());
|
||||
|
||||
send_uninit(std::move(d));
|
||||
|
||||
if (!local_id_.empty()) {
|
||||
nonce_ = td::SecureString{32};
|
||||
td::Random::secure_bytes(nonce_.as_mutable_slice());
|
||||
auto obj = create_tl_object<ton_api::tcp_authentificate>(td::BufferSlice{nonce_.as_slice()});
|
||||
send(serialize_tl_object(obj, true));
|
||||
}
|
||||
}
|
||||
|
||||
void AdnlExtClientImpl::check_ready(td::Promise<td::Unit> promise) {
|
||||
if (conn_.empty() || !conn_.is_alive()) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::notready, "not ready"));
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure(td::actor::ActorId<AdnlExtConnection>{conn_.get()}, &AdnlExtConnection::check_ready_async,
|
||||
std::move(promise));
|
||||
}
|
||||
|
||||
td::actor::ActorOwn<AdnlExtClient> AdnlExtClient::create(AdnlNodeIdFull dst, td::IPAddress dst_addr,
|
||||
std::unique_ptr<AdnlExtClient::Callback> callback) {
|
||||
return td::actor::create_actor<AdnlExtClientImpl>("extclient", std::move(dst), dst_addr, std::move(callback));
|
||||
}
|
||||
|
||||
td::actor::ActorOwn<AdnlExtClient> AdnlExtClient::create(AdnlNodeIdFull dst, PrivateKey local_id,
|
||||
td::IPAddress dst_addr,
|
||||
std::unique_ptr<AdnlExtClient::Callback> callback) {
|
||||
return td::actor::create_actor<AdnlExtClientImpl>("extclient", std::move(dst), std::move(local_id), dst_addr,
|
||||
std::move(callback));
|
||||
}
|
||||
|
||||
td::Status AdnlOutboundConnection::process_packet(td::BufferSlice data) {
|
||||
TRY_RESULT(F, fetch_tl_object<lite_api::adnl_message_answer>(std::move(data), true));
|
||||
td::actor::send_closure(ext_client_, &AdnlExtClientImpl::answer_query, F->query_id_, std::move(F->answer_));
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
48
adnl/adnl-ext-client.h
Normal file
48
adnl/adnl-ext-client.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "adnl-node-id.hpp"
|
||||
#include "td/utils/port/IPAddress.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlExtClient : public td::actor::Actor {
|
||||
public:
|
||||
class Callback {
|
||||
public:
|
||||
virtual ~Callback() = default;
|
||||
virtual void on_ready() = 0;
|
||||
virtual void on_stop_ready() = 0;
|
||||
};
|
||||
virtual ~AdnlExtClient() = default;
|
||||
virtual void check_ready(td::Promise<td::Unit> promise) = 0;
|
||||
virtual void send_query(std::string name, td::BufferSlice data, td::Timestamp timeout,
|
||||
td::Promise<td::BufferSlice> promise) = 0;
|
||||
static td::actor::ActorOwn<AdnlExtClient> create(AdnlNodeIdFull dst, td::IPAddress dst_addr,
|
||||
std::unique_ptr<AdnlExtClient::Callback> callback);
|
||||
static td::actor::ActorOwn<AdnlExtClient> create(AdnlNodeIdFull dst, PrivateKey local_id, td::IPAddress dst_addr,
|
||||
std::unique_ptr<AdnlExtClient::Callback> callback);
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
145
adnl/adnl-ext-client.hpp
Normal file
145
adnl/adnl-ext-client.hpp
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "auto/tl/lite_api.h"
|
||||
#include "adnl-ext-connection.hpp"
|
||||
#include "tl-utils/lite-utils.hpp"
|
||||
#include "td/utils/Random.h"
|
||||
#include "adnl-query.h"
|
||||
#include "keys/encryptor.h"
|
||||
#include "adnl-ext-client.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlExtClientImpl;
|
||||
|
||||
class AdnlOutboundConnection : public AdnlExtConnection {
|
||||
private:
|
||||
AdnlNodeIdFull dst_;
|
||||
PrivateKey local_id_;
|
||||
td::actor::ActorId<AdnlExtClientImpl> ext_client_;
|
||||
td::SecureString nonce_;
|
||||
bool authorization_complete_ = false;
|
||||
|
||||
public:
|
||||
AdnlOutboundConnection(td::SocketFd fd, std::unique_ptr<AdnlExtConnection::Callback> callback, AdnlNodeIdFull dst,
|
||||
td::actor::ActorId<AdnlExtClientImpl> ext_client)
|
||||
: AdnlExtConnection(std::move(fd), std::move(callback), true), dst_(std::move(dst)), ext_client_(ext_client) {
|
||||
}
|
||||
AdnlOutboundConnection(td::SocketFd fd, std::unique_ptr<AdnlExtConnection::Callback> callback, AdnlNodeIdFull dst,
|
||||
PrivateKey local_id, td::actor::ActorId<AdnlExtClientImpl> ext_client)
|
||||
: AdnlExtConnection(std::move(fd), std::move(callback), true)
|
||||
, dst_(std::move(dst))
|
||||
, local_id_(local_id)
|
||||
, ext_client_(ext_client) {
|
||||
}
|
||||
td::Status process_packet(td::BufferSlice data) override;
|
||||
td::Status process_init_packet(td::BufferSlice data) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
td::Status process_custom_packet(td::BufferSlice &data, bool &processed) override;
|
||||
void start_up() override;
|
||||
bool authorized() const override {
|
||||
return local_id_.empty() ? true : authorization_complete_;
|
||||
}
|
||||
};
|
||||
|
||||
class AdnlExtClientImpl : public AdnlExtClient {
|
||||
public:
|
||||
AdnlExtClientImpl(AdnlNodeIdFull dst_id, td::IPAddress dst_addr, std::unique_ptr<Callback> callback)
|
||||
: dst_(std::move(dst_id)), dst_addr_(dst_addr), callback_(std::move(callback)) {
|
||||
}
|
||||
AdnlExtClientImpl(AdnlNodeIdFull dst_id, PrivateKey local_id, td::IPAddress dst_addr,
|
||||
std::unique_ptr<Callback> callback)
|
||||
: dst_(std::move(dst_id)), local_id_(local_id), dst_addr_(dst_addr), callback_(std::move(callback)) {
|
||||
}
|
||||
|
||||
void start_up() override {
|
||||
alarm_timestamp() = next_create_at_;
|
||||
}
|
||||
void conn_stopped(td::actor::ActorId<AdnlExtConnection> conn) {
|
||||
if (!conn_.empty() && conn_.get() == conn) {
|
||||
callback_->on_stop_ready();
|
||||
conn_ = {};
|
||||
alarm_timestamp() = next_create_at_;
|
||||
try_stop();
|
||||
}
|
||||
}
|
||||
void conn_ready(td::actor::ActorId<AdnlExtConnection> conn) {
|
||||
if (!conn_.empty() && conn_.get() == conn) {
|
||||
callback_->on_ready();
|
||||
}
|
||||
}
|
||||
void check_ready(td::Promise<td::Unit> promise) override;
|
||||
void send_query(std::string name, td::BufferSlice data, td::Timestamp timeout,
|
||||
td::Promise<td::BufferSlice> promise) override {
|
||||
auto P = [SelfId = actor_id(this)](AdnlQueryId id) {
|
||||
td::actor::send_closure(SelfId, &AdnlExtClientImpl::destroy_query, id);
|
||||
};
|
||||
auto q_id = generate_next_query_id();
|
||||
out_queries_.emplace(q_id, AdnlQuery::create(std::move(promise), std::move(P), name, timeout, q_id));
|
||||
if (!conn_.empty()) {
|
||||
auto obj = create_tl_object<lite_api::adnl_message_query>(q_id, std::move(data));
|
||||
td::actor::send_closure(conn_, &AdnlOutboundConnection::send, serialize_tl_object(obj, true));
|
||||
}
|
||||
}
|
||||
void destroy_query(AdnlQueryId id) {
|
||||
out_queries_.erase(id);
|
||||
try_stop();
|
||||
}
|
||||
void answer_query(AdnlQueryId id, td::BufferSlice data) {
|
||||
auto it = out_queries_.find(id);
|
||||
if (it != out_queries_.end()) {
|
||||
td::actor::send_closure(it->second, &AdnlQuery::result, std::move(data));
|
||||
}
|
||||
}
|
||||
void alarm() override;
|
||||
void hangup() override;
|
||||
AdnlQueryId generate_next_query_id() {
|
||||
while (true) {
|
||||
AdnlQueryId q_id = AdnlQuery::random_query_id();
|
||||
if (out_queries_.count(q_id) == 0) {
|
||||
return q_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
AdnlNodeIdFull dst_;
|
||||
PrivateKey local_id_;
|
||||
td::IPAddress dst_addr_;
|
||||
|
||||
std::unique_ptr<Callback> callback_;
|
||||
|
||||
td::actor::ActorOwn<AdnlOutboundConnection> conn_;
|
||||
td::Timestamp next_create_at_ = td::Timestamp::now_cached();
|
||||
|
||||
std::map<AdnlQueryId, td::actor::ActorId<AdnlQuery>> out_queries_;
|
||||
|
||||
bool is_closing_{false};
|
||||
td::uint32 ref_cnt_{1};
|
||||
void try_stop();
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
192
adnl/adnl-ext-connection.cpp
Normal file
192
adnl/adnl-ext-connection.cpp
Normal file
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "adnl-ext-connection.hpp"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
void AdnlExtConnection::send_uninit(td::BufferSlice data) {
|
||||
buffered_fd_.output_buffer().append(std::move(data));
|
||||
loop();
|
||||
}
|
||||
|
||||
void AdnlExtConnection::send(td::BufferSlice data) {
|
||||
LOG(DEBUG) << "sending packet of size " << data.size();
|
||||
auto data_size = td::narrow_cast<td::uint32>(data.size()) + 32 + 32;
|
||||
if (data_size < 32 || data_size > (1 << 24)) {
|
||||
LOG(WARNING) << "bad packet size " << data_size;
|
||||
return;
|
||||
}
|
||||
|
||||
td::BufferSlice d{data.size() + 4 + 32 + 32};
|
||||
auto S = d.as_slice();
|
||||
|
||||
S.copy_from(td::Slice(reinterpret_cast<const td::uint8 *>(&data_size), 4));
|
||||
S.remove_prefix(4);
|
||||
auto Sc = S;
|
||||
td::Random::secure_bytes(S.copy().truncate(32));
|
||||
S.remove_prefix(32);
|
||||
S.copy_from(data.as_slice());
|
||||
S.remove_prefix(data.size());
|
||||
|
||||
td::sha256(Sc.truncate(32 + data.size()), S);
|
||||
|
||||
td::BufferSlice e{d.size()};
|
||||
|
||||
out_ctr_.encrypt(d.as_slice(), e.as_slice());
|
||||
|
||||
buffered_fd_.output_buffer().append(std::move(e));
|
||||
loop();
|
||||
}
|
||||
|
||||
td::Status AdnlExtConnection::receive(td::ChainBufferReader &input, bool &exit_loop) {
|
||||
if (stop_read_) {
|
||||
exit_loop = true;
|
||||
return td::Status::OK();
|
||||
}
|
||||
if (input.size() > 0) {
|
||||
received_bytes_ = 1;
|
||||
}
|
||||
if (inited_) {
|
||||
if (!read_len_) {
|
||||
if (input.size() < 4) {
|
||||
exit_loop = true;
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
char x[4];
|
||||
td::MutableSlice s{x, 4};
|
||||
input.advance(4, s);
|
||||
|
||||
td::MutableSlice e{reinterpret_cast<td::uint8 *>(&len_), 4};
|
||||
in_ctr_.encrypt(s, e);
|
||||
LOG(DEBUG) << "len=" << len_;
|
||||
if (len_ > (1 << 24) || len_ < 32) {
|
||||
return td::Status::Error("Too big packet");
|
||||
}
|
||||
read_len_ = true;
|
||||
}
|
||||
if (input.size() < len_) {
|
||||
exit_loop = true;
|
||||
return td::Status::OK();
|
||||
}
|
||||
auto data = input.cut_head(len_).move_as_buffer_slice();
|
||||
update_timer();
|
||||
|
||||
td::BufferSlice dec_data{data.size()};
|
||||
in_ctr_.encrypt(data.as_slice(), dec_data.as_slice());
|
||||
|
||||
exit_loop = false;
|
||||
read_len_ = false;
|
||||
len_ = 0;
|
||||
return receive_packet(std::move(dec_data));
|
||||
} else {
|
||||
if (input.size() < 256) {
|
||||
exit_loop = true;
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
auto data = input.cut_head(256).move_as_buffer_slice();
|
||||
update_timer();
|
||||
|
||||
exit_loop = false;
|
||||
return process_init_packet(std::move(data));
|
||||
}
|
||||
}
|
||||
|
||||
void AdnlExtConnection::loop() {
|
||||
auto status = [&] {
|
||||
TRY_STATUS(buffered_fd_.flush_read());
|
||||
auto &input = buffered_fd_.input_buffer();
|
||||
bool exit_loop = false;
|
||||
while (!exit_loop) {
|
||||
TRY_STATUS(receive(input, exit_loop));
|
||||
}
|
||||
TRY_STATUS(buffered_fd_.flush_write());
|
||||
if (td::can_close(buffered_fd_)) {
|
||||
stop();
|
||||
}
|
||||
return td::Status::OK();
|
||||
}();
|
||||
if (status.is_error()) {
|
||||
LOG(ERROR) << "Client got error " << status;
|
||||
stop();
|
||||
} else {
|
||||
send_ready();
|
||||
}
|
||||
}
|
||||
|
||||
td::Status AdnlExtConnection::init_crypto(td::Slice S) {
|
||||
if (S.size() < 96) {
|
||||
return td::Status::Error(ErrorCode::protoviolation, "too small enc data");
|
||||
}
|
||||
CHECK(S.size() >= 96);
|
||||
td::SecureString s1(32), s2(32);
|
||||
td::SecureString v1(16), v2(16);
|
||||
s1.as_mutable_slice().copy_from(S.copy().truncate(32));
|
||||
S.remove_prefix(32);
|
||||
s2.as_mutable_slice().copy_from(S.copy().truncate(32));
|
||||
S.remove_prefix(32);
|
||||
v1.as_mutable_slice().copy_from(S.copy().truncate(16));
|
||||
S.remove_prefix(16);
|
||||
v2.as_mutable_slice().copy_from(S.copy().truncate(16));
|
||||
S.remove_prefix(16);
|
||||
if (is_client_) {
|
||||
in_ctr_.init(s1, v1);
|
||||
out_ctr_.init(s2, v2);
|
||||
} else {
|
||||
in_ctr_.init(s2, v2);
|
||||
out_ctr_.init(s1, v1);
|
||||
}
|
||||
inited_ = true;
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
td::Status AdnlExtConnection::receive_packet(td::BufferSlice data) {
|
||||
LOG(DEBUG) << "received packet of size " << data.size();
|
||||
auto S = data.as_slice();
|
||||
S.truncate(data.size() - 32);
|
||||
auto D = data.as_slice();
|
||||
D.remove_prefix(data.size() - 32);
|
||||
|
||||
if (td::sha256(S) != D) {
|
||||
return td::Status::Error(ErrorCode::protoviolation, "sha256 mismatch");
|
||||
}
|
||||
|
||||
data.truncate(data.size() - 32);
|
||||
data.confirm_read(32);
|
||||
|
||||
if (data.size() == 0) {
|
||||
// keepalive
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
bool processed = false;
|
||||
TRY_STATUS(process_custom_packet(data, processed));
|
||||
if (processed) {
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
return process_packet(std::move(data));
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
163
adnl/adnl-ext-connection.hpp
Normal file
163
adnl/adnl-ext-connection.hpp
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "td/net/TcpListener.h"
|
||||
#include "td/utils/crypto.h"
|
||||
#include "td/utils/BufferedFd.h"
|
||||
#include "tl-utils/tl-utils.hpp"
|
||||
#include "td/utils/Random.h"
|
||||
#include "common/errorcode.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlExtConnection : public td::actor::Actor, public td::ObserverBase {
|
||||
public:
|
||||
class Callback {
|
||||
public:
|
||||
virtual ~Callback() = default;
|
||||
virtual void on_close(td::actor::ActorId<AdnlExtConnection> conn) = 0;
|
||||
virtual void on_ready(td::actor::ActorId<AdnlExtConnection> conn) = 0;
|
||||
};
|
||||
|
||||
double timeout() {
|
||||
return is_client_ ? 20.0 : 60.0;
|
||||
}
|
||||
|
||||
AdnlExtConnection(td::SocketFd fd, std::unique_ptr<Callback> callback, bool is_client)
|
||||
: buffered_fd_(std::move(fd)), callback_(std::move(callback)), is_client_(is_client) {
|
||||
}
|
||||
void send(td::BufferSlice data);
|
||||
void send_uninit(td::BufferSlice data);
|
||||
td::Status receive(td::ChainBufferReader &input, bool &exit_loop);
|
||||
virtual td::Status process_packet(td::BufferSlice data) = 0;
|
||||
td::Status receive_packet(td::BufferSlice data);
|
||||
virtual td::Status process_custom_packet(td::BufferSlice &data, bool &processed) = 0;
|
||||
virtual td::Status process_init_packet(td::BufferSlice data) = 0;
|
||||
virtual bool authorized() const {
|
||||
return false;
|
||||
}
|
||||
td::Status init_crypto(td::Slice data);
|
||||
void stop_read() {
|
||||
stop_read_ = true;
|
||||
}
|
||||
void resume_read() {
|
||||
stop_read_ = false;
|
||||
}
|
||||
bool check_ready() const {
|
||||
return received_bytes_ && inited_ && authorized() && !td::can_close(buffered_fd_);
|
||||
}
|
||||
void check_ready_async(td::Promise<td::Unit> promise) {
|
||||
if (check_ready()) {
|
||||
promise.set_value(td::Unit());
|
||||
} else {
|
||||
promise.set_error(td::Status::Error(ErrorCode::notready, "not ready"));
|
||||
}
|
||||
}
|
||||
void send_ready() {
|
||||
if (check_ready() && !sent_ready_ && callback_) {
|
||||
callback_->on_ready(actor_id(this));
|
||||
sent_ready_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
td::BufferedFd<td::SocketFd> buffered_fd_;
|
||||
td::actor::ActorId<AdnlExtConnection> self_;
|
||||
std::unique_ptr<Callback> callback_;
|
||||
bool sent_ready_ = false;
|
||||
bool is_client_;
|
||||
|
||||
void notify() override {
|
||||
// NB: Interface will be changed
|
||||
td::actor::send_closure_later(self_, &AdnlExtConnection::on_net);
|
||||
}
|
||||
|
||||
void start_up() override {
|
||||
self_ = actor_id(this);
|
||||
// Subscribe for socket updates
|
||||
// NB: Interface will be changed
|
||||
td::actor::SchedulerContext::get()->get_poll().subscribe(buffered_fd_.get_poll_info().extract_pollable_fd(this),
|
||||
td::PollFlags::ReadWrite());
|
||||
update_timer();
|
||||
notify();
|
||||
}
|
||||
|
||||
private:
|
||||
td::AesCtrState in_ctr_;
|
||||
td::AesCtrState out_ctr_;
|
||||
bool inited_ = false;
|
||||
bool stop_read_ = false;
|
||||
bool read_len_ = false;
|
||||
td::uint32 len_;
|
||||
td::uint32 received_bytes_ = 0;
|
||||
td::Timestamp fail_at_;
|
||||
td::Timestamp send_ping_at_;
|
||||
bool ping_sent_ = false;
|
||||
|
||||
void on_net() {
|
||||
loop();
|
||||
}
|
||||
|
||||
void tear_down() override {
|
||||
if (callback_) {
|
||||
callback_->on_close(actor_id(this));
|
||||
callback_ = nullptr;
|
||||
}
|
||||
// unsubscribe from socket updates
|
||||
// nb: interface will be changed
|
||||
td::actor::SchedulerContext::get()->get_poll().unsubscribe(buffered_fd_.get_poll_info().get_pollable_fd_ref());
|
||||
}
|
||||
|
||||
void update_timer() {
|
||||
fail_at_ = td::Timestamp::in(timeout());
|
||||
alarm_timestamp() = fail_at_;
|
||||
if (is_client_) {
|
||||
ping_sent_ = false;
|
||||
send_ping_at_ = td::Timestamp::in(timeout() / 2);
|
||||
alarm_timestamp().relax(send_ping_at_);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() override;
|
||||
|
||||
void alarm() override {
|
||||
alarm_timestamp() = fail_at_;
|
||||
if (fail_at_.is_in_past()) {
|
||||
stop();
|
||||
} else if (is_client_ && !ping_sent_) {
|
||||
if (send_ping_at_.is_in_past()) {
|
||||
auto obj = create_tl_object<ton_api::tcp_ping>(td::Random::fast_uint64());
|
||||
send(serialize_tl_object(obj, true));
|
||||
ping_sent_ = true;
|
||||
} else {
|
||||
alarm_timestamp().relax(send_ping_at_);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
182
adnl/adnl-ext-server.cpp
Normal file
182
adnl/adnl-ext-server.cpp
Normal file
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "adnl-ext-server.hpp"
|
||||
#include "keys/encryptor.h"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
td::Status AdnlInboundConnection::process_packet(td::BufferSlice data) {
|
||||
TRY_RESULT(f, fetch_tl_object<ton_api::adnl_message_query>(std::move(data), true));
|
||||
|
||||
auto P =
|
||||
td::PromiseCreator::lambda([SelfId = actor_id(this), query_id = f->query_id_](td::Result<td::BufferSlice> R) {
|
||||
if (R.is_error()) {
|
||||
auto S = R.move_as_error();
|
||||
LOG(WARNING) << "failed ext query: " << S;
|
||||
} else {
|
||||
auto B = create_tl_object<ton_api::adnl_message_answer>(query_id, R.move_as_ok());
|
||||
td::actor::send_closure(SelfId, &AdnlInboundConnection::send, serialize_tl_object(B, true));
|
||||
}
|
||||
});
|
||||
td::actor::send_closure(peer_table_, &AdnlPeerTable::deliver_query, remote_id_, local_id_, std::move(f->query_),
|
||||
std::move(P));
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
td::Status AdnlInboundConnection::process_init_packet(td::BufferSlice data) {
|
||||
if (data.size() < 32) {
|
||||
return td::Status::Error(ErrorCode::protoviolation, "too small init packet");
|
||||
}
|
||||
local_id_ = AdnlNodeIdShort{data.as_slice().truncate(32)};
|
||||
data.confirm_read(32);
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::BufferSlice> R) {
|
||||
td::actor::send_closure(SelfId, &AdnlInboundConnection::inited_crypto, std::move(R));
|
||||
});
|
||||
|
||||
td::actor::send_closure(ext_server_, &AdnlExtServerImpl::decrypt_init_packet, local_id_, std::move(data),
|
||||
std::move(P));
|
||||
stop_read();
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
void AdnlInboundConnection::inited_crypto(td::Result<td::BufferSlice> R) {
|
||||
if (R.is_error()) {
|
||||
LOG(ERROR) << "failed to init crypto: " << R.move_as_error();
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
auto S = init_crypto(R.move_as_ok().as_slice());
|
||||
if (S.is_error()) {
|
||||
LOG(ERROR) << "failed to init crypto (2): " << R.move_as_error();
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
send(td::BufferSlice());
|
||||
resume_read();
|
||||
notify();
|
||||
}
|
||||
|
||||
td::Status AdnlInboundConnection::process_custom_packet(td::BufferSlice &data, bool &processed) {
|
||||
if (data.size() == 12) {
|
||||
auto F = fetch_tl_object<ton_api::tcp_ping>(data.clone(), true);
|
||||
if (F.is_ok()) {
|
||||
auto f = F.move_as_ok();
|
||||
auto obj = create_tl_object<ton_api::tcp_pong>(f->random_id_);
|
||||
send(serialize_tl_object(obj, true));
|
||||
processed = true;
|
||||
return td::Status::OK();
|
||||
}
|
||||
}
|
||||
if (1) {
|
||||
auto F = fetch_tl_object<ton_api::tcp_authentificate>(data.clone(), true);
|
||||
if (F.is_ok()) {
|
||||
if (nonce_.size() > 0 || !remote_id_.is_zero()) {
|
||||
return td::Status::Error(ErrorCode::protoviolation, "duplicate authentificate");
|
||||
}
|
||||
auto f = F.move_as_ok();
|
||||
nonce_ = td::SecureString{f->nonce_.size() + 256};
|
||||
nonce_.as_mutable_slice().truncate(f->nonce_.size()).copy_from(f->nonce_.as_slice());
|
||||
td::Random::secure_bytes(nonce_.as_mutable_slice().remove_prefix(f->nonce_.size()));
|
||||
|
||||
auto obj = create_tl_object<ton_api::tcp_authentificationNonce>(
|
||||
td::BufferSlice{nonce_.as_slice().remove_prefix(f->nonce_.size())});
|
||||
send(serialize_tl_object(obj, true));
|
||||
processed = true;
|
||||
return td::Status::OK();
|
||||
}
|
||||
}
|
||||
|
||||
if (nonce_.size() != 0) {
|
||||
auto F = fetch_tl_object<ton_api::tcp_authentificationComplete>(data.clone(), true);
|
||||
if (F.is_ok()) {
|
||||
auto f = F.move_as_ok();
|
||||
if (nonce_.size() == 0 || !remote_id_.is_zero()) {
|
||||
return td::Status::Error(ErrorCode::protoviolation, "duplicate authentificate");
|
||||
}
|
||||
|
||||
auto pub_key = PublicKey{f->key_};
|
||||
TRY_RESULT(enc, pub_key.create_encryptor());
|
||||
TRY_STATUS(enc->check_signature(nonce_.as_slice(), f->signature_.as_slice()));
|
||||
|
||||
remote_id_ = AdnlNodeIdShort{pub_key.compute_short_id()};
|
||||
nonce_.clear();
|
||||
processed = true;
|
||||
return td::Status::OK();
|
||||
}
|
||||
}
|
||||
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
void AdnlExtServerImpl::add_tcp_port(td::uint16 port) {
|
||||
auto it = listeners_.find(port);
|
||||
if (it != listeners_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
class Callback : public td::TcpListener::Callback {
|
||||
private:
|
||||
td::actor::ActorId<AdnlExtServerImpl> id_;
|
||||
|
||||
public:
|
||||
Callback(td::actor::ActorId<AdnlExtServerImpl> id) : id_(id) {
|
||||
}
|
||||
void accept(td::SocketFd fd) override {
|
||||
td::actor::send_closure(id_, &AdnlExtServerImpl::accepted, std::move(fd));
|
||||
}
|
||||
};
|
||||
|
||||
auto act = td::actor::create_actor<td::TcpListener>(td::actor::ActorOptions().with_name("listener").with_poll(), port,
|
||||
std::make_unique<Callback>(actor_id(this)));
|
||||
listeners_.emplace(port, std::move(act));
|
||||
}
|
||||
|
||||
void AdnlExtServerImpl::add_local_id(AdnlNodeIdShort id) {
|
||||
local_ids_.insert(id);
|
||||
}
|
||||
|
||||
void AdnlExtServerImpl::accepted(td::SocketFd fd) {
|
||||
td::actor::create_actor<AdnlInboundConnection>(td::actor::ActorOptions().with_name("inconn").with_poll(),
|
||||
std::move(fd), peer_table_, actor_id(this))
|
||||
.release();
|
||||
}
|
||||
|
||||
void AdnlExtServerImpl::decrypt_init_packet(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(peer_table_, &AdnlPeerTable::decrypt_message, dst, std::move(data), std::move(promise));
|
||||
} else {
|
||||
promise.set_error(td::Status::Error());
|
||||
}
|
||||
}
|
||||
|
||||
td::actor::ActorOwn<AdnlExtServer> AdnlExtServerCreator::create(td::actor::ActorId<AdnlPeerTable> adnl,
|
||||
std::vector<AdnlNodeIdShort> ids,
|
||||
std::vector<td::uint16> ports) {
|
||||
return td::actor::create_actor<AdnlExtServerImpl>("extserver", adnl, std::move(ids), std::move(ports));
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
35
adnl/adnl-ext-server.h
Normal file
35
adnl/adnl-ext-server.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "adnl-peer-table.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlExtServerCreator {
|
||||
public:
|
||||
static td::actor::ActorOwn<AdnlExtServer> create(td::actor::ActorId<AdnlPeerTable> adnl,
|
||||
std::vector<AdnlNodeIdShort> ids, std::vector<td::uint16> ports);
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
92
adnl/adnl-ext-server.hpp
Normal file
92
adnl/adnl-ext-server.hpp
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "adnl-peer-table.h"
|
||||
#include "td/net/TcpListener.h"
|
||||
#include "td/utils/crypto.h"
|
||||
#include "td/utils/BufferedFd.h"
|
||||
#include "adnl-ext-connection.hpp"
|
||||
#include "adnl-ext-server.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlExtServerImpl;
|
||||
|
||||
class AdnlInboundConnection : public AdnlExtConnection {
|
||||
public:
|
||||
AdnlInboundConnection(td::SocketFd fd, td::actor::ActorId<AdnlPeerTable> peer_table,
|
||||
td::actor::ActorId<AdnlExtServerImpl> ext_server)
|
||||
: AdnlExtConnection(std::move(fd), nullptr, false), peer_table_(peer_table), ext_server_(ext_server) {
|
||||
}
|
||||
|
||||
td::Status process_packet(td::BufferSlice data) override;
|
||||
td::Status process_init_packet(td::BufferSlice data) override;
|
||||
td::Status process_custom_packet(td::BufferSlice &data, bool &processed) override;
|
||||
void inited_crypto(td::Result<td::BufferSlice> R);
|
||||
|
||||
private:
|
||||
td::actor::ActorId<AdnlPeerTable> peer_table_;
|
||||
td::actor::ActorId<AdnlExtServerImpl> ext_server_;
|
||||
AdnlNodeIdShort local_id_;
|
||||
|
||||
td::SecureString nonce_;
|
||||
AdnlNodeIdShort remote_id_ = AdnlNodeIdShort::zero();
|
||||
};
|
||||
|
||||
class AdnlExtServerImpl : public AdnlExtServer {
|
||||
public:
|
||||
void add_tcp_port(td::uint16 port) override;
|
||||
void add_local_id(AdnlNodeIdShort id) override;
|
||||
void accepted(td::SocketFd fd);
|
||||
void decrypt_init_packet(AdnlNodeIdShort dst, td::BufferSlice data, td::Promise<td::BufferSlice> promise);
|
||||
|
||||
void start_up() override {
|
||||
for (auto &port : ports_) {
|
||||
add_tcp_port(port);
|
||||
}
|
||||
ports_.clear();
|
||||
}
|
||||
|
||||
AdnlExtServerImpl(td::actor::ActorId<AdnlPeerTable> adnl, std::vector<AdnlNodeIdShort> ids,
|
||||
std::vector<td::uint16> ports)
|
||||
: peer_table_(adnl) {
|
||||
for (auto &id : ids) {
|
||||
add_local_id(id);
|
||||
}
|
||||
for (auto &port : ports) {
|
||||
ports_.insert(port);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
td::actor::ActorId<AdnlPeerTable> peer_table_;
|
||||
std::set<AdnlNodeIdShort> local_ids_;
|
||||
std::set<td::uint16> ports_;
|
||||
std::map<td::uint16, td::actor::ActorOwn<td::TcpListener>> listeners_;
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
279
adnl/adnl-local-id.cpp
Normal file
279
adnl/adnl-local-id.cpp
Normal file
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "td/utils/crypto.h"
|
||||
#include "td/utils/Random.h"
|
||||
|
||||
#include "adnl-local-id.h"
|
||||
#include "keys/encryptor.h"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
AdnlNodeIdFull AdnlLocalId::get_id() const {
|
||||
return id_;
|
||||
}
|
||||
|
||||
AdnlNodeIdShort AdnlLocalId::get_short_id() const {
|
||||
return short_id_;
|
||||
}
|
||||
|
||||
AdnlAddressList AdnlLocalId::get_addr_list() const {
|
||||
CHECK(!addr_list_.empty());
|
||||
return addr_list_;
|
||||
}
|
||||
|
||||
void AdnlLocalId::receive(td::BufferSlice data) {
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[peer_table = peer_table_, dst = short_id_, id = print_id()](td::Result<AdnlPacket> R) {
|
||||
if (R.is_error()) {
|
||||
VLOG(ADNL_WARNING) << id << ": dropping IN message: cannot decrypt: " << R.move_as_error();
|
||||
} else {
|
||||
td::actor::send_closure(peer_table, &AdnlPeerTable::receive_decrypted_packet, dst, R.move_as_ok());
|
||||
}
|
||||
});
|
||||
|
||||
decrypt(std::move(data), std::move(P));
|
||||
}
|
||||
|
||||
void AdnlLocalId::deliver(AdnlNodeIdShort src, td::BufferSlice data) {
|
||||
auto s = std::move(data);
|
||||
for (auto &cb : cb_) {
|
||||
auto f = cb.first;
|
||||
if (f.length() <= s.length() && s.as_slice().substr(0, f.length()) == f) {
|
||||
cb.second->receive_message(src, short_id_, std::move(s));
|
||||
return;
|
||||
}
|
||||
}
|
||||
VLOG(ADNL_INFO) << this << ": dropping IN message from " << src
|
||||
<< ": no callbacks for custom message. firstint=" << td::TlParser(s.as_slice()).fetch_int();
|
||||
}
|
||||
|
||||
void AdnlLocalId::deliver_query(AdnlNodeIdShort src, td::BufferSlice data, td::Promise<td::BufferSlice> promise) {
|
||||
auto s = std::move(data);
|
||||
for (auto &cb : cb_) {
|
||||
auto f = cb.first;
|
||||
if (f.length() <= s.length() && s.as_slice().substr(0, f.length()) == f) {
|
||||
cb.second->receive_query(src, short_id_, std::move(s), std::move(promise));
|
||||
return;
|
||||
}
|
||||
}
|
||||
VLOG(ADNL_INFO) << this << ": dropping IN message from " << src
|
||||
<< ": no callbacks for custom query. firstint=" << td::TlParser(s.as_slice()).fetch_int();
|
||||
promise.set_error(td::Status::Error(ErrorCode::warning, "no callbacks for query"));
|
||||
}
|
||||
|
||||
void AdnlLocalId::subscribe(std::string prefix, std::unique_ptr<AdnlPeerTable::Callback> callback) {
|
||||
auto S = td::Slice(prefix);
|
||||
for (auto &cb : cb_) {
|
||||
auto G = td::Slice(cb.first);
|
||||
if (S.size() < G.size()) {
|
||||
LOG_CHECK(G.substr(0, S.size()) != S) << this << ": duplicate subscribe prefix";
|
||||
} else {
|
||||
LOG_CHECK(S.substr(0, G.size()) != G) << this << ": duplicate subscribe prefix";
|
||||
}
|
||||
}
|
||||
cb_.emplace_back(prefix, std::move(callback));
|
||||
}
|
||||
|
||||
void AdnlLocalId::unsubscribe(std::string prefix) {
|
||||
bool deleted = false;
|
||||
for (auto it = cb_.begin(); it != cb_.end();) {
|
||||
if (it->first == prefix) {
|
||||
it = cb_.erase(it);
|
||||
deleted = true;
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
LOG_CHECK(deleted) << this << ": cannot unsubscribe: prefix not found";
|
||||
}
|
||||
|
||||
void AdnlLocalId::update_address_list(AdnlAddressList addr_list) {
|
||||
addr_list_ = std::move(addr_list);
|
||||
addr_list_.set_reinit_date(Adnl::adnl_start_time());
|
||||
addr_list_.set_version(static_cast<td::int32>(td::Clocks::system()));
|
||||
|
||||
VLOG(ADNL_INFO) << this << ": updated addr list. New version set to " << addr_list_.version();
|
||||
|
||||
publish_address_list();
|
||||
}
|
||||
|
||||
void AdnlLocalId::publish_address_list() {
|
||||
if (dht_node_.empty() || addr_list_.empty()) {
|
||||
VLOG(ADNL_NOTICE) << this << ": skipping public addr list, because localid (or dht node) not fully initialized";
|
||||
return;
|
||||
}
|
||||
|
||||
dht::DhtKey dht_key{short_id_.pubkey_hash(), "address", 0};
|
||||
auto dht_update_rule = dht::DhtUpdateRuleSignature::create().move_as_ok();
|
||||
dht::DhtKeyDescription dht_key_description{std::move(dht_key), id_.pubkey(), std::move(dht_update_rule),
|
||||
td::BufferSlice()};
|
||||
|
||||
auto B = serialize_tl_object(dht_key_description.tl(), true);
|
||||
|
||||
auto P = td::PromiseCreator::lambda([dht_node = dht_node_, SelfId = actor_id(this), addr_list = addr_list_.tl(),
|
||||
dht_key_description = std::move(dht_key_description),
|
||||
print_id = print_id()](td::Result<td::BufferSlice> R) mutable {
|
||||
if (R.is_error()) {
|
||||
LOG(ERROR) << print_id << ": cannot sign: " << R.move_as_error();
|
||||
return;
|
||||
}
|
||||
|
||||
dht_key_description.update_signature(R.move_as_ok());
|
||||
dht_key_description.check().ensure();
|
||||
|
||||
auto ttl = static_cast<td::uint32>(td::Clocks::system() + 3600);
|
||||
dht::DhtValue dht_value{std::move(dht_key_description), serialize_tl_object(addr_list, true), ttl,
|
||||
td::BufferSlice("")};
|
||||
|
||||
auto B = serialize_tl_object(dht_value.tl(), true);
|
||||
|
||||
auto Q = td::PromiseCreator::lambda(
|
||||
[dht_node, dht_value = std::move(dht_value), print_id](td::Result<td::BufferSlice> R) mutable {
|
||||
if (R.is_error()) {
|
||||
LOG(ERROR) << print_id << ": cannot sign: " << R.move_as_error();
|
||||
return;
|
||||
}
|
||||
dht_value.update_signature(R.move_as_ok());
|
||||
dht_value.check().ensure();
|
||||
|
||||
auto E = td::PromiseCreator::lambda([print_id](td::Result<td::Unit> R) {
|
||||
if (R.is_error()) {
|
||||
VLOG(ADNL_NOTICE) << print_id << ": failed to update addr list in DHT: " << R.move_as_error();
|
||||
} else {
|
||||
VLOG(ADNL_INFO) << print_id << ": updated dht addr list";
|
||||
}
|
||||
});
|
||||
|
||||
td::actor::send_closure(dht_node, &dht::Dht::set_value, std::move(dht_value), std::move(E));
|
||||
});
|
||||
|
||||
td::actor::send_closure(SelfId, &AdnlLocalId::sign_async, std::move(B), std::move(Q));
|
||||
});
|
||||
|
||||
td::actor::send_closure(keyring_, &keyring::Keyring::sign_message, short_id_.pubkey_hash(), std::move(B),
|
||||
std::move(P));
|
||||
}
|
||||
|
||||
AdnlLocalId::AdnlLocalId(AdnlNodeIdFull id, AdnlAddressList addr_list, td::actor::ActorId<AdnlPeerTable> peer_table,
|
||||
td::actor::ActorId<keyring::Keyring> keyring, td::actor::ActorId<dht::Dht> dht_node) {
|
||||
id_ = std::move(id);
|
||||
short_id_ = id_.compute_short_id();
|
||||
addr_list_ = std::move(addr_list);
|
||||
if (addr_list_.addrs().size() > 0) {
|
||||
addr_list_.set_version(static_cast<td::int32>(td::Clocks::system()));
|
||||
}
|
||||
peer_table_ = peer_table;
|
||||
keyring_ = keyring;
|
||||
dht_node_ = dht_node;
|
||||
|
||||
VLOG(ADNL_INFO) << this << ": created local id " << short_id_;
|
||||
}
|
||||
|
||||
void AdnlLocalId::get_self_node(td::Promise<AdnlNode> promise) {
|
||||
//addr_list_->version_ = static_cast<td::int32>(td::Clocks::system());
|
||||
promise.set_value(AdnlNode{id_, addr_list_});
|
||||
}
|
||||
|
||||
void AdnlLocalId::decrypt_message(td::BufferSlice data, td::Promise<td::BufferSlice> promise) {
|
||||
td::actor::send_closure(keyring_, &keyring::Keyring::decrypt_message, short_id_.pubkey_hash(), std::move(data),
|
||||
std::move(promise));
|
||||
}
|
||||
|
||||
void AdnlLocalId::decrypt(td::BufferSlice data, td::Promise<AdnlPacket> promise) {
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[SelfId = actor_id(this), p = std::move(promise)](td::Result<td::BufferSlice> res) mutable {
|
||||
if (res.is_error()) {
|
||||
p.set_error(res.move_as_error());
|
||||
} else {
|
||||
td::actor::send_closure_later(SelfId, &AdnlLocalId::decrypt_continue, res.move_as_ok(), std::move(p));
|
||||
}
|
||||
});
|
||||
td::actor::send_closure(keyring_, &keyring::Keyring::decrypt_message, short_id_.pubkey_hash(), std::move(data),
|
||||
std::move(P));
|
||||
}
|
||||
|
||||
void AdnlLocalId::decrypt_continue(td::BufferSlice data, td::Promise<AdnlPacket> promise) {
|
||||
auto R = fetch_tl_object<ton_api::adnl_packetContents>(std::move(data), true);
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
return;
|
||||
}
|
||||
|
||||
auto packetR = AdnlPacket::create(R.move_as_ok());
|
||||
if (packetR.is_error()) {
|
||||
promise.set_error(packetR.move_as_error());
|
||||
return;
|
||||
}
|
||||
promise.set_value(packetR.move_as_ok());
|
||||
}
|
||||
|
||||
void AdnlLocalId::sign_async(td::BufferSlice data, td::Promise<td::BufferSlice> promise) {
|
||||
td::actor::send_closure(keyring_, &keyring::Keyring::sign_message, short_id_.pubkey_hash(), std::move(data),
|
||||
std::move(promise));
|
||||
}
|
||||
|
||||
void AdnlLocalId::sign_batch_async(std::vector<td::BufferSlice> data,
|
||||
td::Promise<std::vector<td::Result<td::BufferSlice>>> promise) {
|
||||
td::actor::send_closure(keyring_, &keyring::Keyring::sign_messages, short_id_.pubkey_hash(), std::move(data),
|
||||
std::move(promise));
|
||||
}
|
||||
|
||||
void AdnlLocalId::start_up() {
|
||||
publish_address_list();
|
||||
alarm_timestamp() = td::Timestamp::in(AdnlPeerTable::republish_addr_list_timeout() * td::Random::fast(1.0, 2.0));
|
||||
}
|
||||
|
||||
void AdnlLocalId::alarm() {
|
||||
publish_address_list();
|
||||
alarm_timestamp() = td::Timestamp::in(AdnlPeerTable::republish_addr_list_timeout() * td::Random::fast(1.0, 2.0));
|
||||
}
|
||||
|
||||
void AdnlLocalId::update_packet(AdnlPacket packet, bool update_id, bool sign, td::int32 update_addr_list_if,
|
||||
td::int32 update_priority_addr_list_if, td::Promise<AdnlPacket> promise) {
|
||||
packet.init_random();
|
||||
if (update_id) {
|
||||
packet.set_source(id_);
|
||||
}
|
||||
if (!addr_list_.empty() && update_addr_list_if < addr_list_.version()) {
|
||||
packet.set_addr_list(addr_list_);
|
||||
}
|
||||
if (!sign) {
|
||||
promise.set_result(std::move(packet));
|
||||
} else {
|
||||
auto to_sign = packet.to_sign();
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[packet = std::move(packet), promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
} else {
|
||||
packet.set_signature(R.move_as_ok());
|
||||
promise.set_value(std::move(packet));
|
||||
}
|
||||
});
|
||||
td::actor::send_closure(keyring_, &keyring::Keyring::sign_message, short_id_.pubkey_hash(), std::move(to_sign),
|
||||
std::move(P));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
117
adnl/adnl-local-id.h
Normal file
117
adnl/adnl-local-id.h
Normal file
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/utils/BufferedUdp.h"
|
||||
#include "auto/tl/ton_api.h"
|
||||
#include "keys/encryptor.h"
|
||||
#include "adnl-peer-table.h"
|
||||
#include "dht/dht.h"
|
||||
|
||||
#include "adnl-peer-table.h"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlLocalId : public td::actor::Actor {
|
||||
public:
|
||||
AdnlNodeIdFull get_id() const;
|
||||
AdnlNodeIdShort get_short_id() const;
|
||||
AdnlAddressList get_addr_list() const;
|
||||
void get_addr_list_async(td::Promise<AdnlAddressList> P) {
|
||||
P.set_value(get_addr_list());
|
||||
}
|
||||
|
||||
void update_dht_node(td::actor::ActorId<dht::Dht> dht_node) {
|
||||
dht_node_ = dht_node;
|
||||
|
||||
publish_address_list();
|
||||
}
|
||||
|
||||
void decrypt(td::BufferSlice data, td::Promise<AdnlPacket> promise);
|
||||
void decrypt_continue(td::BufferSlice data, td::Promise<AdnlPacket> promise);
|
||||
void decrypt_message(td::BufferSlice data, td::Promise<td::BufferSlice> promise);
|
||||
void deliver(AdnlNodeIdShort src, td::BufferSlice data);
|
||||
void deliver_query(AdnlNodeIdShort src, td::BufferSlice data, td::Promise<td::BufferSlice> promise);
|
||||
void receive(td::BufferSlice data);
|
||||
|
||||
void subscribe(std::string prefix, std::unique_ptr<AdnlPeerTable::Callback> callback);
|
||||
void unsubscribe(std::string prefix);
|
||||
|
||||
void update_address_list(AdnlAddressList addr_list);
|
||||
|
||||
void get_self_node(td::Promise<AdnlNode> promise);
|
||||
|
||||
void sign_async(td::BufferSlice data, td::Promise<td::BufferSlice> promise);
|
||||
void sign_batch_async(std::vector<td::BufferSlice> data,
|
||||
td::Promise<std::vector<td::Result<td::BufferSlice>>> promise);
|
||||
|
||||
AdnlLocalId(AdnlNodeIdFull id, AdnlAddressList addr_list, td::actor::ActorId<AdnlPeerTable> peer_table,
|
||||
td::actor::ActorId<keyring::Keyring> keyring, td::actor::ActorId<dht::Dht> dht_node);
|
||||
|
||||
void start_up() override;
|
||||
void alarm() override;
|
||||
|
||||
void update_packet(AdnlPacket packet, bool update_id, bool sign, td::int32 update_addr_list_if,
|
||||
td::int32 update_priority_addr_list_if, td::Promise<AdnlPacket> promise);
|
||||
|
||||
struct PrintId {
|
||||
AdnlNodeIdShort id;
|
||||
};
|
||||
|
||||
PrintId print_id() const {
|
||||
return PrintId{short_id_};
|
||||
}
|
||||
|
||||
private:
|
||||
td::actor::ActorId<AdnlPeerTable> peer_table_;
|
||||
td::actor::ActorId<keyring::Keyring> keyring_;
|
||||
td::actor::ActorId<dht::Dht> dht_node_;
|
||||
std::vector<std::pair<std::string, std::unique_ptr<AdnlPeerTable::Callback>>> cb_;
|
||||
|
||||
AdnlAddressList addr_list_;
|
||||
AdnlNodeIdFull id_;
|
||||
AdnlNodeIdShort short_id_;
|
||||
|
||||
void publish_address_list();
|
||||
};
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const AdnlLocalId::PrintId &id) {
|
||||
sb << "[localid " << id.id << "]";
|
||||
return sb;
|
||||
}
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const AdnlLocalId &localid) {
|
||||
sb << localid.print_id();
|
||||
return sb;
|
||||
}
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const AdnlLocalId *localid) {
|
||||
sb << localid->print_id();
|
||||
return sb;
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
54
adnl/adnl-message.cpp
Normal file
54
adnl/adnl-message.cpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "adnl/adnl-message.h"
|
||||
#include "auto/tl/ton_api.hpp"
|
||||
#include "td/utils/overloaded.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
AdnlMessage::AdnlMessage(tl_object_ptr<ton_api::adnl_Message> message) {
|
||||
ton_api::downcast_call(
|
||||
*message.get(),
|
||||
td::overloaded(
|
||||
[&](ton_api::adnl_message_createChannel &msg) {
|
||||
message_ = adnlmessage::AdnlMessageCreateChannel{msg.key_, msg.date_};
|
||||
},
|
||||
[&](ton_api::adnl_message_confirmChannel &msg) {
|
||||
message_ = adnlmessage::AdnlMessageConfirmChannel{msg.key_, msg.peer_key_, msg.date_};
|
||||
},
|
||||
[&](ton_api::adnl_message_custom &msg) { message_ = adnlmessage::AdnlMessageCustom{std::move(msg.data_)}; },
|
||||
[&](ton_api::adnl_message_nop &msg) { message_ = adnlmessage::AdnlMessageNop{}; },
|
||||
[&](ton_api::adnl_message_reinit &msg) { message_ = adnlmessage::AdnlMessageReinit{msg.date_}; },
|
||||
[&](ton_api::adnl_message_query &msg) {
|
||||
message_ = adnlmessage::AdnlMessageQuery{msg.query_id_, std::move(msg.query_)};
|
||||
},
|
||||
[&](ton_api::adnl_message_answer &msg) {
|
||||
message_ = adnlmessage::AdnlMessageAnswer{msg.query_id_, std::move(msg.answer_)};
|
||||
},
|
||||
[&](ton_api::adnl_message_part &msg) {
|
||||
message_ = adnlmessage::AdnlMessagePart{msg.hash_, static_cast<td::uint32>(msg.total_size_),
|
||||
static_cast<td::uint32>(msg.offset_), std::move(msg.data_)};
|
||||
}));
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
296
adnl/adnl-message.h
Normal file
296
adnl/adnl-message.h
Normal file
|
@ -0,0 +1,296 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "adnl/adnl.h"
|
||||
#include "adnl/adnl-query.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
namespace adnlmessage {
|
||||
|
||||
class AdnlMessageCreateChannel {
|
||||
public:
|
||||
AdnlMessageCreateChannel(pubkeys::Ed25519 key, td::int32 date) : key_(key), date_(date) {
|
||||
}
|
||||
const auto &key() const {
|
||||
return key_;
|
||||
}
|
||||
auto date() const {
|
||||
return date_;
|
||||
}
|
||||
td::uint32 size() const {
|
||||
return 40;
|
||||
}
|
||||
tl_object_ptr<ton_api::adnl_Message> tl() const {
|
||||
return create_tl_object<ton_api::adnl_message_createChannel>(key_.raw(), date_);
|
||||
}
|
||||
|
||||
private:
|
||||
pubkeys::Ed25519 key_;
|
||||
td::int32 date_;
|
||||
};
|
||||
|
||||
class AdnlMessageConfirmChannel {
|
||||
public:
|
||||
AdnlMessageConfirmChannel(pubkeys::Ed25519 key, pubkeys::Ed25519 peer_key, td::int32 date)
|
||||
: key_(key), peer_key_(peer_key), date_(date) {
|
||||
}
|
||||
const auto &key() const {
|
||||
return key_;
|
||||
}
|
||||
const auto &peer_key() const {
|
||||
return peer_key_;
|
||||
}
|
||||
auto date() const {
|
||||
return date_;
|
||||
}
|
||||
td::uint32 size() const {
|
||||
return 72;
|
||||
}
|
||||
tl_object_ptr<ton_api::adnl_Message> tl() const {
|
||||
return create_tl_object<ton_api::adnl_message_confirmChannel>(key_.raw(), peer_key_.raw(), date_);
|
||||
}
|
||||
|
||||
private:
|
||||
pubkeys::Ed25519 key_;
|
||||
pubkeys::Ed25519 peer_key_;
|
||||
td::int32 date_;
|
||||
};
|
||||
|
||||
class AdnlMessageCustom {
|
||||
public:
|
||||
AdnlMessageCustom(td::BufferSlice data) : data_(std::move(data)) {
|
||||
}
|
||||
auto data() const {
|
||||
return data_.clone();
|
||||
}
|
||||
td::uint32 size() const {
|
||||
return static_cast<td::uint32>(data_.size()) + 12;
|
||||
}
|
||||
tl_object_ptr<ton_api::adnl_Message> tl() const {
|
||||
return create_tl_object<ton_api::adnl_message_custom>(data_.clone());
|
||||
}
|
||||
|
||||
private:
|
||||
td::BufferSlice data_;
|
||||
};
|
||||
|
||||
class AdnlMessageNop {
|
||||
public:
|
||||
AdnlMessageNop() {
|
||||
}
|
||||
td::uint32 size() const {
|
||||
return 4;
|
||||
}
|
||||
tl_object_ptr<ton_api::adnl_Message> tl() const {
|
||||
return create_tl_object<ton_api::adnl_message_nop>();
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
class AdnlMessageReinit {
|
||||
public:
|
||||
AdnlMessageReinit(td::int32 date) : date_(date) {
|
||||
}
|
||||
auto date() const {
|
||||
return date_;
|
||||
}
|
||||
td::uint32 size() const {
|
||||
return 8;
|
||||
}
|
||||
tl_object_ptr<ton_api::adnl_Message> tl() const {
|
||||
return create_tl_object<ton_api::adnl_message_reinit>(date_);
|
||||
}
|
||||
|
||||
private:
|
||||
td::int32 date_;
|
||||
};
|
||||
|
||||
class AdnlMessageQuery {
|
||||
public:
|
||||
AdnlMessageQuery(AdnlQueryId query_id, td::BufferSlice data) : query_id_(query_id), data_(std::move(data)) {
|
||||
}
|
||||
const auto &query_id() const {
|
||||
return query_id_;
|
||||
}
|
||||
auto data() const {
|
||||
return data_.clone();
|
||||
}
|
||||
td::uint32 size() const {
|
||||
return static_cast<td::uint32>(data_.size()) + 44;
|
||||
}
|
||||
tl_object_ptr<ton_api::adnl_Message> tl() const {
|
||||
return create_tl_object<ton_api::adnl_message_query>(query_id_, data_.clone());
|
||||
}
|
||||
|
||||
private:
|
||||
AdnlQueryId query_id_;
|
||||
td::BufferSlice data_;
|
||||
};
|
||||
|
||||
class AdnlMessageAnswer {
|
||||
public:
|
||||
AdnlMessageAnswer(AdnlQueryId query_id, td::BufferSlice data) : query_id_(query_id), data_(std::move(data)) {
|
||||
}
|
||||
const auto &query_id() const {
|
||||
return query_id_;
|
||||
}
|
||||
auto data() const {
|
||||
return data_.clone();
|
||||
}
|
||||
td::uint32 size() const {
|
||||
return static_cast<td::uint32>(data_.size()) + 44;
|
||||
}
|
||||
tl_object_ptr<ton_api::adnl_Message> tl() const {
|
||||
return create_tl_object<ton_api::adnl_message_answer>(query_id_, data_.clone());
|
||||
}
|
||||
|
||||
private:
|
||||
AdnlQueryId query_id_;
|
||||
td::BufferSlice data_;
|
||||
};
|
||||
|
||||
class AdnlMessagePart {
|
||||
public:
|
||||
AdnlMessagePart(td::Bits256 hash, td::uint32 total_size, td::uint32 offset, td::BufferSlice data)
|
||||
: hash_(hash), total_size_(total_size), offset_(offset), data_(std::move(data)) {
|
||||
}
|
||||
const auto &hash() const {
|
||||
return hash_;
|
||||
}
|
||||
auto offset() const {
|
||||
return offset_;
|
||||
}
|
||||
auto total_size() const {
|
||||
return total_size_;
|
||||
}
|
||||
auto data() const {
|
||||
return data_.clone();
|
||||
}
|
||||
td::uint32 size() const {
|
||||
return static_cast<td::uint32>(data_.size()) + 48;
|
||||
}
|
||||
tl_object_ptr<ton_api::adnl_Message> tl() const {
|
||||
return create_tl_object<ton_api::adnl_message_part>(hash_, total_size_, offset_, data_.clone());
|
||||
}
|
||||
|
||||
private:
|
||||
td::Bits256 hash_;
|
||||
td::uint32 total_size_;
|
||||
td::uint32 offset_;
|
||||
td::BufferSlice data_;
|
||||
};
|
||||
|
||||
} // namespace adnlmessage
|
||||
|
||||
class AdnlMessage {
|
||||
public:
|
||||
class Empty {
|
||||
public:
|
||||
Empty() {
|
||||
}
|
||||
td::uint32 size() const {
|
||||
UNREACHABLE();
|
||||
}
|
||||
tl_object_ptr<ton_api::adnl_Message> tl() const {
|
||||
UNREACHABLE();
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
td::Variant<Empty, adnlmessage::AdnlMessageCreateChannel, adnlmessage::AdnlMessageConfirmChannel,
|
||||
adnlmessage::AdnlMessageCustom, adnlmessage::AdnlMessageNop, adnlmessage::AdnlMessageReinit,
|
||||
adnlmessage::AdnlMessageQuery, adnlmessage::AdnlMessageAnswer, adnlmessage::AdnlMessagePart>
|
||||
message_{Empty{}};
|
||||
|
||||
public:
|
||||
explicit AdnlMessage(tl_object_ptr<ton_api::adnl_Message> message);
|
||||
template <class T>
|
||||
AdnlMessage(T m) : message_(std::move(m)) {
|
||||
}
|
||||
|
||||
tl_object_ptr<ton_api::adnl_Message> tl() const {
|
||||
tl_object_ptr<ton_api::adnl_Message> res;
|
||||
message_.visit([&](const auto &obj) { res = obj.tl(); });
|
||||
return res;
|
||||
}
|
||||
td::uint32 size() const {
|
||||
td::uint32 res;
|
||||
message_.visit([&](const auto &obj) { res = obj.size(); });
|
||||
return res;
|
||||
}
|
||||
template <class F>
|
||||
void visit(F &&f) {
|
||||
message_.visit(std::move(f));
|
||||
}
|
||||
template <class F>
|
||||
void visit(F &&f) const {
|
||||
message_.visit(std::move(f));
|
||||
}
|
||||
};
|
||||
|
||||
class AdnlMessageList {
|
||||
public:
|
||||
AdnlMessageList() {
|
||||
}
|
||||
AdnlMessageList(tl_object_ptr<ton_api::adnl_Message> message) {
|
||||
auto msg = AdnlMessage{std::move(message)};
|
||||
messages_.emplace_back(std::move(msg));
|
||||
}
|
||||
AdnlMessageList(std::vector<tl_object_ptr<ton_api::adnl_Message>> messages) {
|
||||
for (auto &message : messages) {
|
||||
messages_.push_back(AdnlMessage{std::move(message)});
|
||||
}
|
||||
}
|
||||
void push_back(AdnlMessage message) {
|
||||
messages_.push_back(std::move(message));
|
||||
}
|
||||
|
||||
td::uint32 size() const {
|
||||
return static_cast<td::uint32>(messages_.size());
|
||||
}
|
||||
tl_object_ptr<ton_api::adnl_Message> one_message() const {
|
||||
CHECK(size() == 1);
|
||||
return messages_[0].tl();
|
||||
}
|
||||
std::vector<tl_object_ptr<ton_api::adnl_Message>> mult_messages() const {
|
||||
std::vector<tl_object_ptr<ton_api::adnl_Message>> vec;
|
||||
for (auto &m : messages_) {
|
||||
vec.emplace_back(m.tl());
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
static std::vector<tl_object_ptr<ton_api::adnl_Message>> empty_vector() {
|
||||
return std::vector<tl_object_ptr<ton_api::adnl_Message>>{};
|
||||
}
|
||||
auto &vector() {
|
||||
return messages_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<AdnlMessage> messages_;
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
114
adnl/adnl-network-manager.cpp
Normal file
114
adnl/adnl-network-manager.cpp
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "adnl-network-manager.hpp"
|
||||
#include "adnl-peer-table.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
td::actor::ActorOwn<AdnlNetworkManager> AdnlNetworkManager::create(td::uint16 port) {
|
||||
return td::actor::create_actor<AdnlNetworkManagerImpl>("NetworkManager", port);
|
||||
}
|
||||
|
||||
void AdnlNetworkManagerImpl::add_listening_udp_port(td::uint16 port) {
|
||||
class Callback : public td::UdpServer::Callback {
|
||||
public:
|
||||
Callback(td::actor::ActorShared<AdnlNetworkManagerImpl> manager) : manager_(std::move(manager)) {
|
||||
}
|
||||
|
||||
private:
|
||||
td::actor::ActorShared<AdnlNetworkManagerImpl> manager_;
|
||||
void on_udp_message(td::UdpMessage udp_message) override {
|
||||
td::actor::send_closure_later(manager_, &AdnlNetworkManagerImpl::receive_udp_message, std::move(udp_message));
|
||||
}
|
||||
};
|
||||
|
||||
auto X = td::UdpServer::create("udp server", port, std::make_unique<Callback>(actor_shared(this)));
|
||||
X.ensure();
|
||||
udp_servers_.emplace(port, X.move_as_ok());
|
||||
}
|
||||
|
||||
void AdnlNetworkManagerImpl::receive_udp_message(td::UdpMessage message) {
|
||||
if (!callback_) {
|
||||
LOG(ERROR) << this << ": dropping IN message [?->?]: peer table unitialized";
|
||||
return;
|
||||
}
|
||||
if (message.error.is_error()) {
|
||||
VLOG(ADNL_WARNING) << this << ": dropping ERROR message: " << message.error;
|
||||
return;
|
||||
}
|
||||
if (message.data.size() >= get_mtu()) {
|
||||
VLOG(ADNL_NOTICE) << this << ": received huge packet of size " << message.data.size();
|
||||
}
|
||||
received_messages_++;
|
||||
if (received_messages_ % 64 == 0) {
|
||||
VLOG(ADNL_DEBUG) << this << ": received " << received_messages_ << "udp messages";
|
||||
}
|
||||
|
||||
VLOG(ADNL_EXTRA_DEBUG) << this << ": received message of size " << message.data.size();
|
||||
callback_->receive_packet(message.address, 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";
|
||||
return;
|
||||
}
|
||||
|
||||
auto &dv = out_desc_[priority];
|
||||
auto &v = dv[randseed % dv.size()];
|
||||
|
||||
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));
|
||||
} else {
|
||||
auto it = udp_servers_.find(out_udp_port_);
|
||||
CHECK(it != udp_servers_.end());
|
||||
|
||||
auto enc = v.proxy->encrypt(
|
||||
AdnlProxy::Packet{dst_addr.get_ipv4(), static_cast<td::uint16>(dst_addr.get_port()), std::move(data)});
|
||||
|
||||
td::UdpMessage M;
|
||||
M.address = v.addr;
|
||||
M.data = std::move(enc);
|
||||
|
||||
td::actor::send_closure(it->second, &td::UdpServer::send, std::move(M));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
107
adnl/adnl-network-manager.h
Normal file
107
adnl/adnl-network-manager.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
|
||||
#include "td/actor/PromiseFuture.h"
|
||||
#include "td/utils/port/IPAddress.h"
|
||||
|
||||
#include "adnl-node-id.hpp"
|
||||
#include "adnl-proxy-types.h"
|
||||
|
||||
namespace td {
|
||||
class UdpServer;
|
||||
}
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlPeerTable;
|
||||
|
||||
class AdnlNetworkConnection : public td::actor::Actor {
|
||||
public:
|
||||
class Callback {
|
||||
public:
|
||||
virtual void on_change_state(bool ready) = 0;
|
||||
virtual ~Callback() = default;
|
||||
};
|
||||
virtual void send(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::uint32 priority, td::BufferSlice message) = 0;
|
||||
virtual bool is_alive() const = 0;
|
||||
virtual bool is_active() const = 0;
|
||||
virtual ~AdnlNetworkConnection() = default;
|
||||
};
|
||||
|
||||
class AdnlNetworkManager : public td::actor::Actor {
|
||||
public:
|
||||
//using ConnHandle = td::uint64;
|
||||
class Callback {
|
||||
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;
|
||||
};
|
||||
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 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;
|
||||
|
||||
static constexpr td::uint32 get_mtu() {
|
||||
return 1440;
|
||||
}
|
||||
|
||||
struct PrintId {};
|
||||
PrintId print_id() const {
|
||||
return PrintId{};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
||||
|
||||
namespace td {
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlNetworkManager::PrintId &id) {
|
||||
sb << "[networkmanager]";
|
||||
return sb;
|
||||
}
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlNetworkManager &manager) {
|
||||
sb << manager.print_id();
|
||||
return sb;
|
||||
}
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlNetworkManager *manager) {
|
||||
sb << manager->print_id();
|
||||
return sb;
|
||||
}
|
||||
|
||||
} // namespace td
|
121
adnl/adnl-network-manager.hpp
Normal file
121
adnl/adnl-network-manager.hpp
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/utils/BufferedUdp.h"
|
||||
#include "td/net/UdpServer.h"
|
||||
#include "td/net/TcpListener.h"
|
||||
|
||||
#include "td/actor/PromiseFuture.h"
|
||||
#include "adnl-network-manager.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace td {
|
||||
class UdpServer;
|
||||
}
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlPeerTable;
|
||||
|
||||
class AdnlNetworkManagerImpl : public AdnlNetworkManager {
|
||||
public:
|
||||
struct OutDesc {
|
||||
td::IPAddress addr;
|
||||
std::shared_ptr<AdnlProxy> proxy;
|
||||
|
||||
bool is_proxy() const {
|
||||
return proxy != nullptr;
|
||||
}
|
||||
bool operator==(const OutDesc &with) const {
|
||||
return addr == with.addr && is_proxy() == with.is_proxy();
|
||||
}
|
||||
};
|
||||
|
||||
AdnlNetworkManagerImpl(td::uint16 out_udp_port) : out_udp_port_(out_udp_port) {
|
||||
}
|
||||
|
||||
void install_callback(std::unique_ptr<Callback> callback) override {
|
||||
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) {
|
||||
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_);
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
private:
|
||||
std::unique_ptr<Callback> callback_;
|
||||
|
||||
std::map<td::uint32, std::vector<OutDesc>> out_desc_;
|
||||
|
||||
td::uint64 received_messages_ = 0;
|
||||
td::uint64 sent_messages_ = 0;
|
||||
|
||||
std::map<td::uint16, td::actor::ActorOwn<td::UdpServer>> udp_servers_;
|
||||
|
||||
td::uint16 out_udp_port_;
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
||||
|
||||
namespace td {
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlNetworkManagerImpl &manager) {
|
||||
sb << manager.print_id();
|
||||
return sb;
|
||||
}
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlNetworkManagerImpl *manager) {
|
||||
sb << manager->print_id();
|
||||
return sb;
|
||||
}
|
||||
|
||||
} // namespace td
|
130
adnl/adnl-node-id.hpp
Normal file
130
adnl/adnl-node-id.hpp
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "keys/keys.hpp"
|
||||
#include "common/io.hpp"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlNodeIdShort {
|
||||
public:
|
||||
explicit AdnlNodeIdShort(const PublicKeyHash &hash) : hash_(hash) {
|
||||
}
|
||||
explicit AdnlNodeIdShort(PublicKeyHash &&hash) : hash_(std::move(hash)) {
|
||||
}
|
||||
AdnlNodeIdShort() {
|
||||
}
|
||||
explicit AdnlNodeIdShort(td::Slice data) : hash_(data) {
|
||||
}
|
||||
explicit AdnlNodeIdShort(td::Bits256 value) : hash_(value) {
|
||||
}
|
||||
explicit AdnlNodeIdShort(tl_object_ptr<ton_api::adnl_id_short> obj) : hash_(obj->id_) {
|
||||
}
|
||||
|
||||
const auto &pubkey_hash() const {
|
||||
return hash_;
|
||||
}
|
||||
|
||||
bool operator==(const AdnlNodeIdShort &with) const {
|
||||
return hash_ == with.hash_;
|
||||
}
|
||||
bool operator!=(const AdnlNodeIdShort &with) const {
|
||||
return hash_ != with.hash_;
|
||||
}
|
||||
bool operator<(const AdnlNodeIdShort &with) const {
|
||||
return hash_ < with.hash_;
|
||||
}
|
||||
tl_object_ptr<ton_api::adnl_id_short> tl() const {
|
||||
return create_tl_object<ton_api::adnl_id_short>(hash_.tl());
|
||||
}
|
||||
auto as_slice() {
|
||||
return hash_.as_slice();
|
||||
}
|
||||
auto as_slice() const {
|
||||
return hash_.as_slice();
|
||||
}
|
||||
auto uint256_value() const {
|
||||
return hash_.uint256_value();
|
||||
}
|
||||
auto bits256_value() const {
|
||||
return hash_.bits256_value();
|
||||
}
|
||||
static AdnlNodeIdShort zero() {
|
||||
return AdnlNodeIdShort{PublicKeyHash::zero()};
|
||||
}
|
||||
bool is_zero() const {
|
||||
return hash_.is_zero();
|
||||
}
|
||||
|
||||
private:
|
||||
PublicKeyHash hash_;
|
||||
};
|
||||
|
||||
class AdnlNodeIdFull {
|
||||
private:
|
||||
explicit AdnlNodeIdFull(const tl_object_ptr<ton_api::PublicKey> &pub) : pub_(pub) {
|
||||
}
|
||||
|
||||
public:
|
||||
explicit AdnlNodeIdFull(const PublicKey &pub) : pub_(pub) {
|
||||
}
|
||||
explicit AdnlNodeIdFull(PublicKey &&pub) : pub_(std::move(pub)) {
|
||||
}
|
||||
static td::Result<AdnlNodeIdFull> create(const tl_object_ptr<ton_api::PublicKey> &pub) {
|
||||
return AdnlNodeIdFull{pub};
|
||||
}
|
||||
AdnlNodeIdFull() {
|
||||
}
|
||||
const auto &pubkey() const {
|
||||
return pub_;
|
||||
}
|
||||
bool empty() const {
|
||||
return pub_.empty();
|
||||
}
|
||||
bool operator==(const AdnlNodeIdFull &with) const {
|
||||
return pub_ == with.pub_;
|
||||
}
|
||||
bool operator!=(const AdnlNodeIdFull &with) const {
|
||||
return pub_ != with.pub_;
|
||||
}
|
||||
auto tl() const {
|
||||
return pub_.tl();
|
||||
}
|
||||
AdnlNodeIdShort compute_short_id() const {
|
||||
return AdnlNodeIdShort{pub_.compute_short_id()};
|
||||
}
|
||||
|
||||
private:
|
||||
PublicKey pub_;
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
||||
|
||||
namespace td {
|
||||
|
||||
inline StringBuilder &operator<<(StringBuilder &stream, const ton::adnl::AdnlNodeIdShort &value) {
|
||||
return stream << value.bits256_value();
|
||||
}
|
||||
|
||||
} // namespace td
|
50
adnl/adnl-node.cpp
Normal file
50
adnl/adnl-node.cpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "adnl-node.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
td::Result<AdnlNode> AdnlNode::create(const tl_object_ptr<ton_api::adnl_node> &obj) {
|
||||
TRY_RESULT(id, AdnlNodeIdFull::create(obj->id_));
|
||||
TRY_RESULT(addr_list, AdnlAddressList::create(std::move(obj->addr_list_)));
|
||||
return AdnlNode{std::move(id), std::move(addr_list)};
|
||||
}
|
||||
|
||||
tl_object_ptr<ton_api::adnl_nodes> AdnlNodesList::tl() const {
|
||||
std::vector<tl_object_ptr<ton_api::adnl_node>> vec;
|
||||
for (auto &node : nodes_) {
|
||||
vec.emplace_back(node.tl());
|
||||
}
|
||||
return create_tl_object<ton_api::adnl_nodes>(std::move(vec));
|
||||
}
|
||||
|
||||
td::Result<AdnlNodesList> AdnlNodesList::create(const tl_object_ptr<ton_api::adnl_nodes> &nodes) {
|
||||
AdnlNodesList res{};
|
||||
for (auto &node : nodes->nodes_) {
|
||||
TRY_RESULT(N, AdnlNode::create(node));
|
||||
res.push(std::move(N));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
74
adnl/adnl-node.h
Normal file
74
adnl/adnl-node.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "auto/tl/ton_api.h"
|
||||
#include "adnl-node-id.hpp"
|
||||
#include "adnl-address-list.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlNode {
|
||||
private:
|
||||
AdnlNodeIdFull pub_;
|
||||
AdnlAddressList addr_list_;
|
||||
|
||||
public:
|
||||
AdnlNode(AdnlNodeIdFull pub, AdnlAddressList addr_list) : pub_(std::move(pub)), addr_list_(std::move(addr_list)) {
|
||||
}
|
||||
AdnlNode(const AdnlNode& from) : pub_(from.pub_), addr_list_(from.addr_list_) {
|
||||
}
|
||||
static td::Result<AdnlNode> create(const tl_object_ptr<ton_api::adnl_node>& obj);
|
||||
|
||||
tl_object_ptr<ton_api::adnl_node> tl() const {
|
||||
return create_tl_object<ton_api::adnl_node>(pub_.tl(), addr_list_.tl());
|
||||
}
|
||||
AdnlNodeIdFull pub_id() const {
|
||||
return pub_;
|
||||
}
|
||||
AdnlNodeIdShort compute_short_id() const {
|
||||
return pub_.compute_short_id();
|
||||
}
|
||||
const AdnlAddressList& addr_list() const {
|
||||
return addr_list_;
|
||||
}
|
||||
};
|
||||
|
||||
class AdnlNodesList {
|
||||
private:
|
||||
std::vector<AdnlNode> nodes_;
|
||||
|
||||
public:
|
||||
const auto& nodes() const {
|
||||
return nodes_;
|
||||
}
|
||||
AdnlNodesList() {
|
||||
}
|
||||
void push(AdnlNode node) {
|
||||
nodes_.push_back(std::move(node));
|
||||
}
|
||||
tl_object_ptr<ton_api::adnl_nodes> tl() const;
|
||||
static td::Result<AdnlNodesList> create(const tl_object_ptr<ton_api::adnl_nodes>& nodes);
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
135
adnl/adnl-packet.cpp
Normal file
135
adnl/adnl-packet.cpp
Normal file
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "adnl-packet.h"
|
||||
#include "td/utils/Random.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
/*adnl.packetContents rand1:bytes flags:# from:flags.0?PublicKey from_short:flags.1?adnl.id.short
|
||||
message:flags.2?adnl.Message messages:flags.3?(vector adnl.Message)
|
||||
address:flags.6?adnl.addressList seqno:flags.8?long recv_addr_list_version:flags.9?int
|
||||
confirm_seqno:flags.10?long reinit_date:flags.11?int dst_reinit_date:flags.11?int
|
||||
signature:flags.7?bytes rand2:bytes = adnl.PacketContents;*/
|
||||
|
||||
td::Result<AdnlPacket> AdnlPacket::create(tl_object_ptr<ton_api::adnl_packetContents> packet) {
|
||||
AdnlPacket R;
|
||||
R.rand1_ = std::move(packet->rand1_);
|
||||
R.flags_ = packet->flags_;
|
||||
if (R.flags_ & Flags::f_from) {
|
||||
TRY_RESULT(F, AdnlNodeIdFull::create(packet->from_));
|
||||
R.from_ = std::move(F);
|
||||
}
|
||||
if (R.flags_ & Flags::f_from_short) {
|
||||
R.from_short_ = AdnlNodeIdShort{packet->from_short_->id_};
|
||||
} else if (packet->flags_ & Flags::f_from) {
|
||||
R.from_short_ = R.from_.compute_short_id();
|
||||
}
|
||||
if (R.flags_ & Flags::f_one_message) {
|
||||
R.messages_ = AdnlMessageList{std::move(packet->message_)};
|
||||
}
|
||||
if (R.flags_ & Flags::f_mult_messages) {
|
||||
// may override messages_ if (flags & 0x4)
|
||||
// but this message will fail in run_basic_checks()
|
||||
// so it doesn't matter
|
||||
R.messages_ = AdnlMessageList{std::move(packet->messages_)};
|
||||
}
|
||||
if (R.flags_ & Flags::f_address) {
|
||||
TRY_RESULT(addr_list, AdnlAddressList::create(std::move(packet->address_)));
|
||||
R.addr_ = std::move(addr_list);
|
||||
}
|
||||
if (R.flags_ & Flags::f_priority_address) {
|
||||
TRY_RESULT(addr_list, AdnlAddressList::create(std::move(packet->address_)));
|
||||
R.priority_addr_ = std::move(addr_list);
|
||||
}
|
||||
if (R.flags_ & Flags::f_seqno) {
|
||||
R.seqno_ = packet->seqno_;
|
||||
}
|
||||
if (R.flags_ & Flags::f_confirm_seqno) {
|
||||
R.confirm_seqno_ = packet->confirm_seqno_;
|
||||
}
|
||||
if (R.flags_ & Flags::f_recv_addr_version) {
|
||||
R.recv_addr_list_version_ = packet->recv_addr_list_version_;
|
||||
}
|
||||
if (R.flags_ & Flags::f_recv_priority_addr_version) {
|
||||
R.recv_priority_addr_list_version_ = packet->recv_priority_addr_list_version_;
|
||||
}
|
||||
if (R.flags_ & Flags::f_reinit_date) {
|
||||
R.reinit_date_ = packet->reinit_date_;
|
||||
R.dst_reinit_date_ = packet->dst_reinit_date_;
|
||||
}
|
||||
if (R.flags_ & Flags::f_signature) {
|
||||
R.signature_ = std::move(packet->signature_);
|
||||
}
|
||||
R.rand2_ = std::move(packet->rand2_);
|
||||
|
||||
TRY_STATUS(R.run_basic_checks());
|
||||
return std::move(R);
|
||||
}
|
||||
|
||||
td::Status AdnlPacket::run_basic_checks() const {
|
||||
if ((flags_ & Flags::f_all) != flags_) {
|
||||
return td::Status::Error(ErrorCode::protoviolation, "bad flags");
|
||||
}
|
||||
if ((flags_ & Flags::f_one_message) && (flags_ & Flags::f_mult_messages)) {
|
||||
return td::Status::Error(ErrorCode::protoviolation, "both flags 0x4 and 0x8 set");
|
||||
}
|
||||
if ((flags_ & Flags::f_from) && (flags_ & Flags::f_from_short) && from_.compute_short_id() != from_short_) {
|
||||
return td::Status::Error(ErrorCode::protoviolation, "source and short source mismatch");
|
||||
}
|
||||
if ((flags_ & Flags::f_address) && addr_.empty()) {
|
||||
return td::Status::Error(ErrorCode::protoviolation, "bad addr list");
|
||||
}
|
||||
if ((flags_ & Flags::f_priority_address) && priority_addr_.empty()) {
|
||||
return td::Status::Error(ErrorCode::protoviolation, "bad addr list");
|
||||
}
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
tl_object_ptr<ton_api::adnl_packetContents> AdnlPacket::tl() const {
|
||||
return create_tl_object<ton_api::adnl_packetContents>(
|
||||
rand1_.clone(), flags_ & ~Flags::f_priority, (flags_ & Flags::f_from) ? from_.tl() : nullptr,
|
||||
(flags_ & Flags::f_from_short) ? from_short_.tl() : nullptr,
|
||||
(flags_ & Flags::f_one_message) ? messages_.one_message() : nullptr,
|
||||
(flags_ & Flags::f_mult_messages) ? messages_.mult_messages() : messages_.empty_vector(),
|
||||
(flags_ & Flags::f_address) ? addr_.tl() : nullptr,
|
||||
(flags_ & Flags::f_priority_address) ? priority_addr_.tl() : nullptr, seqno_, confirm_seqno_,
|
||||
recv_addr_list_version_, recv_priority_addr_list_version_, reinit_date_, dst_reinit_date_, signature_.clone(),
|
||||
rand2_.clone());
|
||||
}
|
||||
|
||||
td::BufferSlice AdnlPacket::to_sign() const {
|
||||
auto obj = tl();
|
||||
obj->signature_.clear();
|
||||
obj->flags_ &= ~Flags::f_signature;
|
||||
CHECK(obj->signature_.size() == 0);
|
||||
return serialize_tl_object(obj, true);
|
||||
}
|
||||
|
||||
void AdnlPacket::init_random() {
|
||||
rand1_ = td::BufferSlice{(td::Random::fast_uint32() & 1) ? 7u : 15u};
|
||||
rand2_ = td::BufferSlice{(td::Random::fast_uint32() & 1) ? 7u : 15u};
|
||||
td::Random::secure_bytes(rand1_.as_slice());
|
||||
td::Random::secure_bytes(rand2_.as_slice());
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
211
adnl/adnl-packet.h
Normal file
211
adnl/adnl-packet.h
Normal file
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "adnl/adnl.h"
|
||||
#include "adnl/adnl-message.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
/*
|
||||
from:flags.0?PublicKey
|
||||
from_short:flags.1?adnl.id.short
|
||||
message:flags.2?adnl.Message
|
||||
messages:flags.3?(vector adnl.Message)
|
||||
address:flags.4?adnl.addressList
|
||||
priority_address:flags.5?adnl.addressList
|
||||
seqno:flags.6?long
|
||||
confirm_seqno:flags.7?long
|
||||
recv_addr_list_version:flags.8?int
|
||||
recv_priority_addr_list_version:flags.9?int
|
||||
reinit_date:flags.10?int
|
||||
dst_reinit_date:flags.10?int
|
||||
signature:flags.11?bytes
|
||||
*/
|
||||
|
||||
// total packet length:
|
||||
// for full packet:
|
||||
// 32 (dst) + 64 (encryption overhead) + 4 (magic) + 36 (pubkey) + 4 + M (sum of messages) +
|
||||
// + A1 + A2 + 8 + 8 + 4 + 4 + 4 + 4 + 68 (signature) + 16 (r1) + 16 (r2) =
|
||||
// = 272 + M + A1 + A2
|
||||
// for channel:
|
||||
// 32 (channel id) + 32 (encryption overhead) + 4 (magic) + 4 + M (sum of messages) +
|
||||
// + A1 + A2 + 8 + 8 + 4 + 4 + 16(r1) + 16(r2) = 128 + M + A1 + A2
|
||||
|
||||
class AdnlPacket {
|
||||
private:
|
||||
enum Flags : td::uint32 {
|
||||
f_from = 0x1,
|
||||
f_from_short = 0x2,
|
||||
f_one_message = 0x4,
|
||||
f_mult_messages = 0x8,
|
||||
f_address = 0x10,
|
||||
f_priority_address = 0x20,
|
||||
f_seqno = 0x40,
|
||||
f_confirm_seqno = 0x80,
|
||||
f_recv_addr_version = 0x100,
|
||||
f_recv_priority_addr_version = 0x200,
|
||||
f_reinit_date = 0x400,
|
||||
f_signature = 0x800,
|
||||
f_priority = 0x1000,
|
||||
f_all = 0x1fff
|
||||
};
|
||||
|
||||
public:
|
||||
AdnlPacket() {
|
||||
}
|
||||
static td::Result<AdnlPacket> create(tl_object_ptr<ton_api::adnl_packetContents> packet);
|
||||
tl_object_ptr<ton_api::adnl_packetContents> tl() const;
|
||||
td::BufferSlice to_sign() const;
|
||||
|
||||
td::Status run_basic_checks() const;
|
||||
|
||||
auto flags() const {
|
||||
return flags_;
|
||||
}
|
||||
bool priority() const {
|
||||
return flags_ & f_priority;
|
||||
}
|
||||
bool inited_from_short() const {
|
||||
return flags_ & (Flags::f_from | Flags::f_from_short);
|
||||
}
|
||||
bool inited_from() const {
|
||||
return flags_ & Flags::f_from;
|
||||
}
|
||||
auto from() const {
|
||||
return from_;
|
||||
}
|
||||
auto from_short() const {
|
||||
return from_short_;
|
||||
}
|
||||
const auto &messages() const {
|
||||
return messages_;
|
||||
}
|
||||
auto &messages() {
|
||||
return messages_;
|
||||
}
|
||||
bool inited_addr_list() const {
|
||||
return flags_ & Flags::f_address;
|
||||
}
|
||||
auto addr_list() const {
|
||||
return addr_;
|
||||
}
|
||||
auto priority_addr_list() const {
|
||||
return priority_addr_;
|
||||
}
|
||||
auto seqno() const {
|
||||
return seqno_;
|
||||
}
|
||||
auto confirm_seqno() const {
|
||||
return confirm_seqno_;
|
||||
}
|
||||
auto recv_addr_list_version() const {
|
||||
return recv_addr_list_version_;
|
||||
}
|
||||
auto recv_priority_addr_list_version() const {
|
||||
return recv_priority_addr_list_version_;
|
||||
}
|
||||
auto reinit_date() const {
|
||||
return reinit_date_;
|
||||
}
|
||||
auto dst_reinit_date() const {
|
||||
return dst_reinit_date_;
|
||||
}
|
||||
auto signature() const {
|
||||
return signature_.clone();
|
||||
}
|
||||
|
||||
void init_random();
|
||||
|
||||
void set_signature(td::BufferSlice signature) {
|
||||
signature_ = std::move(signature);
|
||||
flags_ |= Flags::f_signature;
|
||||
}
|
||||
void set_source(AdnlNodeIdFull src) {
|
||||
from_ = src;
|
||||
from_short_ = src.compute_short_id();
|
||||
flags_ = (flags_ | Flags::f_from) & ~Flags::f_from_short;
|
||||
}
|
||||
void set_source(AdnlNodeIdShort src) {
|
||||
if (!(flags_ & Flags::f_from)) {
|
||||
from_short_ = src;
|
||||
flags_ |= Flags::f_from_short;
|
||||
}
|
||||
}
|
||||
void add_message(AdnlMessage message) {
|
||||
messages_.push_back(std::move(message));
|
||||
if (messages_.size() == 1) {
|
||||
flags_ = (flags_ | Flags::f_one_message) & ~Flags::f_mult_messages;
|
||||
} else {
|
||||
flags_ = (flags_ | Flags::f_mult_messages) & ~Flags::f_one_message;
|
||||
}
|
||||
}
|
||||
void set_addr_list(AdnlAddressList addr_list) {
|
||||
addr_ = std::move(addr_list);
|
||||
flags_ |= Flags::f_address;
|
||||
}
|
||||
void set_priority_addr_list(AdnlAddressList addr_list) {
|
||||
priority_addr_ = std::move(addr_list);
|
||||
flags_ |= Flags::f_priority_address;
|
||||
}
|
||||
void set_seqno(td::uint64 seqno) {
|
||||
seqno_ = seqno;
|
||||
flags_ |= Flags::f_seqno;
|
||||
}
|
||||
void set_confirm_seqno(td::uint64 seqno) {
|
||||
confirm_seqno_ = seqno;
|
||||
flags_ |= Flags::f_confirm_seqno;
|
||||
}
|
||||
void set_received_addr_list_version(td::int32 version) {
|
||||
recv_addr_list_version_ = version;
|
||||
flags_ |= Flags::f_recv_addr_version;
|
||||
}
|
||||
void set_received_priority_addr_list_version(td::int32 version) {
|
||||
recv_priority_addr_list_version_ = version;
|
||||
flags_ |= Flags::f_recv_priority_addr_version;
|
||||
}
|
||||
void set_reinit_date(td::int32 date, td::int32 dst_reinit_date) {
|
||||
reinit_date_ = date;
|
||||
dst_reinit_date_ = dst_reinit_date;
|
||||
flags_ |= Flags::f_reinit_date;
|
||||
}
|
||||
|
||||
private:
|
||||
td::BufferSlice rand1_;
|
||||
td::uint32 flags_{0};
|
||||
AdnlNodeIdFull from_;
|
||||
AdnlNodeIdShort from_short_;
|
||||
AdnlMessageList messages_;
|
||||
AdnlAddressList addr_;
|
||||
AdnlAddressList priority_addr_;
|
||||
td::uint64 seqno_{0};
|
||||
td::uint64 confirm_seqno_{0};
|
||||
td::int32 recv_addr_list_version_{0};
|
||||
td::int32 recv_priority_addr_list_version_{0};
|
||||
td::int32 reinit_date_{0};
|
||||
td::int32 dst_reinit_date_{0};
|
||||
td::BufferSlice signature_;
|
||||
td::BufferSlice rand2_;
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
336
adnl/adnl-peer-table.cpp
Normal file
336
adnl/adnl-peer-table.cpp
Normal file
|
@ -0,0 +1,336 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "adnl-peer-table.hpp"
|
||||
#include "adnl-peer.h"
|
||||
#include "adnl-channel.h"
|
||||
#include "utils.hpp"
|
||||
|
||||
#include "td/utils/tl_storers.h"
|
||||
#include "td/utils/crypto.h"
|
||||
#include "td/utils/tl_parsers.h"
|
||||
#include "td/utils/Random.h"
|
||||
#include "td/db/RocksDb.h"
|
||||
|
||||
#include "utils.hpp"
|
||||
#include "adnl-query.h"
|
||||
#include "adnl-ext-client.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
td::int32 Adnl::adnl_start_time() {
|
||||
static td::int32 start_time = [] {
|
||||
auto init_start_time = static_cast<td::int32>(td::Clocks::system());
|
||||
CHECK(init_start_time > 0);
|
||||
return init_start_time;
|
||||
}();
|
||||
return start_time;
|
||||
}
|
||||
|
||||
td::actor::ActorOwn<Adnl> Adnl::create(std::string db, td::actor::ActorId<keyring::Keyring> keyring) {
|
||||
adnl_start_time();
|
||||
return td::actor::ActorOwn<Adnl>(td::actor::create_actor<AdnlPeerTableImpl>("PeerTable", db, keyring));
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::receive_packet(td::BufferSlice data) {
|
||||
if (data.size() < 32) {
|
||||
VLOG(ADNL_WARNING) << this << ": dropping IN message [?->?]: message too short: len=" << data.size();
|
||||
return;
|
||||
}
|
||||
|
||||
AdnlNodeIdShort dst{data.as_slice().truncate(32)};
|
||||
data.confirm_read(32);
|
||||
|
||||
auto it = local_ids_own_.find(dst);
|
||||
if (it != local_ids_own_.end()) {
|
||||
td::actor::send_closure(it->second, &AdnlLocalId::receive, 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, std::move(data));
|
||||
return;
|
||||
}
|
||||
|
||||
VLOG(ADNL_DEBUG) << this << ": dropping IN message [?->" << dst << "]: unknown dst " << dst
|
||||
<< " (len=" << (data.size() + 32) << ")";
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket packet) {
|
||||
packet.run_basic_checks().ensure();
|
||||
|
||||
if (!packet.inited_from_short()) {
|
||||
VLOG(ADNL_INFO) << this << ": dropping IN message [?->" << dst << "]: destination not set";
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = peers_.find(packet.from_short());
|
||||
if (it == peers_.end()) {
|
||||
if (!packet.inited_from()) {
|
||||
VLOG(ADNL_NOTICE) << this << ": dropping IN message [" << packet.from_short() << "->" << dst
|
||||
<< "]: unknown peer and no full src in packet";
|
||||
return;
|
||||
}
|
||||
if (network_manager_.empty()) {
|
||||
VLOG(ADNL_NOTICE) << this << ": dropping IN message [" << packet.from_short() << "->" << dst
|
||||
<< "]: unknown peer and network manager uninitialized";
|
||||
return;
|
||||
}
|
||||
|
||||
it = peers_
|
||||
.emplace(packet.from_short(),
|
||||
AdnlPeer::create(network_manager_, actor_id(this), dht_node_, packet.from_short()))
|
||||
.first;
|
||||
CHECK(it != peers_.end());
|
||||
}
|
||||
|
||||
auto it2 = local_ids_own_.find(dst);
|
||||
if (it2 == local_ids_own_.end()) {
|
||||
VLOG(ADNL_ERROR) << this << ": dropping IN message [" << packet.from_short() << "->" << dst
|
||||
<< "]: unknown dst (but how did we decrypt message?)";
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure(it->second, &AdnlPeer::receive_packet, dst, it2->second.get(), std::move(packet));
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::add_peer(AdnlNodeIdShort local_id, AdnlNodeIdFull id, AdnlAddressList addr_list) {
|
||||
auto id_short = id.compute_short_id();
|
||||
VLOG(ADNL_DEBUG) << this << ": adding peer " << id_short << " for local id " << local_id;
|
||||
|
||||
auto it2 = local_ids_own_.find(local_id);
|
||||
CHECK(it2 != local_ids_own_.end());
|
||||
|
||||
auto it = peers_.find(id_short);
|
||||
if (it == peers_.end()) {
|
||||
it = peers_.emplace(id_short, AdnlPeer::create(network_manager_, actor_id(this), dht_node_, id_short)).first;
|
||||
CHECK(it != peers_.end());
|
||||
}
|
||||
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.get(), std::move(addr_list));
|
||||
}
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::add_static_nodes_from_config(AdnlNodesList nodes) {
|
||||
for (auto &it : nodes.nodes()) {
|
||||
add_static_node(it);
|
||||
}
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::send_message_in(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlMessage message) {
|
||||
auto it = peers_.find(dst);
|
||||
|
||||
if (it == peers_.end()) {
|
||||
it = peers_.emplace(dst, AdnlPeer::create(network_manager_, actor_id(this), dht_node_, dst)).first;
|
||||
}
|
||||
|
||||
auto it2 = local_ids_own_.find(src);
|
||||
if (it2 == local_ids_own_.end()) {
|
||||
LOG(ERROR) << this << ": dropping OUT message [" << src << "->" << dst << "]: unknown src";
|
||||
return;
|
||||
}
|
||||
|
||||
td::actor::send_closure(it->second, &AdnlPeer::send_one_message, src, it2->second.get(), std::move(message));
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::answer_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlQueryId query_id,
|
||||
td::BufferSlice data) {
|
||||
if (data.size() > get_mtu()) {
|
||||
LOG(ERROR) << this << ": dropping OUT message [" << src << "->" << dst
|
||||
<< "]: message too big: size=" << data.size();
|
||||
return;
|
||||
}
|
||||
send_message_in(src, dst, adnlmessage::AdnlMessageAnswer{query_id, std::move(data)});
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::send_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, std::string name,
|
||||
td::Promise<td::BufferSlice> promise, td::Timestamp timeout, td::BufferSlice data) {
|
||||
if (data.size() > huge_packet_max_size()) {
|
||||
VLOG(ADNL_WARNING) << "dropping too big packet [" << src << "->" << dst << "]: size=" << data.size();
|
||||
VLOG(ADNL_WARNING) << "DUMP: " << td::buffer_to_hex(data.as_slice().truncate(128));
|
||||
return;
|
||||
}
|
||||
auto it = peers_.find(dst);
|
||||
|
||||
if (it == peers_.end()) {
|
||||
it = peers_.emplace(dst, AdnlPeer::create(network_manager_, actor_id(this), dht_node_, dst)).first;
|
||||
}
|
||||
|
||||
auto it2 = local_ids_own_.find(src);
|
||||
if (it2 == local_ids_own_.end()) {
|
||||
LOG(ERROR) << this << ": dropping OUT message [" << src << "->" << dst << "]: unknown src";
|
||||
return;
|
||||
}
|
||||
|
||||
td::actor::send_closure(it->second, &AdnlPeer::send_query, src, it2->second.get(), name, std::move(promise), timeout,
|
||||
std::move(data));
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::add_id(AdnlNodeIdFull id, AdnlAddressList addr_list) {
|
||||
auto a = id.compute_short_id();
|
||||
VLOG(ADNL_INFO) << "adnl: adding local id " << a;
|
||||
|
||||
auto it = local_ids_own_.find(a);
|
||||
|
||||
if (it != local_ids_own_.end()) {
|
||||
td::actor::send_closure(it->second, &AdnlLocalId::update_address_list, std::move(addr_list));
|
||||
} else {
|
||||
local_ids_own_[a] = td::actor::create_actor<AdnlLocalId>("localid", std::move(id), std::move(addr_list),
|
||||
actor_id(this), keyring_, dht_node_);
|
||||
}
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::del_id(AdnlNodeIdShort id, td::Promise<td::Unit> promise) {
|
||||
VLOG(ADNL_INFO) << "adnl: deleting local id " << id;
|
||||
local_ids_own_.erase(id);
|
||||
promise.set_value(td::Unit());
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::subscribe(AdnlNodeIdShort dst, std::string prefix, std::unique_ptr<Callback> callback) {
|
||||
auto it = local_ids_own_.find(dst);
|
||||
LOG_CHECK(it != local_ids_own_.end()) << "dst=" << dst;
|
||||
|
||||
td::actor::send_closure(it->second, &AdnlLocalId::subscribe, prefix, std::move(callback));
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::unsubscribe(AdnlNodeIdShort dst, std::string prefix) {
|
||||
auto it = local_ids_own_.find(dst);
|
||||
|
||||
if (it != local_ids_own_.end()) {
|
||||
td::actor::send_closure(it->second, &AdnlLocalId::unsubscribe, prefix);
|
||||
}
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::register_dht_node(td::actor::ActorId<dht::Dht> dht_node) {
|
||||
dht_node_ = dht_node;
|
||||
|
||||
for (auto it = peers_.begin(); it != peers_.end(); it++) {
|
||||
td::actor::send_closure(it->second, &AdnlPeer::update_dht_node, dht_node_);
|
||||
}
|
||||
for (auto it = local_ids_own_.begin(); it != local_ids_own_.end(); it++) {
|
||||
td::actor::send_closure(it->second, &AdnlLocalId::update_dht_node, dht_node_);
|
||||
}
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::register_network_manager(td::actor::ActorId<AdnlNetworkManager> network_manager) {
|
||||
network_manager_ = std::move(network_manager);
|
||||
|
||||
class Cb : public AdnlNetworkManager::Callback {
|
||||
public:
|
||||
void receive_packet(td::IPAddress addr, td::BufferSlice data) override {
|
||||
td::actor::send_closure(id_, &AdnlPeerTableImpl::receive_packet, std::move(data));
|
||||
}
|
||||
Cb(td::actor::ActorId<AdnlPeerTableImpl> id) : id_(id) {
|
||||
}
|
||||
|
||||
private:
|
||||
td::actor::ActorId<AdnlPeerTableImpl> id_;
|
||||
};
|
||||
|
||||
auto cb = std::make_unique<Cb>(actor_id(this));
|
||||
td::actor::send_closure(network_manager_, &AdnlNetworkManager::install_callback, std::move(cb));
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::get_addr_list(AdnlNodeIdShort id, td::Promise<AdnlAddressList> promise) {
|
||||
auto it = local_ids_own_.find(id);
|
||||
if (it == local_ids_own_.end()) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::notready));
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure(it->second, &AdnlLocalId::get_addr_list_async, std::move(promise));
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::get_self_node(AdnlNodeIdShort id, td::Promise<AdnlNode> promise) {
|
||||
auto it = local_ids_own_.find(id);
|
||||
if (it == local_ids_own_.end()) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::notready));
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure(it->second, &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;
|
||||
CHECK(success);
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::unregister_channel(AdnlChannelIdShort id) {
|
||||
auto erased = channels_.erase(id);
|
||||
CHECK(erased == 1);
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::start_up() {
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::write_new_addr_list_to_db(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id, AdnlDbItem node,
|
||||
td::Promise<td::Unit> promise) {
|
||||
td::actor::send_closure(db_, &AdnlDb::update, local_id, peer_id, std::move(node), std::move(promise));
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::get_addr_list_from_db(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id,
|
||||
td::Promise<AdnlDbItem> promise) {
|
||||
td::actor::send_closure(db_, &AdnlDb::get, local_id, peer_id, std::move(promise));
|
||||
}
|
||||
|
||||
AdnlPeerTableImpl::AdnlPeerTableImpl(std::string db_root, td::actor::ActorId<keyring::Keyring> keyring) {
|
||||
keyring_ = keyring;
|
||||
static_nodes_manager_ = AdnlStaticNodesManager::create();
|
||||
|
||||
db_ = AdnlDb::create(db_root + "/adnl");
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::deliver(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data) {
|
||||
auto it = local_ids_own_.find(dst);
|
||||
if (it != local_ids_own_.end()) {
|
||||
td::actor::send_closure(it->second, &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_own_.find(dst);
|
||||
if (it != local_ids_own_.end()) {
|
||||
td::actor::send_closure(it->second, &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"));
|
||||
}
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::decrypt_message(AdnlNodeIdShort dst, td::BufferSlice data,
|
||||
td::Promise<td::BufferSlice> promise) {
|
||||
auto it = local_ids_own_.find(dst);
|
||||
if (it != local_ids_own_.end()) {
|
||||
td::actor::send_closure(it->second, &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"));
|
||||
}
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::create_ext_server(std::vector<AdnlNodeIdShort> ids, std::vector<td::uint16> ports,
|
||||
td::Promise<td::actor::ActorOwn<AdnlExtServer>> promise) {
|
||||
promise.set_value(AdnlExtServerCreator::create(actor_id(this), std::move(ids), std::move(ports)));
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
124
adnl/adnl-peer-table.h
Normal file
124
adnl/adnl-peer-table.h
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/utils/BufferedUdp.h"
|
||||
|
||||
#include "adnl.h"
|
||||
#include "utils.hpp"
|
||||
#include "adnl/adnl-query.h"
|
||||
#include "adnl/adnl-db.h"
|
||||
#include "common/io.hpp"
|
||||
|
||||
#include "adnl-packet.h"
|
||||
|
||||
#include "auto/tl/ton_api.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
constexpr int VERBOSITY_NAME(ADNL_ERROR) = verbosity_WARNING;
|
||||
constexpr int VERBOSITY_NAME(ADNL_WARNING) = verbosity_INFO;
|
||||
constexpr int VERBOSITY_NAME(ADNL_NOTICE) = verbosity_DEBUG;
|
||||
constexpr int VERBOSITY_NAME(ADNL_INFO) = verbosity_DEBUG;
|
||||
constexpr int VERBOSITY_NAME(ADNL_DEBUG) = verbosity_DEBUG + 1;
|
||||
constexpr int VERBOSITY_NAME(ADNL_EXTRA_DEBUG) = verbosity_DEBUG + 10;
|
||||
|
||||
class AdnlChannelIdShortImpl {
|
||||
public:
|
||||
explicit AdnlChannelIdShortImpl(PublicKeyHash value) {
|
||||
value_ = value.bits256_value();
|
||||
}
|
||||
explicit AdnlChannelIdShortImpl(td::Bits256 value) {
|
||||
value_ = value;
|
||||
}
|
||||
AdnlChannelIdShortImpl() {
|
||||
}
|
||||
td::Bits256 bits256_value() const {
|
||||
return value_;
|
||||
}
|
||||
auto tl() const {
|
||||
return value_;
|
||||
}
|
||||
|
||||
bool operator<(const AdnlChannelIdShortImpl &with) const {
|
||||
return value_ < with.value_;
|
||||
}
|
||||
bool operator==(const AdnlChannelIdShortImpl &with) const {
|
||||
return value_ == with.value_;
|
||||
}
|
||||
bool operator!=(const AdnlChannelIdShortImpl &with) const {
|
||||
return value_ != with.value_;
|
||||
}
|
||||
td::Slice as_slice() const {
|
||||
return td::as_slice(value_);
|
||||
}
|
||||
|
||||
private:
|
||||
td::Bits256 value_;
|
||||
};
|
||||
|
||||
using AdnlChannelIdShort = AdnlChannelIdShortImpl;
|
||||
|
||||
class AdnlLocalId;
|
||||
class AdnlChannel;
|
||||
|
||||
class AdnlPeerTable : public Adnl {
|
||||
public:
|
||||
static constexpr double republish_addr_list_timeout() {
|
||||
return 60.0;
|
||||
}
|
||||
|
||||
virtual void answer_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlQueryId query_id, td::BufferSlice data) = 0;
|
||||
|
||||
virtual void receive_packet(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) = 0;
|
||||
|
||||
virtual void register_channel(AdnlChannelIdShort id, td::actor::ActorId<AdnlChannel> channel) = 0;
|
||||
virtual void unregister_channel(AdnlChannelIdShort id) = 0;
|
||||
|
||||
virtual void add_static_node(AdnlNode node) = 0;
|
||||
virtual void del_static_node(AdnlNodeIdShort id) = 0;
|
||||
virtual void get_static_node(AdnlNodeIdShort id, td::Promise<AdnlNode> promise) = 0;
|
||||
|
||||
virtual void write_new_addr_list_to_db(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id, AdnlDbItem node,
|
||||
td::Promise<td::Unit> promise) = 0;
|
||||
virtual void get_addr_list_from_db(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id,
|
||||
td::Promise<AdnlDbItem> promise) = 0;
|
||||
|
||||
virtual void deliver(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data) = 0;
|
||||
virtual void deliver_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data,
|
||||
td::Promise<td::BufferSlice> promise) = 0;
|
||||
virtual void decrypt_message(AdnlNodeIdShort dst, td::BufferSlice data, td::Promise<td::BufferSlice> promise) = 0;
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
||||
|
||||
namespace td {
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &stream, const ton::adnl::AdnlChannelIdShort &value) {
|
||||
return stream << value.bits256_value();
|
||||
}
|
||||
|
||||
} // namespace td
|
137
adnl/adnl-peer-table.hpp
Normal file
137
adnl/adnl-peer-table.hpp
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "adnl-peer-table.h"
|
||||
#include "adnl-peer.h"
|
||||
#include "keys/encryptor.h"
|
||||
//#include "adnl-decryptor.h"
|
||||
#include "adnl-local-id.h"
|
||||
#include "adnl-query.h"
|
||||
#include "utils.hpp"
|
||||
#include "adnl-static-nodes.h"
|
||||
#include "adnl-ext-server.h"
|
||||
#include "adnl-address-list.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlPeerTableImpl : public AdnlPeerTable {
|
||||
public:
|
||||
AdnlPeerTableImpl(std::string db_root, td::actor::ActorId<keyring::Keyring> keyring);
|
||||
|
||||
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::BufferSlice data) override;
|
||||
void receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket data) override;
|
||||
void send_message_in(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlMessage message) override;
|
||||
void send_message(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data) override {
|
||||
if (data.size() > huge_packet_max_size()) {
|
||||
VLOG(ADNL_WARNING) << "dropping too big packet [" << src << "->" << dst << "]: size=" << data.size();
|
||||
VLOG(ADNL_WARNING) << "DUMP: " << td::buffer_to_hex(data.as_slice().truncate(128));
|
||||
return;
|
||||
}
|
||||
send_message_in(src, dst, AdnlMessage{adnlmessage::AdnlMessageCustom{std::move(data)}});
|
||||
}
|
||||
void answer_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlQueryId query_id, td::BufferSlice data) override;
|
||||
void send_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, std::string name, td::Promise<td::BufferSlice> promise,
|
||||
td::Timestamp timeout, td::BufferSlice data) override;
|
||||
void send_query_ex(AdnlNodeIdShort src, AdnlNodeIdShort dst, std::string name, td::Promise<td::BufferSlice> promise,
|
||||
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(AdnlNodeIdFull id, AdnlAddressList addr_list) 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;
|
||||
void register_dht_node(td::actor::ActorId<dht::Dht> dht_node) override;
|
||||
void register_network_manager(td::actor::ActorId<AdnlNetworkManager> network_manager) override;
|
||||
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 unregister_channel(AdnlChannelIdShort id) override;
|
||||
|
||||
void write_new_addr_list_to_db(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id, AdnlDbItem node,
|
||||
td::Promise<td::Unit> promise) override;
|
||||
void get_addr_list_from_db(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id,
|
||||
td::Promise<AdnlDbItem> promise) override;
|
||||
|
||||
void add_static_node(AdnlNode node) override {
|
||||
CHECK(!static_nodes_manager_.empty());
|
||||
td::actor::send_closure(static_nodes_manager_, &AdnlStaticNodesManager::add_node, std::move(node));
|
||||
}
|
||||
void del_static_node(AdnlNodeIdShort id) override {
|
||||
td::actor::send_closure(static_nodes_manager_, &AdnlStaticNodesManager::del_node, id);
|
||||
}
|
||||
void get_static_node(AdnlNodeIdShort id, td::Promise<AdnlNode> promise) override {
|
||||
td::actor::send_closure(static_nodes_manager_, &AdnlStaticNodesManager::get_node, id, std::move(promise));
|
||||
}
|
||||
void deliver(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data) override;
|
||||
void deliver_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data,
|
||||
td::Promise<td::BufferSlice> promise) override;
|
||||
void decrypt_message(AdnlNodeIdShort dst, td::BufferSlice data, td::Promise<td::BufferSlice> promise) override;
|
||||
|
||||
void create_ext_server(std::vector<AdnlNodeIdShort> ids, std::vector<td::uint16> ports,
|
||||
td::Promise<td::actor::ActorOwn<AdnlExtServer>> promise) override;
|
||||
|
||||
struct PrintId {};
|
||||
PrintId print_id() const {
|
||||
return PrintId{};
|
||||
}
|
||||
|
||||
private:
|
||||
td::actor::ActorId<keyring::Keyring> keyring_;
|
||||
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager_;
|
||||
td::actor::ActorId<dht::Dht> dht_node_;
|
||||
td::actor::ActorOwn<AdnlStaticNodesManager> static_nodes_manager_;
|
||||
|
||||
void deliver_one_message(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlMessage message);
|
||||
|
||||
std::map<AdnlNodeIdShort, td::actor::ActorOwn<AdnlPeer>> peers_;
|
||||
std::map<AdnlNodeIdShort, td::actor::ActorOwn<AdnlLocalId>> local_ids_own_;
|
||||
std::map<AdnlChannelIdShort, td::actor::ActorId<AdnlChannel>> channels_;
|
||||
|
||||
td::actor::ActorOwn<AdnlDb> db_;
|
||||
|
||||
td::actor::ActorOwn<AdnlExtServer> ext_server_;
|
||||
|
||||
//std::map<td::uint64, td::actor::ActorId<AdnlQuery>> out_queries_;
|
||||
//td::uint64 last_query_id_ = 1;
|
||||
};
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const AdnlPeerTableImpl::PrintId &id) {
|
||||
sb << "[peertable]";
|
||||
return sb;
|
||||
}
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const AdnlPeerTableImpl &manager) {
|
||||
sb << manager.print_id();
|
||||
return sb;
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
878
adnl/adnl-peer.cpp
Normal file
878
adnl/adnl-peer.cpp
Normal file
|
@ -0,0 +1,878 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "adnl-peer.h"
|
||||
#include "adnl-peer.hpp"
|
||||
#include "adnl-local-id.h"
|
||||
|
||||
#include "utils.hpp"
|
||||
|
||||
#include "td/actor/PromiseFuture.h"
|
||||
#include "td/utils/base64.h"
|
||||
#include "td/utils/Random.h"
|
||||
#include "auto/tl/ton_api.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
static_assert(AdnlPeerPairImpl::get_mtu() + AdnlPeerPairImpl::packet_header_max_size() <= AdnlNetworkManager::get_mtu(),
|
||||
"wrong mtu configuration");
|
||||
|
||||
void AdnlPeerPairImpl::start_up() {
|
||||
auto P1 = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<AdnlDbItem> R) {
|
||||
td::actor::send_closure(SelfId, &AdnlPeerPairImpl::got_data_from_db, std::move(R));
|
||||
});
|
||||
td::actor::send_closure(peer_table_, &AdnlPeerTable::get_addr_list_from_db, local_id_, peer_id_short_, std::move(P1));
|
||||
auto P2 = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<AdnlNode> R) {
|
||||
td::actor::send_closure(SelfId, &AdnlPeerPairImpl::got_data_from_static_nodes, std::move(R));
|
||||
});
|
||||
td::actor::send_closure(peer_table_, &AdnlPeerTable::get_static_node, peer_id_short_, std::move(P2));
|
||||
|
||||
if (!dht_node_.empty()) {
|
||||
discover();
|
||||
}
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::alarm() {
|
||||
if (next_dht_query_at_ && next_dht_query_at_.is_in_past()) {
|
||||
next_dht_query_at_ = td::Timestamp::never();
|
||||
discover();
|
||||
}
|
||||
if (next_db_update_at_ && next_db_update_at_.is_in_past()) {
|
||||
if (received_from_db_ && received_from_static_nodes_ && !peer_id_.empty()) {
|
||||
AdnlDbItem item;
|
||||
item.id = peer_id_;
|
||||
item.addr_list = addr_list_;
|
||||
item.priority_addr_list = priority_addr_list_;
|
||||
|
||||
td::actor::send_closure(peer_table_, &AdnlPeerTable::write_new_addr_list_to_db, local_id_, peer_id_short_,
|
||||
std::move(item), [](td::Unit) {});
|
||||
}
|
||||
next_db_update_at_ = td::Timestamp::in(td::Random::fast(60.0, 120.0));
|
||||
}
|
||||
if (retry_send_at_ && retry_send_at_.is_in_past()) {
|
||||
retry_send_at_ = td::Timestamp::never();
|
||||
send_messages_in(std::move(pending_messages_), false);
|
||||
}
|
||||
alarm_timestamp().relax(next_dht_query_at_);
|
||||
alarm_timestamp().relax(next_db_update_at_);
|
||||
alarm_timestamp().relax(retry_send_at_);
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::discover() {
|
||||
CHECK(!dht_query_active_);
|
||||
CHECK(!dht_node_.empty());
|
||||
dht_query_active_ = true;
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), id = print_id(),
|
||||
peer_id = peer_id_short_](td::Result<dht::DhtValue> kv) {
|
||||
if (kv.is_error()) {
|
||||
td::actor::send_closure(SelfId, &AdnlPeerPairImpl::got_data_from_dht,
|
||||
kv.move_as_error_prefix("failed to get from dht: "));
|
||||
return;
|
||||
}
|
||||
auto k = kv.move_as_ok();
|
||||
auto pub = AdnlNodeIdFull{k.key().public_key()};
|
||||
CHECK(pub.compute_short_id() == peer_id);
|
||||
|
||||
auto addr_list = fetch_tl_object<ton_api::adnl_addressList>(k.value().clone(), true);
|
||||
if (addr_list.is_error()) {
|
||||
td::actor::send_closure(SelfId, &AdnlPeerPairImpl::got_data_from_dht,
|
||||
addr_list.move_as_error_prefix("bad dht value: "));
|
||||
return;
|
||||
}
|
||||
|
||||
auto F = AdnlAddressList::create(addr_list.move_as_ok());
|
||||
if (F.is_error()) {
|
||||
td::actor::send_closure(SelfId, &AdnlPeerPairImpl::got_data_from_dht, F.move_as_error_prefix("bad dht value: "));
|
||||
return;
|
||||
}
|
||||
|
||||
AdnlNode node{pub, F.move_as_ok()};
|
||||
td::actor::send_closure(SelfId, &AdnlPeerPairImpl::got_data_from_dht, std::move(node));
|
||||
});
|
||||
|
||||
td::actor::send_closure(dht_node_, &dht::Dht::get_value, dht::DhtKey{peer_id_short_.pubkey_hash(), "address", 0},
|
||||
std::move(P));
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::receive_packet_checked(AdnlPacket packet) {
|
||||
auto d = Adnl::adnl_start_time();
|
||||
if (packet.dst_reinit_date() > d) {
|
||||
VLOG(ADNL_WARNING) << this << ": dropping IN message: too new our reinit date " << packet.dst_reinit_date();
|
||||
return;
|
||||
}
|
||||
if (packet.reinit_date() > td::Clocks::system() + 60) {
|
||||
VLOG(ADNL_NOTICE) << this << ": dropping IN message: too new peer reinit date " << packet.reinit_date();
|
||||
return;
|
||||
}
|
||||
if (packet.reinit_date() > reinit_date_) {
|
||||
reinit(packet.reinit_date());
|
||||
}
|
||||
if (packet.reinit_date() > 0 && packet.reinit_date() < reinit_date_) {
|
||||
VLOG(ADNL_NOTICE) << this << ": dropping IN message: old peer reinit date " << packet.reinit_date();
|
||||
return;
|
||||
}
|
||||
if (packet.dst_reinit_date() > 0 && packet.dst_reinit_date() < d) {
|
||||
if (!packet.addr_list().empty()) {
|
||||
update_addr_list(packet.addr_list());
|
||||
}
|
||||
if (!packet.priority_addr_list().empty()) {
|
||||
update_addr_list(packet.priority_addr_list());
|
||||
}
|
||||
VLOG(ADNL_NOTICE) << this << ": dropping IN message old our reinit date " << packet.reinit_date() << " date=" << d;
|
||||
auto M = AdnlMessage{adnlmessage::AdnlMessageNop{}};
|
||||
send_message(std::move(M));
|
||||
return;
|
||||
}
|
||||
if (packet.seqno() > 0) {
|
||||
if (received_packet(static_cast<td::uint32>(packet.seqno()))) {
|
||||
VLOG(ADNL_INFO) << this << ": dropping IN message: old seqno: " << packet.seqno() << " (current max " << in_seqno_
|
||||
<< ")";
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (packet.confirm_seqno() > 0) {
|
||||
if (packet.confirm_seqno() > out_seqno_) {
|
||||
VLOG(ADNL_WARNING) << this << ": dropping IN message: new ack seqno: " << packet.confirm_seqno()
|
||||
<< " (current max sent " << out_seqno_ << ")";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// accepted
|
||||
// delivering
|
||||
|
||||
add_received_packet(static_cast<td::uint32>(packet.seqno()));
|
||||
|
||||
if (packet.confirm_seqno() > ack_seqno_) {
|
||||
ack_seqno_ = packet.confirm_seqno();
|
||||
}
|
||||
|
||||
if (packet.recv_addr_list_version() > peer_recv_addr_list_version_) {
|
||||
peer_recv_addr_list_version_ = packet.recv_addr_list_version();
|
||||
}
|
||||
|
||||
if (packet.recv_priority_addr_list_version() > peer_recv_priority_addr_list_version_) {
|
||||
peer_recv_priority_addr_list_version_ = packet.recv_priority_addr_list_version();
|
||||
}
|
||||
|
||||
if (!packet.addr_list().empty()) {
|
||||
update_addr_list(packet.addr_list());
|
||||
}
|
||||
if (!packet.priority_addr_list().empty()) {
|
||||
update_addr_list(packet.priority_addr_list());
|
||||
}
|
||||
|
||||
received_messages_++;
|
||||
if (received_messages_ % 64 == 0) {
|
||||
VLOG(ADNL_INFO) << this << ": received " << received_messages_ << " messages";
|
||||
}
|
||||
for (auto &M : packet.messages().vector()) {
|
||||
deliver_message(std::move(M));
|
||||
}
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::receive_packet_from_channel(AdnlChannelIdShort id, AdnlPacket packet) {
|
||||
if (id != channel_in_id_) {
|
||||
VLOG(ADNL_NOTICE) << this << ": dropping IN message: outdated channel id" << id;
|
||||
return;
|
||||
}
|
||||
channel_ready_ = true;
|
||||
receive_packet_checked(std::move(packet));
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::receive_packet(AdnlPacket packet) {
|
||||
packet.run_basic_checks().ensure();
|
||||
|
||||
if (!encryptor_) {
|
||||
VLOG(ADNL_NOTICE) << this << "dropping IN message: unitialized id";
|
||||
return;
|
||||
}
|
||||
|
||||
auto S = encryptor_->check_signature(packet.to_sign().as_slice(), packet.signature().as_slice());
|
||||
if (S.is_error()) {
|
||||
VLOG(ADNL_NOTICE) << this << "dropping IN message: bad signature: " << S;
|
||||
return;
|
||||
}
|
||||
|
||||
receive_packet_checked(std::move(packet));
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::deliver_message(AdnlMessage message) {
|
||||
message.visit([&](const auto &obj) { this->process_message(obj); });
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::send_messages_in(std::vector<AdnlMessage> messages, bool allow_postpone) {
|
||||
auto connR = get_conn();
|
||||
if (connR.is_error()) {
|
||||
if (!allow_postpone) {
|
||||
VLOG(ADNL_NOTICE) << this << ": dropping OUT messages: cannot get conn: " << connR.move_as_error();
|
||||
return;
|
||||
}
|
||||
VLOG(ADNL_INFO) << this << ": delaying OUT messages: cannot get conn: " << connR.move_as_error();
|
||||
if (!retry_send_at_) {
|
||||
retry_send_at_.relax(td::Timestamp::in(10.0));
|
||||
alarm_timestamp().relax(retry_send_at_);
|
||||
}
|
||||
for (auto &m : messages) {
|
||||
pending_messages_.push_back(std::move(m));
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto conn = connR.move_as_ok();
|
||||
|
||||
size_t ptr = 0;
|
||||
bool first = true;
|
||||
do {
|
||||
size_t s = (channel_ready_ ? channel_packet_header_max_size() : packet_header_max_size());
|
||||
if (first) {
|
||||
s += 2 * addr_list_max_size();
|
||||
}
|
||||
|
||||
AdnlPacket packet;
|
||||
packet.set_seqno(++out_seqno_);
|
||||
packet.set_confirm_seqno(in_seqno_);
|
||||
|
||||
if (first) {
|
||||
if (!channel_inited_) {
|
||||
auto M = adnlmessage::AdnlMessageCreateChannel{channel_pub_, channel_pk_date_};
|
||||
s += M.size();
|
||||
packet.add_message(std::move(M));
|
||||
} else if (!channel_ready_) {
|
||||
auto M = adnlmessage::AdnlMessageConfirmChannel{channel_pub_, peer_channel_pub_, channel_pk_date_};
|
||||
s += M.size();
|
||||
packet.add_message(std::move(M));
|
||||
}
|
||||
}
|
||||
|
||||
if (!addr_list_.empty()) {
|
||||
packet.set_received_addr_list_version(addr_list_.version());
|
||||
}
|
||||
if (!priority_addr_list_.empty()) {
|
||||
packet.set_received_priority_addr_list_version(priority_addr_list_.version());
|
||||
}
|
||||
|
||||
while (ptr < messages.size()) {
|
||||
auto &M = messages[ptr];
|
||||
CHECK(M.size() <= get_mtu());
|
||||
if (s + M.size() <= AdnlNetworkManager::get_mtu()) {
|
||||
s += M.size();
|
||||
packet.add_message(std::move(M));
|
||||
ptr++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!channel_ready_) {
|
||||
packet.set_reinit_date(Adnl::adnl_start_time(), reinit_date_);
|
||||
packet.set_source(local_id_);
|
||||
}
|
||||
|
||||
if (!first) {
|
||||
if (!channel_inited_) {
|
||||
auto M = adnlmessage::AdnlMessageCreateChannel{channel_pub_, channel_pk_date_};
|
||||
if (s + M.size() <= AdnlNetworkManager::get_mtu()) {
|
||||
s += M.size();
|
||||
packet.add_message(std::move(M));
|
||||
}
|
||||
} else if (!channel_ready_) {
|
||||
auto M = adnlmessage::AdnlMessageConfirmChannel{channel_pub_, peer_channel_pub_, channel_pk_date_};
|
||||
if (s + M.size() <= AdnlNetworkManager::get_mtu()) {
|
||||
s += M.size();
|
||||
packet.add_message(std::move(M));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
packet.run_basic_checks().ensure();
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), conn, id = print_id(),
|
||||
via_channel = channel_ready_](td::Result<AdnlPacket> res) {
|
||||
if (res.is_error()) {
|
||||
LOG(ERROR) << id << ": dropping OUT message: error while creating packet: " << res.move_as_error();
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &AdnlPeerPairImpl::send_packet_continue, res.move_as_ok(), conn, via_channel);
|
||||
}
|
||||
});
|
||||
|
||||
td::actor::send_closure(
|
||||
local_actor_, &AdnlLocalId::update_packet, std::move(packet),
|
||||
!channel_ready_ && ack_seqno_ == 0 && in_seqno_ == 0, !channel_ready_,
|
||||
(first || s + addr_list_max_size() <= AdnlNetworkManager::get_mtu()) ? peer_recv_addr_list_version_
|
||||
: 0x7fffffff,
|
||||
(first || s + 2 * addr_list_max_size() <= AdnlNetworkManager::get_mtu()) ? peer_recv_priority_addr_list_version_
|
||||
: 0x7fffffff,
|
||||
std::move(P));
|
||||
first = false;
|
||||
} while (ptr < messages.size());
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::send_messages(std::vector<AdnlMessage> messages) {
|
||||
std::vector<AdnlMessage> new_vec;
|
||||
for (auto &M : messages) {
|
||||
if (M.size() <= get_mtu()) {
|
||||
new_vec.push_back(std::move(M));
|
||||
} else {
|
||||
auto B = serialize_tl_object(M.tl(), true);
|
||||
CHECK(B.size() <= huge_packet_max_size());
|
||||
|
||||
auto hash = sha256_bits256(B.as_slice());
|
||||
|
||||
auto size = static_cast<td::uint32>(B.size());
|
||||
td::uint32 offset = 0;
|
||||
td::uint32 part_size = Adnl::get_mtu();
|
||||
while (offset < size) {
|
||||
auto data = B.clone();
|
||||
if (data.size() > part_size) {
|
||||
data.truncate(part_size);
|
||||
}
|
||||
B.confirm_read(data.size());
|
||||
|
||||
new_vec.push_back(AdnlMessage{adnlmessage::AdnlMessagePart{hash, size, offset, std::move(data)}});
|
||||
offset += part_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
send_messages_in(std::move(new_vec), true);
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::send_packet_continue(AdnlPacket packet, td::actor::ActorId<AdnlNetworkConnection> conn,
|
||||
bool via_channel) {
|
||||
packet.run_basic_checks().ensure();
|
||||
auto B = serialize_tl_object(packet.tl(), true);
|
||||
if (via_channel) {
|
||||
if (channel_ready_) {
|
||||
td::actor::send_closure(channel_, &AdnlChannel::send_message, priority_, conn, std::move(B));
|
||||
} else {
|
||||
VLOG(ADNL_WARNING) << this << ": dropping OUT message [" << local_id_ << "->" << peer_id_short_
|
||||
<< "]: channel destroyed in process";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!encryptor_) {
|
||||
VLOG(ADNL_INFO) << this << ": dropping OUT message [" << local_id_ << "->" << peer_id_short_
|
||||
<< "]: empty encryptor";
|
||||
return;
|
||||
}
|
||||
|
||||
auto res = encryptor_->encrypt(B.as_slice());
|
||||
if (res.is_error()) {
|
||||
VLOG(ADNL_WARNING) << this << ": dropping OUT message [" << local_id_ << "->" << peer_id_short_
|
||||
<< "]: failed to encrypt: " << res.move_as_error();
|
||||
return;
|
||||
}
|
||||
auto X = res.move_as_ok();
|
||||
auto enc = td::BufferSlice(X.size() + 32);
|
||||
td::MutableSlice S = enc.as_slice();
|
||||
S.copy_from(peer_id_short_.as_slice());
|
||||
S.remove_prefix(32);
|
||||
S.copy_from(X.as_slice());
|
||||
|
||||
td::actor::send_closure(conn, &AdnlNetworkConnection::send, local_id_, peer_id_short_, priority_, std::move(enc));
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::send_query(std::string name, td::Promise<td::BufferSlice> promise, td::Timestamp timeout,
|
||||
td::BufferSlice data) {
|
||||
AdnlQueryId id = AdnlQuery::random_query_id();
|
||||
CHECK(out_queries_.count(id) == 0);
|
||||
|
||||
auto P = [SelfId = actor_id(this)](AdnlQueryId id) {
|
||||
td::actor::send_closure(SelfId, &AdnlPeerPairImpl::delete_query, id);
|
||||
};
|
||||
|
||||
out_queries_[id] = AdnlQuery::create(std::move(promise), std::move(P), name, timeout, id);
|
||||
|
||||
send_message(adnlmessage::AdnlMessageQuery{id, std::move(data)});
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::alarm_query(AdnlQueryId id) {
|
||||
out_queries_.erase(id);
|
||||
}
|
||||
|
||||
AdnlPeerPairImpl::AdnlPeerPairImpl(td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
td::actor::ActorId<AdnlPeerTable> peer_table,
|
||||
td::actor::ActorId<AdnlLocalId> local_actor, td::actor::ActorId<AdnlPeer> peer,
|
||||
td::actor::ActorId<dht::Dht> dht_node, AdnlNodeIdShort local_id,
|
||||
AdnlNodeIdShort peer_id) {
|
||||
network_manager_ = network_manager;
|
||||
peer_table_ = peer_table;
|
||||
local_actor_ = local_actor;
|
||||
peer_ = peer;
|
||||
dht_node_ = dht_node;
|
||||
|
||||
local_id_ = local_id;
|
||||
peer_id_short_ = peer_id;
|
||||
|
||||
channel_pk_ = privkeys::Ed25519::random();
|
||||
channel_pub_ = channel_pk_.pub();
|
||||
channel_pk_date_ = static_cast<td::int32>(td::Clocks::system());
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::create_channel(pubkeys::Ed25519 pub, td::uint32 date) {
|
||||
if (channel_inited_ && peer_channel_pub_ == pub) {
|
||||
return;
|
||||
}
|
||||
if (channel_inited_ && date <= peer_channel_date_) {
|
||||
return;
|
||||
}
|
||||
if (channel_inited_) {
|
||||
td::actor::send_closure(peer_table_, &AdnlPeerTable::unregister_channel, channel_in_id_);
|
||||
channel_.reset();
|
||||
channel_inited_ = false;
|
||||
channel_ready_ = false;
|
||||
}
|
||||
CHECK(!channel_ready_);
|
||||
|
||||
peer_channel_pub_ = pub;
|
||||
peer_channel_date_ = date;
|
||||
|
||||
auto R = AdnlChannel::create(channel_pk_, peer_channel_pub_, local_id_, peer_id_short_, channel_out_id_,
|
||||
channel_in_id_, actor_id(this));
|
||||
if (R.is_ok()) {
|
||||
channel_ = R.move_as_ok();
|
||||
channel_inited_ = true;
|
||||
|
||||
td::actor::send_closure_later(peer_table_, &AdnlPeerTable::register_channel, channel_in_id_, channel_.get());
|
||||
} else {
|
||||
VLOG(ADNL_WARNING) << this << ": failed to create channel: " << R.move_as_error();
|
||||
}
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessageCreateChannel &message) {
|
||||
create_channel(message.key(), message.date());
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessageConfirmChannel &message) {
|
||||
if (message.peer_key() != channel_pub_) {
|
||||
VLOG(ADNL_NOTICE) << this << ": received adnl.message.confirmChannel with bad peer_key";
|
||||
return;
|
||||
}
|
||||
create_channel(message.key(), message.date());
|
||||
if (!channel_inited_ || peer_channel_pub_ != message.key()) {
|
||||
VLOG(ADNL_NOTICE) << this << ": received adnl.message.confirmChannel with old key";
|
||||
return;
|
||||
}
|
||||
channel_ready_ = true;
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessageCustom &message) {
|
||||
td::actor::send_closure(local_actor_, &AdnlLocalId::deliver, peer_id_short_, message.data());
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessageNop &message) {
|
||||
// nop
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessageReinit &message) {
|
||||
reinit(message.date());
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessageQuery &message) {
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[SelfId = actor_id(this), query_id = message.query_id()](td::Result<td::BufferSlice> R) {
|
||||
if (R.is_error()) {
|
||||
LOG(WARNING) << "failed to answer query: " << R.move_as_error();
|
||||
} else {
|
||||
auto data = R.move_as_ok();
|
||||
if (data.size() > Adnl::huge_packet_max_size()) {
|
||||
LOG(WARNING) << "dropping too big answer query: size=" << data.size();
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &AdnlPeerPairImpl::send_message,
|
||||
AdnlMessage{adnlmessage::AdnlMessageAnswer{query_id, std::move(data)}});
|
||||
}
|
||||
}
|
||||
});
|
||||
td::actor::send_closure(local_actor_, &AdnlLocalId::deliver_query, peer_id_short_, message.data(), std::move(P));
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessageAnswer &message) {
|
||||
auto Q = out_queries_.find(message.query_id());
|
||||
|
||||
if (Q == out_queries_.end()) {
|
||||
VLOG(ADNL_NOTICE) << this << ": dropping IN answer: unknown query id " << message.query_id();
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.data().size() > Adnl::huge_packet_max_size()) {
|
||||
VLOG(ADNL_NOTICE) << this << ": dropping IN answer: too big answer size";
|
||||
return;
|
||||
}
|
||||
|
||||
td::actor::send_closure_later(Q->second, &AdnlQuery::result, message.data());
|
||||
out_queries_.erase(Q);
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessagePart &message) {
|
||||
auto size = message.total_size();
|
||||
if (size > huge_packet_max_size()) {
|
||||
VLOG(ADNL_WARNING) << this << ": dropping too big huge message: size=" << size;
|
||||
return;
|
||||
}
|
||||
if (message.hash().is_zero()) {
|
||||
VLOG(ADNL_WARNING) << this << ": dropping huge message with zero hash";
|
||||
return;
|
||||
}
|
||||
if (message.hash() != huge_message_hash_) {
|
||||
huge_message_hash_.set_zero();
|
||||
huge_message_.clear();
|
||||
huge_message_offset_ = 0;
|
||||
if (message.offset() == 0) {
|
||||
huge_message_hash_ = message.hash();
|
||||
huge_message_ = td::BufferSlice{size};
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto data = message.data();
|
||||
if (data.size() + message.offset() > size) {
|
||||
VLOG(ADNL_WARNING) << this << ": dropping huge message with bad part";
|
||||
return;
|
||||
}
|
||||
if (size != huge_message_.size()) {
|
||||
VLOG(ADNL_WARNING) << this << ": dropping huge message part with inconsistent size";
|
||||
return;
|
||||
}
|
||||
if (message.offset() == huge_message_offset_) {
|
||||
auto S = huge_message_.as_slice();
|
||||
S.remove_prefix(huge_message_offset_);
|
||||
S.copy_from(data.as_slice());
|
||||
huge_message_offset_ += static_cast<td::uint32>(data.size());
|
||||
|
||||
if (huge_message_offset_ == huge_message_.size()) {
|
||||
//td::actor::send_closure(local_actor_, &AdnlLocalId::deliver, peer_id_short_, std::move(huge_message_));
|
||||
if (sha256_bits256(huge_message_.as_slice()) != huge_message_hash_) {
|
||||
VLOG(ADNL_WARNING) << this << ": dropping huge message: hash mismatch";
|
||||
return;
|
||||
}
|
||||
huge_message_hash_.set_zero();
|
||||
huge_message_offset_ = 0;
|
||||
auto MR = fetch_tl_object<ton_api::adnl_Message>(std::move(huge_message_), true);
|
||||
if (MR.is_error()) {
|
||||
VLOG(ADNL_WARNING) << this << ": dropping huge message part with bad data";
|
||||
return;
|
||||
}
|
||||
auto M = AdnlMessage{MR.move_as_ok()};
|
||||
deliver_message(std::move(M));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::delete_query(AdnlQueryId id) {
|
||||
auto Q = out_queries_.find(id);
|
||||
|
||||
if (Q != out_queries_.end()) {
|
||||
out_queries_.erase(Q);
|
||||
}
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::reinit(td::int32 date) {
|
||||
if (reinit_date_ == 0) {
|
||||
reinit_date_ = date;
|
||||
}
|
||||
if (reinit_date_ < date) {
|
||||
if (channel_inited_) {
|
||||
td::actor::send_closure(peer_table_, &AdnlPeerTable::unregister_channel, channel_in_id_);
|
||||
}
|
||||
|
||||
in_seqno_ = 0;
|
||||
out_seqno_ = 0;
|
||||
ack_seqno_ = 0;
|
||||
recv_seqno_mask_ = 0;
|
||||
|
||||
channel_ready_ = false;
|
||||
channel_inited_ = false;
|
||||
|
||||
peer_recv_addr_list_version_ = 0;
|
||||
|
||||
huge_message_offset_ = 0;
|
||||
huge_message_hash_.set_zero();
|
||||
huge_message_.clear();
|
||||
|
||||
channel_.release();
|
||||
|
||||
reinit_date_ = date;
|
||||
}
|
||||
}
|
||||
|
||||
td::Result<td::actor::ActorId<AdnlNetworkConnection>> AdnlPeerPairImpl::get_conn() {
|
||||
if (!priority_addr_list_.empty() && priority_addr_list_.expire_at() < td::Clocks::system()) {
|
||||
priority_addr_list_ = AdnlAddressList{};
|
||||
priority_conns_.clear();
|
||||
}
|
||||
|
||||
if (conns_.size() == 0 && priority_conns_.size() == 0) {
|
||||
return td::Status::Error(ErrorCode::notready, PSTRING()
|
||||
<< "empty network information: version=" << addr_list_.version()
|
||||
<< " reinit_date=" << addr_list_.reinit_date()
|
||||
<< " real_reinit_date=" << reinit_date_);
|
||||
}
|
||||
|
||||
for (auto &conn : priority_conns_) {
|
||||
if (conn.ready()) {
|
||||
return conn.conn.get();
|
||||
}
|
||||
}
|
||||
for (auto &conn : conns_) {
|
||||
if (conn.ready()) {
|
||||
return conn.conn.get();
|
||||
}
|
||||
}
|
||||
return td::Status::Error(ErrorCode::notready, "no active connections");
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::update_addr_list(AdnlAddressList addr_list) {
|
||||
if (addr_list.empty()) {
|
||||
return;
|
||||
}
|
||||
CHECK(addr_list.size() > 0);
|
||||
|
||||
if (addr_list.reinit_date() > td::Clocks::system() + 60) {
|
||||
VLOG(ADNL_WARNING) << "dropping addr list with too new reinit date";
|
||||
return;
|
||||
}
|
||||
|
||||
if (addr_list.reinit_date() > reinit_date_) {
|
||||
reinit(addr_list.reinit_date());
|
||||
} else if (addr_list.reinit_date() < reinit_date_) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool priority = addr_list.priority() > 0;
|
||||
|
||||
if ((priority ? priority_addr_list_ : addr_list_).version() >= addr_list.version()) {
|
||||
if (priority && priority_addr_list_.version() == addr_list.version()) {
|
||||
auto expire_at = addr_list.expire_at();
|
||||
if (expire_at > priority_addr_list_.expire_at()) {
|
||||
priority_addr_list_.set_expire_at(expire_at);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VLOG(ADNL_INFO) << this << ": updating addr list to version " << addr_list.version() << " size=" << addr_list.size();
|
||||
|
||||
const auto addrs = addr_list.addrs();
|
||||
std::vector<Conn> conns;
|
||||
conns.resize(std::min(addr_list.size(), 3u));
|
||||
auto &old_conns = priority ? priority_conns_ : conns_;
|
||||
|
||||
for (size_t i = 0; i < conns.size(); i++) {
|
||||
auto &addr = addrs[i];
|
||||
auto hash = addr->get_hash();
|
||||
if (i < old_conns.size() && old_conns[i].addr->get_hash() == hash) {
|
||||
conns[i] = std::move(old_conns[i]);
|
||||
} else {
|
||||
conns[i] = Conn{addr, actor_id(this), network_manager_};
|
||||
}
|
||||
}
|
||||
|
||||
old_conns = std::move(conns);
|
||||
(priority ? priority_addr_list_ : addr_list_) = addr_list;
|
||||
}
|
||||
|
||||
void AdnlPeerImpl::update_id(AdnlNodeIdFull id) {
|
||||
CHECK(id.compute_short_id() == peer_id_short_);
|
||||
if (!peer_id_.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
peer_id_ = std::move(id);
|
||||
|
||||
for (auto &it : peer_pairs_) {
|
||||
td::actor::send_closure(it.second.get(), &AdnlPeerPair::update_peer_id, peer_id_);
|
||||
}
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::Conn::create_conn(td::actor::ActorId<AdnlPeerPairImpl> peer,
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager) {
|
||||
auto id = addr->get_hash();
|
||||
|
||||
conn = addr->create_connection(network_manager, std::make_unique<ConnCallback>(peer, id));
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::conn_change_state(AdnlConnectionIdShort id, bool ready) {
|
||||
if (ready) {
|
||||
if (pending_messages_.size() > 0) {
|
||||
send_messages_in(std::move(pending_messages_), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
td::actor::ActorOwn<AdnlPeerPair> AdnlPeerPair::create(td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
td::actor::ActorId<AdnlPeerTable> peer_table,
|
||||
td::actor::ActorId<AdnlLocalId> local_actor,
|
||||
td::actor::ActorId<AdnlPeer> peer_actor,
|
||||
td::actor::ActorId<dht::Dht> dht_node, AdnlNodeIdShort local_id,
|
||||
AdnlNodeIdShort peer_id) {
|
||||
auto X = td::actor::create_actor<AdnlPeerPairImpl>("peerpair", network_manager, peer_table, local_actor, peer_actor,
|
||||
dht_node, local_id, peer_id);
|
||||
return td::actor::ActorOwn<AdnlPeerPair>(std::move(X));
|
||||
}
|
||||
|
||||
td::actor::ActorOwn<AdnlPeer> AdnlPeer::create(td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
td::actor::ActorId<AdnlPeerTable> peer_table,
|
||||
td::actor::ActorId<dht::Dht> dht_node, AdnlNodeIdShort peer_id) {
|
||||
auto X = td::actor::create_actor<AdnlPeerImpl>("peer", network_manager, peer_table, dht_node, peer_id);
|
||||
return td::actor::ActorOwn<AdnlPeer>(std::move(X));
|
||||
}
|
||||
|
||||
void AdnlPeerImpl::receive_packet(AdnlNodeIdShort dst, td::actor::ActorId<AdnlLocalId> dst_actor, AdnlPacket packet) {
|
||||
if (packet.inited_from()) {
|
||||
update_id(packet.from());
|
||||
}
|
||||
|
||||
auto it = peer_pairs_.find(dst);
|
||||
if (it == peer_pairs_.end()) {
|
||||
auto X =
|
||||
AdnlPeerPair::create(network_manager_, peer_table_, dst_actor, actor_id(this), dht_node_, dst, peer_id_short_);
|
||||
peer_pairs_.emplace(dst, std::move(X));
|
||||
it = peer_pairs_.find(dst);
|
||||
CHECK(it != peer_pairs_.end());
|
||||
|
||||
if (!peer_id_.empty()) {
|
||||
td::actor::send_closure(it->second.get(), &AdnlPeerPair::update_peer_id, peer_id_);
|
||||
}
|
||||
}
|
||||
|
||||
td::actor::send_closure(it->second.get(), &AdnlPeerPair::receive_packet_checked, std::move(packet));
|
||||
}
|
||||
|
||||
void AdnlPeerImpl::send_messages(AdnlNodeIdShort src, td::actor::ActorId<AdnlLocalId> src_actor,
|
||||
std::vector<AdnlMessage> messages) {
|
||||
auto it = peer_pairs_.find(src);
|
||||
if (it == peer_pairs_.end()) {
|
||||
auto X =
|
||||
AdnlPeerPair::create(network_manager_, peer_table_, src_actor, actor_id(this), dht_node_, src, peer_id_short_);
|
||||
peer_pairs_.emplace(src, std::move(X));
|
||||
it = peer_pairs_.find(src);
|
||||
CHECK(it != peer_pairs_.end());
|
||||
|
||||
if (!peer_id_.empty()) {
|
||||
td::actor::send_closure(it->second.get(), &AdnlPeerPair::update_peer_id, peer_id_);
|
||||
}
|
||||
}
|
||||
|
||||
td::actor::send_closure(it->second, &AdnlPeerPair::send_messages, std::move(messages));
|
||||
}
|
||||
|
||||
void AdnlPeerImpl::send_query(AdnlNodeIdShort src, td::actor::ActorId<AdnlLocalId> src_actor, std::string name,
|
||||
td::Promise<td::BufferSlice> promise, td::Timestamp timeout, td::BufferSlice data) {
|
||||
auto it = peer_pairs_.find(src);
|
||||
if (it == peer_pairs_.end()) {
|
||||
auto X =
|
||||
AdnlPeerPair::create(network_manager_, peer_table_, src_actor, actor_id(this), dht_node_, src, peer_id_short_);
|
||||
peer_pairs_.emplace(src, std::move(X));
|
||||
it = peer_pairs_.find(src);
|
||||
CHECK(it != peer_pairs_.end());
|
||||
|
||||
if (!peer_id_.empty()) {
|
||||
td::actor::send_closure(it->second.get(), &AdnlPeerPair::update_peer_id, peer_id_);
|
||||
}
|
||||
}
|
||||
|
||||
td::actor::send_closure(it->second, &AdnlPeerPair::send_query, name, std::move(promise), timeout, std::move(data));
|
||||
}
|
||||
|
||||
void AdnlPeerImpl::del_local_id(AdnlNodeIdShort local_id) {
|
||||
peer_pairs_.erase(local_id);
|
||||
}
|
||||
|
||||
void AdnlPeerImpl::update_dht_node(td::actor::ActorId<dht::Dht> dht_node) {
|
||||
dht_node_ = dht_node;
|
||||
for (auto it = peer_pairs_.begin(); it != peer_pairs_.end(); it++) {
|
||||
td::actor::send_closure(it->second, &AdnlPeerPair::update_dht_node, dht_node_);
|
||||
}
|
||||
}
|
||||
|
||||
void AdnlPeerImpl::update_addr_list(AdnlNodeIdShort local_id, td::actor::ActorId<AdnlLocalId> local_actor,
|
||||
AdnlAddressList addr_list) {
|
||||
auto it = peer_pairs_.find(local_id);
|
||||
if (it == peer_pairs_.end()) {
|
||||
auto X = AdnlPeerPair::create(network_manager_, peer_table_, local_actor, actor_id(this), dht_node_, local_id,
|
||||
peer_id_short_);
|
||||
peer_pairs_.emplace(local_id, std::move(X));
|
||||
it = peer_pairs_.find(local_id);
|
||||
CHECK(it != peer_pairs_.end());
|
||||
|
||||
if (!peer_id_.empty()) {
|
||||
td::actor::send_closure(it->second.get(), &AdnlPeerPair::update_peer_id, peer_id_);
|
||||
}
|
||||
}
|
||||
|
||||
td::actor::send_closure(it->second, &AdnlPeerPair::update_addr_list, std::move(addr_list));
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::got_data_from_db(td::Result<AdnlDbItem> R) {
|
||||
received_from_db_ = false;
|
||||
if (R.is_error()) {
|
||||
return;
|
||||
}
|
||||
auto value = R.move_as_ok();
|
||||
if (!value.id.empty()) {
|
||||
update_peer_id(value.id);
|
||||
}
|
||||
update_addr_list(value.addr_list);
|
||||
update_addr_list(value.priority_addr_list);
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::got_data_from_static_nodes(td::Result<AdnlNode> R) {
|
||||
received_from_static_nodes_ = false;
|
||||
if (R.is_error()) {
|
||||
return;
|
||||
}
|
||||
auto value = R.move_as_ok();
|
||||
if (!value.pub_id().empty()) {
|
||||
update_peer_id(value.pub_id());
|
||||
}
|
||||
update_addr_list(value.addr_list());
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::got_data_from_dht(td::Result<AdnlNode> R) {
|
||||
CHECK(dht_query_active_);
|
||||
dht_query_active_ = false;
|
||||
next_dht_query_at_ = td::Timestamp::in(td::Random::fast(60.0, 120.0));
|
||||
if (R.is_error()) {
|
||||
VLOG(ADNL_INFO) << this << ": dht query failed: " << R.move_as_error();
|
||||
return;
|
||||
}
|
||||
auto value = R.move_as_ok();
|
||||
if (!value.pub_id().empty()) {
|
||||
update_peer_id(value.pub_id());
|
||||
}
|
||||
update_addr_list(value.addr_list());
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::update_peer_id(AdnlNodeIdFull id) {
|
||||
if (peer_id_.empty()) {
|
||||
peer_id_ = std::move(id);
|
||||
auto R = peer_id_.pubkey().create_encryptor();
|
||||
if (R.is_ok()) {
|
||||
encryptor_ = R.move_as_ok();
|
||||
} else {
|
||||
VLOG(ADNL_WARNING) << this << ": failed to create encryptor: " << R.move_as_error();
|
||||
}
|
||||
}
|
||||
CHECK(!peer_id_.empty());
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
101
adnl/adnl-peer.h
Normal file
101
adnl/adnl-peer.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/utils/BufferedUdp.h"
|
||||
|
||||
#include "dht/dht.h"
|
||||
#include "adnl-peer-table.h"
|
||||
#include "utils.hpp"
|
||||
#include "auto/tl/ton_api.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlPeerTable;
|
||||
class AdnlNetworkManager;
|
||||
class AdnlLocalId;
|
||||
class AdnlNetworkConnection;
|
||||
|
||||
class AdnlPeer;
|
||||
|
||||
class AdnlPeerPair : public td::actor::Actor {
|
||||
public:
|
||||
virtual void receive_packet_from_channel(AdnlChannelIdShort id, AdnlPacket packet) = 0;
|
||||
virtual void receive_packet_checked(AdnlPacket packet) = 0;
|
||||
virtual void receive_packet(AdnlPacket packet) = 0;
|
||||
|
||||
virtual void send_messages(std::vector<AdnlMessage> message) = 0;
|
||||
inline void send_message(AdnlMessage message) {
|
||||
std::vector<AdnlMessage> vec;
|
||||
vec.push_back(std::move(message));
|
||||
send_messages(std::move(vec));
|
||||
}
|
||||
static constexpr td::uint32 get_mtu() {
|
||||
return Adnl::get_mtu() + 128;
|
||||
}
|
||||
virtual void send_query(std::string name, td::Promise<td::BufferSlice> promise, td::Timestamp timeout,
|
||||
td::BufferSlice data) = 0;
|
||||
virtual void alarm_query(AdnlQueryId query_id) = 0;
|
||||
virtual void update_dht_node(td::actor::ActorId<dht::Dht> dht_node) = 0;
|
||||
virtual void update_peer_id(AdnlNodeIdFull id) = 0;
|
||||
virtual void update_addr_list(AdnlAddressList addr_list) = 0;
|
||||
|
||||
static td::actor::ActorOwn<AdnlPeerPair> create(td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
td::actor::ActorId<AdnlPeerTable> peer_table,
|
||||
td::actor::ActorId<AdnlLocalId> local_actor,
|
||||
td::actor::ActorId<AdnlPeer> peer_actor,
|
||||
td::actor::ActorId<dht::Dht> dht_node, AdnlNodeIdShort local_id,
|
||||
AdnlNodeIdShort peer_id);
|
||||
};
|
||||
|
||||
class AdnlPeer : public td::actor::Actor {
|
||||
public:
|
||||
virtual void receive_packet(AdnlNodeIdShort dst, td::actor::ActorId<AdnlLocalId> dst_actor, AdnlPacket message) = 0;
|
||||
virtual void send_messages(AdnlNodeIdShort src, td::actor::ActorId<AdnlLocalId> src_actor,
|
||||
std::vector<AdnlMessage> messages) = 0;
|
||||
virtual void send_query(AdnlNodeIdShort src, td::actor::ActorId<AdnlLocalId> src_actor, std::string name,
|
||||
td::Promise<td::BufferSlice> promise, td::Timestamp timeout, td::BufferSlice data) = 0;
|
||||
void send_one_message(AdnlNodeIdShort src, td::actor::ActorId<AdnlLocalId> src_actor, AdnlMessage message) {
|
||||
std::vector<AdnlMessage> vec;
|
||||
vec.push_back(std::move(message));
|
||||
send_messages(src, src_actor, std::move(vec));
|
||||
}
|
||||
|
||||
void send_message(AdnlNodeIdShort src, td::actor::ActorId<AdnlLocalId> src_actor, td::BufferSlice data) {
|
||||
auto M = AdnlMessage{adnlmessage::AdnlMessageCustom{std::move(data)}};
|
||||
send_one_message(src, src_actor, std::move(M));
|
||||
}
|
||||
|
||||
static td::actor::ActorOwn<AdnlPeer> create(td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
td::actor::ActorId<AdnlPeerTable> peer_table,
|
||||
td::actor::ActorId<dht::Dht> dht_node, AdnlNodeIdShort peer_id);
|
||||
|
||||
virtual void del_local_id(AdnlNodeIdShort local_id) = 0;
|
||||
virtual void update_id(AdnlNodeIdFull id) = 0;
|
||||
virtual void update_addr_list(AdnlNodeIdShort local_id, td::actor::ActorId<AdnlLocalId> local_actor,
|
||||
AdnlAddressList addr_list) = 0;
|
||||
virtual void update_dht_node(td::actor::ActorId<dht::Dht> dht_node) = 0;
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
318
adnl/adnl-peer.hpp
Normal file
318
adnl/adnl-peer.hpp
Normal file
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "adnl-peer.h"
|
||||
#include "adnl-peer-table.h"
|
||||
#include "adnl-network-manager.h"
|
||||
#include "keys/encryptor.h"
|
||||
#include "adnl-channel.h"
|
||||
#include "adnl-query.h"
|
||||
|
||||
#include "crypto/Ed25519.h"
|
||||
#include "td/utils/DecTree.h"
|
||||
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
using AdnlConnectionIdShort = AdnlAddressImpl::Hash;
|
||||
|
||||
class AdnlPeerPairImpl : public AdnlPeerPair {
|
||||
public:
|
||||
static constexpr td::uint32 packet_header_max_size() {
|
||||
return 272;
|
||||
}
|
||||
static constexpr td::uint32 channel_packet_header_max_size() {
|
||||
return 128;
|
||||
}
|
||||
static constexpr td::uint32 addr_list_max_size() {
|
||||
return 128;
|
||||
}
|
||||
static constexpr td::uint32 get_mtu() {
|
||||
return Adnl::get_mtu() + 128;
|
||||
}
|
||||
static constexpr td::uint32 huge_packet_max_size() {
|
||||
return Adnl::huge_packet_max_size() + 128;
|
||||
}
|
||||
|
||||
AdnlPeerPairImpl(td::actor::ActorId<AdnlNetworkManager> network_manager, td::actor::ActorId<AdnlPeerTable> peer_table,
|
||||
td::actor::ActorId<AdnlLocalId> local_actor, td::actor::ActorId<AdnlPeer> peer,
|
||||
td::actor::ActorId<dht::Dht> dht_node, AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id);
|
||||
void start_up() override;
|
||||
void alarm() override;
|
||||
|
||||
void discover();
|
||||
|
||||
void receive_packet_from_channel(AdnlChannelIdShort id, AdnlPacket packet) override;
|
||||
void receive_packet_checked(AdnlPacket packet) override;
|
||||
void receive_packet(AdnlPacket packet) override;
|
||||
void deliver_message(AdnlMessage message);
|
||||
|
||||
void send_messages_in(std::vector<AdnlMessage> messages, bool allow_postpone);
|
||||
void send_messages(std::vector<AdnlMessage> messages) override;
|
||||
void send_packet_continue(AdnlPacket packet, td::actor::ActorId<AdnlNetworkConnection> conn, bool via_channel);
|
||||
void send_query(std::string name, td::Promise<td::BufferSlice> promise, td::Timestamp timeout,
|
||||
td::BufferSlice data) override;
|
||||
|
||||
void alarm_query(AdnlQueryId id) override;
|
||||
|
||||
void discover_query_result(td::Result<dht::DhtValue> B, bool dummy);
|
||||
|
||||
void update_dht_node(td::actor::ActorId<dht::Dht> dht_node) override {
|
||||
dht_node_ = dht_node;
|
||||
}
|
||||
|
||||
void update_addr_list(AdnlAddressList addr_list) override;
|
||||
void update_peer_id(AdnlNodeIdFull id) override;
|
||||
|
||||
void got_data_from_db(td::Result<AdnlDbItem> R);
|
||||
void got_data_from_static_nodes(td::Result<AdnlNode> R);
|
||||
void got_data_from_dht(td::Result<AdnlNode> R);
|
||||
|
||||
//void conn_ready(AdnlConnectionIdShort id, td::Result<td::actor::ActorOwn<AdnlNetworkConnection>> R);
|
||||
|
||||
void process_message(const adnlmessage::AdnlMessageCreateChannel &message);
|
||||
void process_message(const adnlmessage::AdnlMessageConfirmChannel &message);
|
||||
void process_message(const adnlmessage::AdnlMessageCustom &message);
|
||||
void process_message(const adnlmessage::AdnlMessageNop &message);
|
||||
void process_message(const adnlmessage::AdnlMessageReinit &message);
|
||||
void process_message(const adnlmessage::AdnlMessageQuery &message);
|
||||
void process_message(const adnlmessage::AdnlMessageAnswer &message);
|
||||
void process_message(const adnlmessage::AdnlMessagePart &message);
|
||||
void process_message(const AdnlMessage::Empty &message) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void conn_change_state(AdnlConnectionIdShort conn_id, bool ready);
|
||||
|
||||
void delete_query(AdnlQueryId id);
|
||||
|
||||
struct PrintId {
|
||||
AdnlNodeIdShort peer_id;
|
||||
AdnlNodeIdShort local_id;
|
||||
};
|
||||
|
||||
PrintId print_id() const {
|
||||
return PrintId{peer_id_short_, local_id_};
|
||||
}
|
||||
|
||||
private:
|
||||
void reinit(td::int32 date);
|
||||
td::Result<td::actor::ActorId<AdnlNetworkConnection>> get_conn();
|
||||
void create_channel(pubkeys::Ed25519 pub, td::uint32 date);
|
||||
|
||||
bool received_packet(td::uint32 seqno) const {
|
||||
CHECK(seqno > 0);
|
||||
if (seqno + 64 <= in_seqno_) {
|
||||
return true;
|
||||
}
|
||||
if (seqno > in_seqno_) {
|
||||
return false;
|
||||
}
|
||||
return recv_seqno_mask_ & (1ull << (in_seqno_ - seqno));
|
||||
}
|
||||
|
||||
void add_received_packet(td::uint32 seqno) {
|
||||
CHECK(!received_packet(seqno));
|
||||
if (seqno <= in_seqno_) {
|
||||
recv_seqno_mask_ |= (1ull << (in_seqno_ - seqno));
|
||||
} else {
|
||||
auto old = in_seqno_;
|
||||
in_seqno_ = seqno;
|
||||
if (in_seqno_ - old >= 64) {
|
||||
recv_seqno_mask_ = 1;
|
||||
} else {
|
||||
recv_seqno_mask_ = recv_seqno_mask_ << (in_seqno_ - old);
|
||||
recv_seqno_mask_ |= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Conn {
|
||||
class ConnCallback : public AdnlNetworkConnection::Callback {
|
||||
public:
|
||||
void on_change_state(bool ready) override {
|
||||
td::actor::send_closure(root_, &AdnlPeerPairImpl::conn_change_state, conn_id_, ready);
|
||||
}
|
||||
ConnCallback(td::actor::ActorId<AdnlPeerPairImpl> root, AdnlConnectionIdShort conn_id)
|
||||
: root_(root), conn_id_(conn_id) {
|
||||
}
|
||||
|
||||
private:
|
||||
td::actor::ActorId<AdnlPeerPairImpl> root_;
|
||||
AdnlConnectionIdShort conn_id_;
|
||||
};
|
||||
|
||||
AdnlAddress addr;
|
||||
td::actor::ActorOwn<AdnlNetworkConnection> conn;
|
||||
|
||||
Conn(AdnlAddress addr, td::actor::ActorId<AdnlPeerPairImpl> peer,
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager)
|
||||
: addr(std::move(addr)) {
|
||||
create_conn(peer, network_manager);
|
||||
}
|
||||
Conn() {
|
||||
}
|
||||
|
||||
bool ready() {
|
||||
return !conn.empty() && conn.get_actor_unsafe().is_active();
|
||||
}
|
||||
|
||||
void create_conn(td::actor::ActorId<AdnlPeerPairImpl> peer, td::actor::ActorId<AdnlNetworkManager> network_manager);
|
||||
};
|
||||
|
||||
std::vector<AdnlMessage> pending_messages_;
|
||||
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager_;
|
||||
td::actor::ActorId<AdnlPeerTable> peer_table_;
|
||||
td::actor::ActorId<AdnlLocalId> local_actor_;
|
||||
td::actor::ActorId<AdnlPeer> peer_;
|
||||
td::actor::ActorId<dht::Dht> dht_node_;
|
||||
|
||||
td::uint32 priority_ = 0;
|
||||
|
||||
td::int32 reinit_date_ = 0;
|
||||
|
||||
bool channel_ready_ = false;
|
||||
bool channel_inited_ = false;
|
||||
AdnlChannelIdShort channel_in_id_;
|
||||
AdnlChannelIdShort channel_out_id_;
|
||||
privkeys::Ed25519 channel_pk_;
|
||||
pubkeys::Ed25519 channel_pub_;
|
||||
td::int32 channel_pk_date_;
|
||||
td::actor::ActorOwn<AdnlChannel> channel_;
|
||||
|
||||
td::uint64 in_seqno_ = 0;
|
||||
td::uint64 out_seqno_ = 0;
|
||||
td::uint64 ack_seqno_ = 0;
|
||||
td::uint64 recv_seqno_mask_ = 0;
|
||||
|
||||
td::uint32 peer_channel_date_ = 0;
|
||||
pubkeys::Ed25519 peer_channel_pub_;
|
||||
td::int32 peer_recv_addr_list_version_ = -1;
|
||||
td::int32 peer_recv_priority_addr_list_version_ = -1;
|
||||
|
||||
td::Bits256 huge_message_hash_ = td::Bits256::zero();
|
||||
td::BufferSlice huge_message_;
|
||||
td::uint32 huge_message_offset_ = 0;
|
||||
|
||||
AdnlAddressList addr_list_;
|
||||
AdnlAddressList priority_addr_list_;
|
||||
|
||||
std::vector<Conn> conns_;
|
||||
std::vector<Conn> priority_conns_;
|
||||
|
||||
AdnlNodeIdFull peer_id_;
|
||||
AdnlNodeIdShort peer_id_short_;
|
||||
AdnlNodeIdShort local_id_;
|
||||
|
||||
std::unique_ptr<Encryptor> encryptor_;
|
||||
|
||||
std::map<AdnlQueryId, td::actor::ActorId<AdnlQuery>> out_queries_;
|
||||
|
||||
td::uint32 received_messages_ = 0;
|
||||
bool received_from_db_ = false;
|
||||
bool received_from_static_nodes_ = false;
|
||||
bool dht_query_active_ = false;
|
||||
|
||||
td::Timestamp next_dht_query_at_ = td::Timestamp::never();
|
||||
td::Timestamp next_db_update_at_ = td::Timestamp::never();
|
||||
td::Timestamp retry_send_at_ = td::Timestamp::never();
|
||||
};
|
||||
|
||||
class AdnlPeerImpl : public AdnlPeer {
|
||||
public:
|
||||
void receive_packet(AdnlNodeIdShort dst, td::actor::ActorId<AdnlLocalId> dst_actor, AdnlPacket packet) override;
|
||||
void send_messages(AdnlNodeIdShort src, td::actor::ActorId<AdnlLocalId> src_actor,
|
||||
std::vector<AdnlMessage> messages) override;
|
||||
void send_query(AdnlNodeIdShort src, td::actor::ActorId<AdnlLocalId> src_actor, std::string name,
|
||||
td::Promise<td::BufferSlice> promise, td::Timestamp timeout, td::BufferSlice data) override;
|
||||
|
||||
void del_local_id(AdnlNodeIdShort local_id) override;
|
||||
void update_id(AdnlNodeIdFull id) override;
|
||||
void update_addr_list(AdnlNodeIdShort local_id, td::actor::ActorId<AdnlLocalId> local_actor,
|
||||
AdnlAddressList addr_list) override;
|
||||
void update_dht_node(td::actor::ActorId<dht::Dht> dht_node) override;
|
||||
//void check_signature(td::BufferSlice data, td::BufferSlice signature, td::Promise<td::Unit> promise) override;
|
||||
|
||||
AdnlPeerImpl(td::actor::ActorId<AdnlNetworkManager> network_manager, td::actor::ActorId<AdnlPeerTable> peer_table,
|
||||
td::actor::ActorId<dht::Dht> dht_node, AdnlNodeIdShort peer_id)
|
||||
: peer_id_short_(peer_id), dht_node_(dht_node), peer_table_(peer_table), network_manager_(network_manager) {
|
||||
}
|
||||
|
||||
struct PrintId {
|
||||
AdnlNodeIdShort peer_id;
|
||||
};
|
||||
|
||||
PrintId print_id() const {
|
||||
return PrintId{peer_id_short_};
|
||||
}
|
||||
|
||||
private:
|
||||
AdnlNodeIdShort peer_id_short_;
|
||||
AdnlNodeIdFull peer_id_;
|
||||
std::map<AdnlNodeIdShort, td::actor::ActorOwn<AdnlPeerPair>> peer_pairs_;
|
||||
td::actor::ActorId<dht::Dht> dht_node_;
|
||||
td::actor::ActorId<AdnlPeerTable> peer_table_;
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager_;
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
||||
|
||||
namespace td {
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlPeerImpl::PrintId &id) {
|
||||
sb << "[peer " << id.peer_id << "]";
|
||||
return sb;
|
||||
}
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlPeerImpl &peer) {
|
||||
sb << peer.print_id();
|
||||
return sb;
|
||||
}
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlPeerImpl *peer) {
|
||||
sb << peer->print_id();
|
||||
return sb;
|
||||
}
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlPeerPairImpl::PrintId &id) {
|
||||
sb << "[peerpair " << id.peer_id << "-" << id.local_id << "]";
|
||||
return sb;
|
||||
}
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlPeerPairImpl &peer) {
|
||||
sb << peer.print_id();
|
||||
return sb;
|
||||
}
|
||||
|
||||
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const ton::adnl::AdnlPeerPairImpl *peer) {
|
||||
sb << peer->print_id();
|
||||
return sb;
|
||||
}
|
||||
|
||||
} // namespace td
|
87
adnl/adnl-proxy-types.cpp
Normal file
87
adnl/adnl-proxy-types.cpp
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "adnl-proxy-types.hpp"
|
||||
#include "tl-utils/tl-utils.hpp"
|
||||
#include "auto/tl/ton_api.hpp"
|
||||
#include "td/utils/overloaded.h"
|
||||
#include "td/utils/Time.h"
|
||||
#include "common/errorcode.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
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());
|
||||
S.remove_prefix(32);
|
||||
S.copy_from(obj.as_slice());
|
||||
S.remove_prefix(obj.size());
|
||||
S.copy_from(packet.data.as_slice());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
td::Result<AdnlProxy::Packet> AdnlProxyFast::decrypt(td::BufferSlice packet) const {
|
||||
if (packet.size() < 36) {
|
||||
return td::Status::Error(ErrorCode::protoviolation, "too short packet");
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
TRY_RESULT(R, fetch_tl_prefix<ton_api::adnl_proxyToFast>(packet, true));
|
||||
|
||||
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_) {
|
||||
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)};
|
||||
}
|
||||
|
||||
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>(); },
|
||||
[&](const ton_api::adnl_proxy_fast &x) {
|
||||
R = std::make_shared<AdnlProxyFast>(x.shared_secret_.as_slice());
|
||||
}));
|
||||
return R;
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
45
adnl/adnl-proxy-types.h
Normal file
45
adnl/adnl-proxy-types.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "td/utils/buffer.h"
|
||||
#include "auto/tl/ton_api.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlProxy {
|
||||
public:
|
||||
struct Packet {
|
||||
td::uint32 ip;
|
||||
td::uint16 port;
|
||||
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;
|
||||
|
||||
static td::Result<std::shared_ptr<AdnlProxy>> create(const ton_api::adnl_Proxy &proxy_type);
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
62
adnl/adnl-proxy-types.hpp
Normal file
62
adnl/adnl-proxy-types.hpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "adnl-proxy-types.h"
|
||||
|
||||
#include "common/checksum.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlProxyNone : public AdnlProxy {
|
||||
public:
|
||||
AdnlProxyNone() {
|
||||
}
|
||||
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)};
|
||||
}
|
||||
tl_object_ptr<ton_api::adnl_Proxy> tl() const override {
|
||||
return create_tl_object<ton_api::adnl_proxy_none>();
|
||||
}
|
||||
};
|
||||
|
||||
class AdnlProxyFast : public AdnlProxy {
|
||||
public:
|
||||
AdnlProxyFast(td::Slice shared_secret)
|
||||
: 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());
|
||||
}
|
||||
|
||||
private:
|
||||
td::Bits256 shared_secret_;
|
||||
td::SharedSlice shared_secret_raw_;
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
265
adnl/adnl-proxy.cpp
Normal file
265
adnl/adnl-proxy.cpp
Normal file
|
@ -0,0 +1,265 @@
|
|||
/*
|
||||
This file is part of TON Blockchain source code.
|
||||
|
||||
TON Blockchain is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
TON Blockchain is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with TON Blockchain. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
You must obey the GNU General Public License in all respects for all
|
||||
of the code used other than OpenSSL. If you modify file(s) with this
|
||||
exception, you may extend this exception to your version of the file(s),
|
||||
but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
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
|
||||
*/
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/port/IPAddress.h"
|
||||
#include "td/net/UdpServer.h"
|
||||
#include "td/utils/port/signals.h"
|
||||
#include "td/utils/OptionsParser.h"
|
||||
#include "td/utils/FileLog.h"
|
||||
#include "td/utils/port/path.h"
|
||||
#include "td/utils/port/user.h"
|
||||
#include "td/utils/filesystem.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 <map>
|
||||
|
||||
#if TD_DARWIN || TD_LINUX
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
}
|
||||
|
||||
private:
|
||||
td::uint16 in_port_;
|
||||
td::uint16 out_port_;
|
||||
std::shared_ptr<ton::adnl::AdnlProxy> proxy_;
|
||||
td::IPAddress addr_;
|
||||
td::actor::ActorOwn<td::UdpServer> out_udp_server_;
|
||||
td::actor::ActorOwn<td::UdpServer> in_udp_server_;
|
||||
};
|
||||
|
||||
void Receiver::start_up() {
|
||||
class Callback : public td::UdpServer::Callback {
|
||||
public:
|
||||
Callback(td::actor::ActorId<Receiver> manager, td::uint32 mode) : manager_(std::move(manager)), mode_(mode) {
|
||||
}
|
||||
|
||||
private:
|
||||
td::actor::ActorId<Receiver> manager_;
|
||||
const td::uint32 mode_;
|
||||
void on_udp_message(td::UdpMessage udp_message) override {
|
||||
if (udp_message.error.is_error()) {
|
||||
LOG(DEBUG) << udp_message.error;
|
||||
return;
|
||||
}
|
||||
if (mode_ == 0) {
|
||||
td::actor::send_closure_later(manager_, &Receiver::receive_common, std::move(udp_message.data));
|
||||
} else if (mode_ == 1) {
|
||||
td::actor::send_closure_later(manager_, &Receiver::receive_from_client, std::move(udp_message.data));
|
||||
} else {
|
||||
td::actor::send_closure_later(manager_, &Receiver::receive_to_client, std::move(udp_message.data));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (in_port_ == out_port_) {
|
||||
auto X = td::UdpServer::create("udp server", in_port_, std::make_unique<Callback>(actor_id(this), 0));
|
||||
X.ensure();
|
||||
in_udp_server_ = X.move_as_ok();
|
||||
} else {
|
||||
auto X = td::UdpServer::create("udp server", in_port_, std::make_unique<Callback>(actor_id(this), 1));
|
||||
X.ensure();
|
||||
in_udp_server_ = X.move_as_ok();
|
||||
X = td::UdpServer::create("udp server", out_port_, std::make_unique<Callback>(actor_id(this), 2));
|
||||
X.ensure();
|
||||
out_udp_server_ = X.move_as_ok();
|
||||
}
|
||||
}
|
||||
|
||||
void Receiver::receive_common(td::BufferSlice data) {
|
||||
if (data.size() <= 32) {
|
||||
return;
|
||||
}
|
||||
|
||||
td::Bits256 id;
|
||||
id.as_slice().copy_from(data.as_slice().truncate(32));
|
||||
|
||||
if (id.is_zero()) {
|
||||
receive_from_client(std::move(data));
|
||||
} else {
|
||||
receive_to_client(std::move(data));
|
||||
}
|
||||
}
|
||||
|
||||
void Receiver::receive_from_client(td::BufferSlice data) {
|
||||
auto F = proxy_->decrypt(std::move(data));
|
||||
if (F.is_error()) {
|
||||
return;
|
||||
}
|
||||
auto f = F.move_as_ok();
|
||||
|
||||
td::IPAddress a;
|
||||
if (a.init_ipv4_port(td::IPAddress::ipv4_to_str(f.ip), f.port).is_error()) {
|
||||
return;
|
||||
}
|
||||
|
||||
td::UdpMessage M;
|
||||
M.address = a;
|
||||
M.data = std::move(f.data);
|
||||
|
||||
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) {
|
||||
LOG(DEBUG) << "proxying to " << addr_;
|
||||
td::UdpMessage M;
|
||||
M.address = addr_;
|
||||
M.data = std::move(data);
|
||||
|
||||
td::actor::send_closure(in_udp_server_.empty() ? out_udp_server_.get() : in_udp_server_.get(), &td::UdpServer::send,
|
||||
std::move(M));
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
SET_VERBOSITY_LEVEL(verbosity_INFO);
|
||||
|
||||
td::set_default_failure_signal_handler().ensure();
|
||||
|
||||
std::vector<td::actor::ActorOwn<ton::adnl::Receiver>> x;
|
||||
std::unique_ptr<td::LogInterface> logger_;
|
||||
SCOPE_EXIT {
|
||||
td::log_interface = td::default_log_interface;
|
||||
};
|
||||
|
||||
std::string config = "/var/ton-work/etc/adnl-proxy.conf.json";
|
||||
|
||||
td::OptionsParser p;
|
||||
p.set_description("validator or full node for TON network");
|
||||
p.add_option('v', "verbosity", "set verbosity level", [&](td::Slice arg) {
|
||||
int v = VERBOSITY_NAME(FATAL) + (td::to_integer<int>(arg));
|
||||
SET_VERBOSITY_LEVEL(v);
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('h', "help", "prints_help", [&]() {
|
||||
char b[10240];
|
||||
td::StringBuilder sb(td::MutableSlice{b, 10000});
|
||||
sb << p;
|
||||
std::cout << sb.as_cslice().c_str();
|
||||
std::exit(2);
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('c', "config", "config file", [&](td::Slice arg) {
|
||||
config = arg.str();
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('d', "daemonize", "set SIGHUP", [&]() {
|
||||
td::set_signal_handler(td::SignalType::HangUp, [](int sig) {
|
||||
#if TD_DARWIN || TD_LINUX
|
||||
close(0);
|
||||
setsid();
|
||||
#endif
|
||||
}).ensure();
|
||||
return td::Status::OK();
|
||||
});
|
||||
#if TD_DARWIN || TD_LINUX
|
||||
p.add_option('l', "logname", "log to file", [&](td::Slice fname) {
|
||||
auto F = std::make_unique<td::FileLog>();
|
||||
TRY_STATUS(F->init(fname.str()));
|
||||
logger_ = std::move(F);
|
||||
td::log_interface = logger_.get();
|
||||
return td::Status::OK();
|
||||
});
|
||||
#endif
|
||||
td::uint32 threads = 7;
|
||||
p.add_option('t', "threads", PSTRING() << "number of threads (default=" << threads << ")", [&](td::Slice fname) {
|
||||
td::int32 v;
|
||||
try {
|
||||
v = std::stoi(fname.str());
|
||||
} catch (...) {
|
||||
return td::Status::Error(ton::ErrorCode::error, "bad value for --threads: not a number");
|
||||
}
|
||||
if (v < 1 || v > 256) {
|
||||
return td::Status::Error(ton::ErrorCode::error, "bad value for --threads: should be in range [1..256]");
|
||||
}
|
||||
threads = v;
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('u', "user", "change user", [&](td::Slice user) { return td::change_user(user); });
|
||||
|
||||
p.run(argc, argv).ensure();
|
||||
|
||||
td::actor::Scheduler scheduler({threads});
|
||||
|
||||
auto R = [&]() -> td::Status {
|
||||
TRY_RESULT_PREFIX(conf_data, td::read_file(config), "failed to read: ");
|
||||
TRY_RESULT_PREFIX(conf_json, td::json_decode(conf_data.as_slice()), "failed to parse json: ");
|
||||
|
||||
ton::ton_api::engine_adnlProxy_config conf;
|
||||
TRY_STATUS_PREFIX(ton::ton_api::from_json(conf, conf_json.get_object()), "json does not fit TL scheme: ");
|
||||
|
||||
if (!conf.ports_.size()) {
|
||||
return td::Status::Error("empty config");
|
||||
}
|
||||
|
||||
for (auto &y : conf.ports_) {
|
||||
auto in_port = static_cast<td::uint16>(y->in_port_);
|
||||
auto out_port = static_cast<td::uint16>(y->out_port_);
|
||||
if (!y->proxy_type_) {
|
||||
return td::Status::Error("empty proxy type");
|
||||
}
|
||||
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();
|
||||
|
||||
scheduler.run_in_context([&] {
|
||||
x.push_back(td::actor::create_actor<ton::adnl::Receiver>("adnl-proxy", in_port, out_port, std::move(proxy), a));
|
||||
});
|
||||
}
|
||||
|
||||
return td::Status::OK();
|
||||
}();
|
||||
|
||||
if (R.is_error()) {
|
||||
LOG(FATAL) << "bad config: " << R.move_as_error();
|
||||
}
|
||||
|
||||
while (scheduler.run(1)) {
|
||||
}
|
||||
}
|
44
adnl/adnl-query.cpp
Normal file
44
adnl/adnl-query.cpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "adnl-query.h"
|
||||
#include "common/errorcode.h"
|
||||
#include "td/utils/Random.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
void AdnlQuery::alarm() {
|
||||
promise_.set_error(td::Status::Error(ErrorCode::timeout, "adnl query timeout"));
|
||||
stop();
|
||||
}
|
||||
void AdnlQuery::result(td::BufferSlice data) {
|
||||
promise_.set_value(std::move(data));
|
||||
stop();
|
||||
}
|
||||
|
||||
AdnlQueryId AdnlQuery::random_query_id() {
|
||||
AdnlQueryId q_id;
|
||||
td::Random::secure_bytes(q_id.as_slice());
|
||||
return q_id;
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
67
adnl/adnl-query.h
Normal file
67
adnl/adnl-query.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "common/bitstring.h"
|
||||
#include "td/utils/buffer.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlPeerPair;
|
||||
|
||||
using AdnlQueryId = td::Bits256;
|
||||
|
||||
class AdnlQuery : public td::actor::Actor {
|
||||
public:
|
||||
static td::actor::ActorId<AdnlQuery> create(td::Promise<td::BufferSlice> promise,
|
||||
std::function<void(AdnlQueryId)> destroy, std::string name,
|
||||
td::Timestamp timeout, AdnlQueryId id) {
|
||||
return td::actor::create_actor<AdnlQuery>("query", name, std::move(promise), std::move(destroy), timeout, id)
|
||||
.release();
|
||||
}
|
||||
static AdnlQueryId random_query_id();
|
||||
AdnlQuery(std::string name, td::Promise<td::BufferSlice> promise, std::function<void(AdnlQueryId)> destroy,
|
||||
td::Timestamp timeout, AdnlQueryId id)
|
||||
: name_(std::move(name)), timeout_(timeout), promise_(std::move(promise)), destroy_(std::move(destroy)), id_(id) {
|
||||
}
|
||||
void alarm() override;
|
||||
void result(td::BufferSlice data);
|
||||
void start_up() override {
|
||||
alarm_timestamp() = timeout_;
|
||||
}
|
||||
void tear_down() override {
|
||||
destroy_(id_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
td::Timestamp timeout_;
|
||||
td::Promise<td::BufferSlice> promise_;
|
||||
std::function<void(AdnlQueryId)> destroy_;
|
||||
AdnlQueryId id_;
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
55
adnl/adnl-static-nodes.cpp
Normal file
55
adnl/adnl-static-nodes.cpp
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "adnl-static-nodes.h"
|
||||
#include "adnl-static-nodes.hpp"
|
||||
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
void AdnlStaticNodesManagerImpl::add_node(AdnlNode node) {
|
||||
auto id_short = node.compute_short_id();
|
||||
VLOG(ADNL_INFO) << "[staticnodes] adding static node " << id_short;
|
||||
|
||||
nodes_.emplace(id_short, std::move(node));
|
||||
}
|
||||
|
||||
void AdnlStaticNodesManagerImpl::del_node(AdnlNodeIdShort id) {
|
||||
nodes_.erase(id);
|
||||
}
|
||||
|
||||
td::Result<AdnlNode> AdnlStaticNodesManagerImpl::get_node(AdnlNodeIdShort id) {
|
||||
auto it = nodes_.find(id);
|
||||
if (it == nodes_.end()) {
|
||||
return td::Status::Error(ErrorCode::notready, "static node not found");
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
td::actor::ActorOwn<AdnlStaticNodesManager> AdnlStaticNodesManager::create() {
|
||||
auto X = td::actor::create_actor<AdnlStaticNodesManagerImpl>("staticnodesmanager");
|
||||
return td::actor::ActorOwn<AdnlStaticNodesManager>(std::move(X));
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
43
adnl/adnl-static-nodes.h
Normal file
43
adnl/adnl-static-nodes.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/utils/Status.h"
|
||||
#include "td/actor/PromiseFuture.h"
|
||||
#include "auto/tl/ton_api.h"
|
||||
|
||||
#include "adnl-peer-table.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlStaticNodesManager : public td::actor::Actor {
|
||||
public:
|
||||
virtual void add_node(AdnlNode node) = 0;
|
||||
virtual void del_node(AdnlNodeIdShort id) = 0;
|
||||
virtual td::Result<AdnlNode> get_node(AdnlNodeIdShort id) = 0;
|
||||
|
||||
static td::actor::ActorOwn<AdnlStaticNodesManager> create();
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
42
adnl/adnl-static-nodes.hpp
Normal file
42
adnl/adnl-static-nodes.hpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include "adnl-static-nodes.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlStaticNodesManagerImpl : public AdnlStaticNodesManager {
|
||||
public:
|
||||
void add_node(AdnlNode node) override;
|
||||
void del_node(AdnlNodeIdShort id) override;
|
||||
td::Result<AdnlNode> get_node(AdnlNodeIdShort id) override;
|
||||
AdnlStaticNodesManagerImpl() {
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<AdnlNodeIdShort, AdnlNode> nodes_;
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
38
adnl/adnl-test-loopback-implementation.cpp
Normal file
38
adnl/adnl-test-loopback-implementation.cpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "adnl-test-loopback-implementation.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
AdnlAddressList TestLoopbackNetworkManager::generate_dummy_addr_list(bool empty) {
|
||||
auto obj = ton::create_tl_object<ton::ton_api::adnl_address_udp>(1, 1);
|
||||
auto objv = std::vector<ton::tl_object_ptr<ton::ton_api::adnl_Address>>();
|
||||
objv.push_back(std::move(obj));
|
||||
td::uint32 now = Adnl::adnl_start_time();
|
||||
auto addrR = ton::adnl::AdnlAddressList::create(
|
||||
ton::create_tl_object<ton::ton_api::adnl_addressList>(std::move(objv), empty ? 0 : now, empty ? 0 : now, 0, 0));
|
||||
addrR.ensure();
|
||||
return addrR.move_as_ok();
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
86
adnl/adnl-test-loopback-implementation.h
Normal file
86
adnl/adnl-test-loopback-implementation.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "adnl/adnl.h"
|
||||
#include "td/utils/Random.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class TestLoopbackNetworkManager : public ton::adnl::AdnlNetworkManager {
|
||||
public:
|
||||
void install_callback(std::unique_ptr<Callback> callback) override {
|
||||
CHECK(!callback_);
|
||||
callback_ = std::move(callback);
|
||||
}
|
||||
|
||||
void add_self_addr(td::IPAddress addr, td::uint32 priority) override {
|
||||
}
|
||||
void add_proxy_addr(td::IPAddress addr, std::shared_ptr<AdnlProxy> proxy, 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 {
|
||||
if (allowed_sources_.count(src_id) == 0 || allowed_destinations_.count(dst_id) == 0) {
|
||||
// just drop
|
||||
return;
|
||||
}
|
||||
if (loss_probability_ > 0 && td::Random::fast(0, 10000) < loss_probability_ * 10000) {
|
||||
return;
|
||||
}
|
||||
CHECK(callback_);
|
||||
callback_->receive_packet(dst_addr, std::move(data));
|
||||
}
|
||||
|
||||
void add_node_id(AdnlNodeIdShort id, bool allow_send, bool allow_receive) {
|
||||
if (allow_send) {
|
||||
allowed_sources_.insert(id);
|
||||
} else {
|
||||
allowed_sources_.erase(id);
|
||||
}
|
||||
if (allow_receive) {
|
||||
allowed_destinations_.insert(id);
|
||||
} else {
|
||||
allowed_destinations_.erase(id);
|
||||
}
|
||||
}
|
||||
|
||||
void set_loss_probability(double p) {
|
||||
CHECK(p >= 0 && p <= 1);
|
||||
loss_probability_ = p;
|
||||
}
|
||||
|
||||
TestLoopbackNetworkManager() {
|
||||
}
|
||||
|
||||
static AdnlAddressList generate_dummy_addr_list(bool empty = false);
|
||||
|
||||
private:
|
||||
std::set<AdnlNodeIdShort> allowed_sources_;
|
||||
std::set<AdnlNodeIdShort> allowed_destinations_;
|
||||
std::unique_ptr<Callback> callback_;
|
||||
double loss_probability_ = 0.0;
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
120
adnl/adnl.h
Normal file
120
adnl/adnl.h
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "auto/tl/ton_api.h"
|
||||
#include "td/utils/port/IPAddress.h"
|
||||
#include "adnl-node-id.hpp"
|
||||
#include "adnl-node.h"
|
||||
#include "common/errorcode.h"
|
||||
#include "keyring/keyring.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace dht {
|
||||
class Dht;
|
||||
}
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class AdnlNetworkManager;
|
||||
|
||||
class AdnlExtServer : public td::actor::Actor {
|
||||
public:
|
||||
virtual void add_local_id(AdnlNodeIdShort id) = 0;
|
||||
virtual void add_tcp_port(td::uint16 port) = 0;
|
||||
virtual ~AdnlExtServer() = default;
|
||||
};
|
||||
|
||||
class AdnlSenderInterface : public td::actor::Actor {
|
||||
public:
|
||||
virtual ~AdnlSenderInterface() = default;
|
||||
|
||||
virtual void send_message(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data) = 0;
|
||||
|
||||
virtual void send_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, std::string name,
|
||||
td::Promise<td::BufferSlice> promise, td::Timestamp timeout, td::BufferSlice data) = 0;
|
||||
virtual void send_query_ex(AdnlNodeIdShort src, AdnlNodeIdShort dst, std::string name,
|
||||
td::Promise<td::BufferSlice> promise, td::Timestamp timeout, td::BufferSlice data,
|
||||
td::uint64 max_answer_size) = 0;
|
||||
};
|
||||
|
||||
class Adnl : public AdnlSenderInterface {
|
||||
public:
|
||||
class Callback {
|
||||
public:
|
||||
virtual void receive_message(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data) = 0;
|
||||
virtual void receive_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data,
|
||||
td::Promise<td::BufferSlice> promise) = 0;
|
||||
virtual ~Callback() = default;
|
||||
};
|
||||
|
||||
static constexpr td::uint32 get_mtu() {
|
||||
return 1024;
|
||||
}
|
||||
static constexpr td::uint32 huge_packet_max_size() {
|
||||
return 1024 * 8;
|
||||
}
|
||||
|
||||
// adds node to peer table
|
||||
// used mostly from DHT to avoid loops
|
||||
virtual void add_peer(AdnlNodeIdShort local_id, AdnlNodeIdFull id, AdnlAddressList addr_list) = 0;
|
||||
|
||||
// adds address list for nodes from config
|
||||
virtual void add_static_nodes_from_config(AdnlNodesList nodes) = 0;
|
||||
|
||||
// adds local id. After that you can send/receive messages from/to this id
|
||||
virtual void add_id(AdnlNodeIdFull id, AdnlAddressList addr_list) = 0;
|
||||
virtual void del_id(AdnlNodeIdShort id, td::Promise<td::Unit> promise) = 0;
|
||||
|
||||
// subscribe to (some) messages(+queries) to this local id
|
||||
virtual void subscribe(AdnlNodeIdShort dst, std::string prefix, std::unique_ptr<Callback> callback) = 0;
|
||||
virtual void unsubscribe(AdnlNodeIdShort dst, std::string prefix) = 0;
|
||||
|
||||
// register (main) dht node
|
||||
// it will be used to send queries to DHT from adnl
|
||||
// there are two types of queries:
|
||||
// - discover node addr list for unknown node
|
||||
// - update local node information
|
||||
virtual void register_dht_node(td::actor::ActorId<dht::Dht> dht_node) = 0;
|
||||
virtual void register_network_manager(td::actor::ActorId<AdnlNetworkManager> network_manager) = 0;
|
||||
|
||||
// get local id information
|
||||
// for example when you need to sent it further
|
||||
virtual void get_addr_list(AdnlNodeIdShort id, td::Promise<AdnlAddressList> promise) = 0;
|
||||
virtual void get_self_node(AdnlNodeIdShort id, td::Promise<AdnlNode> promise) = 0;
|
||||
|
||||
virtual void create_ext_server(std::vector<AdnlNodeIdShort> ids, std::vector<td::uint16> ports,
|
||||
td::Promise<td::actor::ActorOwn<AdnlExtServer>> promise) = 0;
|
||||
|
||||
static td::actor::ActorOwn<Adnl> create(std::string db, td::actor::ActorId<keyring::Keyring> keyring);
|
||||
|
||||
static std::string int_to_bytestring(td::int32 id) {
|
||||
return std::string(reinterpret_cast<char *>(&id), 4);
|
||||
}
|
||||
|
||||
static td::int32 adnl_start_time();
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
using Adnl = adnl::Adnl;
|
||||
|
||||
} // namespace ton
|
240
adnl/test/adnl-test-ping.cpp
Normal file
240
adnl/test/adnl-test-ping.cpp
Normal file
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
This file is part of TON Blockchain source code.
|
||||
|
||||
TON Blockchain is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
TON Blockchain is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with TON Blockchain. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
You must obey the GNU General Public License in all respects for all
|
||||
of the code used other than OpenSSL. If you modify file(s) with this
|
||||
exception, you may extend this exception to your version of the file(s),
|
||||
but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
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
|
||||
*/
|
||||
#include "adnl/adnl-network-manager.h"
|
||||
#include "adnl/adnl-peer-table.h"
|
||||
#include "adnl/utils.hpp"
|
||||
#include "keys/encryptor.h"
|
||||
#include "td/utils/Time.h"
|
||||
#include "td/utils/format.h"
|
||||
#include "td/utils/OptionsParser.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
template <std::size_t size>
|
||||
std::ostream &operator<<(std::ostream &stream, const td::UInt<size> &x) {
|
||||
for (size_t i = 0; i < size / 8; i++) {
|
||||
stream << td::format::hex_digit((x.raw[i] >> 4) & 15) << td::format::hex_digit(x.raw[i] & 15);
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
class AdnlNode : public td::actor::Actor {
|
||||
private:
|
||||
std::vector<td::UInt256> ping_ids_;
|
||||
|
||||
td::actor::ActorOwn<ton::AdnlNetworkManager> network_manager_;
|
||||
td::actor::ActorOwn<ton::AdnlPeerTable> peer_table_;
|
||||
|
||||
td::UInt256 local_id_;
|
||||
bool local_id_set_ = false;
|
||||
|
||||
std::string host_ = "127.0.0.1";
|
||||
td::uint32 ip_ = 0x7f000001;
|
||||
td::uint16 port_ = 2380;
|
||||
|
||||
void receive_message(td::UInt256 src, td::UInt256 dst, td::BufferSlice data) {
|
||||
std::cout << "MESSAGE FROM " << src << " to " << dst << " of size " << std::to_string(data.size()) << "\n";
|
||||
}
|
||||
|
||||
void receive_query(td::UInt256 src, td::UInt256 dst, td::uint64 query_id, td::BufferSlice data) {
|
||||
std::cout << "QUERY " << std::to_string(query_id) << " FROM " << src << " to " << dst << " of size "
|
||||
<< std::to_string(data.size()) << "\n";
|
||||
td::actor::send_closure(peer_table_, &ton::AdnlPeerTable::answer_query, dst, src, query_id,
|
||||
ton::create_tl_object<ton::ton_api::testObject>());
|
||||
}
|
||||
|
||||
std::unique_ptr<ton::AdnlPeerTable::Callback> make_callback() {
|
||||
class Callback : public ton::AdnlPeerTable::Callback {
|
||||
public:
|
||||
void receive_message(td::UInt256 src, td::UInt256 dst, td::BufferSlice data) override {
|
||||
td::actor::send_closure(id_, &AdnlNode::receive_message, src, dst, std::move(data));
|
||||
}
|
||||
void receive_query(td::UInt256 src, td::UInt256 dst, td::uint64 query_id, td::BufferSlice data) override {
|
||||
td::actor::send_closure(id_, &AdnlNode::receive_query, src, dst, query_id, std::move(data));
|
||||
}
|
||||
Callback(td::actor::ActorId<AdnlNode> id) : id_(std::move(id)) {
|
||||
}
|
||||
|
||||
private:
|
||||
td::actor::ActorId<AdnlNode> id_;
|
||||
};
|
||||
|
||||
return std::make_unique<Callback>(td::actor::actor_id(this));
|
||||
}
|
||||
|
||||
public:
|
||||
void start_up() override {
|
||||
alarm_timestamp() = td::Timestamp::in(1);
|
||||
}
|
||||
AdnlNode() {
|
||||
network_manager_ = ton::AdnlNetworkManager::create();
|
||||
peer_table_ = ton::AdnlPeerTable::create();
|
||||
td::actor::send_closure(network_manager_, &ton::AdnlNetworkManager::register_peer_table, peer_table_.get());
|
||||
td::actor::send_closure(peer_table_, &ton::AdnlPeerTable::register_network_manager, network_manager_.get());
|
||||
}
|
||||
void listen_udp(td::uint16 port) {
|
||||
td::actor::send_closure(network_manager_, &ton::AdnlNetworkManager::add_listening_udp_port, "0.0.0.0", port);
|
||||
port_ = port;
|
||||
}
|
||||
void set_host(td::IPAddress ip, std::string host) {
|
||||
ip_ = ip.get_ipv4();
|
||||
host_ = host;
|
||||
}
|
||||
void send_pings_to(td::UInt256 id) {
|
||||
std::cout << "send pings to " << id << "\n";
|
||||
ping_ids_.push_back(id);
|
||||
}
|
||||
void add_local_id(ton::tl_object_ptr<ton::ton_api::adnl_id_Pk> pk_) {
|
||||
auto pub_ = ton::get_public_key(pk_);
|
||||
local_id_ = ton::adnl_short_id(pub_);
|
||||
std::cout << "local_id = '" << local_id_ << "'\n";
|
||||
auto x = ton::create_tl_object<ton::ton_api::adnl_address_udp>(ip_, port_);
|
||||
auto v = std::vector<ton::tl_object_ptr<ton::ton_api::adnl_Address>>();
|
||||
v.push_back(ton::move_tl_object_as<ton::ton_api::adnl_Address>(x));
|
||||
auto y =
|
||||
ton::create_tl_object<ton::ton_api::adnl_addressList>(std::move(v), static_cast<td::int32>(td::Time::now()));
|
||||
|
||||
LOG(INFO) << "local_addr_list: " << ton::ton_api::to_string(y);
|
||||
td::actor::send_closure(peer_table_, &ton::AdnlPeerTable::add_id, std::move(pk_), std::move(y));
|
||||
td::actor::send_closure(peer_table_, &ton::AdnlPeerTable::subscribe, local_id_, "", make_callback());
|
||||
local_id_set_ = true;
|
||||
}
|
||||
|
||||
void add_foreign(ton::tl_object_ptr<ton::ton_api::adnl_id_Full> id,
|
||||
ton::tl_object_ptr<ton::ton_api::adnl_addressList> addr_list) {
|
||||
std::cout << ton::adnl_short_id(id) << "\n";
|
||||
td::actor::send_closure(peer_table_, &ton::AdnlPeerTable::add_peer, std::move(id), std::move(addr_list));
|
||||
}
|
||||
|
||||
void alarm() override {
|
||||
std::cout << "alarm\n";
|
||||
if (local_id_set_) {
|
||||
for (auto it = ping_ids_.begin(); it != ping_ids_.end(); it++) {
|
||||
auto P = td::PromiseCreator::lambda([](td::Result<td::BufferSlice> result) {
|
||||
if (result.is_error()) {
|
||||
std::cout << "received error " << result.move_as_error().to_string() << "\n";
|
||||
} else {
|
||||
auto message = result.move_as_ok();
|
||||
std::cout << "received answer to query\n";
|
||||
}
|
||||
});
|
||||
td::actor::send_closure(peer_table_, &ton::AdnlPeerTable::send_query, local_id_, *it, std::move(P),
|
||||
td::Timestamp::in(5), ton::create_tl_object<ton::ton_api::getTestObject>());
|
||||
}
|
||||
}
|
||||
|
||||
alarm_timestamp() = td::Timestamp::in(1);
|
||||
}
|
||||
};
|
||||
|
||||
td::Result<td::UInt256> get_uint256(std::string str) {
|
||||
if (str.size() != 64) {
|
||||
return td::Status::Error("uint256 must have 64 bytes");
|
||||
}
|
||||
td::UInt256 res;
|
||||
for (size_t i = 0; i < 32; i++) {
|
||||
res.raw[i] = static_cast<td::uint8>(td::hex_to_int(str[2 * i]) * 16 + td::hex_to_int(str[2 * i + 1]));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
td::actor::ActorOwn<AdnlNode> x;
|
||||
|
||||
td::OptionsParser p;
|
||||
p.set_description("test basic adnl functionality");
|
||||
p.add_option('h', "help", "prints_help", [&]() {
|
||||
char b[10240];
|
||||
td::StringBuilder sb({b, 10000});
|
||||
sb << p;
|
||||
std::cout << sb.as_cslice().c_str();
|
||||
std::exit(2);
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('p', "port", "sets udp port", [&](td::Slice port) {
|
||||
td::actor::send_closure(x, &AdnlNode::listen_udp, static_cast<td::uint16>(std::stoi(port.str())));
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('a', "host", "sets local ip", [&](td::Slice ip) {
|
||||
td::IPAddress addr;
|
||||
auto R = addr.init_host_port(ip.str(), 0);
|
||||
if (R.is_error()) {
|
||||
return R;
|
||||
}
|
||||
td::actor::send_closure(x, &AdnlNode::set_host, addr, ip.str());
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('i', "id", "sets local id", [&](td::Slice id) {
|
||||
td::actor::send_closure(x, &AdnlNode::add_local_id,
|
||||
ton::create_tl_object<ton::ton_api::adnl_id_pk_unenc>(id.str()));
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('P', "peer", "adds peer id@host:port", [&](td::Slice id) {
|
||||
auto pos = id.rfind('@');
|
||||
if (pos == static_cast<size_t>(-1)) {
|
||||
return td::Status::Error("--peer expected randomtag@host:port as argument");
|
||||
}
|
||||
auto s1 = id.substr(0, pos);
|
||||
auto f_id = ton::create_tl_object<ton::ton_api::adnl_id_unenc>(s1.str());
|
||||
td::IPAddress addr;
|
||||
auto R = addr.init_host_port(td::CSlice(id.substr(pos + 1).str()));
|
||||
if (R.is_error()) {
|
||||
return R.move_as_error();
|
||||
}
|
||||
|
||||
auto f_addr = ton::create_tl_object<ton::ton_api::adnl_address_udp>(addr.get_ipv4(), addr.get_port());
|
||||
std::vector<ton::tl_object_ptr<ton::ton_api::adnl_Address>> vv;
|
||||
vv.push_back(ton::move_tl_object_as<ton::ton_api::adnl_Address>(f_addr));
|
||||
|
||||
auto f_addr_list =
|
||||
ton::create_tl_object<ton::ton_api::adnl_addressList>(std::move(vv), static_cast<int>(td::Time::now()));
|
||||
|
||||
td::actor::send_closure(x, &AdnlNode::add_foreign, ton::move_tl_object_as<ton::ton_api::adnl_id_Full>(f_id),
|
||||
std::move(f_addr_list));
|
||||
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('n', "node", "node to send pings to", [&](td::Slice node) {
|
||||
auto R = get_uint256(node.str());
|
||||
if (R.is_error()) {
|
||||
return R.move_as_error();
|
||||
}
|
||||
|
||||
td::actor::send_closure(x, &AdnlNode::send_pings_to, R.move_as_ok());
|
||||
return td::Status::OK();
|
||||
});
|
||||
|
||||
td::actor::Scheduler scheduler({2});
|
||||
scheduler.run_in_context([&] {
|
||||
x = td::actor::create_actor<AdnlNode>(td::actor::ActorInfoCreator::Options().with_name("A").with_poll());
|
||||
});
|
||||
scheudler.run();
|
||||
return 0;
|
||||
}
|
27
adnl/utils.cpp
Normal file
27
adnl/utils.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "utils.hpp"
|
||||
#include "tl/tl_object_store.h"
|
||||
#include "td/utils/format.h"
|
||||
#include "td/utils/Random.h"
|
||||
#include "keys/encryptor.h"
|
||||
#include "auto/tl/ton_api.hpp"
|
||||
#include "adnl-node-id.hpp"
|
||||
|
||||
namespace ton {} // namespace ton
|
45
adnl/utils.hpp
Normal file
45
adnl/utils.hpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/misc.h"
|
||||
#include "td/utils/crypto.h"
|
||||
#include "td/utils/format.h"
|
||||
#include "td/utils/base64.h"
|
||||
#include "tl-utils/tl-utils.hpp"
|
||||
|
||||
#include "common/errorcode.h"
|
||||
#include "common/checksum.h"
|
||||
#include "adnl-node-id.hpp"
|
||||
#include "common/status.h"
|
||||
#include "adnl-node.h"
|
||||
#include "adnl-address-list.hpp"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
inline bool adnl_node_is_older(AdnlNode &a, AdnlNode &b) {
|
||||
return a.addr_list().version() < b.addr_list().version();
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
Loading…
Add table
Add a link
Reference in a new issue