Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Unified Diff: net/socket/socket_bio_adapter.h

Issue 2411033003: Drop buffers in idle SSLClientSockets (and SSLServerSockets). (Closed)
Patch Set: rsleevi comments Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/net.gypi ('k') | net/socket/socket_bio_adapter.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/socket/socket_bio_adapter.h
diff --git a/net/socket/socket_bio_adapter.h b/net/socket/socket_bio_adapter.h
new file mode 100644
index 0000000000000000000000000000000000000000..d4c81725c49d8510dcbf07bc8b72bf540a763f3f
--- /dev/null
+++ b/net/socket/socket_bio_adapter.h
@@ -0,0 +1,143 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_SOCKET_SOCKET_BIO_ADAPTER_H_
+#define NET_SOCKET_SOCKET_BIO_ADAPTER_H_
+
+#include <openssl/base.h>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "net/base/completion_callback.h"
+#include "net/base/net_export.h"
+
+namespace net {
+
+class GrowableIOBuffer;
+class IOBuffer;
+class StreamSocket;
+
+// An adapter to convert between StreamSocket and OpenSSL BIO I/O models.
+//
+// BIO exposes a UNIX-like interface where BIO_read and BIO_write may either
+// succeed synchronously or be retried (with no memory between calls).
+// StreamSocket exposes an asynchronous interface where an asynchronous
+// operation continues running and completes with a callback.
+//
+// For reading, SocketBIOAdapter maintains a buffer to pass to
+// StreamSocket::Read. Once that Read completes, BIO_read synchronously drains
+// the buffer and signals BIO_should_read once empty.
+//
+// For writing, SocketBIOAdapter maintains a ring buffer of data to be written
+// to the StreamSocket. BIO_write synchronously copies data into the buffer or
+// signals BIO_should_write if the buffer is full. The ring buffer is drained
+// asynchronously into the socket. Note this means write errors are reported at
+// a later BIO_write.
+//
+// To work around this delay, write errors are also surfaced out of
+// BIO_read. Otherwise a failure in the final BIO_write of an application may go
+// unnoticed. If this occurs, OnReadReady will be signaled as if it were a read
+// error. See https://crbug.com/249848.
+class NET_EXPORT_PRIVATE SocketBIOAdapter {
+ public:
+ // A delegate interface for when the sockets are ready. BIO assumes external
+ // knowledge of when to retry operations (such as a select() loop for UNIX),
+ // which is signaled out of StreamSocket's callbacks here.
+ //
+ // Callers should implement these methods and, when signaled, retry the
+ // BIO_read or BIO_write. This usually is done by retrying a higher-level
+ // operation, such as SSL_read or SSL_write.
+ //
+ // Callers may assume that OnReadReady and OnWriteReady will only be called
+ // from a PostTask or StreamSocket callback.
+ class Delegate {
+ public:
+ // Called when the BIO is ready to handle BIO_read, after having previously
+ // been blocked.
+ virtual void OnReadReady() = 0;
+
+ // Called when the BIO is ready to handle BIO_write, after having previously
+ // been blocked.
+ virtual void OnWriteReady() = 0;
+
+ protected:
+ virtual ~Delegate() {}
+ };
+
+ // Creates a new SocketBIOAdapter for the specified socket. |socket| and
+ // |delegate| must remain valid for the lifetime of the SocketBIOAdapter.
+ SocketBIOAdapter(StreamSocket* socket,
+ int read_buffer_capacity,
+ int write_buffer_capacity,
+ Delegate* delegate);
+ ~SocketBIOAdapter();
+
+ BIO* bio() { return bio_.get(); }
+
+ // Returns true if any data has been read from the underlying StreamSocket,
+ // but not yet consumed by the BIO.
+ bool HasPendingReadData();
+
+ private:
+ int BIORead(char* out, int len);
+ void HandleSocketReadResult(int result);
+ void OnSocketReadComplete(int result);
+
+ int BIOWrite(const char* in, int len);
+ void SocketWrite();
+ void HandleSocketWriteResult(int result);
+ void OnSocketWriteComplete(int result);
+ void CallOnReadReady();
+
+ static SocketBIOAdapter* GetAdapter(BIO* bio);
+ static int BIOReadWrapper(BIO* bio, char* out, int len);
+ static int BIOWriteWrapper(BIO* bio, const char* in, int len);
+ static long BIOCtrlWrapper(BIO* bio, int cmd, long larg, void* parg);
+
+ static const BIO_METHOD kBIOMethod;
+
+ bssl::UniquePtr<BIO> bio_;
+
+ // The pointer is non-owning so this class may be used with both
+ // ClientSocketHandles and raw StreamSockets.
+ StreamSocket* socket_;
+
+ CompletionCallback read_callback_;
+ CompletionCallback write_callback_;
+
+ // The capacity of the read buffer.
+ int read_buffer_capacity_;
+ // A buffer containing data from the most recent socket Read(). The buffer is
+ // deallocated when unused.
+ scoped_refptr<IOBuffer> read_buffer_;
+ // The number of bytes of read_buffer_ consumed.
+ int read_offset_;
+ // The result of the most recent socket Read(). If ERR_IO_PENDING, there is a
+ // socket Read() in progress. If another error, Read() has failed. Otherwise,
+ // it is the number of bytes in the buffer (zero if empty).
+ int read_result_;
+
+ // The capacity of the write buffer.
+ int write_buffer_capacity_;
+ // A ring buffer of data to be written to the transport. The offset of the
+ // buffer is the start of the ring buffer and is advanced on successful
+ // Write(). The buffer is deallocated when unused.
+ scoped_refptr<GrowableIOBuffer> write_buffer_;
+ // The number of bytes of data in write_buffer_.
+ int write_buffer_used_;
+ // The most recent socket Write() error. If ERR_IO_PENDING, there is a socket
+ // Write() in progress. If OK, there is no socket Write() in progress and none
+ // have failed.
+ int write_error_;
+
+ Delegate* delegate_;
+
+ base::WeakPtrFactory<SocketBIOAdapter> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(SocketBIOAdapter);
+};
+
+} // namespace net
+
+#endif // NET_SOCKET_SOCKET_BIO_ADAPTER_H_
« no previous file with comments | « net/net.gypi ('k') | net/socket/socket_bio_adapter.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698