summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--Makefile17
m---------boost-asio-fastbuffer0
-rw-r--r--socks5.cpp104
-rw-r--r--socks5.hpp69
5 files changed, 81 insertions, 112 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..9980dbe
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "boost-asio-fastbuffer"]
+ path = boost-asio-fastbuffer
+ url = https://github.com/utoni/boost-asio-fastbuffer.git
diff --git a/Makefile b/Makefile
index 64facb5..fbef309 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,6 @@
CXX = g++
-CXXFLAGS = -Wall -Wextra
+GIT = git
+CXXFLAGS = -Wall -Wextra -Iboost-asio-fastbuffer
SERVER_HDRS = socks5.hpp
SERVER_SRCS = socks5.cpp main.cpp
@@ -14,12 +15,20 @@ ifneq ($(DEBUG),)
CXXFLAGS += -g #-DBOOST_ASIO_ENABLE_HANDLER_TRACKING=1
endif
-all: server
+all: git server
-server: $(SERVER_HDRS) $(SERVER_SRCS)
+git: boost-asio-fastbuffer/fastbuffer.hpp
+
+boost-asio-fastbuffer/fastbuffer.hpp:
+ $(GIT) submodule update --init
+
+server: boost-asio-fastbuffer/fastbuffer.hpp $(SERVER_HDRS) $(SERVER_SRCS)
$(CXX) $(CXXFLAGS) $(SERVER_SRCS) -o $@
clean:
rm -f server
-.PHONY: clean
+distclean: clean
+ $(GIT) submodule deinit --all --force
+
+.PHONY: all git clean distclean
diff --git a/boost-asio-fastbuffer b/boost-asio-fastbuffer
new file mode 160000
+Subproject c652e22dd1cfe059a30604e772529f1d86a1a28
diff --git a/socks5.cpp b/socks5.cpp
index a876715..641c086 100644
--- a/socks5.cpp
+++ b/socks5.cpp
@@ -28,12 +28,34 @@ ProxySessionBase::ProxySessionBase(std::uint32_t session_id,
ProxySessionBase::ProxySessionBase(std::uint32_t session_id,
boost::asio::ip::tcp::socket &&client_socket,
- StreamBuffer &&input_buffer,
- StreamBuffer &&output_buffer)
+ ContiguousStreamBuffer &&input_buffer,
+ ContiguousStreamBuffer &&output_buffer)
: m_sessionId{session_id}, m_inBuf{std::move(input_buffer)},
m_outBuf{std::move(output_buffer)},
m_clientSocket{std::move(client_socket)} {}
+void ProxySessionBase::async_read(const CompletionHandler &handler,
+ std::size_t expected_length) {
+ if (expected_length == 0)
+ m_clientSocket.async_read_some(
+ +m_inBuf, [this, handler](const boost::system::error_code &ec,
+ const std::size_t length) {
+ if (ec || length == 0)
+ return;
+ handler(length);
+ });
+ else
+ boost::asio::async_read(
+ m_clientSocket, +m_inBuf,
+ boost::asio::transfer_exactly(expected_length),
+ [this, expected_length, handler](const boost::system::error_code &ec,
+ const std::size_t length) {
+ if (ec || length != expected_length)
+ return;
+ handler(length);
+ });
+}
+
ProxySessionAuth::ProxySessionAuth(std::uint32_t session_id,
tcp::socket &&client_socket)
: ProxySessionBase(session_id, std::move(client_socket), 32),
@@ -41,28 +63,21 @@ ProxySessionAuth::ProxySessionAuth(std::uint32_t session_id,
m_destinationSocket{m_clientSocket.get_executor()} {}
void ProxySessionAuth::start() {
- boost::asio::async_read(
- m_clientSocket, +m_inBuf, boost::asio::transfer_exactly(2),
- boost::bind(&ProxySessionAuth::recv_client_greeting, shared_from_this(),
- boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred));
+ async_read([self = shared_from_this()](
+ std::size_t length) { self->recv_client_greeting(length); },
+ 2);
}
-void ProxySessionAuth::recv_client_greeting(const boost::system::error_code &ec,
- std::size_t length) {
- if (ec || length == 0)
- return;
+void ProxySessionAuth::recv_client_greeting(std::size_t length) {
m_inBuf += length;
if (m_inBuf[0] != 0x05 || m_inBuf[1] > 0x09 || m_inBuf[1] == 0x00)
return;
const std::size_t expected_size = std::size_t(2) + m_inBuf[1];
if (m_inBuf.size() < expected_size) {
- boost::asio::async_read(
- m_clientSocket, +m_inBuf, boost::asio::transfer_exactly(expected_size - m_inBuf.size()),
- boost::bind(&ProxySessionAuth::recv_client_greeting, shared_from_this(),
- boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred));
+ async_read([self = shared_from_this(), expected_size](
+ std::size_t length) { self->recv_client_greeting(length); },
+ expected_size - m_inBuf.size());
return;
}
@@ -95,28 +110,17 @@ void ProxySessionAuth::send_server_greeting(bool auth_supported) {
boost::bind(&ProxySessionAuth::handle_write, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
- process_connection_request();
+ async_read([self = shared_from_this()](
+ std::size_t length) { self->recv_connection_request(length); },
+ 6);
}
-void ProxySessionAuth::recv_connection_request(
- const boost::system::error_code &ec, std::size_t length) {
- if (ec || length == 0)
- return;
+void ProxySessionAuth::recv_connection_request(std::size_t length) {
m_inBuf += length;
-
process_connection_request();
}
void ProxySessionAuth::process_connection_request() {
- if (m_inBuf.size() < 6) {
- boost::asio::async_read(
- m_clientSocket, +m_inBuf, boost::asio::transfer_exactly(6 - m_inBuf.size()),
- boost::bind(&ProxySessionAuth::recv_connection_request,
- shared_from_this(), boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred));
- return;
- }
-
if (m_inBuf[0] != 0x05 || m_inBuf[1] > 0x03 || m_inBuf[2] != 0x00)
return;
@@ -142,12 +146,11 @@ void ProxySessionAuth::process_connection_request() {
expected_size += std::size_t(6) + address_size;
if (m_inBuf.size() < expected_size) {
- boost::asio::async_read(
- m_clientSocket, +m_inBuf,
- boost::asio::transfer_exactly(expected_size - m_inBuf.size()),
- boost::bind(&ProxySessionAuth::recv_connection_request,
- shared_from_this(), boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred));
+ async_read(
+ [self = shared_from_this(), expected_size](std::size_t length) {
+ self->recv_connection_request(length);
+ },
+ expected_size - m_inBuf.size());
return;
}
@@ -232,8 +235,8 @@ void ProxySessionAuth::connect_to_destination(std::uint8_t proxy_cmd) {
case 0x01: // TCP client connection
{
m_destinationSocket.async_connect(
- m_endpoint,
- [this, self = shared_from_this(), proxy_cmd](const boost::system::error_code &ec) {
+ m_endpoint, [this, self = shared_from_this(),
+ proxy_cmd](const boost::system::error_code &ec) {
if (ec) {
send_server_response(proxy_cmd, 0x04);
return;
@@ -322,11 +325,9 @@ void ProxySessionTcp::start() { recv_from_both(); }
void ProxySessionTcp::recv_from_both() {
BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, __func__));
- m_clientSocket.async_read_some(
- +m_inBuf,
- boost::bind(&ProxySessionTcp::recv_from_client, shared_from_this(),
- boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred));
+ async_read([self = shared_from_this()](std::size_t length) {
+ self->recv_from_client(length);
+ });
m_destinationSocket.async_read_some(
+m_outBuf,
boost::bind(&ProxySessionTcp::recv_from_destination, shared_from_this(),
@@ -351,15 +352,10 @@ void ProxySessionTcp::recv_from_destination(const boost::system::error_code &ec,
boost::asio::placeholders::bytes_transferred));
}
-void ProxySessionTcp::recv_from_client(const boost::system::error_code &ec,
+void ProxySessionTcp::recv_from_client(
std::size_t length) {
BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, __func__));
- if (ec || length == 0) {
- m_destinationSocket.cancel();
- return;
- }
-
m_inBuf += length;
boost::asio::async_write(
m_destinationSocket, -m_inBuf, boost::asio::transfer_exactly(length),
@@ -395,11 +391,9 @@ void ProxySessionTcp::handle_destination_write(
}
m_inBuf -= length;
- m_clientSocket.async_read_some(
- +m_inBuf,
- boost::bind(&ProxySessionTcp::recv_from_client, shared_from_this(),
- boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred));
+ async_read([self = shared_from_this()](std::size_t length) {
+ self->recv_from_client(length);
+ });
}
ProxyServer::ProxyServer(io_context &ioc, const tcp::endpoint &local_endpoint)
diff --git a/socks5.hpp b/socks5.hpp
index 203bdfe..07d0253 100644
--- a/socks5.hpp
+++ b/socks5.hpp
@@ -11,63 +11,29 @@
#include <memory>
#include <string_view>
-namespace SOCKS5 {
-class StreamBuffer : public boost::noncopyable {
-public:
- explicit StreamBuffer(std::size_t size)
- : m_bufferUsed{0}, m_bufferSize{size} {
- m_buffer = new std::uint8_t[size];
- }
- StreamBuffer(StreamBuffer &&moveable) {
- m_bufferUsed = moveable.m_bufferUsed;
- m_bufferSize = moveable.m_bufferSize;
- m_buffer = moveable.m_buffer;
- moveable.m_buffer = nullptr;
- }
- ~StreamBuffer() { delete[] m_buffer; }
- void operator+=(std::size_t commit_size) { m_bufferUsed += commit_size; }
- void operator+=(const std::initializer_list<uint8_t> &to_add) {
- std::copy(to_add.begin(), to_add.end(), &m_buffer[m_bufferUsed]);
- m_bufferUsed += to_add.size();
- }
- void operator-=(std::size_t consume_size) { m_bufferUsed -= consume_size; }
- auto operator+() {
- return boost::asio::buffer(&m_buffer[m_bufferUsed],
- m_bufferSize - m_bufferUsed);
- }
- auto operator-() { return boost::asio::buffer(&m_buffer[0], m_bufferUsed); }
- auto operator[](std::size_t index) const { return m_buffer[index]; }
- const auto *operator()(std::size_t index = 0) const {
- return &m_buffer[index];
- }
- auto size() const { return m_bufferUsed; }
- auto getHealth() const {
- return (static_cast<float>(m_bufferUsed) /
- static_cast<float>(m_bufferSize));
- }
-
-private:
- std::size_t m_bufferUsed;
- std::size_t m_bufferSize;
- std::uint8_t *m_buffer;
-};
+#include "fastbuffer.hpp"
-class ProxySessionBase : public boost::noncopyable {
+namespace SOCKS5 {
+class ProxySessionBase : private boost::noncopyable {
public:
+ using CompletionHandler = std::function<void(std::size_t length)>;
ProxySessionBase(std::uint32_t session_id,
boost::asio::ip::tcp::socket &&client_socket,
std::size_t buffer_size = BUFSIZ);
ProxySessionBase(std::uint32_t session_id,
boost::asio::ip::tcp::socket &&client_socket,
- StreamBuffer &&input_buffer, StreamBuffer &&output_buffer);
+ ContiguousStreamBuffer &&input_buffer, ContiguousStreamBuffer &&output_buffer);
+ void async_read(const CompletionHandler &handler,
+ std::size_t expected_length = 0);
+protected:
std::uint32_t m_sessionId;
- StreamBuffer m_inBuf;
- StreamBuffer m_outBuf;
+ ContiguousStreamBuffer m_inBuf;
+ ContiguousStreamBuffer m_outBuf;
boost::asio::ip::tcp::socket m_clientSocket;
};
-class ProxySessionAuth : public ProxySessionBase,
+class ProxySessionAuth : private ProxySessionBase,
public std::enable_shared_from_this<ProxySessionAuth> {
public:
ProxySessionAuth(std::uint32_t session_id,
@@ -75,11 +41,9 @@ public:
void start();
private:
- void recv_client_greeting(const boost::system::error_code &ec,
- std::size_t length);
+ void recv_client_greeting(std::size_t length);
void send_server_greeting(bool auth_supported);
- void recv_connection_request(const boost::system::error_code &ec,
- std::size_t length);
+ void recv_connection_request(std::size_t length);
void process_connection_request();
void send_server_response(std::uint8_t proxy_cmd, std::uint8_t status_code);
void resolve_destination_host(std::uint8_t proxy_cmd,
@@ -96,7 +60,7 @@ private:
boost::asio::ip::tcp::socket m_destinationSocket;
};
-class ProxySessionTcp : public ProxySessionBase,
+class ProxySessionTcp : private ProxySessionBase,
public std::enable_shared_from_this<ProxySessionTcp> {
public:
explicit ProxySessionTcp(std::uint32_t session_id,
@@ -109,8 +73,7 @@ private:
void recv_from_both();
void recv_from_destination(const boost::system::error_code &ec,
std::size_t length);
- void recv_from_client(const boost::system::error_code &ec,
- std::size_t length);
+ void recv_from_client(std::size_t length);
void handle_client_write(const boost::system::error_code &ec,
std::size_t length);
void handle_destination_write(const boost::system::error_code &ec,
@@ -119,7 +82,7 @@ private:
boost::asio::ip::tcp::socket m_destinationSocket;
};
-class ProxyServer : public boost::noncopyable {
+class ProxyServer : private boost::noncopyable {
public:
ProxyServer(boost::asio::io_context &ioc,
const boost::asio::ip::tcp::endpoint &local_endpoint);