Skip to content

Commit c7f06fa

Browse files
Dendi Suhubdyclaude
andcommitted
Fix obfs4_listener to use buffer-based TcpConnection API
- read() returns expected<size_t>, not data; use buffer + bytes_read - Replace io_context reference member with pointer for aggregate init - Use aggregate initialization for HandshakeReader - Construct proper spans for write() calls - Use [[maybe_unused]] for stub proxy_connection parameters Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent bd5d1cf commit c7f06fa

File tree

1 file changed

+39
-53
lines changed

1 file changed

+39
-53
lines changed

src/transport/obfs4_listener.cpp

Lines changed: 39 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -66,44 +66,41 @@ std::string Obfs4Listener::cert() const {
6666
}
6767

6868
void Obfs4Listener::handle_connection(std::shared_ptr<net::TcpConnection> conn) {
69-
// Perform obfs4 handshake asynchronously
7069
auto handshake = std::make_shared<Obfs4ServerHandshake>(node_id_, identity_key_);
7170

72-
// Read data in a loop until handshake completes
73-
// Use the io_context to post async work
74-
auto self_stats_completed = &handshakes_completed_;
75-
auto self_stats_failed = &handshakes_failed_;
76-
auto self_or_port = or_port_;
77-
auto& self_io = io_context_;
71+
auto stats_completed = &handshakes_completed_;
72+
auto stats_failed = &handshakes_failed_;
73+
auto local_or_port = or_port_;
74+
auto& io = io_context_;
7875

79-
// Buffer for reading handshake data
8076
auto buffer = std::make_shared<std::array<uint8_t, 4096>>();
8177

82-
// Recursive lambda for async handshake reads
78+
// Handshake state machine: read -> consume -> check state -> loop or finish
8379
struct HandshakeReader : std::enable_shared_from_this<HandshakeReader> {
8480
std::shared_ptr<net::TcpConnection> conn;
8581
std::shared_ptr<Obfs4ServerHandshake> handshake;
8682
std::shared_ptr<std::array<uint8_t, 4096>> buffer;
8783
std::atomic<uint64_t>* completed;
8884
std::atomic<uint64_t>* failed;
8985
uint16_t or_port;
90-
boost::asio::io_context& io_ctx;
86+
boost::asio::io_context* io_ctx;
9187

9288
void start() {
9389
read_more();
9490
}
9591

9692
void read_more() {
97-
auto read_result = conn->read(
93+
auto bytes_read = conn->read(
9894
std::span<uint8_t>(buffer->data(), buffer->size()));
9995

100-
if (!read_result || read_result->empty()) {
96+
if (!bytes_read || *bytes_read == 0) {
10197
LOG_DEBUG("obfs4 handshake: connection closed during read");
10298
failed->fetch_add(1, std::memory_order_relaxed);
10399
return;
104100
}
105101

106-
auto consume_result = handshake->consume(*read_result);
102+
auto data = std::span<const uint8_t>(buffer->data(), *bytes_read);
103+
auto consume_result = handshake->consume(data);
107104
if (!consume_result) {
108105
LOG_DEBUG("obfs4 handshake failed: {}",
109106
obfs4_error_message(consume_result.error()));
@@ -112,15 +109,15 @@ void Obfs4Listener::handle_connection(std::shared_ptr<net::TcpConnection> conn)
112109
}
113110

114111
if (handshake->state() == Obfs4ServerHandshake::State::Completed) {
115-
// Generate and send server hello
116112
auto hello = handshake->generate_server_hello();
117113
if (!hello) {
118114
LOG_ERROR("obfs4: failed to generate server hello");
119115
failed->fetch_add(1, std::memory_order_relaxed);
120116
return;
121117
}
122118

123-
auto write_result = conn->write(*hello);
119+
auto hello_span = std::span<const uint8_t>(hello->data(), hello->size());
120+
auto write_result = conn->write(hello_span);
124121
if (!write_result) {
125122
LOG_ERROR("obfs4: failed to send server hello");
126123
failed->fetch_add(1, std::memory_order_relaxed);
@@ -132,27 +129,23 @@ void Obfs4Listener::handle_connection(std::shared_ptr<net::TcpConnection> conn)
132129

133130
// Set up framing with session keys
134131
auto framing = std::make_unique<Obfs4Framing>();
135-
auto& keys = handshake->session_keys();
132+
const auto& keys = handshake->session_keys();
136133
framing->init_send(keys.send_key, keys.send_nonce);
137134
framing->init_recv(keys.recv_key, keys.recv_nonce);
138135

139136
// Connect to local OR port and start proxying
140-
auto or_conn = std::make_shared<net::TcpConnection>(io_ctx);
137+
auto or_conn = std::make_shared<net::TcpConnection>(*io_ctx);
141138
auto connect_result = or_conn->connect("127.0.0.1", or_port);
142139
if (!connect_result) {
143140
LOG_ERROR("obfs4: failed to connect to local OR port {}", or_port);
144141
return;
145142
}
146143

147-
// Start bidirectional proxy
148-
// obfs4 -> decrypt -> OR port
149-
// OR port -> encrypt -> obfs4
150144
proxy_loop(conn, or_conn, std::move(framing));
151145
} else if (handshake->state() == Obfs4ServerHandshake::State::Failed) {
152146
failed->fetch_add(1, std::memory_order_relaxed);
153147
return;
154148
} else {
155-
// Need more data
156149
read_more();
157150
}
158151
}
@@ -165,68 +158,61 @@ void Obfs4Listener::handle_connection(std::shared_ptr<net::TcpConnection> conn)
165158
auto shared_framing = std::shared_ptr<Obfs4Framing>(std::move(framing));
166159
auto proxy_buf = std::make_shared<std::array<uint8_t, 4096>>();
167160

168-
// Simple synchronous proxy for now
169-
// TODO: Use async I/O for production
170161
while (true) {
171-
// Read from obfs4 connection
172-
auto obfs4_data = obfs4_conn->read(
162+
// Read encrypted data from obfs4 client
163+
auto obfs4_read = obfs4_conn->read(
173164
std::span<uint8_t>(proxy_buf->data(), proxy_buf->size()));
174-
if (!obfs4_data || obfs4_data->empty()) {
165+
if (!obfs4_read || *obfs4_read == 0) {
175166
break;
176167
}
177168

178169
// Decrypt frames
179-
auto frames = shared_framing->decode(*obfs4_data);
170+
auto encrypted = std::span<const uint8_t>(proxy_buf->data(), *obfs4_read);
171+
auto frames = shared_framing->decode(encrypted);
180172
if (!frames) {
181173
LOG_DEBUG("obfs4: frame decryption failed");
182174
break;
183175
}
184176

185177
// Forward decrypted data to OR port
186-
for (auto& frame : frames->frames) {
187-
auto write_result = or_conn->write(frame);
188-
if (!write_result) {
189-
break;
178+
for (const auto& frame : frames->frames) {
179+
auto frame_span = std::span<const uint8_t>(frame.data(), frame.size());
180+
auto wr = or_conn->write(frame_span);
181+
if (!wr) {
182+
goto done;
190183
}
191184
}
192185

193-
// Read from OR port
194-
auto or_data = or_conn->read(
186+
// Read plaintext from OR port
187+
auto or_read = or_conn->read(
195188
std::span<uint8_t>(proxy_buf->data(), proxy_buf->size()));
196-
if (or_data && !or_data->empty()) {
197-
// Encrypt and send back to obfs4 connection
198-
auto encoded = shared_framing->encode(*or_data);
199-
auto send_result = obfs4_conn->write(encoded);
200-
if (!send_result) {
189+
if (or_read && *or_read > 0) {
190+
auto plaintext = std::span<const uint8_t>(proxy_buf->data(), *or_read);
191+
auto encoded = shared_framing->encode(plaintext);
192+
auto enc_span = std::span<const uint8_t>(encoded.data(), encoded.size());
193+
auto wr = obfs4_conn->write(enc_span);
194+
if (!wr) {
201195
break;
202196
}
203197
}
204198
}
205-
199+
done:
206200
obfs4_conn->close();
207201
or_conn->close();
208202
}
209203
};
210204

211-
auto reader = std::make_shared<HandshakeReader>();
212-
reader->conn = conn;
213-
reader->handshake = handshake;
214-
reader->buffer = buffer;
215-
reader->completed = self_stats_completed;
216-
reader->failed = self_stats_failed;
217-
reader->or_port = self_or_port;
218-
reader->io_ctx = self_io;
205+
auto reader = std::make_shared<HandshakeReader>(
206+
HandshakeReader{conn, handshake, buffer,
207+
stats_completed, stats_failed, local_or_port, &io});
219208
reader->start();
220209
}
221210

222211
void Obfs4Listener::proxy_connection(
223-
std::shared_ptr<net::TcpConnection> obfs4_conn,
224-
std::shared_ptr<net::TcpConnection> or_conn,
225-
std::unique_ptr<Obfs4Framing> framing) {
212+
[[maybe_unused]] std::shared_ptr<net::TcpConnection> obfs4_conn,
213+
[[maybe_unused]] std::shared_ptr<net::TcpConnection> or_conn,
214+
[[maybe_unused]] std::unique_ptr<Obfs4Framing> framing) {
226215
// Proxy logic is handled inside HandshakeReader::proxy_loop
227-
(void)obfs4_conn;
228-
(void)or_conn;
229-
(void)framing;
230216
}
231217

232218
} // namespace tor::transport

0 commit comments

Comments
 (0)