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