Add TransparentProxy abstract class.
GitOrigin-RevId: 77ced69b5d87c17a1bbc6d654bb0206a4e32e69d
This commit is contained in:
parent
236636e129
commit
2ca3c7eeed
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "td/net/GetHostByNameActor.h"
|
#include "td/net/GetHostByNameActor.h"
|
||||||
#include "td/net/Socks5.h"
|
#include "td/net/Socks5.h"
|
||||||
|
#include "td/net/TransparentProxy.h"
|
||||||
|
|
||||||
#include "td/utils/format.h"
|
#include "td/utils/format.h"
|
||||||
#include "td/utils/logging.h"
|
#include "td/utils/logging.h"
|
||||||
@ -493,7 +494,7 @@ void ConnectionCreator::ping_proxy_resolved(int32 proxy_id, IPAddress ip_address
|
|||||||
});
|
});
|
||||||
CHECK(proxy.use_proxy());
|
CHECK(proxy.use_proxy());
|
||||||
if (proxy.use_socks5_proxy()) {
|
if (proxy.use_socks5_proxy()) {
|
||||||
class Callback : public Socks5::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)) {
|
||||||
}
|
}
|
||||||
@ -905,7 +906,7 @@ void ConnectionCreator::client_loop(ClientInfo &client) {
|
|||||||
extra.stat);
|
extra.stat);
|
||||||
|
|
||||||
if (proxy.use_socks5_proxy()) {
|
if (proxy.use_socks5_proxy()) {
|
||||||
class Callback : public Socks5::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)
|
||||||
: promise_(std::move(promise)), stats_callback_(std::move(stats_callback)) {
|
: promise_(std::move(promise)), stats_callback_(std::move(stats_callback)) {
|
||||||
|
@ -19,6 +19,7 @@ set(TDNET_SOURCE
|
|||||||
td/net/Socks5.cpp
|
td/net/Socks5.cpp
|
||||||
td/net/SslFd.cpp
|
td/net/SslFd.cpp
|
||||||
td/net/TcpListener.cpp
|
td/net/TcpListener.cpp
|
||||||
|
td/net/TransparentProxy.cpp
|
||||||
td/net/Wget.cpp
|
td/net/Wget.cpp
|
||||||
|
|
||||||
td/net/GetHostByNameActor.h
|
td/net/GetHostByNameActor.h
|
||||||
@ -35,6 +36,7 @@ set(TDNET_SOURCE
|
|||||||
td/net/Socks5.h
|
td/net/Socks5.h
|
||||||
td/net/SslFd.h
|
td/net/SslFd.h
|
||||||
td/net/TcpListener.h
|
td/net/TcpListener.h
|
||||||
|
td/net/TransparentProxy.h
|
||||||
td/net/Wget.h
|
td/net/Wget.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,54 +13,8 @@
|
|||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
static int VERBOSITY_NAME(socks5) = VERBOSITY_NAME(DEBUG);
|
|
||||||
|
|
||||||
Socks5::Socks5(SocketFd socket_fd, IPAddress ip_address, string username, string password,
|
|
||||||
std::unique_ptr<Callback> callback, ActorShared<> parent)
|
|
||||||
: fd_(std::move(socket_fd))
|
|
||||||
, ip_address_(std::move(ip_address))
|
|
||||||
, username_(std::move(username))
|
|
||||||
, password_(std::move(password))
|
|
||||||
, callback_(std::move(callback))
|
|
||||||
, parent_(std::move(parent)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void Socks5::on_error(Status status) {
|
|
||||||
CHECK(status.is_error());
|
|
||||||
VLOG(socks5) << "Receive " << status;
|
|
||||||
if (callback_) {
|
|
||||||
callback_->set_result(std::move(status));
|
|
||||||
callback_.reset();
|
|
||||||
}
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Socks5::tear_down() {
|
|
||||||
VLOG(socks5) << "Finish to connect to proxy";
|
|
||||||
unsubscribe(fd_.get_fd());
|
|
||||||
fd_.get_fd().set_observer(nullptr);
|
|
||||||
if (callback_) {
|
|
||||||
callback_->set_result(std::move(fd_));
|
|
||||||
callback_.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Socks5::hangup() {
|
|
||||||
on_error(Status::Error("Cancelled"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Socks5::start_up() {
|
|
||||||
VLOG(socks5) << "Begin to connect to proxy";
|
|
||||||
fd_.get_fd().set_observer(this);
|
|
||||||
subscribe(fd_.get_fd());
|
|
||||||
set_timeout_in(10);
|
|
||||||
if (can_write(fd_)) {
|
|
||||||
loop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Socks5::send_greeting() {
|
void Socks5::send_greeting() {
|
||||||
VLOG(socks5) << "Send greeting to proxy";
|
VLOG(proxy) << "Send greeting to proxy";
|
||||||
CHECK(state_ == State::SendGreeting);
|
CHECK(state_ == State::SendGreeting);
|
||||||
state_ = State::WaitGreetingResponse;
|
state_ = State::WaitGreetingResponse;
|
||||||
|
|
||||||
@ -79,7 +33,7 @@ void Socks5::send_greeting() {
|
|||||||
|
|
||||||
Status Socks5::wait_greeting_response() {
|
Status Socks5::wait_greeting_response() {
|
||||||
auto &buf = fd_.input_buffer();
|
auto &buf = fd_.input_buffer();
|
||||||
VLOG(socks5) << "Receive greeting response of size " << buf.size();
|
VLOG(proxy) << "Receive greeting response of size " << buf.size();
|
||||||
if (buf.size() < 2) {
|
if (buf.size() < 2) {
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
@ -101,7 +55,7 @@ Status Socks5::wait_greeting_response() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Status Socks5::send_username_password() {
|
Status Socks5::send_username_password() {
|
||||||
VLOG(socks5) << "Send username and password";
|
VLOG(proxy) << "Send username and password";
|
||||||
if (username_.size() >= 128) {
|
if (username_.size() >= 128) {
|
||||||
return Status::Error("Username is too long");
|
return Status::Error("Username is too long");
|
||||||
}
|
}
|
||||||
@ -123,7 +77,7 @@ Status Socks5::send_username_password() {
|
|||||||
|
|
||||||
Status Socks5::wait_password_response() {
|
Status Socks5::wait_password_response() {
|
||||||
auto &buf = fd_.input_buffer();
|
auto &buf = fd_.input_buffer();
|
||||||
VLOG(socks5) << "Receive password response of size " << buf.size();
|
VLOG(proxy) << "Receive password response of size " << buf.size();
|
||||||
if (buf.size() < 2) {
|
if (buf.size() < 2) {
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
@ -142,7 +96,7 @@ Status Socks5::wait_password_response() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Socks5::send_ip_address() {
|
void Socks5::send_ip_address() {
|
||||||
VLOG(socks5) << "Send IP address";
|
VLOG(proxy) << "Send IP address";
|
||||||
CHECK(state_ == State::SendIpAddress);
|
CHECK(state_ == State::SendIpAddress);
|
||||||
callback_->on_connected();
|
callback_->on_connected();
|
||||||
string request;
|
string request;
|
||||||
@ -170,7 +124,7 @@ void Socks5::send_ip_address() {
|
|||||||
Status Socks5::wait_ip_address_response() {
|
Status Socks5::wait_ip_address_response() {
|
||||||
CHECK(state_ == State::WaitIpAddressResponse);
|
CHECK(state_ == State::WaitIpAddressResponse);
|
||||||
auto it = fd_.input_buffer().clone();
|
auto it = fd_.input_buffer().clone();
|
||||||
VLOG(socks5) << "Receive IP address response of size " << it.size();
|
VLOG(proxy) << "Receive IP address response of size " << it.size();
|
||||||
if (it.size() < 4) {
|
if (it.size() < 4) {
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
@ -189,16 +143,19 @@ Status Socks5::wait_ip_address_response() {
|
|||||||
return Status::Error("byte must be zero");
|
return Status::Error("byte must be zero");
|
||||||
}
|
}
|
||||||
it.advance(1, c_slice);
|
it.advance(1, c_slice);
|
||||||
|
size_t total_size = 6;
|
||||||
if (c == '\x01') {
|
if (c == '\x01') {
|
||||||
if (it.size() < 4) {
|
if (it.size() < 4) {
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
it.advance(4);
|
it.advance(4);
|
||||||
|
total_size += 4;
|
||||||
} else if (c == '\x04') {
|
} else if (c == '\x04') {
|
||||||
if (it.size() < 16) {
|
if (it.size() < 16) {
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
it.advance(16);
|
it.advance(16);
|
||||||
|
total_size += 16;
|
||||||
} else {
|
} else {
|
||||||
return Status::Error("Invalid response");
|
return Status::Error("Invalid response");
|
||||||
}
|
}
|
||||||
@ -206,43 +163,30 @@ Status Socks5::wait_ip_address_response() {
|
|||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
it.advance(2);
|
it.advance(2);
|
||||||
|
fd_.input_buffer().advance(total_size);
|
||||||
stop();
|
stop();
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Socks5::loop() {
|
Status Socks5::loop_impl() {
|
||||||
auto status = [&] {
|
switch (state_) {
|
||||||
TRY_STATUS(fd_.flush_read());
|
case State::SendGreeting:
|
||||||
switch (state_) {
|
send_greeting();
|
||||||
case State::SendGreeting:
|
break;
|
||||||
send_greeting();
|
case State::WaitGreetingResponse:
|
||||||
break;
|
TRY_STATUS(wait_greeting_response());
|
||||||
case State::WaitGreetingResponse:
|
break;
|
||||||
TRY_STATUS(wait_greeting_response());
|
case State::WaitPasswordResponse:
|
||||||
break;
|
TRY_STATUS(wait_password_response());
|
||||||
case State::WaitPasswordResponse:
|
break;
|
||||||
TRY_STATUS(wait_password_response());
|
case State::WaitIpAddressResponse:
|
||||||
break;
|
TRY_STATUS(wait_ip_address_response());
|
||||||
case State::WaitIpAddressResponse:
|
break;
|
||||||
TRY_STATUS(wait_ip_address_response());
|
case State::SendIpAddress:
|
||||||
break;
|
case State::Stop:
|
||||||
case State::SendIpAddress:
|
UNREACHABLE();
|
||||||
case State::Stop:
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
TRY_STATUS(fd_.flush_write());
|
|
||||||
return Status::OK();
|
|
||||||
}();
|
|
||||||
if (status.is_error()) {
|
|
||||||
on_error(std::move(status));
|
|
||||||
}
|
}
|
||||||
if (can_close(fd_)) {
|
return Status::OK();
|
||||||
on_error(Status::Error("Connection closed"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Socks5::timeout_expired() {
|
|
||||||
on_error(Status::Error("Timeout expired"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -6,45 +6,17 @@
|
|||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "td/actor/actor.h"
|
#include "td/net/TransparentProxy.h"
|
||||||
|
|
||||||
#include "td/utils/BufferedFd.h"
|
|
||||||
#include "td/utils/common.h"
|
|
||||||
#include "td/utils/port/IPAddress.h"
|
|
||||||
#include "td/utils/port/SocketFd.h"
|
|
||||||
#include "td/utils/Status.h"
|
#include "td/utils/Status.h"
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
class Socks5 : public Actor {
|
class Socks5 : public TransparentProxy {
|
||||||
public:
|
public:
|
||||||
class Callback {
|
using TransparentProxy::TransparentProxy;
|
||||||
public:
|
|
||||||
Callback() = default;
|
|
||||||
Callback(const Callback &) = delete;
|
|
||||||
Callback &operator=(const Callback &) = delete;
|
|
||||||
virtual ~Callback() = default;
|
|
||||||
|
|
||||||
virtual void set_result(Result<SocketFd>) = 0;
|
|
||||||
virtual void on_connected() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
Socks5(SocketFd socket_fd, IPAddress ip_address, string username, string password, std::unique_ptr<Callback> callback,
|
|
||||||
ActorShared<> parent);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BufferedFd<SocketFd> fd_;
|
|
||||||
IPAddress ip_address_;
|
|
||||||
string username_;
|
|
||||||
string password_;
|
|
||||||
std::unique_ptr<Callback> callback_;
|
|
||||||
ActorShared<> parent_;
|
|
||||||
|
|
||||||
void on_error(Status status);
|
|
||||||
void tear_down() override;
|
|
||||||
void start_up() override;
|
|
||||||
void hangup() override;
|
|
||||||
|
|
||||||
enum class State {
|
enum class State {
|
||||||
SendGreeting,
|
SendGreeting,
|
||||||
WaitGreetingResponse,
|
WaitGreetingResponse,
|
||||||
@ -63,8 +35,7 @@ class Socks5 : public Actor {
|
|||||||
void send_ip_address();
|
void send_ip_address();
|
||||||
Status wait_ip_address_response();
|
Status wait_ip_address_response();
|
||||||
|
|
||||||
void loop() override;
|
Status loop_impl() override;
|
||||||
void timeout_expired() override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
85
tdnet/td/net/TransparentProxy.cpp
Normal file
85
tdnet/td/net/TransparentProxy.cpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
//
|
||||||
|
// 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/TransparentProxy.h"
|
||||||
|
|
||||||
|
#include "td/utils/logging.h"
|
||||||
|
#include "td/utils/port/Fd.h"
|
||||||
|
#include "td/utils/Slice.h"
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
|
||||||
|
int VERBOSITY_NAME(proxy) = VERBOSITY_NAME(DEBUG);
|
||||||
|
|
||||||
|
TransparentProxy::TransparentProxy(SocketFd socket_fd, IPAddress ip_address, string username, string password,
|
||||||
|
std::unique_ptr<Callback> callback, ActorShared<> parent)
|
||||||
|
: fd_(std::move(socket_fd))
|
||||||
|
, ip_address_(std::move(ip_address))
|
||||||
|
, username_(std::move(username))
|
||||||
|
, password_(std::move(password))
|
||||||
|
, callback_(std::move(callback))
|
||||||
|
, parent_(std::move(parent)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransparentProxy::on_error(Status status) {
|
||||||
|
CHECK(status.is_error());
|
||||||
|
VLOG(proxy) << "Receive " << status;
|
||||||
|
if (callback_) {
|
||||||
|
callback_->set_result(std::move(status));
|
||||||
|
callback_.reset();
|
||||||
|
}
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransparentProxy::tear_down() {
|
||||||
|
VLOG(proxy) << "Finish to connect to proxy";
|
||||||
|
unsubscribe(fd_.get_fd());
|
||||||
|
fd_.get_fd().set_observer(nullptr);
|
||||||
|
if (callback_) {
|
||||||
|
if (!fd_.input_buffer().empty()) {
|
||||||
|
LOG(ERROR) << "Have " << fd_.input_buffer().size() << " unread bytes";
|
||||||
|
callback_->set_result(Status::Error("Proxy has sent to much data"));
|
||||||
|
} else {
|
||||||
|
callback_->set_result(std::move(fd_));
|
||||||
|
}
|
||||||
|
callback_.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransparentProxy::hangup() {
|
||||||
|
on_error(Status::Error("Cancelled"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransparentProxy::start_up() {
|
||||||
|
VLOG(proxy) << "Begin to connect to proxy";
|
||||||
|
fd_.get_fd().set_observer(this);
|
||||||
|
subscribe(fd_.get_fd());
|
||||||
|
set_timeout_in(10);
|
||||||
|
if (can_write(fd_)) {
|
||||||
|
loop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransparentProxy::loop() {
|
||||||
|
auto status = [&] {
|
||||||
|
TRY_STATUS(fd_.flush_read());
|
||||||
|
TRY_STATUS(loop_impl());
|
||||||
|
TRY_STATUS(fd_.flush_write());
|
||||||
|
return Status::OK();
|
||||||
|
}();
|
||||||
|
if (status.is_error()) {
|
||||||
|
on_error(std::move(status));
|
||||||
|
}
|
||||||
|
if (can_close(fd_)) {
|
||||||
|
on_error(Status::Error("Connection closed"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransparentProxy::timeout_expired() {
|
||||||
|
on_error(Status::Error("Timeout expired"));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace td
|
56
tdnet/td/net/TransparentProxy.h
Normal file
56
tdnet/td/net/TransparentProxy.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// 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/actor/actor.h"
|
||||||
|
|
||||||
|
#include "td/utils/BufferedFd.h"
|
||||||
|
#include "td/utils/common.h"
|
||||||
|
#include "td/utils/port/IPAddress.h"
|
||||||
|
#include "td/utils/port/SocketFd.h"
|
||||||
|
#include "td/utils/Status.h"
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
|
||||||
|
extern int VERBOSITY_NAME(proxy);
|
||||||
|
|
||||||
|
class TransparentProxy : public Actor {
|
||||||
|
public:
|
||||||
|
class Callback {
|
||||||
|
public:
|
||||||
|
Callback() = default;
|
||||||
|
Callback(const Callback &) = delete;
|
||||||
|
Callback &operator=(const Callback &) = delete;
|
||||||
|
virtual ~Callback() = default;
|
||||||
|
|
||||||
|
virtual void set_result(Result<SocketFd>) = 0;
|
||||||
|
virtual void on_connected() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
TransparentProxy(SocketFd socket_fd, IPAddress ip_address, string username, string password, std::unique_ptr<Callback> callback,
|
||||||
|
ActorShared<> parent);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BufferedFd<SocketFd> fd_;
|
||||||
|
IPAddress ip_address_;
|
||||||
|
string username_;
|
||||||
|
string password_;
|
||||||
|
std::unique_ptr<Callback> callback_;
|
||||||
|
ActorShared<> parent_;
|
||||||
|
|
||||||
|
void on_error(Status status);
|
||||||
|
void tear_down() override;
|
||||||
|
void start_up() override;
|
||||||
|
void hangup() override;
|
||||||
|
|
||||||
|
void loop() override;
|
||||||
|
void timeout_expired() override;
|
||||||
|
|
||||||
|
virtual Status loop_impl() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace td
|
@ -17,6 +17,7 @@
|
|||||||
#include "td/mtproto/RawConnection.h"
|
#include "td/mtproto/RawConnection.h"
|
||||||
|
|
||||||
#include "td/net/Socks5.h"
|
#include "td/net/Socks5.h"
|
||||||
|
#include "td/net/TransparentProxy.h"
|
||||||
|
|
||||||
#include "td/telegram/ConfigManager.h"
|
#include "td/telegram/ConfigManager.h"
|
||||||
#include "td/telegram/net/DcId.h"
|
#include "td/telegram/net/DcId.h"
|
||||||
@ -302,7 +303,7 @@ class Socks5TestActor : public Actor {
|
|||||||
send_closure(actor_id, &Socks5TestActor::on_result, std::move(res), false);
|
send_closure(actor_id, &Socks5TestActor::on_result, std::move(res), false);
|
||||||
});
|
});
|
||||||
|
|
||||||
class Callback : public Socks5::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)) {
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user