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/Socks5.h"
|
||||
#include "td/net/TransparentProxy.h"
|
||||
|
||||
#include "td/utils/format.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());
|
||||
if (proxy.use_socks5_proxy()) {
|
||||
class Callback : public Socks5::Callback {
|
||||
class Callback : public TransparentProxy::Callback {
|
||||
public:
|
||||
explicit Callback(Promise<SocketFd> promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
@ -905,7 +906,7 @@ void ConnectionCreator::client_loop(ClientInfo &client) {
|
||||
extra.stat);
|
||||
|
||||
if (proxy.use_socks5_proxy()) {
|
||||
class Callback : public Socks5::Callback {
|
||||
class Callback : public TransparentProxy::Callback {
|
||||
public:
|
||||
explicit Callback(Promise<ConnectionData> promise, std::unique_ptr<detail::StatsCallback> 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/SslFd.cpp
|
||||
td/net/TcpListener.cpp
|
||||
td/net/TransparentProxy.cpp
|
||||
td/net/Wget.cpp
|
||||
|
||||
td/net/GetHostByNameActor.h
|
||||
@ -35,6 +36,7 @@ set(TDNET_SOURCE
|
||||
td/net/Socks5.h
|
||||
td/net/SslFd.h
|
||||
td/net/TcpListener.h
|
||||
td/net/TransparentProxy.h
|
||||
td/net/Wget.h
|
||||
)
|
||||
|
||||
|
@ -13,54 +13,8 @@
|
||||
|
||||
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() {
|
||||
VLOG(socks5) << "Send greeting to proxy";
|
||||
VLOG(proxy) << "Send greeting to proxy";
|
||||
CHECK(state_ == State::SendGreeting);
|
||||
state_ = State::WaitGreetingResponse;
|
||||
|
||||
@ -79,7 +33,7 @@ void Socks5::send_greeting() {
|
||||
|
||||
Status Socks5::wait_greeting_response() {
|
||||
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) {
|
||||
return Status::OK();
|
||||
}
|
||||
@ -101,7 +55,7 @@ Status Socks5::wait_greeting_response() {
|
||||
}
|
||||
|
||||
Status Socks5::send_username_password() {
|
||||
VLOG(socks5) << "Send username and password";
|
||||
VLOG(proxy) << "Send username and password";
|
||||
if (username_.size() >= 128) {
|
||||
return Status::Error("Username is too long");
|
||||
}
|
||||
@ -123,7 +77,7 @@ Status Socks5::send_username_password() {
|
||||
|
||||
Status Socks5::wait_password_response() {
|
||||
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) {
|
||||
return Status::OK();
|
||||
}
|
||||
@ -142,7 +96,7 @@ Status Socks5::wait_password_response() {
|
||||
}
|
||||
|
||||
void Socks5::send_ip_address() {
|
||||
VLOG(socks5) << "Send IP address";
|
||||
VLOG(proxy) << "Send IP address";
|
||||
CHECK(state_ == State::SendIpAddress);
|
||||
callback_->on_connected();
|
||||
string request;
|
||||
@ -170,7 +124,7 @@ void Socks5::send_ip_address() {
|
||||
Status Socks5::wait_ip_address_response() {
|
||||
CHECK(state_ == State::WaitIpAddressResponse);
|
||||
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) {
|
||||
return Status::OK();
|
||||
}
|
||||
@ -189,16 +143,19 @@ Status Socks5::wait_ip_address_response() {
|
||||
return Status::Error("byte must be zero");
|
||||
}
|
||||
it.advance(1, c_slice);
|
||||
size_t total_size = 6;
|
||||
if (c == '\x01') {
|
||||
if (it.size() < 4) {
|
||||
return Status::OK();
|
||||
}
|
||||
it.advance(4);
|
||||
total_size += 4;
|
||||
} else if (c == '\x04') {
|
||||
if (it.size() < 16) {
|
||||
return Status::OK();
|
||||
}
|
||||
it.advance(16);
|
||||
total_size += 16;
|
||||
} else {
|
||||
return Status::Error("Invalid response");
|
||||
}
|
||||
@ -206,43 +163,30 @@ Status Socks5::wait_ip_address_response() {
|
||||
return Status::OK();
|
||||
}
|
||||
it.advance(2);
|
||||
fd_.input_buffer().advance(total_size);
|
||||
stop();
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
void Socks5::loop() {
|
||||
auto status = [&] {
|
||||
TRY_STATUS(fd_.flush_read());
|
||||
switch (state_) {
|
||||
case State::SendGreeting:
|
||||
send_greeting();
|
||||
break;
|
||||
case State::WaitGreetingResponse:
|
||||
TRY_STATUS(wait_greeting_response());
|
||||
break;
|
||||
case State::WaitPasswordResponse:
|
||||
TRY_STATUS(wait_password_response());
|
||||
break;
|
||||
case State::WaitIpAddressResponse:
|
||||
TRY_STATUS(wait_ip_address_response());
|
||||
break;
|
||||
case State::SendIpAddress:
|
||||
case State::Stop:
|
||||
UNREACHABLE();
|
||||
}
|
||||
TRY_STATUS(fd_.flush_write());
|
||||
return Status::OK();
|
||||
}();
|
||||
if (status.is_error()) {
|
||||
on_error(std::move(status));
|
||||
Status Socks5::loop_impl() {
|
||||
switch (state_) {
|
||||
case State::SendGreeting:
|
||||
send_greeting();
|
||||
break;
|
||||
case State::WaitGreetingResponse:
|
||||
TRY_STATUS(wait_greeting_response());
|
||||
break;
|
||||
case State::WaitPasswordResponse:
|
||||
TRY_STATUS(wait_password_response());
|
||||
break;
|
||||
case State::WaitIpAddressResponse:
|
||||
TRY_STATUS(wait_ip_address_response());
|
||||
break;
|
||||
case State::SendIpAddress:
|
||||
case State::Stop:
|
||||
UNREACHABLE();
|
||||
}
|
||||
if (can_close(fd_)) {
|
||||
on_error(Status::Error("Connection closed"));
|
||||
}
|
||||
}
|
||||
|
||||
void Socks5::timeout_expired() {
|
||||
on_error(Status::Error("Timeout expired"));
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -6,45 +6,17 @@
|
||||
//
|
||||
#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"
|
||||
|
||||
namespace td {
|
||||
|
||||
class Socks5 : public Actor {
|
||||
class Socks5 : public TransparentProxy {
|
||||
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;
|
||||
};
|
||||
|
||||
Socks5(SocketFd socket_fd, IPAddress ip_address, string username, string password, std::unique_ptr<Callback> callback,
|
||||
ActorShared<> parent);
|
||||
using TransparentProxy::TransparentProxy;
|
||||
|
||||
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 {
|
||||
SendGreeting,
|
||||
WaitGreetingResponse,
|
||||
@ -63,8 +35,7 @@ class Socks5 : public Actor {
|
||||
void send_ip_address();
|
||||
Status wait_ip_address_response();
|
||||
|
||||
void loop() override;
|
||||
void timeout_expired() override;
|
||||
Status loop_impl() override;
|
||||
};
|
||||
|
||||
} // 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/net/Socks5.h"
|
||||
#include "td/net/TransparentProxy.h"
|
||||
|
||||
#include "td/telegram/ConfigManager.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);
|
||||
});
|
||||
|
||||
class Callback : public Socks5::Callback {
|
||||
class Callback : public TransparentProxy::Callback {
|
||||
public:
|
||||
explicit Callback(Promise<SocketFd> promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
Reference in New Issue
Block a user