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

Side by Side Diff: net/socket/socket_bio_adapter.h

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

Powered by Google App Engine
This is Rietveld 408576698