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 #ifndef NET_SOCKET_SOCKET_BIO_ADAPTER_H_ 6 #define NET_SOCKET_SOCKET_BIO_ADAPTER_H_ 7 8 #include "base/containers/span.h" 9 #include "base/memory/raw_ptr.h" 10 #include "base/memory/scoped_refptr.h" 11 #include "base/memory/weak_ptr.h" 12 #include "base/sequence_checker.h" 13 #include "net/base/completion_repeating_callback.h" 14 #include "net/base/net_errors.h" 15 #include "net/base/net_export.h" 16 #include "third_party/boringssl/src/include/openssl/base.h" 17 18 namespace net { 19 20 class GrowableIOBuffer; 21 class IOBuffer; 22 class StreamSocket; 23 24 // An adapter to convert between StreamSocket and OpenSSL BIO I/O models. 25 // 26 // BIO exposes a UNIX-like interface where BIO_read and BIO_write may either 27 // succeed synchronously or be retried (with no memory between calls). 28 // StreamSocket exposes an asynchronous interface where an asynchronous 29 // operation continues running and completes with a callback. 30 // 31 // For reading, SocketBIOAdapter maintains a buffer to pass to 32 // StreamSocket::Read. Once that Read completes, BIO_read synchronously drains 33 // the buffer and signals BIO_should_read once empty. 34 // 35 // For writing, SocketBIOAdapter maintains a ring buffer of data to be written 36 // to the StreamSocket. BIO_write synchronously copies data into the buffer or 37 // signals BIO_should_write if the buffer is full. The ring buffer is drained 38 // asynchronously into the socket. Note this means write errors are reported at 39 // a later BIO_write. 40 // 41 // To work around this delay, write errors are also surfaced out of 42 // BIO_read. Otherwise a failure in the final BIO_write of an application may go 43 // unnoticed. If this occurs, OnReadReady will be signaled as if it were a read 44 // error. See https://crbug.com/249848. 45 class NET_EXPORT_PRIVATE SocketBIOAdapter { 46 public: 47 // A delegate interface for when the sockets are ready. BIO assumes external 48 // knowledge of when to retry operations (such as a select() loop for UNIX), 49 // which is signaled out of StreamSocket's callbacks here. 50 // 51 // Callers should implement these methods and, when signaled, retry the 52 // BIO_read or BIO_write. This usually is done by retrying a higher-level 53 // operation, such as SSL_read or SSL_write. 54 // 55 // Callers may assume that OnReadReady and OnWriteReady will only be called 56 // from a PostTask or StreamSocket callback. 57 class Delegate { 58 public: 59 // Called when the BIO is ready to handle BIO_read, after having previously 60 // been blocked. 61 virtual void OnReadReady() = 0; 62 63 // Called when the BIO is ready to handle BIO_write, after having previously 64 // been blocked. 65 virtual void OnWriteReady() = 0; 66 67 protected: 68 virtual ~Delegate() = default; 69 }; 70 71 // Creates a new SocketBIOAdapter for the specified socket. |socket| and 72 // |delegate| must remain valid for the lifetime of the SocketBIOAdapter. 73 SocketBIOAdapter(StreamSocket* socket, 74 int read_buffer_capacity, 75 int write_buffer_capacity, 76 Delegate* delegate); 77 78 SocketBIOAdapter(const SocketBIOAdapter&) = delete; 79 SocketBIOAdapter& operator=(const SocketBIOAdapter&) = delete; 80 81 ~SocketBIOAdapter(); 82 bio()83 BIO* bio() { return bio_.get(); } 84 85 // Returns true if any data has been read from the underlying StreamSocket, 86 // but not yet consumed by the BIO. 87 bool HasPendingReadData(); 88 89 // Returns the allocation size estimate in bytes. 90 size_t GetAllocationSize() const; 91 92 private: 93 int BIORead(base::span<uint8_t> out); 94 void HandleSocketReadResult(int result); 95 void OnSocketReadComplete(int result); 96 void OnSocketReadIfReadyComplete(int result); 97 98 int BIOWrite(base::span<const uint8_t> in); 99 void SocketWrite(); 100 void HandleSocketWriteResult(int result); 101 void OnSocketWriteComplete(int result); 102 void CallOnReadReady(); 103 104 static SocketBIOAdapter* GetAdapter(BIO* bio); 105 static int BIOReadWrapper(BIO* bio, char* out, int len); 106 static int BIOWriteWrapper(BIO* bio, const char* in, int len); 107 static long BIOCtrlWrapper(BIO* bio, int cmd, long larg, void* parg); 108 109 static const BIO_METHOD* BIOMethod(); 110 111 bssl::UniquePtr<BIO> bio_; 112 113 // The pointer is non-owning so this class may be used with both 114 // ClientSocketHandles and raw StreamSockets. 115 raw_ptr<StreamSocket> socket_; 116 117 CompletionRepeatingCallback read_callback_; 118 CompletionRepeatingCallback write_callback_; 119 120 // The capacity of the read buffer. 121 int read_buffer_capacity_; 122 // A buffer containing data from the most recent socket Read(). The buffer is 123 // deallocated when unused. 124 scoped_refptr<IOBuffer> read_buffer_; 125 // The number of bytes of read_buffer_ consumed. 126 size_t read_offset_ = 0; 127 // The result of the most recent socket Read(). If ERR_IO_PENDING, there is a 128 // socket Read() in progress. If another error, Read() has failed. Otherwise, 129 // it is the number of bytes in the buffer (zero if empty). 130 int read_result_ = 0; 131 132 // The capacity of the write buffer. 133 int write_buffer_capacity_; 134 // A ring buffer of data to be written to the transport. The offset of the 135 // buffer is the start of the ring buffer and is advanced on successful 136 // Write(). The buffer is deallocated when unused. 137 scoped_refptr<GrowableIOBuffer> write_buffer_; 138 // The number of bytes of data in write_buffer_. 139 size_t write_buffer_used_ = 0; 140 // The most recent socket Write() error. If ERR_IO_PENDING, there is a socket 141 // Write() in progress. If OK, there is no socket Write() in progress and none 142 // have failed. 143 int write_error_ = OK; 144 145 raw_ptr<Delegate> delegate_; 146 147 SEQUENCE_CHECKER(sequence_checker_); 148 base::WeakPtrFactory<SocketBIOAdapter> weak_factory_{this}; 149 }; 150 151 } // namespace net 152 153 #endif // NET_SOCKET_SOCKET_BIO_ADAPTER_H_ 154