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