@@ -66,44 +66,41 @@ std::string Obfs4Listener::cert() const {
6666}
6767
6868void 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
222211void 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