diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 706e48be9..1bd918ddc 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3995,7 +3995,7 @@ testCallVectorStringObject x:vector = TestVectorStringObject; testSquareInt x:int32 = TestInt; //@description Sends a simple network request to the Telegram servers; for testing only. Can be called before authorization testNetwork = Ok; -//@description Sends a simple network request to the Telegram servers via proxy; for testing only. Can be called before authorization @server Proxy ip @port Proxy port @type Proxy type +//@description Sends a simple network request to the Telegram servers via proxy; for testing only. Can be called before authorization @server Proxy server IP address @port Proxy server port @type Proxy type testProxy server:string port:int32 type:ProxyType = Ok; //@description Forces an updates.getDifference call to the Telegram servers; for testing only testGetDifference = Ok; diff --git a/td/mtproto/RawConnection.h b/td/mtproto/RawConnection.h index 34d1513d2..aeb0503be 100644 --- a/td/mtproto/RawConnection.h +++ b/td/mtproto/RawConnection.h @@ -36,7 +36,7 @@ class RawConnection { virtual void on_write(uint64 bytes) = 0; virtual void on_pong() = 0; // called when we know that connection is alive - virtual void on_error() = 0; // called on RawConnectin error. Such error should be very rare on good connections. + virtual void on_error() = 0; // called on RawConnection error. Such error should be very rare on good connections. virtual void on_mtproto_error() = 0; }; RawConnection() = default; diff --git a/td/mtproto/TlsInit.h b/td/mtproto/TlsInit.h index 79069e241..ce6e75692 100644 --- a/td/mtproto/TlsInit.h +++ b/td/mtproto/TlsInit.h @@ -21,10 +21,10 @@ class Grease { class TlsInit : public TransparentProxy { public: - TlsInit(SocketFd socket_fd, IPAddress ip_address, string domain, string secret, unique_ptr callback, - ActorShared<> parent, double server_time_difference) - : TransparentProxy(std::move(socket_fd), std::move(ip_address), std::move(domain), std::move(secret), - std::move(callback), std::move(parent)) + TlsInit(SocketFd socket_fd, string domain, string secret, unique_ptr callback, ActorShared<> parent, + double server_time_difference) + : TransparentProxy(std::move(socket_fd), IPAddress(), std::move(domain), std::move(secret), std::move(callback), + std::move(parent)) , server_time_difference_(server_time_difference) { } diff --git a/td/telegram/Global.cpp b/td/telegram/Global.cpp index c0bf8813a..fc78d0b7a 100644 --- a/td/telegram/Global.cpp +++ b/td/telegram/Global.cpp @@ -120,7 +120,10 @@ double Global::get_dns_time_difference() const { if (dns_flag) { return std::max(dns_diff, server_diff); } - return server_diff; + if (td_db_) { + return server_diff; + } + return Clocks::system() - Time::now(); } DcId Global::get_webfile_dc_id() const { diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index c0ec199bd..9eb964224 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -51,6 +51,7 @@ #include "td/telegram/net/NetStatsManager.h" #include "td/telegram/net/NetType.h" #include "td/telegram/net/Proxy.h" +#include "td/telegram/net/PublicRsaKeyShared.h" #include "td/telegram/net/TempAuthKeyWatchdog.h" #include "td/telegram/NotificationGroupId.h" #include "td/telegram/NotificationId.h" @@ -88,6 +89,8 @@ #include "td/db/binlog/BinlogEvent.h" +#include "td/mtproto/HandshakeActor.h" +#include "td/mtproto/RawConnection.h" #include "td/mtproto/utils.h" // for create_storer, fetch_result, etc, TODO #include "td/utils/buffer.h" @@ -104,10 +107,6 @@ #include "td/utils/tl_parsers.h" #include "td/utils/utf8.h" -#include "td/mtproto/HandshakeActor.h" -#include "td/mtproto/RawConnection.h" -#include "td/telegram/net/PublicRsaKeyShared.h" - #include #include #include @@ -544,41 +543,50 @@ class TestQuery : public Td::ResultHandler { private: uint64 request_id_; }; -class TestProxyRequest : public RequestActor { + +class TestProxyRequest : public RequestOnceActor { Proxy proxy_; ActorOwn<> child_; + static constexpr int16 DC_ID = 2; + auto get_transport() { - return mtproto::TransportType{mtproto::TransportType::ObfuscatedTcp, 2, proxy_.secret()}; + return mtproto::TransportType{mtproto::TransportType::ObfuscatedTcp, DC_ID, proxy_.secret()}; } void do_run(Promise &&promise) override { - if (get_tries() < 2) { - promise.set_value(Unit()); - } - IPAddress ip; auto status = ip.init_host_port(proxy_.server(), proxy_.port()); if (status.is_error()) { - return promise.set_error(std::move(status)); + return promise.set_error(Status::Error(400, status.public_message())); } auto r_socket_fd = SocketFd::open(ip); if (r_socket_fd.is_error()) { - return promise.set_error(r_socket_fd.move_as_error()); + return promise.set_error(Status::Error(400, r_socket_fd.error().public_message())); } - auto connection_promise = PromiseCreator::lambda( - [actor_id = actor_id(this), promise = std::move(promise)](Result r) mutable { - send_closure(actor_id, &TestProxyRequest::on_connection_data, std::move(r), std::move(promise)); - }); + auto dc_options = ConnectionCreator::get_default_dc_options(false); + IPAddress mtproto_ip; + for (auto &dc_option : dc_options.dc_options) { + if (dc_option.get_dc_id().get_raw_id() == DC_ID) { + mtproto_ip = dc_option.get_ip_address(); + break; + } + } - child_ = ConnectionCreator::prepare_connection(r_socket_fd.move_as_ok(), {&proxy_, ip}, get_transport(), "", - IPAddress(), nullptr, {}, false, std::move(connection_promise)); + auto connection_promise = PromiseCreator::lambda([actor_id = actor_id(this), promise = std::move(promise)]( + Result r_data) mutable { + send_closure(actor_id, &TestProxyRequest::on_connection_data, std::move(r_data), std::move(promise)); + }); + + child_ = + ConnectionCreator::prepare_connection(r_socket_fd.move_as_ok(), {&proxy_, ip}, get_transport(), "TestPingDC2", + std::move(mtproto_ip), nullptr, {}, false, std::move(connection_promise)); } - void on_connection_data(Result r, Promise &&promise) { - if (r.is_error()) { - return promise.set_error(r.move_as_error()); + void on_connection_data(Result r_data, Promise &&promise) { + if (r_data.is_error()) { + return promise.set_error(r_data.move_as_error()); } class HandshakeContext : public mtproto::AuthKeyHandshakeContext { public: @@ -592,8 +600,8 @@ class TestProxyRequest : public RequestActor { private: PublicRsaKeyShared public_rsa_key{DcId::empty(), false}; }; - auto handshake = make_unique(2, 0); - auto data = r.move_as_ok(); + auto handshake = make_unique(DC_ID, 3600); + auto data = r_data.move_as_ok(); auto raw_connection = make_unique(std::move(data.socket_fd), get_transport(), nullptr); child_ = create_actor( "HandshakeActor", std::move(handshake), std::move(raw_connection), make_unique(), 10.0, @@ -601,22 +609,15 @@ class TestProxyRequest : public RequestActor { PromiseCreator::lambda( [promise = std::move(promise)](Result> handshake) mutable { if (handshake.is_error()) { - return promise.set_error(handshake.move_as_error()); + return promise.set_error(Status::Error(400, handshake.error().public_message())); } promise.set_value(Unit()); })); } - void do_set_result(Unit &&result) override { - } - - void do_send_result() override { - send_result(make_tl_object()); - } - public: TestProxyRequest(ActorShared td, uint64 request_id, Proxy proxy) - : RequestActor(std::move(td), request_id), proxy_(std::move(proxy)) { + : RequestOnceActor(std::move(td), request_id), proxy_(std::move(proxy)) { } }; @@ -7605,9 +7606,9 @@ void Td::on_request(uint64 id, td_api::testNetwork &request) { } void Td::on_request(uint64 id, td_api::testProxy &request) { - auto r_proxy = Proxy::from_td_api(std::move(request.server_), request.port_, std::move(request.type_)); + auto r_proxy = Proxy::from_td_api(std::move(request.server_), request.port_, request.type_.get()); if (r_proxy.is_error()) { - return send_error(id, r_proxy.move_as_error()); + return send_closure(actor_id(this), &Td::send_error, id, r_proxy.move_as_error()); } CREATE_REQUEST(TestProxyRequest, r_proxy.move_as_ok()); } diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index ffea27820..2401a1044 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3612,13 +3612,14 @@ class CliClient final : public Actor { type = td_api::make_object(user, password); } } + auto port_int = to_integer(port); if (op[0] == 'e') { - send_request(td_api::make_object(as_proxy_id(proxy_id), server, to_integer(port), - enable, std::move(type))); + send_request( + td_api::make_object(as_proxy_id(proxy_id), server, port_int, enable, std::move(type))); } else if (op == "tproxy") { - send_request(td_api::make_object(server, to_integer(port), std::move(type))); + send_request(td_api::make_object(server, port_int, std::move(type))); } else { - send_request(td_api::make_object(server, to_integer(port), enable, std::move(type))); + send_request(td_api::make_object(server, port_int, enable, std::move(type))); } } else if (op == "gproxy" || op == "gproxies") { send_request(td_api::make_object()); diff --git a/td/telegram/net/ConnectionCreator.cpp b/td/telegram/net/ConnectionCreator.cpp index caf044df8..03b78979b 100644 --- a/td/telegram/net/ConnectionCreator.cpp +++ b/td/telegram/net/ConnectionCreator.cpp @@ -140,7 +140,7 @@ void ConnectionCreator::set_net_stats_callback(std::shared_ptr void ConnectionCreator::add_proxy(int32 old_proxy_id, string server, int32 port, bool enable, td_api::object_ptr proxy_type, Promise> promise) { - auto r_proxy = Proxy::from_td_api(std::move(server), port, std::move(proxy_type)); + auto r_proxy = Proxy::from_td_api(std::move(server), port, proxy_type.get()); if (r_proxy.is_error()) { return promise.set_error(r_proxy.move_as_error()); } @@ -368,8 +368,6 @@ void ConnectionCreator::ping_proxy_resolved(int32 proxy_id, IPAddress ip_address } auto socket_fd = r_socket_fd.move_as_ok(); - auto secret = extra.transport_type.secret; - auto connection_promise = PromiseCreator::lambda([promise = std::move(promise), actor_id = actor_id(this), transport_type = extra.transport_type](Result r_connection_data) mutable { @@ -382,7 +380,7 @@ void ConnectionCreator::ping_proxy_resolved(int32 proxy_id, IPAddress ip_address CHECK(proxy.use_proxy()); auto token = next_token(); auto ref = prepare_connection(std::move(socket_fd), proxy, extra.transport_type, extra.debug_str, extra.mtproto_ip, - nullptr, create_reference(token), true, std::move(connection_promise)); + nullptr, create_reference(token), false, std::move(connection_promise)); if (!ref.empty()) { children_[token] = {false, std::move(ref)}; } @@ -640,8 +638,9 @@ void ConnectionCreator::request_raw_connection_by_ip(IPAddress ip_address, mtpro }); auto token = next_token(); - auto ref = prepare_connection(std::move(socket_fd), {nullptr, IPAddress()}, transport_type, "", IPAddress(), nullptr, - create_reference(token), true, std::move(connection_promise)); + auto ref = prepare_connection(std::move(socket_fd), {nullptr, IPAddress()}, transport_type, + PSTRING() << "to IP address " << ip_address, IPAddress(), nullptr, + create_reference(token), false, std::move(connection_promise)); if (!ref.empty()) { children_[token] = {false, std::move(ref)}; } @@ -721,7 +720,7 @@ ActorOwn<> ConnectionCreator::prepare_connection(SocketFd socket_fd, const Proxy ActorShared<> parent, bool use_connection_token, Promise promise) { if (proxy.use_socks5_proxy() || proxy.use_http_tcp_proxy() || transport_type.secret.emulate_tls()) { - VLOG(connections) << "In client_loop: create new transparent proxy connection " << debug_str; + VLOG(connections) << "Create new transparent proxy connection " << debug_str; class Callback : public TransparentProxy::Callback { public: explicit Callback(Promise promise, @@ -738,7 +737,7 @@ ActorOwn<> ConnectionCreator::prepare_connection(SocketFd socket_fd, const Proxy if (was_connected_ && stats_callback_) { stats_callback_->on_error(); } - promise_.set_error(result.move_as_error()); + promise_.set_error(Status::Error(400, result.error().public_message())); } else { ConnectionData data; data.socket_fd = result.move_as_ok(); @@ -763,7 +762,7 @@ ActorOwn<> ConnectionCreator::prepare_connection(SocketFd socket_fd, const Proxy }; LOG(INFO) << "Start " << (proxy.use_socks5_proxy() ? "Socks5" : (proxy.use_http_tcp_proxy() ? "HTTP" : "TLS")) << ": " << debug_str; - auto callback = td::make_unique(std::move(promise), std::move(stats_callback), use_connection_token); + auto callback = make_unique(std::move(promise), std::move(stats_callback), use_connection_token); if (proxy.use_socks5_proxy()) { return ActorOwn<>(create_actor("Socks5", std::move(socket_fd), mtproto_ip, proxy.proxy().user().str(), proxy.proxy().password().str(), std::move(callback), std::move(parent))); @@ -772,15 +771,15 @@ ActorOwn<> ConnectionCreator::prepare_connection(SocketFd socket_fd, const Proxy proxy.proxy().user().str(), proxy.proxy().password().str(), std::move(callback), std::move(parent))); } else if (transport_type.secret.emulate_tls()) { - return ActorOwn<>(create_actor( - "TlsInit", std::move(socket_fd), mtproto_ip, transport_type.secret.get_domain(), - transport_type.secret.get_proxy_secret().str(), std::move(callback), std::move(parent), - G()->get_dns_time_difference())); + return ActorOwn<>( + create_actor("TlsInit", std::move(socket_fd), transport_type.secret.get_domain(), + transport_type.secret.get_proxy_secret().str(), std::move(callback), + std::move(parent), G()->get_dns_time_difference())); } else { UNREACHABLE(); } } else { - VLOG(connections) << "In client_loop: create new direct connection " << debug_str; + VLOG(connections) << "Create new direct connection " << debug_str; ConnectionData data; data.socket_fd = std::move(socket_fd); @@ -898,8 +897,6 @@ void ConnectionCreator::client_loop(ClientInfo &client) { client.checking_connections++; } - mtproto::ProxySecret secret = extra.transport_type.secret; - auto promise = PromiseCreator::lambda( [actor_id = actor_id(this), check_mode, transport_type = extra.transport_type, hash = client.hash, debug_str = extra.debug_str, diff --git a/td/telegram/net/ConnectionCreator.h b/td/telegram/net/ConnectionCreator.h index 662b99d09..4e0da4f5a 100644 --- a/td/telegram/net/ConnectionCreator.h +++ b/td/telegram/net/ConnectionCreator.h @@ -17,8 +17,8 @@ #include "td/telegram/StateManager.h" #include "td/mtproto/AuthData.h" -#include "td/mtproto/TransportType.h" #include "td/mtproto/RawConnection.h" +#include "td/mtproto/TransportType.h" #include "td/net/NetStats.h" @@ -42,13 +42,13 @@ #include namespace td { -namespace mtproto { -class RawConnection; -} // namespace mtproto + namespace detail { class StatsCallback; -} +} // namespace detail + class GetHostByNameActor; + } // namespace td namespace td { @@ -124,6 +124,8 @@ class ConnectionCreator : public NetQueryCallback { IPAddress ip_address_; }; + static DcOptions get_default_dc_options(bool is_test); + static ActorOwn<> prepare_connection(SocketFd socket_fd, const ProxyInfo &proxy, mtproto::TransportType transport_type, string debug_str, IPAddress mtproto_ip, unique_ptr stats_callback, @@ -267,8 +269,6 @@ class ConnectionCreator : public NetQueryCallback { void on_proxy_resolved(Result ip_address, bool dummy); - static DcOptions get_default_dc_options(bool is_test); - struct FindConnectionExtra { DcOptionsSet::Stat *stat{nullptr}; mtproto::TransportType transport_type; diff --git a/td/telegram/net/Proxy.cpp b/td/telegram/net/Proxy.cpp index aedcd275b..60b4cfe5b 100644 --- a/td/telegram/net/Proxy.cpp +++ b/td/telegram/net/Proxy.cpp @@ -5,9 +5,12 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #include "td/telegram/net/Proxy.h" + #include "td/telegram/td_api.h" + namespace td { -Result Proxy::from_td_api(string server, int port, td_api::object_ptr proxy_type) { + +Result Proxy::from_td_api(string server, int port, td_api::ProxyType *proxy_type) { if (proxy_type == nullptr) { return Status::Error(400, "Proxy type should not be empty"); } @@ -18,31 +21,47 @@ Result Proxy::from_td_api(string server, int port, td_api::object_ptrget_id()) { case td_api::proxyTypeSocks5::ID: { - auto type = td_api::move_object_as(proxy_type); - new_proxy = Proxy::socks5(server, port, type->username_, type->password_); - break; + auto type = static_cast(proxy_type); + return Proxy::socks5(std::move(server), port, std::move(type->username_), std::move(type->password_)); } case td_api::proxyTypeHttp::ID: { - auto type = td_api::move_object_as(proxy_type); + auto type = static_cast(proxy_type); if (type->http_only_) { - new_proxy = Proxy::http_caching(server, port, type->username_, type->password_); + return Proxy::http_caching(std::move(server), port, std::move(type->username_), std::move(type->password_)); } else { - new_proxy = Proxy::http_tcp(server, port, type->username_, type->password_); + return Proxy::http_tcp(std::move(server), port, std::move(type->username_), std::move(type->password_)); } - break; } case td_api::proxyTypeMtproto::ID: { - auto type = td_api::move_object_as(proxy_type); + auto type = static_cast(proxy_type); TRY_RESULT(secret, mtproto::ProxySecret::from_link(type->secret_)); - new_proxy = Proxy::mtproto(server, port, secret); - break; + return Proxy::mtproto(std::move(server), port, std::move(secret)); } default: UNREACHABLE(); + return Status::Error(400, "Wrong proxy type"); } - return new_proxy; } + +StringBuilder &operator<<(StringBuilder &string_builder, const Proxy &proxy) { + switch (proxy.type()) { + case Proxy::Type::Socks5: + return string_builder << "ProxySocks5 " << proxy.server() << ":" << proxy.port(); + case Proxy::Type::HttpTcp: + return string_builder << "ProxyHttpTcp " << proxy.server() << ":" << proxy.port(); + case Proxy::Type::HttpCaching: + return string_builder << "ProxyHttpCaching " << proxy.server() << ":" << proxy.port(); + case Proxy::Type::Mtproto: + return string_builder << "ProxyMtproto " << proxy.server() << ":" << proxy.port() << "/" + << proxy.secret().get_encoded_secret(); + case Proxy::Type::None: + return string_builder << "ProxyEmpty"; + default: + UNREACHABLE(); + return string_builder; + } +} + } // namespace td diff --git a/td/telegram/net/Proxy.h b/td/telegram/net/Proxy.h index 267d37880..d9abcf568 100644 --- a/td/telegram/net/Proxy.h +++ b/td/telegram/net/Proxy.h @@ -10,11 +10,10 @@ #include "td/utils/common.h" #include "td/utils/Slice.h" +#include "td/utils/Status.h" #include "td/utils/StringBuilder.h" #include "td/utils/tl_helpers.h" -#include "td/tl/TlObject.h" - namespace td { namespace td_api { @@ -23,7 +22,7 @@ class ProxyType; class Proxy { public: - static Result from_td_api(string server, int port, tl_object_ptr proxy_type); + static Result from_td_api(string server, int port, td_api::ProxyType *proxy_type); static Proxy socks5(string server, int32 port, string user, string password) { Proxy proxy; @@ -143,23 +142,6 @@ inline bool operator!=(const Proxy &lhs, const Proxy &rhs) { return !(lhs == rhs); } -inline StringBuilder &operator<<(StringBuilder &string_builder, const Proxy &proxy) { - switch (proxy.type()) { - case Proxy::Type::Socks5: - return string_builder << "ProxySocks5 " << proxy.server() << ":" << proxy.port(); - case Proxy::Type::HttpTcp: - return string_builder << "ProxyHttpTcp " << proxy.server() << ":" << proxy.port(); - case Proxy::Type::HttpCaching: - return string_builder << "ProxyHttpCaching " << proxy.server() << ":" << proxy.port(); - case Proxy::Type::Mtproto: - return string_builder << "ProxyMtproto " << proxy.server() << ":" << proxy.port() << "/" - << proxy.secret().get_encoded_secret(); - case Proxy::Type::None: - return string_builder << "ProxyEmpty"; - default: - UNREACHABLE(); - return string_builder; - } -} +StringBuilder &operator<<(StringBuilder &string_builder, const Proxy &proxy); } // namespace td diff --git a/tdutils/td/utils/port/IPAddress.h b/tdutils/td/utils/port/IPAddress.h index 82c5c9b3c..c6160cbe9 100644 --- a/tdutils/td/utils/port/IPAddress.h +++ b/tdutils/td/utils/port/IPAddress.h @@ -82,6 +82,7 @@ class IPAddress { void init_ipv4_any(); void init_ipv6_any(); }; + StringBuilder &operator<<(StringBuilder &builder, const IPAddress &address); } // namespace td diff --git a/test/mtproto.cpp b/test/mtproto.cpp index 44025b155..8c8d7eca0 100644 --- a/test/mtproto.cpp +++ b/test/mtproto.cpp @@ -645,8 +645,8 @@ TEST(Mtproto, TlsTransport) { IPAddress ip_address; ip_address.init_host_port(domain, 443).ensure(); SocketFd fd = SocketFd::open(ip_address).move_as_ok(); - create_actor("TlsInit", std::move(fd), IPAddress(), domain, "0123456789secret", - make_unique(), ActorShared<>(), Clocks::system() - Time::now()) + create_actor("TlsInit", std::move(fd), domain, "0123456789secret", make_unique(), + ActorShared<>(), Clocks::system() - Time::now()) .release(); } };