Add support for transparent HTTP proxies.
GitOrigin-RevId: 5ae836625a60d1f84b0ca8df2c41bf07e8ba59fd
This commit is contained in:
parent
2ca3c7eeed
commit
a547f42886
@ -2051,6 +2051,9 @@ textParseModeHTML = TextParseMode;
|
|||||||
//@description A SOCKS5 proxy server @username Username for logging in; may be empty @password Password for logging in; may be empty
|
//@description A SOCKS5 proxy server @username Username for logging in; may be empty @password Password for logging in; may be empty
|
||||||
proxyTypeSocks5 username:string password:string = ProxyType;
|
proxyTypeSocks5 username:string password:string = ProxyType;
|
||||||
|
|
||||||
|
//@description A HTTP transparent proxy server @username Username for logging in; may be empty @password Password for logging in; may be empty
|
||||||
|
proxyTypeHttp username:string password:string = ProxyType;
|
||||||
|
|
||||||
//@description An MTProto proxy server @secret The proxy's secret in hexadecimal encoding
|
//@description An MTProto proxy server @secret The proxy's secret in hexadecimal encoding
|
||||||
proxyTypeMtproto secret:string = ProxyType;
|
proxyTypeMtproto secret:string = ProxyType;
|
||||||
|
|
||||||
|
Binary file not shown.
@ -3244,7 +3244,11 @@ class CliClient final : public Actor {
|
|||||||
if (!user.empty() && password.empty()) {
|
if (!user.empty() && password.empty()) {
|
||||||
type = make_tl_object<td_api::proxyTypeMtproto>(user);
|
type = make_tl_object<td_api::proxyTypeMtproto>(user);
|
||||||
} else {
|
} else {
|
||||||
type = make_tl_object<td_api::proxyTypeSocks5>(user, password);
|
if (port == "80") {
|
||||||
|
type = make_tl_object<td_api::proxyTypeHttp>(user, password);
|
||||||
|
} else {
|
||||||
|
type = make_tl_object<td_api::proxyTypeSocks5>(user, password);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
send_request(make_tl_object<td_api::addProxy>(server, to_integer<int32>(port), op == "aeproxy", std::move(type)));
|
send_request(make_tl_object<td_api::addProxy>(server, to_integer<int32>(port), op == "aeproxy", std::move(type)));
|
||||||
} else if (op == "gproxy" || op == "gproxies") {
|
} else if (op == "gproxy" || op == "gproxies") {
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "td/mtproto/RawConnection.h"
|
#include "td/mtproto/RawConnection.h"
|
||||||
|
|
||||||
#include "td/net/GetHostByNameActor.h"
|
#include "td/net/GetHostByNameActor.h"
|
||||||
|
#include "td/net/HttpProxy.h"
|
||||||
#include "td/net/Socks5.h"
|
#include "td/net/Socks5.h"
|
||||||
#include "td/net/TransparentProxy.h"
|
#include "td/net/TransparentProxy.h"
|
||||||
|
|
||||||
@ -174,6 +175,9 @@ class ConnectionCreator::ProxyInfo {
|
|||||||
bool use_socks5_proxy() const {
|
bool use_socks5_proxy() const {
|
||||||
return proxy_type() == Proxy::Type::Socks5;
|
return proxy_type() == Proxy::Type::Socks5;
|
||||||
}
|
}
|
||||||
|
bool use_http_proxy() const {
|
||||||
|
return proxy_type() == Proxy::Type::Http;
|
||||||
|
}
|
||||||
bool use_mtproto_proxy() const {
|
bool use_mtproto_proxy() const {
|
||||||
return proxy_type() == Proxy::Type::Mtproto;
|
return proxy_type() == Proxy::Type::Mtproto;
|
||||||
}
|
}
|
||||||
@ -194,7 +198,7 @@ template <class T>
|
|||||||
void Proxy::parse(T &parser) {
|
void Proxy::parse(T &parser) {
|
||||||
using td::parse;
|
using td::parse;
|
||||||
parse(type_, parser);
|
parse(type_, parser);
|
||||||
if (type_ == Proxy::Type::Socks5) {
|
if (type_ == Proxy::Type::Socks5 || type_ == Proxy::Type::Http) {
|
||||||
parse(server_, parser);
|
parse(server_, parser);
|
||||||
parse(port_, parser);
|
parse(port_, parser);
|
||||||
parse(user_, parser);
|
parse(user_, parser);
|
||||||
@ -212,7 +216,7 @@ template <class T>
|
|||||||
void Proxy::store(T &storer) const {
|
void Proxy::store(T &storer) const {
|
||||||
using td::store;
|
using td::store;
|
||||||
store(type_, storer);
|
store(type_, storer);
|
||||||
if (type_ == Proxy::Type::Socks5) {
|
if (type_ == Proxy::Type::Socks5 || type_ == Proxy::Type::Http) {
|
||||||
store(server_, storer);
|
store(server_, storer);
|
||||||
store(port_, storer);
|
store(port_, storer);
|
||||||
store(user_, storer);
|
store(user_, storer);
|
||||||
@ -230,6 +234,8 @@ StringBuilder &operator<<(StringBuilder &string_builder, const Proxy &proxy) {
|
|||||||
switch (proxy.type()) {
|
switch (proxy.type()) {
|
||||||
case Proxy::Type::Socks5:
|
case Proxy::Type::Socks5:
|
||||||
return string_builder << "ProxySocks5 " << proxy.server() << ":" << proxy.port();
|
return string_builder << "ProxySocks5 " << proxy.server() << ":" << proxy.port();
|
||||||
|
case Proxy::Type::Http:
|
||||||
|
return string_builder << "ProxyHttp " << proxy.server() << ":" << proxy.port();
|
||||||
case Proxy::Type::Mtproto:
|
case Proxy::Type::Mtproto:
|
||||||
return string_builder << "ProxyMtproto " << proxy.server() << ":" << proxy.port() << "/" << proxy.secret();
|
return string_builder << "ProxyMtproto " << proxy.server() << ":" << proxy.port() << "/" << proxy.secret();
|
||||||
case Proxy::Type::None:
|
case Proxy::Type::None:
|
||||||
@ -298,6 +304,11 @@ void ConnectionCreator::add_proxy(string server, int32 port, bool enable,
|
|||||||
new_proxy = Proxy::socks5(server, port, type->username_, type->password_);
|
new_proxy = Proxy::socks5(server, port, type->username_, type->password_);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case td_api::proxyTypeHttp::ID: {
|
||||||
|
auto type = td_api::move_object_as<td_api::proxyTypeHttp>(proxy_type);
|
||||||
|
new_proxy = Proxy::http(server, port, type->username_, type->password_);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case td_api::proxyTypeMtproto::ID: {
|
case td_api::proxyTypeMtproto::ID: {
|
||||||
auto type = td_api::move_object_as<td_api::proxyTypeMtproto>(proxy_type);
|
auto type = td_api::move_object_as<td_api::proxyTypeMtproto>(proxy_type);
|
||||||
if (hex_decode(type->secret_).is_error()) {
|
if (hex_decode(type->secret_).is_error()) {
|
||||||
@ -384,6 +395,8 @@ void ConnectionCreator::get_proxy_link(int32 proxy_id, Promise<string> promise)
|
|||||||
url += "socks";
|
url += "socks";
|
||||||
is_socks = true;
|
is_socks = true;
|
||||||
break;
|
break;
|
||||||
|
case Proxy::Type::Http:
|
||||||
|
return promise.set_error(Status::Error(400, "HTTP proxy can't have public link"));
|
||||||
case Proxy::Type::Mtproto:
|
case Proxy::Type::Mtproto:
|
||||||
url += "proxy";
|
url += "proxy";
|
||||||
break;
|
break;
|
||||||
@ -493,7 +506,7 @@ void ConnectionCreator::ping_proxy_resolved(int32 proxy_id, IPAddress ip_address
|
|||||||
std::move(transport_type), std::move(promise));
|
std::move(transport_type), std::move(promise));
|
||||||
});
|
});
|
||||||
CHECK(proxy.use_proxy());
|
CHECK(proxy.use_proxy());
|
||||||
if (proxy.use_socks5_proxy()) {
|
if (proxy.use_socks5_proxy() || proxy.use_http_proxy()) {
|
||||||
class Callback : public TransparentProxy::Callback {
|
class Callback : public TransparentProxy::Callback {
|
||||||
public:
|
public:
|
||||||
explicit Callback(Promise<SocketFd> promise) : promise_(std::move(promise)) {
|
explicit Callback(Promise<SocketFd> promise) : promise_(std::move(promise)) {
|
||||||
@ -507,12 +520,19 @@ void ConnectionCreator::ping_proxy_resolved(int32 proxy_id, IPAddress ip_address
|
|||||||
private:
|
private:
|
||||||
Promise<SocketFd> promise_;
|
Promise<SocketFd> promise_;
|
||||||
};
|
};
|
||||||
LOG(INFO) << "Start socks5: " << extra.debug_str;
|
LOG(INFO) << "Start ping proxy: " << extra.debug_str;
|
||||||
auto token = next_token();
|
auto token = next_token();
|
||||||
children_[token] = {
|
if (proxy.use_socks5_proxy()) {
|
||||||
false, create_actor<Socks5>("PingSocks5", std::move(socket_fd), extra.mtproto_ip, proxy.proxy().user().str(),
|
children_[token] = {false, create_actor<Socks5>("PingSocks5", std::move(socket_fd), extra.mtproto_ip,
|
||||||
proxy.proxy().password().str(),
|
proxy.proxy().user().str(), proxy.proxy().password().str(),
|
||||||
std::make_unique<Callback>(std::move(socket_fd_promise)), create_reference(token))};
|
std::make_unique<Callback>(std::move(socket_fd_promise)),
|
||||||
|
create_reference(token))};
|
||||||
|
} else {
|
||||||
|
children_[token] = {false, create_actor<HttpProxy>("PingHttpProxy", std::move(socket_fd), extra.mtproto_ip,
|
||||||
|
proxy.proxy().user().str(), proxy.proxy().password().str(),
|
||||||
|
std::make_unique<Callback>(std::move(socket_fd_promise)),
|
||||||
|
create_reference(token))};
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
socket_fd_promise.set_value(std::move(socket_fd));
|
socket_fd_promise.set_value(std::move(socket_fd));
|
||||||
}
|
}
|
||||||
@ -574,7 +594,7 @@ void ConnectionCreator::disable_proxy_impl() {
|
|||||||
|
|
||||||
void ConnectionCreator::on_proxy_changed(bool from_db) {
|
void ConnectionCreator::on_proxy_changed(bool from_db) {
|
||||||
send_closure(G()->state_manager(), &StateManager::on_proxy,
|
send_closure(G()->state_manager(), &StateManager::on_proxy,
|
||||||
active_proxy_id_ != 0 && proxies_[active_proxy_id_].type() == Proxy::Type::Socks5);
|
active_proxy_id_ != 0 && proxies_[active_proxy_id_].type() != Proxy::Type::Mtproto);
|
||||||
|
|
||||||
if (!from_db) {
|
if (!from_db) {
|
||||||
for (auto &child : children_) {
|
for (auto &child : children_) {
|
||||||
@ -638,6 +658,9 @@ td_api::object_ptr<td_api::proxy> ConnectionCreator::get_proxy_object(int32 prox
|
|||||||
case Proxy::Type::Socks5:
|
case Proxy::Type::Socks5:
|
||||||
type = make_tl_object<td_api::proxyTypeSocks5>(proxy.user().str(), proxy.password().str());
|
type = make_tl_object<td_api::proxyTypeSocks5>(proxy.user().str(), proxy.password().str());
|
||||||
break;
|
break;
|
||||||
|
case Proxy::Type::Http:
|
||||||
|
type = make_tl_object<td_api::proxyTypeHttp>(proxy.user().str(), proxy.password().str());
|
||||||
|
break;
|
||||||
case Proxy::Type::Mtproto:
|
case Proxy::Type::Mtproto:
|
||||||
type = make_tl_object<td_api::proxyTypeMtproto>(proxy.secret().str());
|
type = make_tl_object<td_api::proxyTypeMtproto>(proxy.secret().str());
|
||||||
break;
|
break;
|
||||||
@ -776,9 +799,10 @@ Result<SocketFd> ConnectionCreator::find_connection(const ProxyInfo &proxy, DcId
|
|||||||
|
|
||||||
extra.check_mode |= info.should_check;
|
extra.check_mode |= info.should_check;
|
||||||
|
|
||||||
if (proxy.use_socks5_proxy()) {
|
if (proxy.use_socks5_proxy() || proxy.use_http_proxy()) {
|
||||||
extra.mtproto_ip = info.option->get_ip_address();
|
extra.mtproto_ip = info.option->get_ip_address();
|
||||||
extra.debug_str = PSTRING() << "Socks5 " << proxy.ip_address() << " --> " << extra.mtproto_ip << extra.debug_str;
|
extra.debug_str = PSTRING() << (proxy.use_socks5_proxy() ? "Socks5 " : "HTTP ") << proxy.ip_address() << " --> "
|
||||||
|
<< extra.mtproto_ip << extra.debug_str;
|
||||||
LOG(INFO) << "Create: " << extra.debug_str;
|
LOG(INFO) << "Create: " << extra.debug_str;
|
||||||
return SocketFd::open(proxy.ip_address());
|
return SocketFd::open(proxy.ip_address());
|
||||||
} else {
|
} else {
|
||||||
@ -905,7 +929,7 @@ void ConnectionCreator::client_loop(ClientInfo &client) {
|
|||||||
client.is_media ? media_net_stats_callback_ : common_net_stats_callback_, actor_id(this), client.hash,
|
client.is_media ? media_net_stats_callback_ : common_net_stats_callback_, actor_id(this), client.hash,
|
||||||
extra.stat);
|
extra.stat);
|
||||||
|
|
||||||
if (proxy.use_socks5_proxy()) {
|
if (proxy.use_socks5_proxy() || proxy.use_http_proxy()) {
|
||||||
class Callback : public TransparentProxy::Callback {
|
class Callback : public TransparentProxy::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)
|
||||||
@ -937,13 +961,21 @@ void ConnectionCreator::client_loop(ClientInfo &client) {
|
|||||||
bool was_connected_{false};
|
bool was_connected_{false};
|
||||||
std::unique_ptr<detail::StatsCallback> stats_callback_;
|
std::unique_ptr<detail::StatsCallback> stats_callback_;
|
||||||
};
|
};
|
||||||
LOG(INFO) << "Start socks5: " << extra.debug_str;
|
LOG(INFO) << "Start " << (proxy.use_socks5_proxy() ? "Socks5" : "HTTP") << ": " << extra.debug_str;
|
||||||
auto token = next_token();
|
auto token = next_token();
|
||||||
children_[token] = {
|
if (proxy.use_socks5_proxy()) {
|
||||||
true, create_actor<Socks5>("Socks5", std::move(socket_fd), extra.mtproto_ip, proxy.proxy().user().str(),
|
children_[token] = {
|
||||||
proxy.proxy().password().str(),
|
true, create_actor<Socks5>("Socks5", std::move(socket_fd), extra.mtproto_ip, proxy.proxy().user().str(),
|
||||||
std::make_unique<Callback>(std::move(promise), std::move(stats_callback)),
|
proxy.proxy().password().str(),
|
||||||
create_reference(token))};
|
std::make_unique<Callback>(std::move(promise), std::move(stats_callback)),
|
||||||
|
create_reference(token))};
|
||||||
|
} else {
|
||||||
|
children_[token] = {
|
||||||
|
true, create_actor<HttpProxy>("HttpProxy", std::move(socket_fd), extra.mtproto_ip,
|
||||||
|
proxy.proxy().user().str(), proxy.proxy().password().str(),
|
||||||
|
std::make_unique<Callback>(std::move(promise), std::move(stats_callback)),
|
||||||
|
create_reference(token))};
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ConnectionData data;
|
ConnectionData data;
|
||||||
data.socket_fd = std::move(socket_fd);
|
data.socket_fd = std::move(socket_fd);
|
||||||
|
@ -60,6 +60,16 @@ class Proxy {
|
|||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Proxy http(string server, int32 port, string user, string password) {
|
||||||
|
Proxy proxy;
|
||||||
|
proxy.type_ = Type::Http;
|
||||||
|
proxy.server_ = std::move(server);
|
||||||
|
proxy.port_ = std::move(port);
|
||||||
|
proxy.user_ = std::move(user);
|
||||||
|
proxy.password_ = std::move(password);
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
|
|
||||||
static Proxy mtproto(string server, int32 port, string secret) {
|
static Proxy mtproto(string server, int32 port, string secret) {
|
||||||
Proxy proxy;
|
Proxy proxy;
|
||||||
proxy.type_ = Type::Mtproto;
|
proxy.type_ = Type::Mtproto;
|
||||||
@ -89,7 +99,7 @@ class Proxy {
|
|||||||
return secret_;
|
return secret_;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Type : int32 { None, Socks5, Mtproto };
|
enum class Type : int32 { None, Socks5, Mtproto, Http };
|
||||||
Type type() const {
|
Type type() const {
|
||||||
return type_;
|
return type_;
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ set(TDNET_SOURCE
|
|||||||
td/net/HttpFile.cpp
|
td/net/HttpFile.cpp
|
||||||
td/net/HttpInboundConnection.cpp
|
td/net/HttpInboundConnection.cpp
|
||||||
td/net/HttpOutboundConnection.cpp
|
td/net/HttpOutboundConnection.cpp
|
||||||
|
td/net/HttpProxy.cpp
|
||||||
td/net/HttpQuery.cpp
|
td/net/HttpQuery.cpp
|
||||||
td/net/HttpReader.cpp
|
td/net/HttpReader.cpp
|
||||||
td/net/Socks5.cpp
|
td/net/Socks5.cpp
|
||||||
@ -30,6 +31,7 @@ set(TDNET_SOURCE
|
|||||||
td/net/HttpHeaderCreator.h
|
td/net/HttpHeaderCreator.h
|
||||||
td/net/HttpInboundConnection.h
|
td/net/HttpInboundConnection.h
|
||||||
td/net/HttpOutboundConnection.h
|
td/net/HttpOutboundConnection.h
|
||||||
|
td/net/HttpProxy.h
|
||||||
td/net/HttpQuery.h
|
td/net/HttpQuery.h
|
||||||
td/net/HttpReader.h
|
td/net/HttpReader.h
|
||||||
td/net/NetStats.h
|
td/net/NetStats.h
|
||||||
|
103
tdnet/td/net/HttpProxy.cpp
Normal file
103
tdnet/td/net/HttpProxy.cpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
//
|
||||||
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
|
||||||
|
//
|
||||||
|
// 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/net/HttpProxy.h"
|
||||||
|
|
||||||
|
#include "td/utils/base64.h"
|
||||||
|
#include "td/utils/logging.h"
|
||||||
|
#include "td/utils/misc.h"
|
||||||
|
#include "td/utils/port/Fd.h"
|
||||||
|
#include "td/utils/Slice.h"
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
|
||||||
|
void HttpProxy::send_connect() {
|
||||||
|
VLOG(proxy) << "Send CONNECT to proxy";
|
||||||
|
CHECK(state_ == State::SendConnect);
|
||||||
|
state_ = State::WaitConnectResponse;
|
||||||
|
|
||||||
|
string host = PSTRING() << ip_address_.get_ip_str() << ':' << ip_address_.get_port();
|
||||||
|
string proxy_authorization;
|
||||||
|
if (!username_.empty() || !password_.empty()) {
|
||||||
|
auto userinfo = PSTRING() << username_ << ':' << password_;
|
||||||
|
proxy_authorization = PSTRING() << "Proxy-Authorization: basic " << td::base64_encode(userinfo) << "\r\n";
|
||||||
|
}
|
||||||
|
fd_.output_buffer().append(PSLICE() << "CONNECT " << host << " HTTP/1.1\r\n"
|
||||||
|
<< "Host: " << host << "\r\n"
|
||||||
|
<< proxy_authorization << "\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
Status HttpProxy::wait_connect_response() {
|
||||||
|
CHECK(state_ == State::WaitConnectResponse);
|
||||||
|
auto it = fd_.input_buffer().clone();
|
||||||
|
VLOG(proxy) << "Receive CONNECT response of size " << it.size();
|
||||||
|
if (it.size() < 12 + 1 + 1) {
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
char begin_buf[12];
|
||||||
|
MutableSlice begin(begin_buf, 12);
|
||||||
|
it.advance(12, begin);
|
||||||
|
if ((begin.substr(0, 10) != "HTTP/1.1 2" && begin.substr(0, 10) != "HTTP/1.0 2") || !is_digit(begin[10]) ||
|
||||||
|
!is_digit(begin[11])) {
|
||||||
|
return Status::Error("Failed to connect");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t total_size = 12;
|
||||||
|
char c;
|
||||||
|
MutableSlice c_slice(&c, 1);
|
||||||
|
while (!it.empty()) {
|
||||||
|
it.advance(1, c_slice);
|
||||||
|
total_size++;
|
||||||
|
if (c == '\n') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (it.empty()) {
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
char prev = '\n';
|
||||||
|
size_t pos = 0;
|
||||||
|
bool found = false;
|
||||||
|
while (!it.empty()) {
|
||||||
|
it.advance(1, c_slice);
|
||||||
|
total_size++;
|
||||||
|
if (c == '\n') {
|
||||||
|
if (pos == 0 || (pos == 1 && prev == '\r')) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pos = 0;
|
||||||
|
} else {
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
prev = c;
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
CHECK(it.empty());
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
fd_.input_buffer().advance(total_size);
|
||||||
|
stop();
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
Status HttpProxy::loop_impl() {
|
||||||
|
switch (state_) {
|
||||||
|
case State::SendConnect:
|
||||||
|
send_connect();
|
||||||
|
break;
|
||||||
|
case State::WaitConnectResponse:
|
||||||
|
TRY_STATUS(wait_connect_response());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace td
|
28
tdnet/td/net/HttpProxy.h
Normal file
28
tdnet/td/net/HttpProxy.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
|
||||||
|
//
|
||||||
|
// 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)
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "td/net/TransparentProxy.h"
|
||||||
|
|
||||||
|
#include "td/utils/Status.h"
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
|
||||||
|
class HttpProxy : public TransparentProxy {
|
||||||
|
public:
|
||||||
|
using TransparentProxy::TransparentProxy;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class State { SendConnect, WaitConnectResponse } state_ = State::SendConnect;
|
||||||
|
|
||||||
|
void send_connect();
|
||||||
|
Status wait_connect_response();
|
||||||
|
|
||||||
|
Status loop_impl() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace td
|
@ -44,7 +44,6 @@ Status Socks5::wait_greeting_response() {
|
|||||||
}
|
}
|
||||||
auto authentication_method = slice[1];
|
auto authentication_method = slice[1];
|
||||||
if (authentication_method == '\0') {
|
if (authentication_method == '\0') {
|
||||||
state_ = State::SendIpAddress;
|
|
||||||
send_ip_address();
|
send_ip_address();
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
@ -90,14 +89,12 @@ Status Socks5::wait_password_response() {
|
|||||||
return Status::Error("Wrong username or password");
|
return Status::Error("Wrong username or password");
|
||||||
}
|
}
|
||||||
|
|
||||||
state_ = State::SendIpAddress;
|
|
||||||
send_ip_address();
|
send_ip_address();
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Socks5::send_ip_address() {
|
void Socks5::send_ip_address() {
|
||||||
VLOG(proxy) << "Send IP address";
|
VLOG(proxy) << "Send IP address";
|
||||||
CHECK(state_ == State::SendIpAddress);
|
|
||||||
callback_->on_connected();
|
callback_->on_connected();
|
||||||
string request;
|
string request;
|
||||||
request += '\x05';
|
request += '\x05';
|
||||||
@ -182,8 +179,7 @@ Status Socks5::loop_impl() {
|
|||||||
case State::WaitIpAddressResponse:
|
case State::WaitIpAddressResponse:
|
||||||
TRY_STATUS(wait_ip_address_response());
|
TRY_STATUS(wait_ip_address_response());
|
||||||
break;
|
break;
|
||||||
case State::SendIpAddress:
|
default:
|
||||||
case State::Stop:
|
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
|
@ -21,9 +21,7 @@ class Socks5 : public TransparentProxy {
|
|||||||
SendGreeting,
|
SendGreeting,
|
||||||
WaitGreetingResponse,
|
WaitGreetingResponse,
|
||||||
WaitPasswordResponse,
|
WaitPasswordResponse,
|
||||||
SendIpAddress,
|
WaitIpAddressResponse
|
||||||
WaitIpAddressResponse,
|
|
||||||
Stop
|
|
||||||
} state_ = State::SendGreeting;
|
} state_ = State::SendGreeting;
|
||||||
|
|
||||||
void send_greeting();
|
void send_greeting();
|
||||||
|
@ -15,7 +15,7 @@ namespace td {
|
|||||||
int VERBOSITY_NAME(proxy) = VERBOSITY_NAME(DEBUG);
|
int VERBOSITY_NAME(proxy) = VERBOSITY_NAME(DEBUG);
|
||||||
|
|
||||||
TransparentProxy::TransparentProxy(SocketFd socket_fd, IPAddress ip_address, string username, string password,
|
TransparentProxy::TransparentProxy(SocketFd socket_fd, IPAddress ip_address, string username, string password,
|
||||||
std::unique_ptr<Callback> callback, ActorShared<> parent)
|
std::unique_ptr<Callback> callback, ActorShared<> parent)
|
||||||
: fd_(std::move(socket_fd))
|
: fd_(std::move(socket_fd))
|
||||||
, ip_address_(std::move(ip_address))
|
, ip_address_(std::move(ip_address))
|
||||||
, username_(std::move(username))
|
, username_(std::move(username))
|
||||||
|
@ -31,8 +31,8 @@ class TransparentProxy : public Actor {
|
|||||||
virtual void on_connected() = 0;
|
virtual void on_connected() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
TransparentProxy(SocketFd socket_fd, IPAddress ip_address, string username, string password, std::unique_ptr<Callback> callback,
|
TransparentProxy(SocketFd socket_fd, IPAddress ip_address, string username, string password,
|
||||||
ActorShared<> parent);
|
std::unique_ptr<Callback> callback, ActorShared<> parent);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BufferedFd<SocketFd> fd_;
|
BufferedFd<SocketFd> fd_;
|
||||||
|
@ -405,7 +405,7 @@ Status IPAddress::init_peer_address(const SocketFd &socket_fd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static CSlice get_ip_str(int family, const void *addr) {
|
static CSlice get_ip_str(int family, const void *addr) {
|
||||||
const int buf_size = INET6_ADDRSTRLEN; //, INET_ADDRSTRLEN;
|
const int buf_size = INET6_ADDRSTRLEN;
|
||||||
static TD_THREAD_LOCAL char *buf;
|
static TD_THREAD_LOCAL char *buf;
|
||||||
init_thread_local<char[]>(buf, buf_size);
|
init_thread_local<char[]>(buf, buf_size);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user