From 4079363f1a00699cb4080ca3be7918575b2e71b1 Mon Sep 17 00:00:00 2001 From: Arseny Smirnov Date: Sat, 20 Jul 2019 15:13:36 +0200 Subject: [PATCH] td_api: TestProxy query draft GitOrigin-RevId: 67944e916813c6260df5be6cb4e77f7163854738 --- CMakeLists.txt | 1 + td/generate/scheme/td_api.tl | 2 + td/generate/scheme/td_api.tlo | Bin 156136 -> 156284 bytes td/telegram/Td.cpp | 89 ++++++++++ td/telegram/Td.h | 1 + td/telegram/cli.cpp | 4 +- td/telegram/net/ConnectionCreator.cpp | 232 +++++++++++++------------- td/telegram/net/ConnectionCreator.h | 53 +++++- td/telegram/net/Proxy.cpp | 48 ++++++ td/telegram/net/Proxy.h | 8 + 10 files changed, 312 insertions(+), 126 deletions(-) create mode 100644 td/telegram/net/Proxy.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d58e786d..2f5890373 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -423,6 +423,7 @@ set(TDLIB_SOURCE td/telegram/net/NetQueryDelayer.cpp td/telegram/net/NetQueryDispatcher.cpp td/telegram/net/NetStatsManager.cpp + td/telegram/net/Proxy.cpp td/telegram/net/PublicRsaKeyShared.cpp td/telegram/net/PublicRsaKeyWatchdog.cpp td/telegram/net/Session.cpp diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 9ca3b1825..706e48be9 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3995,6 +3995,8 @@ 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 +testProxy server:string port:int32 type:ProxyType = Ok; //@description Forces an updates.getDifference call to the Telegram servers; for testing only testGetDifference = Ok; //@description Does nothing and ensures that the Update object is used; for testing only. This is an offline method. Can be called before authorization diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index abb68f6354f0cae432563f94a36eaadd3a338d72..6b38b1bcd90c5b776dd556146d2a4c0281058fc1 100644 GIT binary patch delta 70 zcmV-M0J;C@!wLMv34pW#xViyYx4F6jm!265Cxtl)bY*jNP;zg0c>n-uzU|c6#u7{e cmrdpYN0VUq5SJXl0Th=I#{m(yQCR|)2uw^I(EtDd delta 25 jcmV+!0OtSv#0lub34pW#xViyXx4F6jm!7xeSpt{{t=$ZB diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index fe54e0b5a..c0ec199bd 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -50,6 +50,7 @@ #include "td/telegram/net/NetQueryDispatcher.h" #include "td/telegram/net/NetStatsManager.h" #include "td/telegram/net/NetType.h" +#include "td/telegram/net/Proxy.h" #include "td/telegram/net/TempAuthKeyWatchdog.h" #include "td/telegram/NotificationGroupId.h" #include "td/telegram/NotificationId.h" @@ -103,6 +104,10 @@ #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 @@ -539,6 +544,81 @@ class TestQuery : public Td::ResultHandler { private: uint64 request_id_; }; +class TestProxyRequest : public RequestActor { + Proxy proxy_; + ActorOwn<> child_; + + auto get_transport() { + return mtproto::TransportType{mtproto::TransportType::ObfuscatedTcp, 2, 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)); + } + auto r_socket_fd = SocketFd::open(ip); + if (r_socket_fd.is_error()) { + return promise.set_error(r_socket_fd.move_as_error()); + } + + 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)); + }); + + child_ = ConnectionCreator::prepare_connection(r_socket_fd.move_as_ok(), {&proxy_, ip}, get_transport(), "", + IPAddress(), 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()); + } + class HandshakeContext : public mtproto::AuthKeyHandshakeContext { + public: + DhCallback *get_dh_callback() override { + return nullptr; + } + PublicRsaKeyInterface *get_public_rsa_key_interface() override { + return &public_rsa_key; + } + + private: + PublicRsaKeyShared public_rsa_key{DcId::empty(), false}; + }; + auto handshake = make_unique(2, 0); + auto data = r.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, + PromiseCreator::lambda([](Result> raw_connection) {}), + PromiseCreator::lambda( + [promise = std::move(promise)](Result> handshake) mutable { + if (handshake.is_error()) { + return promise.set_error(handshake.move_as_error()); + } + 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)) { + } +}; class GetAccountTtlRequest : public RequestActor { int32 account_ttl_; @@ -3309,6 +3389,7 @@ bool Td::is_preinitialization_request(int32 id) { case td_api::testCallVectorIntObject::ID: case td_api::testCallVectorString::ID: case td_api::testCallVectorStringObject::ID: + case td_api::testProxy::ID: return true; default: return false; @@ -7523,6 +7604,14 @@ void Td::on_request(uint64 id, td_api::testNetwork &request) { create_handler(id)->send(); } +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_)); + if (r_proxy.is_error()) { + return send_error(id, r_proxy.move_as_error()); + } + CREATE_REQUEST(TestProxyRequest, r_proxy.move_as_ok()); +} + void Td::on_request(uint64 id, td_api::testGetDifference &request) { updates_manager_->get_difference("testGetDifference"); send_closure(actor_id(this), &Td::send_result, id, make_tl_object()); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 259d0dcb8..c309bfbb5 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1022,6 +1022,7 @@ class Td final : public NetQueryCallback { // test void on_request(uint64 id, td_api::testNetwork &request); + void on_request(uint64 id, td_api::testProxy &request); void on_request(uint64 id, td_api::testGetDifference &request); void on_request(uint64 id, td_api::testUseUpdate &request); void on_request(uint64 id, td_api::testUseError &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index d65939126..ffea27820 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3589,7 +3589,7 @@ class CliClient final : public Actor { } else if (op == "rproxy") { send_request(td_api::make_object(as_proxy_id(args))); } else if (op == "aproxy" || op == "aeproxy" || op == "aeproxytcp" || op == "editproxy" || op == "editeproxy" || - op == "editeproxytcp") { + op == "editeproxytcp" || op == "tproxy") { string proxy_id; string server; string port; @@ -3615,6 +3615,8 @@ class CliClient final : public Actor { if (op[0] == 'e') { send_request(td_api::make_object(as_proxy_id(proxy_id), server, to_integer(port), enable, std::move(type))); + } else if (op == "tproxy") { + send_request(td_api::make_object(server, to_integer(port), std::move(type))); } else { send_request(td_api::make_object(server, to_integer(port), enable, std::move(type))); } diff --git a/td/telegram/net/ConnectionCreator.cpp b/td/telegram/net/ConnectionCreator.cpp index eb9f0fc87..eeee4466d 100644 --- a/td/telegram/net/ConnectionCreator.cpp +++ b/td/telegram/net/ConnectionCreator.cpp @@ -90,41 +90,6 @@ class StatsCallback final : public mtproto::RawConnection::StatsCallback { } // namespace detail -class ConnectionCreator::ProxyInfo { - public: - ProxyInfo(Proxy *proxy, IPAddress ip_address) : proxy_(proxy), ip_address_(std::move(ip_address)) { - } - bool use_proxy() const { - return proxy_ != nullptr; - } - Proxy::Type proxy_type() const { - return proxy_ == nullptr ? Proxy::Type::None : proxy_->type(); - } - bool use_socks5_proxy() const { - return proxy_type() == Proxy::Type::Socks5; - } - bool use_http_tcp_proxy() const { - return proxy_type() == Proxy::Type::HttpTcp; - } - bool use_http_caching_proxy() const { - return proxy_type() == Proxy::Type::HttpCaching; - } - bool use_mtproto_proxy() const { - return proxy_type() == Proxy::Type::Mtproto; - } - const Proxy &proxy() const { - CHECK(use_proxy()); - return *proxy_; - } - const IPAddress &ip_address() const { - return ip_address_; - } - - private: - Proxy *proxy_; - IPAddress ip_address_; -}; - ConnectionCreator::ClientInfo::ClientInfo() { flood_control.add_limit(1, 1); flood_control.add_limit(4, 2); @@ -175,44 +140,11 @@ 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) { - if (proxy_type == nullptr) { - return promise.set_error(Status::Error(400, "Proxy type should not be empty")); - } - if (server.empty()) { - return promise.set_error(Status::Error(400, "Server name can't be empty")); - } - if (port <= 0 || port > 65535) { - return promise.set_error(Status::Error(400, "Wrong port number")); - } - - Proxy new_proxy; - switch (proxy_type->get_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; - } - case td_api::proxyTypeHttp::ID: { - auto type = td_api::move_object_as(proxy_type); - if (type->http_only_) { - new_proxy = Proxy::http_caching(server, port, type->username_, type->password_); - } else { - new_proxy = Proxy::http_tcp(server, port, type->username_, type->password_); - } - break; - } - case td_api::proxyTypeMtproto::ID: { - auto type = td_api::move_object_as(proxy_type); - auto r_secret = mtproto::ProxySecret::from_link(type->secret_); - if (r_secret.is_error()) { - return promise.set_error(r_secret.move_as_error()); - } - new_proxy = Proxy::mtproto(server, port, r_secret.move_as_ok()); - break; - } - default: - UNREACHABLE(); + auto r_proxy = Proxy::from_td_api(std::move(server), port, std::move(proxy_type)); + if (r_proxy.is_error()) { + return promise.set_error(r_proxy.move_as_error()); } + auto new_proxy = r_proxy.move_as_ok(); if (old_proxy_id >= 0) { if (proxies_.count(old_proxy_id) == 0) { return promise.set_error(Status::Error(400, "Proxy not found")); @@ -438,52 +370,21 @@ void ConnectionCreator::ping_proxy_resolved(int32 proxy_id, IPAddress ip_address auto secret = extra.transport_type.secret; - auto socket_fd_promise = + auto connection_promise = PromiseCreator::lambda([promise = std::move(promise), actor_id = actor_id(this), - transport_type = std::move(extra.transport_type)](Result r_socket_fd) mutable { - if (r_socket_fd.is_error()) { - return promise.set_error(Status::Error(400, r_socket_fd.error().public_message())); + transport_type = extra.transport_type](Result r_connection_data) mutable { + if (r_connection_data.is_error()) { + return promise.set_error(Status::Error(400, r_connection_data.error().public_message())); } - send_closure(actor_id, &ConnectionCreator::ping_proxy_socket_fd, r_socket_fd.move_as_ok(), + send_closure(actor_id, &ConnectionCreator::ping_proxy_socket_fd, r_connection_data.move_as_ok().socket_fd, std::move(transport_type), std::move(promise)); }); CHECK(proxy.use_proxy()); - if (proxy.use_socks5_proxy() || proxy.use_http_tcp_proxy() || secret.emulate_tls()) { - class Callback : public TransparentProxy::Callback { - public: - explicit Callback(Promise promise) : promise_(std::move(promise)) { - } - void set_result(Result result) override { - promise_.set_result(std::move(result)); - } - void on_connected() override { - } - - private: - Promise promise_; - }; - auto callback = make_unique(std::move(socket_fd_promise)); - - LOG(INFO) << "Start ping proxy: " << extra.debug_str; - auto token = next_token(); - if (proxy.use_socks5_proxy()) { - children_[token] = { - false, create_actor("PingSocks5", std::move(socket_fd), extra.mtproto_ip, proxy.proxy().user().str(), - proxy.proxy().password().str(), std::move(callback), create_reference(token))}; - } else if (proxy.use_http_tcp_proxy()) { - children_[token] = {false, create_actor("PingHttpProxy", std::move(socket_fd), extra.mtproto_ip, - proxy.proxy().user().str(), proxy.proxy().password().str(), - std::move(callback), create_reference(token))}; - } else if (secret.emulate_tls()) { - children_[token] = {false, create_actor("PingTlsInit", std::move(socket_fd), extra.mtproto_ip, - secret.get_domain(), secret.get_proxy_secret().str(), - std::move(callback), create_reference(token), - G()->get_dns_time_difference())}; - } else { - UNREACHABLE(); - } - } else { - socket_fd_promise.set_value(std::move(socket_fd)); + 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)); + if (!ref.empty()) { + children_[token] = {false, std::move(ref)}; } } @@ -726,17 +627,19 @@ void ConnectionCreator::request_raw_connection_by_ip(IPAddress ip_address, mtpro } auto socket_fd = r_socket_fd.move_as_ok(); - auto socket_fd_promise = - PromiseCreator::lambda([promise = std::move(promise), actor_id = actor_id(this), transport_type, - network_generation = network_generation_](Result r_socket_fd) mutable { - if (r_socket_fd.is_error()) { - return promise.set_error(Status::Error(400, r_socket_fd.error().public_message())); + auto connection_promise = PromiseCreator::lambda( + [promise = std::move(promise), actor_id = actor_id(this), transport_type, + network_generation = network_generation_](Result r_connection_data) mutable { + if (r_connection_data.is_error()) { + return promise.set_error(Status::Error(400, r_connection_data.error().public_message())); } - auto raw_connection = make_unique(r_socket_fd.move_as_ok(), transport_type, nullptr); + auto raw_connection = + make_unique(r_connection_data.move_as_ok().socket_fd, transport_type, nullptr); raw_connection->extra_ = network_generation; promise.set_value(std::move(raw_connection)); }); +<<<<<<< HEAD if (transport_type.secret.emulate_tls()) { class Callback : public TransparentProxy::Callback { public: @@ -762,6 +665,13 @@ void ConnectionCreator::request_raw_connection_by_ip(IPAddress ip_address, mtpro create_reference(token), G()->get_dns_time_difference())}; } else { socket_fd_promise.set_value(std::move(socket_fd)); +======= + 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)); + if (!ref.empty()) { + children_[token] = {false, std::move(ref)}; +>>>>>>> td_api: TestProxy query draft } } @@ -832,6 +742,82 @@ Result ConnectionCreator::find_connection(const ProxyInfo &proxy, DcId } } +ActorOwn<> ConnectionCreator::prepare_connection(SocketFd socket_fd, const ProxyInfo &proxy, + mtproto::TransportType transport_type, string debug_str, + IPAddress mtproto_ip, + unique_ptr stats_callback, + 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; + class Callback : public TransparentProxy::Callback { + public: + explicit Callback(Promise promise, + unique_ptr stats_callback, bool use_connection_token) + : promise_(std::move(promise)) + , stats_callback_(std::move(stats_callback)) + , use_connection_token_(use_connection_token) { + } + void set_result(Result result) override { + if (result.is_error()) { + if (use_connection_token_) { + connection_token_ = StateManager::ConnectionToken(); + } + if (was_connected_ && stats_callback_) { + stats_callback_->on_error(); + } + promise_.set_error(result.move_as_error()); + } else { + ConnectionData data; + data.socket_fd = result.move_as_ok(); + data.connection_token = std::move(connection_token_); + data.stats_callback = std::move(stats_callback_); + promise_.set_value(std::move(data)); + } + } + void on_connected() override { + if (use_connection_token_) { + connection_token_ = StateManager::connection_proxy(G()->state_manager()); + } + was_connected_ = true; + } + + private: + Promise promise_; + StateManager::ConnectionToken connection_token_; + bool was_connected_{false}; + unique_ptr stats_callback_; + bool use_connection_token_; + }; + 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); + 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))); + } else if (proxy.use_http_tcp_proxy()) { + return ActorOwn<>(create_actor("HttpProxy", std::move(socket_fd), mtproto_ip, + 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())); + } else { + UNREACHABLE(); + } + } else { + VLOG(connections) << "In client_loop: create new direct connection " << debug_str; + + ConnectionData data; + data.socket_fd = std::move(socket_fd); + data.stats_callback = std::move(stats_callback); + promise.set_result(std::move(data)); + return {}; + } +} + void ConnectionCreator::client_loop(ClientInfo &client) { CHECK(client.hash != 0); if (!network_flag_) { @@ -953,6 +939,7 @@ void ConnectionCreator::client_loop(ClientInfo &client) { auto stats_callback = td::make_unique(client.is_media ? media_net_stats_callback_ : common_net_stats_callback_, actor_id(this), client.hash, extra.stat); +<<<<<<< HEAD if (proxy.use_socks5_proxy() || proxy.use_http_tcp_proxy() || secret.emulate_tls()) { VLOG(connections) << "In client_loop: create new transparent proxy connection " << extra.debug_str; @@ -1014,6 +1001,13 @@ void ConnectionCreator::client_loop(ClientInfo &client) { data.socket_fd = std::move(socket_fd); data.stats_callback = std::move(stats_callback); promise.set_result(std::move(data)); +======= + auto token = next_token(); + auto ref = prepare_connection(std::move(socket_fd), proxy, extra.transport_type, extra.debug_str, extra.mtproto_ip, + std::move(stats_callback), create_reference(token), true, std::move(promise)); + if (!ref.empty()) { + children_[token] = {true, std::move(ref)}; +>>>>>>> td_api: TestProxy query draft } } } diff --git a/td/telegram/net/ConnectionCreator.h b/td/telegram/net/ConnectionCreator.h index 74a5bca28..662b99d09 100644 --- a/td/telegram/net/ConnectionCreator.h +++ b/td/telegram/net/ConnectionCreator.h @@ -18,6 +18,7 @@ #include "td/mtproto/AuthData.h" #include "td/mtproto/TransportType.h" +#include "td/mtproto/RawConnection.h" #include "td/net/NetStats.h" @@ -83,6 +84,52 @@ class ConnectionCreator : public NetQueryCallback { void get_proxy_link(int32 proxy_id, Promise promise); void ping_proxy(int32 proxy_id, Promise promise); + struct ConnectionData { + SocketFd socket_fd; + StateManager::ConnectionToken connection_token; + unique_ptr stats_callback; + }; + class ProxyInfo { + public: + ProxyInfo(Proxy *proxy, IPAddress ip_address) : proxy_(proxy), ip_address_(std::move(ip_address)) { + } + bool use_proxy() const { + return proxy_ != nullptr; + } + Proxy::Type proxy_type() const { + return proxy_ == nullptr ? Proxy::Type::None : proxy_->type(); + } + bool use_socks5_proxy() const { + return proxy_type() == Proxy::Type::Socks5; + } + bool use_http_tcp_proxy() const { + return proxy_type() == Proxy::Type::HttpTcp; + } + bool use_http_caching_proxy() const { + return proxy_type() == Proxy::Type::HttpCaching; + } + bool use_mtproto_proxy() const { + return proxy_type() == Proxy::Type::Mtproto; + } + const Proxy &proxy() const { + CHECK(use_proxy()); + return *proxy_; + } + const IPAddress &ip_address() const { + return ip_address_; + } + + private: + Proxy *proxy_; + IPAddress ip_address_; + }; + + static ActorOwn<> prepare_connection(SocketFd socket_fd, const ProxyInfo &proxy, + mtproto::TransportType transport_type, string debug_str, IPAddress mtproto_ip, + unique_ptr stats_callback, + ActorShared<> parent, bool use_connection_token, + Promise promise); + private: ActorShared<> parent_; DcOptionsSet dc_options_set_; @@ -207,11 +254,6 @@ class ConnectionCreator : public NetQueryCallback { void client_wakeup(size_t hash); void client_loop(ClientInfo &client); - struct ConnectionData { - SocketFd socket_fd; - StateManager::ConnectionToken connection_token; - unique_ptr stats_callback; - }; void client_create_raw_connection(Result r_connection_data, bool check_mode, mtproto::TransportType transport_type, size_t hash, string debug_str, uint32 network_generation); @@ -234,7 +276,6 @@ class ConnectionCreator : public NetQueryCallback { IPAddress mtproto_ip; bool check_mode{false}; }; - class ProxyInfo; static Result get_transport_type(const ProxyInfo &proxy, const DcOptionsSet::ConnectionInfo &info); diff --git a/td/telegram/net/Proxy.cpp b/td/telegram/net/Proxy.cpp new file mode 100644 index 000000000..aedcd275b --- /dev/null +++ b/td/telegram/net/Proxy.cpp @@ -0,0 +1,48 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2019 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// 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) { + if (proxy_type == nullptr) { + return Status::Error(400, "Proxy type should not be empty"); + } + if (server.empty()) { + return Status::Error(400, "Server name can't be empty"); + } + if (port <= 0 || port > 65535) { + return Status::Error(400, "Wrong port number"); + } + + Proxy new_proxy; + switch (proxy_type->get_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; + } + case td_api::proxyTypeHttp::ID: { + auto type = td_api::move_object_as(proxy_type); + if (type->http_only_) { + new_proxy = Proxy::http_caching(server, port, type->username_, type->password_); + } else { + new_proxy = Proxy::http_tcp(server, port, type->username_, type->password_); + } + break; + } + case td_api::proxyTypeMtproto::ID: { + auto type = td_api::move_object_as(proxy_type); + TRY_RESULT(secret, mtproto::ProxySecret::from_link(type->secret_)); + new_proxy = Proxy::mtproto(server, port, secret); + break; + } + default: + UNREACHABLE(); + } + return new_proxy; +} +} // namespace td diff --git a/td/telegram/net/Proxy.h b/td/telegram/net/Proxy.h index 43840cf80..267d37880 100644 --- a/td/telegram/net/Proxy.h +++ b/td/telegram/net/Proxy.h @@ -13,10 +13,18 @@ #include "td/utils/StringBuilder.h" #include "td/utils/tl_helpers.h" +#include "td/tl/TlObject.h" + namespace td { +namespace td_api { +class ProxyType; +} + class Proxy { public: + static Result from_td_api(string server, int port, tl_object_ptr proxy_type); + static Proxy socks5(string server, int32 port, string user, string password) { Proxy proxy; proxy.type_ = Type::Socks5;