xref: /aosp_15_r20/external/cronet/net/socket/socket_bio_adapter.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/socket/socket_bio_adapter.h"
6 
7 #include <stdio.h>
8 #include <string.h>
9 
10 #include <algorithm>
11 
12 #include "base/check_op.h"
13 #include "base/debug/alias.h"
14 #include "base/functional/bind.h"
15 #include "base/location.h"
16 #include "base/notreached.h"
17 #include "base/task/single_thread_task_runner.h"
18 #include "net/base/io_buffer.h"
19 #include "net/base/net_errors.h"
20 #include "net/socket/socket.h"
21 #include "net/socket/stream_socket.h"
22 #include "net/ssl/openssl_ssl_util.h"
23 #include "net/traffic_annotation/network_traffic_annotation.h"
24 #include "third_party/boringssl/src/include/openssl/bio.h"
25 
26 namespace {
27 
28 const net::NetworkTrafficAnnotationTag kTrafficAnnotation =
29     net::DefineNetworkTrafficAnnotation("socket_bio_adapter", R"(
30       semantics {
31         sender: "Socket BIO Adapter"
32         description:
33           "SocketBIOAdapter is used only internal to //net code as an internal "
34           "detail to implement a TLS connection for a Socket class, and is not "
35           "being called directly outside of this abstraction."
36         trigger:
37           "Establishing a TLS connection to a remote endpoint. There are many "
38           "different ways in which a TLS connection may be triggered, such as "
39           "loading an HTTPS URL."
40         data:
41           "All data sent or received over a TLS connection. This traffic may "
42           "either be the handshake or application data. During the handshake, "
43           "the target host name, user's IP, data related to previous "
44           "handshake, client certificates, and channel ID, may be sent. When "
45           "the connection is used to load an HTTPS URL, the application data "
46           "includes cookies, request headers, and the response body."
47         destination: OTHER
48         destination_other:
49           "Any destination the implementing socket is connected to."
50       }
51       policy {
52         cookies_allowed: NO
53         setting: "This feature cannot be disabled."
54         policy_exception_justification: "Essential for navigation."
55       })");
56 
57 }  // namespace
58 
59 namespace net {
60 
SocketBIOAdapter(StreamSocket * socket,int read_buffer_capacity,int write_buffer_capacity,Delegate * delegate)61 SocketBIOAdapter::SocketBIOAdapter(StreamSocket* socket,
62                                    int read_buffer_capacity,
63                                    int write_buffer_capacity,
64                                    Delegate* delegate)
65     : socket_(socket),
66       read_buffer_capacity_(read_buffer_capacity),
67       write_buffer_capacity_(write_buffer_capacity),
68       delegate_(delegate) {
69   bio_.reset(BIO_new(BIOMethod()));
70   BIO_set_data(bio_.get(), this);
71   BIO_set_init(bio_.get(), 1);
72 
73   read_callback_ = base::BindRepeating(&SocketBIOAdapter::OnSocketReadComplete,
74                                        weak_factory_.GetWeakPtr());
75   write_callback_ = base::BindRepeating(
76       &SocketBIOAdapter::OnSocketWriteComplete, weak_factory_.GetWeakPtr());
77 }
78 
79 SocketBIOAdapter::~SocketBIOAdapter() {
80   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
81   // BIOs are reference-counted and may outlive the adapter. Clear the pointer
82   // so future operations fail.
83   BIO_set_data(bio_.get(), nullptr);
84 }
85 
86 bool SocketBIOAdapter::HasPendingReadData() {
87   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
88   return read_result_ > 0;
89 }
90 
91 size_t SocketBIOAdapter::GetAllocationSize() const {
92   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
93   size_t buffer_size = 0;
94   if (read_buffer_)
95     buffer_size += read_buffer_capacity_;
96 
97   if (write_buffer_)
98     buffer_size += write_buffer_capacity_;
99   return buffer_size;
100 }
101 
102 int SocketBIOAdapter::BIORead(char* out, int len) {
103   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
104   if (len <= 0)
105     return len;
106 
107   // If there is no result available synchronously, report any Write() errors
108   // that were observed. Otherwise the application may have encountered a socket
109   // error while writing that would otherwise not be reported until the
110   // application attempted to write again - which it may never do. See
111   // https://crbug.com/249848.
112   if (write_error_ != OK && write_error_ != ERR_IO_PENDING &&
113       (read_result_ == 0 || read_result_ == ERR_IO_PENDING)) {
114     OpenSSLPutNetError(FROM_HERE, write_error_);
115     return -1;
116   }
117 
118   if (read_result_ == 0) {
119     // Instantiate the read buffer and read from the socket. Although only |len|
120     // bytes were requested, intentionally read to the full buffer size. The SSL
121     // layer reads the record header and body in separate reads to avoid
122     // overreading, but issuing one is more efficient. SSL sockets are not
123     // reused after shutdown for non-SSL traffic, so overreading is fine.
124     CHECK(!read_buffer_);
125     CHECK_EQ(0, read_offset_);
126     read_buffer_ =
127         base::MakeRefCounted<IOBufferWithSize>(read_buffer_capacity_);
128     read_result_ = ERR_IO_PENDING;
129     int result = socket_->ReadIfReady(
130         read_buffer_.get(), read_buffer_capacity_,
131         base::BindOnce(&SocketBIOAdapter::OnSocketReadIfReadyComplete,
132                        weak_factory_.GetWeakPtr()));
133     if (result == ERR_IO_PENDING)
134       read_buffer_ = nullptr;
135     if (result == ERR_READ_IF_READY_NOT_IMPLEMENTED) {
136       result = socket_->Read(read_buffer_.get(), read_buffer_capacity_,
137                              read_callback_);
138     }
139     if (result != ERR_IO_PENDING) {
140       // `HandleSocketReadResult` will update `read_result_` based on `result`.
141       HandleSocketReadResult(result);
142     }
143   }
144 
145   // There is a pending Read(). Inform the caller to retry when it completes.
146   if (read_result_ == ERR_IO_PENDING) {
147     BIO_set_retry_read(bio());
148     return -1;
149   }
150 
151   // If the last Read() failed, report the error.
152   if (read_result_ < 0) {
153     OpenSSLPutNetError(FROM_HERE, read_result_);
154     return -1;
155   }
156 
157   // Report the result of the last Read() if non-empty.
158   CHECK_LT(read_offset_, read_result_);
159   len = std::min(len, read_result_ - read_offset_);
160   memcpy(out, read_buffer_->data() + read_offset_, len);
161   read_offset_ += len;
162 
163   // Release the buffer when empty.
164   if (read_offset_ == read_result_) {
165     read_buffer_ = nullptr;
166     read_offset_ = 0;
167     read_result_ = 0;
168   }
169 
170   return len;
171 }
172 
173 void SocketBIOAdapter::HandleSocketReadResult(int result) {
174   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
175   CHECK_NE(ERR_IO_PENDING, result);
176   CHECK_EQ(ERR_IO_PENDING, read_result_);
177 
178   // If an EOF, canonicalize to ERR_CONNECTION_CLOSED here, so that higher
179   // levels don't report success.
180   if (result == 0)
181     result = ERR_CONNECTION_CLOSED;
182 
183   read_result_ = result;
184 
185   // The read buffer is no longer needed.
186   if (read_result_ <= 0)
187     read_buffer_ = nullptr;
188 }
189 
190 void SocketBIOAdapter::OnSocketReadComplete(int result) {
191   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
192   CHECK_EQ(ERR_IO_PENDING, read_result_);
193 
194   HandleSocketReadResult(result);
195   delegate_->OnReadReady();
196 }
197 
198 void SocketBIOAdapter::OnSocketReadIfReadyComplete(int result) {
199   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
200   CHECK_EQ(ERR_IO_PENDING, read_result_);
201   CHECK_GE(OK, result);
202 
203   // Do not use HandleSocketReadResult() because result == OK doesn't mean EOF.
204   read_result_ = result;
205 
206   delegate_->OnReadReady();
207 }
208 
209 int SocketBIOAdapter::BIOWrite(const char* in, int len) {
210   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
211   if (len <= 0)
212     return len;
213 
214   // If the write buffer is not empty, there must be a pending Write() to flush
215   // it.
216   CHECK(write_buffer_used_ == 0 || write_error_ == ERR_IO_PENDING);
217 
218   // If a previous Write() failed, report the error.
219   if (write_error_ != OK && write_error_ != ERR_IO_PENDING) {
220     OpenSSLPutNetError(FROM_HERE, write_error_);
221     return -1;
222   }
223 
224   // Instantiate the write buffer if needed.
225   if (!write_buffer_) {
226     CHECK_EQ(0, write_buffer_used_);
227     write_buffer_ = base::MakeRefCounted<GrowableIOBuffer>();
228     write_buffer_->SetCapacity(write_buffer_capacity_);
229   }
230 
231   // If the ring buffer is full, inform the caller to try again later.
232   if (write_buffer_used_ == write_buffer_->capacity()) {
233     BIO_set_retry_write(bio());
234     return -1;
235   }
236 
237   int bytes_copied = 0;
238 
239   // If there is space after the offset, fill it.
240   if (write_buffer_used_ < write_buffer_->RemainingCapacity()) {
241     int chunk =
242         std::min(write_buffer_->RemainingCapacity() - write_buffer_used_, len);
243     memcpy(write_buffer_->data() + write_buffer_used_, in, chunk);
244     in += chunk;
245     len -= chunk;
246     bytes_copied += chunk;
247     write_buffer_used_ += chunk;
248   }
249 
250   // If there is still space for remaining data, try to wrap around.
251   if (len > 0 && write_buffer_used_ < write_buffer_->capacity()) {
252     // If there were any room after the offset, the previous branch would have
253     // filled it.
254     CHECK_LE(write_buffer_->RemainingCapacity(), write_buffer_used_);
255     int write_offset = write_buffer_used_ - write_buffer_->RemainingCapacity();
256     int chunk = std::min(len, write_buffer_->capacity() - write_buffer_used_);
257     memcpy(write_buffer_->StartOfBuffer() + write_offset, in, chunk);
258     in += chunk;
259     len -= chunk;
260     bytes_copied += chunk;
261     write_buffer_used_ += chunk;
262   }
263 
264   // Either the buffer is now full or there is no more input.
265   CHECK(len == 0 || write_buffer_used_ == write_buffer_->capacity());
266 
267   // Schedule a socket Write() if necessary. (The ring buffer may previously
268   // have been empty.)
269   SocketWrite();
270 
271   // If a read-interrupting write error was synchronously discovered,
272   // asynchronously notify OnReadReady. See https://crbug.com/249848. Avoid
273   // reentrancy by deferring it to a later event loop iteration.
274   if (write_error_ != OK && write_error_ != ERR_IO_PENDING &&
275       read_result_ == ERR_IO_PENDING) {
276     base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
277         FROM_HERE, base::BindOnce(&SocketBIOAdapter::CallOnReadReady,
278                                   weak_factory_.GetWeakPtr()));
279   }
280 
281   return bytes_copied;
282 }
283 
284 void SocketBIOAdapter::SocketWrite() {
285   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
286   while (write_error_ == OK && write_buffer_used_ > 0) {
287     int write_buffer_used_old = write_buffer_used_;
288     int write_size =
289         std::min(write_buffer_used_, write_buffer_->RemainingCapacity());
290 
291     // TODO(crbug.com/1440692): Remove this once the crash is resolved.
292     char debug[128];
293     snprintf(debug, sizeof(debug),
294              "offset=%d;remaining=%d;used=%d;write_size=%d",
295              write_buffer_->offset(), write_buffer_->RemainingCapacity(),
296              write_buffer_used_, write_size);
297     base::debug::Alias(debug);
298 
299     write_error_ = ERR_IO_PENDING;
300     int result = socket_->Write(write_buffer_.get(), write_size,
301                                 write_callback_, kTrafficAnnotation);
302 
303     // TODO(crbug.com/1440692): Remove this once the crash is resolved.
304     char debug2[32];
305     snprintf(debug2, sizeof(debug2), "result=%d", result);
306     base::debug::Alias(debug2);
307 
308     // If `write_buffer_used_` changed across a call to the underlying socket,
309     // something went very wrong.
310     //
311     // TODO(crbug.com/1440692): Remove this once the crash is resolved.
312     CHECK_EQ(write_buffer_used_old, write_buffer_used_);
313     if (result != ERR_IO_PENDING) {
314       // `HandleSocketWriteResult` will update `write_error_` based on `result.
315       HandleSocketWriteResult(result);
316     }
317   }
318 }
319 
HandleSocketWriteResult(int result)320 void SocketBIOAdapter::HandleSocketWriteResult(int result) {
321   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
322   CHECK_NE(ERR_IO_PENDING, result);
323   CHECK_EQ(ERR_IO_PENDING, write_error_);
324 
325   if (result < 0) {
326     write_error_ = result;
327 
328     // The write buffer is no longer needed.
329     write_buffer_ = nullptr;
330     write_buffer_used_ = 0;
331     return;
332   }
333 
334   // Advance the ring buffer.
335   CHECK_LE(result, write_buffer_used_);
336   CHECK_LE(result, write_buffer_->RemainingCapacity());
337   write_buffer_->set_offset(write_buffer_->offset() + result);
338   write_buffer_used_ -= result;
339   if (write_buffer_->RemainingCapacity() == 0)
340     write_buffer_->set_offset(0);
341   write_error_ = OK;
342 
343   // Release the write buffer if empty.
344   if (write_buffer_used_ == 0)
345     write_buffer_ = nullptr;
346 }
347 
348 void SocketBIOAdapter::OnSocketWriteComplete(int result) {
349   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
350   CHECK_EQ(ERR_IO_PENDING, write_error_);
351 
352   bool was_full = write_buffer_used_ == write_buffer_->capacity();
353 
354   HandleSocketWriteResult(result);
355   SocketWrite();
356 
357   // If transitioning from being unable to accept data to being able to, signal
358   // OnWriteReady.
359   if (was_full) {
360     base::WeakPtr<SocketBIOAdapter> guard(weak_factory_.GetWeakPtr());
361     delegate_->OnWriteReady();
362     // OnWriteReady may delete the adapter.
363     if (!guard)
364       return;
365   }
366 
367   // Write errors are fed back into BIO_read once the read buffer is empty. If
368   // BIO_read is currently blocked, signal early that a read result is ready.
369   if (result < 0 && read_result_ == ERR_IO_PENDING)
370     delegate_->OnReadReady();
371 }
372 
373 void SocketBIOAdapter::CallOnReadReady() {
374   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
375   if (read_result_ == ERR_IO_PENDING)
376     delegate_->OnReadReady();
377 }
378 
379 SocketBIOAdapter* SocketBIOAdapter::GetAdapter(BIO* bio) {
380   SocketBIOAdapter* adapter =
381       reinterpret_cast<SocketBIOAdapter*>(BIO_get_data(bio));
382   if (adapter) {
383     CHECK_EQ(bio, adapter->bio());
384   }
385   return adapter;
386 }
387 
388 int SocketBIOAdapter::BIOWriteWrapper(BIO* bio, const char* in, int len) {
389   BIO_clear_retry_flags(bio);
390 
391   SocketBIOAdapter* adapter = GetAdapter(bio);
392   if (!adapter) {
393     OpenSSLPutNetError(FROM_HERE, ERR_UNEXPECTED);
394     return -1;
395   }
396 
397   return adapter->BIOWrite(in, len);
398 }
399 
400 int SocketBIOAdapter::BIOReadWrapper(BIO* bio, char* out, int len) {
401   BIO_clear_retry_flags(bio);
402 
403   SocketBIOAdapter* adapter = GetAdapter(bio);
404   if (!adapter) {
405     OpenSSLPutNetError(FROM_HERE, ERR_UNEXPECTED);
406     return -1;
407   }
408 
409   return adapter->BIORead(out, len);
410 }
411 
412 long SocketBIOAdapter::BIOCtrlWrapper(BIO* bio,
413                                       int cmd,
414                                       long larg,
415                                       void* parg) {
416   switch (cmd) {
417     case BIO_CTRL_FLUSH:
418       // The SSL stack requires BIOs handle BIO_flush.
419       return 1;
420   }
421 
422   NOTIMPLEMENTED();
423   return 0;
424 }
425 
426 const BIO_METHOD* SocketBIOAdapter::BIOMethod() {
427   static const BIO_METHOD* kMethod = []() {
428     BIO_METHOD* method = BIO_meth_new(0, nullptr);
429     CHECK(method);
430     CHECK(BIO_meth_set_write(method, SocketBIOAdapter::BIOWriteWrapper));
431     CHECK(BIO_meth_set_read(method, SocketBIOAdapter::BIOReadWrapper));
432     CHECK(BIO_meth_set_ctrl(method, SocketBIOAdapter::BIOCtrlWrapper));
433     return method;
434   }();
435   return kMethod;
436 }
437 
438 }  // namespace net
439