From 98289b9963c9078d7e0ec9de6039b6f60308060a Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 8 May 2018 17:48:30 +0300 Subject: [PATCH] Add proxyMtproto to td_api. GitOrigin-RevId: c872c063bc6e5d94c80ac1daa6b916f8ce5f4c23 --- td/generate/scheme/td_api.tl | 3 ++ td/generate/scheme/td_api.tlo | Bin 124724 -> 124876 bytes td/telegram/cli.cpp | 10 ++-- td/telegram/net/ConnectionCreator.cpp | 65 ++++++++++++++++++-------- td/telegram/net/ConnectionCreator.h | 24 +++++++++- td/telegram/net/MtprotoHeader.cpp | 9 ++-- tdnet/td/net/Socks5.cpp | 3 +- 7 files changed, 84 insertions(+), 30 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index a049b9a2..79f7738a 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2001,6 +2001,9 @@ proxyEmpty = Proxy; //@description A SOCKS5 proxy server @server Proxy server IP address @port Proxy server port @username Username for logging in @password Password for logging in proxySocks5 server:string port:int32 username:string password:string = Proxy; +//@description An MTProro proxy server @server Proxy server IP address @port Proxy server port @secret Server's secret +proxyMtproto server:string port:int32 secret:string = Proxy; + //@description Describes a sticker that should be added to a sticker set @png_sticker PNG image with the sticker; must be up to 512 kB in size and fit in a 512x512 square @emojis Emoji corresponding to the sticker @mask_position For masks, position where the mask should be placed; may be null inputSticker png_sticker:InputFile emojis:string mask_position:maskPosition = InputSticker; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 98fbf587803a94ebbe9ec0e1d349062abcbf8042..0ba96127c7a4d3c7c021478c9cebb648e4f60bd0 100644 GIT binary patch delta 210 zcmdmTj{VGe_6;9Ic#|7`v$F;iO6!oVF8J5{_yR=VhNZ$$TDOHY=1F}(Zm|8aJ#}aMiD^( DOV3NL delta 158 zcmX?eo_)(X_6;9Ic-PGhu3`-+%CD$oU|^bD$SA&9L{x&C(P^`;!uzWhAlaM8gnSr) zpvaj`hr_n*AV>_v2Z5_{Trm>Y&xdgrfJ_L^PtGnj1<6ki`8IN{lQ`hT*ho~ Yn9XQn%?dVg`o>H~`RzBZF@6yM0PaaU$^ZZW diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index f7545f38..0a897ea8 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3062,9 +3062,13 @@ class CliClient final : public Actor { std::tie(server, args) = split(args); std::tie(port, args) = split(args); std::tie(user, password) = split(args); - - send_request(make_tl_object( - make_tl_object(server, to_integer(port), user, password))); + if (!user.empty() && password.empty()) { + send_request(make_tl_object( + make_tl_object(server, to_integer(port), user))); + } else { + send_request(make_tl_object( + make_tl_object(server, to_integer(port), user, password))); + } } else if (op == "gproxy") { send_request(make_tl_object()); } else if (op == "touch") { diff --git a/td/telegram/net/ConnectionCreator.cpp b/td/telegram/net/ConnectionCreator.cpp index 8ae8a3cb..4a31bb27 100644 --- a/td/telegram/net/ConnectionCreator.cpp +++ b/td/telegram/net/ConnectionCreator.cpp @@ -49,10 +49,14 @@ class StatsCallback final : public mtproto::RawConnection::StatsCallback { } void on_pong() final { - send_lambda(connection_creator_, [stat = option_stat_] { stat->on_ok(); }); + if (option_stat_) { + send_lambda(connection_creator_, [stat = option_stat_] { stat->on_ok(); }); + } } void on_error() final { - send_lambda(connection_creator_, [stat = option_stat_] { stat->on_error(); }); + if (option_stat_) { + send_lambda(connection_creator_, [stat = option_stat_] { stat->on_error(); }); + } } void on_mtproto_error() final { @@ -150,6 +154,10 @@ void Proxy::parse(T &parser) { parse(port_, parser); parse(user_, parser); parse(password_, parser); + } else if (type_ == Proxy::Type::Mtproto) { + parse(server_, parser); + parse(port_, parser); + parse(secret_, parser); } else { CHECK(type_ == Proxy::Type::None); } @@ -164,6 +172,10 @@ void Proxy::store(T &storer) const { store(port_, storer); store(user_, storer); store(password_, storer); + } else if (type_ == Proxy::Type::Mtproto) { + store(server_, storer); + store(port_, storer); + store(secret_, storer); } else { CHECK(type_ == Proxy::Type::None); } @@ -304,8 +316,11 @@ void ConnectionCreator::client_loop(ClientInfo &client) { if (close_flag_) { return; } - bool use_socks5 = proxy_.type() == Proxy::Type::Socks5; - if (use_socks5 && !proxy_ip_address_.is_valid()) { + auto proxy_type = proxy_.type(); + bool use_proxy = proxy_type != Proxy::Type::None; + bool use_socks5_proxy = proxy_type == Proxy::Type::Socks5; + bool use_mtproto_proxy = proxy_type == Proxy::Type::Mtproto; + if (use_proxy && !proxy_ip_address_.is_valid()) { return; } @@ -335,7 +350,7 @@ void ConnectionCreator::client_loop(ClientInfo &client) { } // Main loop. Create new connections till needed - bool check_mode = client.checking_connections != 0; + bool check_mode = client.checking_connections != 0 && !use_proxy; while (true) { // Check if we need new connections if (client.queries.empty()) { @@ -377,7 +392,18 @@ void ConnectionCreator::client_loop(ClientInfo &client) { // sync part auto r_socket_fd = [&, dc_id = client.dc_id, allow_media_only = client.allow_media_only]() -> Result { - TRY_RESULT(info, dc_options_set_.find_connection(dc_id, allow_media_only, use_socks5)); + if (use_mtproto_proxy) { + TRY_RESULT(info, dc_options_set_.find_connection(dc_id, allow_media_only, use_proxy)); + stat = nullptr; + int16 raw_dc_id = narrow_cast(info.option->is_media_only() ? -dc_id.get_raw_id() : dc_id.get_raw_id()); + transport_type = {mtproto::TransportType::ObfuscatedTcp, raw_dc_id, proxy_.secret().str()}; + + debug_str = PSTRING() << "Mtproto " << proxy_ip_address_ << " to DC" << raw_dc_id; + LOG(INFO) << "Create: " << debug_str; + return SocketFd::open(proxy_ip_address_); + } + + TRY_RESULT(info, dc_options_set_.find_connection(dc_id, allow_media_only, use_proxy)); stat = info.stat; if (info.use_http) { transport_type = {mtproto::TransportType::Http, 0, ""}; @@ -387,16 +413,14 @@ void ConnectionCreator::client_loop(ClientInfo &client) { } check_mode |= info.should_check; - if (use_socks5) { + if (use_socks5_proxy) { mtproto_ip = info.option->get_ip_address(); - IPAddress socks5_ip; - TRY_STATUS(socks5_ip.init_host_port(proxy_.server(), proxy_.port())); - debug_str = PSTRING() << "Sock5 " << socks5_ip << " --> " << info.option->get_ip_address() << " " << dc_id - << (info.use_http ? " HTTP" : ""); + debug_str = PSTRING() << "Sock5 " << proxy_ip_address_ << " --> " << mtproto_ip << " " << dc_id; LOG(INFO) << "Create: " << debug_str; - return SocketFd::open(socks5_ip); + return SocketFd::open(proxy_ip_address_); } else { - debug_str = PSTRING() << info.option->get_ip_address() << " " << dc_id << (info.use_http ? " HTTP" : ""); + debug_str = PSTRING() << info.option->get_ip_address() << " " << dc_id << (info.use_http ? " HTTP" : "") + << (info.option->is_media_only() ? " MEDIA" : ""); LOG(INFO) << "Create: " << debug_str; return SocketFd::open(info.option->get_ip_address()); } @@ -413,14 +437,16 @@ void ConnectionCreator::client_loop(ClientInfo &client) { IPAddress debug_ip; auto debug_ip_status = debug_ip.init_socket_address(socket_fd); if (debug_ip_status.is_ok()) { - debug_str = PSTRING() << debug_str << debug_ip; + debug_str = PSTRING() << debug_str << " from " << debug_ip; } else { LOG(ERROR) << debug_ip_status; } client.pending_connections++; if (check_mode) { - stat->on_check(); + if (stat) { + stat->on_check(); + } client.checking_connections++; } @@ -434,7 +460,7 @@ void ConnectionCreator::client_loop(ClientInfo &client) { auto stats_callback = std::make_unique( client.is_media ? media_net_stats_callback_ : common_net_stats_callback_, actor_id(this), client.hash, stat); - if (use_socks5) { + if (use_socks5_proxy) { class Callback : public Socks5::Callback { public: explicit Callback(Promise promise, std::unique_ptr stats_callback) @@ -675,7 +701,7 @@ void ConnectionCreator::loop() { if (!network_flag_) { return; } - if (proxy_.type() != Proxy::Type::Socks5) { + if (proxy_.type() == Proxy::Type::None) { return; } if (resolve_proxy_query_token_ != 0) { @@ -702,11 +728,12 @@ void ConnectionCreator::on_proxy_resolved(Result r_ip_address, bool d } resolve_proxy_query_token_ = 0; if (r_ip_address.is_error()) { - resolve_proxy_timestamp_ = Timestamp::in(5 * 60); + resolve_proxy_timestamp_ = Timestamp::in(1 * 60); return; } proxy_ip_address_ = r_ip_address.move_as_ok(); - resolve_proxy_timestamp_ = Timestamp::in(29 * 60); + proxy_ip_address_.set_port(proxy_.port()); + resolve_proxy_timestamp_ = Timestamp::in(5 * 60); for (auto &client : clients_) { client_loop(client.second); } diff --git a/td/telegram/net/ConnectionCreator.h b/td/telegram/net/ConnectionCreator.h index 7d9096ce..403b8ea8 100644 --- a/td/telegram/net/ConnectionCreator.h +++ b/td/telegram/net/ConnectionCreator.h @@ -52,6 +52,8 @@ class Proxy { return make_tl_object(); case Type::Socks5: return make_tl_object(server_, port_, user_, password_); + case Type::Mtproto: + return make_tl_object(server_, port_, secret_); } UNREACHABLE(); return nullptr; @@ -69,6 +71,10 @@ class Proxy { auto &socks5_proxy = static_cast(*proxy); return Proxy::socks5(socks5_proxy.server_, socks5_proxy.port_, socks5_proxy.username_, socks5_proxy.password_); } + case td_api::proxyMtproto::ID: { + auto &mtproto_proxy = static_cast(*proxy); + return Proxy::mtproto(mtproto_proxy.server_, mtproto_proxy.port_, mtproto_proxy.secret_); + } } UNREACHABLE(); return Proxy(); @@ -84,6 +90,15 @@ class Proxy { return proxy; } + static Proxy mtproto(string server, int32 port, string secret) { + Proxy proxy; + proxy.type_ = Type::Mtproto; + proxy.server_ = std::move(server); + proxy.port_ = std::move(port); + proxy.secret_ = std::move(secret); + return proxy; + } + CSlice server() const { return server_; } @@ -100,7 +115,11 @@ class Proxy { return password_; } - enum class Type : int32 { None, Socks5 }; + CSlice secret() const { + return secret_; + } + + enum class Type : int32 { None, Socks5, Mtproto }; Type type() const { return type_; } @@ -117,11 +136,12 @@ class Proxy { int32 port_ = 0; string user_; string password_; + string secret_; }; inline bool operator==(const Proxy &lhs, const Proxy &rhs) { return lhs.type() == rhs.type() && lhs.server() == rhs.server() && lhs.port() == rhs.port() && - lhs.user() == rhs.user() && lhs.password() == rhs.password(); + lhs.user() == rhs.user() && lhs.password() == rhs.password() && lhs.secret() == rhs.secret(); } inline bool operator!=(const Proxy &lhs, const Proxy &rhs) { diff --git a/td/telegram/net/MtprotoHeader.cpp b/td/telegram/net/MtprotoHeader.cpp index 12d81815..ac310ba1 100644 --- a/td/telegram/net/MtprotoHeader.cpp +++ b/td/telegram/net/MtprotoHeader.cpp @@ -28,11 +28,9 @@ class HeaderStorer { // system_lang_code:string lang_pack:string lang_code:string proxy:flags.0?InputClientProxy query:!X = X; store(static_cast(0x785188b8), storer); int32 flags = 0; - /* - if (!is_anonymous && proxy.type() == Proxy::Type::Mtproto) { + if (!is_anonymous && options.proxy.type() == Proxy::Type::Mtproto) { flags |= 1 << 0; } - */ store(flags, storer); store(options.api_id, storer); if (is_anonymous) { @@ -47,7 +45,10 @@ class HeaderStorer { store(string(), storer); store(string(), storer); if ((flags & 1) != 0) { - // TODO + // inputClientProxy#75588b3f address:string port:int = InputClientProxy; + store(static_cast(0x75588b3f), storer); + store(Slice(options.proxy.server()), storer); + store(options.proxy.port(), storer); } } diff --git a/tdnet/td/net/Socks5.cpp b/tdnet/td/net/Socks5.cpp index 02e1e067..4170f573 100644 --- a/tdnet/td/net/Socks5.cpp +++ b/tdnet/td/net/Socks5.cpp @@ -6,7 +6,6 @@ // #include "td/net/Socks5.h" -#include "td/utils/format.h" #include "td/utils/logging.h" #include "td/utils/misc.h" #include "td/utils/port/Fd.h" @@ -183,7 +182,7 @@ Status Socks5::wait_ip_address_response() { } it.advance(1, c_slice); if (c != '\0') { - return Status::Error(PSLICE() << tag("code", c)); + return Status::Error(PSLICE() << "Receive error code " << static_cast(c) << " from server"); } it.advance(1, c_slice); if (c != '\0') {