Add proxyMtproto to td_api.

GitOrigin-RevId: c872c063bc6e5d94c80ac1daa6b916f8ce5f4c23
This commit is contained in:
levlam 2018-05-08 17:48:30 +03:00
parent 63695490e0
commit 98289b9963
7 changed files with 84 additions and 30 deletions

View File

@ -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 //@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; 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 //@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; inputSticker png_sticker:InputFile emojis:string mask_position:maskPosition = InputSticker;

Binary file not shown.

View File

@ -3062,9 +3062,13 @@ class CliClient final : public Actor {
std::tie(server, args) = split(args); std::tie(server, args) = split(args);
std::tie(port, args) = split(args); std::tie(port, args) = split(args);
std::tie(user, password) = split(args); std::tie(user, password) = split(args);
if (!user.empty() && password.empty()) {
send_request(make_tl_object<td_api::setProxy>( send_request(make_tl_object<td_api::setProxy>(
make_tl_object<td_api::proxySocks5>(server, to_integer<int32>(port), user, password))); make_tl_object<td_api::proxyMtproto>(server, to_integer<int32>(port), user)));
} else {
send_request(make_tl_object<td_api::setProxy>(
make_tl_object<td_api::proxySocks5>(server, to_integer<int32>(port), user, password)));
}
} else if (op == "gproxy") { } else if (op == "gproxy") {
send_request(make_tl_object<td_api::getProxy>()); send_request(make_tl_object<td_api::getProxy>());
} else if (op == "touch") { } else if (op == "touch") {

View File

@ -49,10 +49,14 @@ class StatsCallback final : public mtproto::RawConnection::StatsCallback {
} }
void on_pong() final { 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 { 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 { void on_mtproto_error() final {
@ -150,6 +154,10 @@ void Proxy::parse(T &parser) {
parse(port_, parser); parse(port_, parser);
parse(user_, parser); parse(user_, parser);
parse(password_, parser); parse(password_, parser);
} else if (type_ == Proxy::Type::Mtproto) {
parse(server_, parser);
parse(port_, parser);
parse(secret_, parser);
} else { } else {
CHECK(type_ == Proxy::Type::None); CHECK(type_ == Proxy::Type::None);
} }
@ -164,6 +172,10 @@ void Proxy::store(T &storer) const {
store(port_, storer); store(port_, storer);
store(user_, storer); store(user_, storer);
store(password_, storer); store(password_, storer);
} else if (type_ == Proxy::Type::Mtproto) {
store(server_, storer);
store(port_, storer);
store(secret_, storer);
} else { } else {
CHECK(type_ == Proxy::Type::None); CHECK(type_ == Proxy::Type::None);
} }
@ -304,8 +316,11 @@ void ConnectionCreator::client_loop(ClientInfo &client) {
if (close_flag_) { if (close_flag_) {
return; return;
} }
bool use_socks5 = proxy_.type() == Proxy::Type::Socks5; auto proxy_type = proxy_.type();
if (use_socks5 && !proxy_ip_address_.is_valid()) { 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; return;
} }
@ -335,7 +350,7 @@ void ConnectionCreator::client_loop(ClientInfo &client) {
} }
// Main loop. Create new connections till needed // 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) { while (true) {
// Check if we need new connections // Check if we need new connections
if (client.queries.empty()) { if (client.queries.empty()) {
@ -377,7 +392,18 @@ void ConnectionCreator::client_loop(ClientInfo &client) {
// sync part // sync part
auto r_socket_fd = [&, dc_id = client.dc_id, allow_media_only = client.allow_media_only]() -> Result<SocketFd> { auto r_socket_fd = [&, dc_id = client.dc_id, allow_media_only = client.allow_media_only]() -> Result<SocketFd> {
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<int16>(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; stat = info.stat;
if (info.use_http) { if (info.use_http) {
transport_type = {mtproto::TransportType::Http, 0, ""}; transport_type = {mtproto::TransportType::Http, 0, ""};
@ -387,16 +413,14 @@ void ConnectionCreator::client_loop(ClientInfo &client) {
} }
check_mode |= info.should_check; check_mode |= info.should_check;
if (use_socks5) { if (use_socks5_proxy) {
mtproto_ip = info.option->get_ip_address(); mtproto_ip = info.option->get_ip_address();
IPAddress socks5_ip; debug_str = PSTRING() << "Sock5 " << proxy_ip_address_ << " --> " << mtproto_ip << " " << dc_id;
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" : "");
LOG(INFO) << "Create: " << debug_str; LOG(INFO) << "Create: " << debug_str;
return SocketFd::open(socks5_ip); return SocketFd::open(proxy_ip_address_);
} else { } 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; LOG(INFO) << "Create: " << debug_str;
return SocketFd::open(info.option->get_ip_address()); return SocketFd::open(info.option->get_ip_address());
} }
@ -413,14 +437,16 @@ void ConnectionCreator::client_loop(ClientInfo &client) {
IPAddress debug_ip; IPAddress debug_ip;
auto debug_ip_status = debug_ip.init_socket_address(socket_fd); auto debug_ip_status = debug_ip.init_socket_address(socket_fd);
if (debug_ip_status.is_ok()) { if (debug_ip_status.is_ok()) {
debug_str = PSTRING() << debug_str << debug_ip; debug_str = PSTRING() << debug_str << " from " << debug_ip;
} else { } else {
LOG(ERROR) << debug_ip_status; LOG(ERROR) << debug_ip_status;
} }
client.pending_connections++; client.pending_connections++;
if (check_mode) { if (check_mode) {
stat->on_check(); if (stat) {
stat->on_check();
}
client.checking_connections++; client.checking_connections++;
} }
@ -434,7 +460,7 @@ void ConnectionCreator::client_loop(ClientInfo &client) {
auto stats_callback = std::make_unique<detail::StatsCallback>( auto stats_callback = std::make_unique<detail::StatsCallback>(
client.is_media ? media_net_stats_callback_ : common_net_stats_callback_, actor_id(this), client.hash, stat); 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 { class Callback : public Socks5::Callback {
public: public:
explicit Callback(Promise<ConnectionData> promise, std::unique_ptr<detail::StatsCallback> stats_callback) explicit Callback(Promise<ConnectionData> promise, std::unique_ptr<detail::StatsCallback> stats_callback)
@ -675,7 +701,7 @@ void ConnectionCreator::loop() {
if (!network_flag_) { if (!network_flag_) {
return; return;
} }
if (proxy_.type() != Proxy::Type::Socks5) { if (proxy_.type() == Proxy::Type::None) {
return; return;
} }
if (resolve_proxy_query_token_ != 0) { if (resolve_proxy_query_token_ != 0) {
@ -702,11 +728,12 @@ void ConnectionCreator::on_proxy_resolved(Result<IPAddress> r_ip_address, bool d
} }
resolve_proxy_query_token_ = 0; resolve_proxy_query_token_ = 0;
if (r_ip_address.is_error()) { if (r_ip_address.is_error()) {
resolve_proxy_timestamp_ = Timestamp::in(5 * 60); resolve_proxy_timestamp_ = Timestamp::in(1 * 60);
return; return;
} }
proxy_ip_address_ = r_ip_address.move_as_ok(); 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_) { for (auto &client : clients_) {
client_loop(client.second); client_loop(client.second);
} }

View File

@ -52,6 +52,8 @@ class Proxy {
return make_tl_object<td_api::proxyEmpty>(); return make_tl_object<td_api::proxyEmpty>();
case Type::Socks5: case Type::Socks5:
return make_tl_object<td_api::proxySocks5>(server_, port_, user_, password_); return make_tl_object<td_api::proxySocks5>(server_, port_, user_, password_);
case Type::Mtproto:
return make_tl_object<td_api::proxyMtproto>(server_, port_, secret_);
} }
UNREACHABLE(); UNREACHABLE();
return nullptr; return nullptr;
@ -69,6 +71,10 @@ class Proxy {
auto &socks5_proxy = static_cast<const td_api::proxySocks5 &>(*proxy); auto &socks5_proxy = static_cast<const td_api::proxySocks5 &>(*proxy);
return Proxy::socks5(socks5_proxy.server_, socks5_proxy.port_, socks5_proxy.username_, socks5_proxy.password_); 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<const td_api::proxyMtproto &>(*proxy);
return Proxy::mtproto(mtproto_proxy.server_, mtproto_proxy.port_, mtproto_proxy.secret_);
}
} }
UNREACHABLE(); UNREACHABLE();
return Proxy(); return Proxy();
@ -84,6 +90,15 @@ class Proxy {
return 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 { CSlice server() const {
return server_; return server_;
} }
@ -100,7 +115,11 @@ class Proxy {
return password_; return password_;
} }
enum class Type : int32 { None, Socks5 }; CSlice secret() const {
return secret_;
}
enum class Type : int32 { None, Socks5, Mtproto };
Type type() const { Type type() const {
return type_; return type_;
} }
@ -117,11 +136,12 @@ class Proxy {
int32 port_ = 0; int32 port_ = 0;
string user_; string user_;
string password_; string password_;
string secret_;
}; };
inline bool operator==(const Proxy &lhs, const Proxy &rhs) { inline bool operator==(const Proxy &lhs, const Proxy &rhs) {
return lhs.type() == rhs.type() && lhs.server() == rhs.server() && lhs.port() == rhs.port() && 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) { inline bool operator!=(const Proxy &lhs, const Proxy &rhs) {

View File

@ -28,11 +28,9 @@ class HeaderStorer {
// system_lang_code:string lang_pack:string lang_code:string proxy:flags.0?InputClientProxy query:!X = X; // system_lang_code:string lang_pack:string lang_code:string proxy:flags.0?InputClientProxy query:!X = X;
store(static_cast<int32>(0x785188b8), storer); store(static_cast<int32>(0x785188b8), storer);
int32 flags = 0; int32 flags = 0;
/* if (!is_anonymous && options.proxy.type() == Proxy::Type::Mtproto) {
if (!is_anonymous && proxy.type() == Proxy::Type::Mtproto) {
flags |= 1 << 0; flags |= 1 << 0;
} }
*/
store(flags, storer); store(flags, storer);
store(options.api_id, storer); store(options.api_id, storer);
if (is_anonymous) { if (is_anonymous) {
@ -47,7 +45,10 @@ class HeaderStorer {
store(string(), storer); store(string(), storer);
store(string(), storer); store(string(), storer);
if ((flags & 1) != 0) { if ((flags & 1) != 0) {
// TODO // inputClientProxy#75588b3f address:string port:int = InputClientProxy;
store(static_cast<int32>(0x75588b3f), storer);
store(Slice(options.proxy.server()), storer);
store(options.proxy.port(), storer);
} }
} }

View File

@ -6,7 +6,6 @@
// //
#include "td/net/Socks5.h" #include "td/net/Socks5.h"
#include "td/utils/format.h"
#include "td/utils/logging.h" #include "td/utils/logging.h"
#include "td/utils/misc.h" #include "td/utils/misc.h"
#include "td/utils/port/Fd.h" #include "td/utils/port/Fd.h"
@ -183,7 +182,7 @@ Status Socks5::wait_ip_address_response() {
} }
it.advance(1, c_slice); it.advance(1, c_slice);
if (c != '\0') { if (c != '\0') {
return Status::Error(PSLICE() << tag("code", c)); return Status::Error(PSLICE() << "Receive error code " << static_cast<int32>(c) << " from server");
} }
it.advance(1, c_slice); it.advance(1, c_slice);
if (c != '\0') { if (c != '\0') {