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

Side by Side Diff: sdk/lib/io/tls_socket.dart

Issue 11416108: Implement input and output streams for secure network sockets. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Minimize diff to tls_server_test.dart. Created 8 years, 1 month 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * TlsSocket provides a secure (SSL or TLS) client connection to a server. 6 * TlsSocket provides a secure (SSL or TLS) client connection to a server.
7 * The certificate provided by the server is checked 7 * The certificate provided by the server is checked
8 * using the certificate database provided in setCertificateDatabase. 8 * using the certificate database provided in setCertificateDatabase.
9 */ 9 */
10 abstract class TlsSocket implements Socket { 10 abstract class TlsSocket implements Socket {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 if (_socket == null) { 75 if (_socket == null) {
76 _socket = new Socket(host, port); 76 _socket = new Socket(host, port);
77 } 77 }
78 _socket.onConnect = _tlsConnectHandler; 78 _socket.onConnect = _tlsConnectHandler;
79 _socket.onData = _tlsDataHandler; 79 _socket.onData = _tlsDataHandler;
80 _socket.onClosed = _tlsCloseHandler; 80 _socket.onClosed = _tlsCloseHandler;
81 _tlsFilter.init(); 81 _tlsFilter.init();
82 _tlsFilter.registerHandshakeCompleteCallback(_tlsHandshakeCompleteHandler); 82 _tlsFilter.registerHandshakeCompleteCallback(_tlsHandshakeCompleteHandler);
83 } 83 }
84 84
85 InputStream get inputStream {
86 // TODO(6701): Implement stream interfaces on TlsSocket.
87 throw new UnimplementedError("TlsSocket.inputStream not implemented yet");
88 }
89
90 int get port => _socket.port; 85 int get port => _socket.port;
91 86
92 String get remoteHost => _socket.remoteHost; 87 String get remoteHost => _socket.remoteHost;
93 88
94 int get remotePort => _socket.remotePort; 89 int get remotePort => _socket.remotePort;
95 90
96 void set onClosed(void callback()) { 91 void set onClosed(void callback()) {
92 if (_inputStream != null) {
93 throw new StreamException(
94 "Cannot set close handler when input stream is used");
95 }
96 _onClosed = callback;
97 }
98
99 void set _onClosed(void callback()) {
97 _socketCloseHandler = callback; 100 _socketCloseHandler = callback;
98 } 101 }
99 102
100 void set onConnect(void callback()) { 103 void set onConnect(void callback()) {
104 if (_outputStream != null) {
105 throw new StreamException(
106 "Cannot set connect handler when output stream is used");
107 }
108 if (_status == CONNECTED || _status == CLOSED) {
109 throw new StreamException(
110 "Cannot set connect handler when already connected");
111 }
112 _onConnect = callback;
113 }
114
115 void set _onConnect(void callback()) {
101 _socketConnectHandler = callback; 116 _socketConnectHandler = callback;
102 } 117 }
103 118
104 void set onData(void callback()) { 119 void set onData(void callback()) {
120 if (_outputStream != null) {
121 throw new StreamException(
122 "Cannot set data handler when input stream is used");
123 }
124 _onData = callback;
125 }
126
127 void set _onData(void callback()) {
105 _socketDataHandler = callback; 128 _socketDataHandler = callback;
106 } 129 }
107 130
108 void set onWrite(void callback()) { 131 void set onWrite(void callback()) {
132 if (_outputStream != null) {
133 throw new StreamException(
134 "Cannot set write handler when output stream is used");
135 }
136 _onWrite = callback;
137 }
138
139 void set _onWrite(void callback()) {
109 _socketWriteHandler = callback; 140 _socketWriteHandler = callback;
110 // Reset the one-shot onWrite handler. 141 // Reset the one-shot onWrite handler.
111 _socket.onWrite = _tlsWriteHandler; 142 _socket.onWrite = _tlsWriteHandler;
112 } 143 }
113 144
145 InputStream get inputStream {
146 if (_inputStream == null) {
147 if (_socketDataHandler != null || _socketCloseHandler != null) {
148 throw new StreamException(
149 "Cannot get input stream when socket handlers are used");
150 }
151 _inputStream = new _SocketInputStream(this);
152 }
153 return _inputStream;
154 }
155
114 OutputStream get outputStream { 156 OutputStream get outputStream {
115 // TODO(6701): Implement stream interfaces on TlsSocket. 157 if (_outputStream == null) {
116 throw new UnimplementedError("TlsSocket.inputStream not implemented yet"); 158 if (_socketConnectHandler != null || _socketWriteHandler != null) {
159 throw new StreamException(
160 "Cannot get output stream when socket handlers are used");
161 }
162 _outputStream = new _SocketOutputStream(this);
163 }
164 return _outputStream;
117 } 165 }
118 166
119 int available() { 167 int available() {
120 throw new UnimplementedError("TlsSocket.available not implemented yet"); 168 throw new UnimplementedError("TlsSocket.available not implemented yet");
121 } 169 }
122 170
123 void close([bool halfClose]) { 171 void close([bool halfClose]) {
124 _socket.close(halfClose); 172 _socket.close(halfClose);
125 } 173 }
126 174
175 void _closeWrite() => close(true);
176
127 List<int> read([int len]) { 177 List<int> read([int len]) {
178 if (_status != CONNECTED && _status != CLOSED) {
179 return new List<int>(0);
180 }
128 var buffer = _tlsFilter.buffers[READ_PLAINTEXT]; 181 var buffer = _tlsFilter.buffers[READ_PLAINTEXT];
129 _readEncryptedData(); 182 _readEncryptedData();
130 int toRead = buffer.length; 183 int toRead = buffer.length;
131 if (len != null) { 184 if (len != null) {
132 if (len is! int || len < 0) { 185 if (len is! int || len < 0) {
133 throw new ArgumentError( 186 throw new ArgumentError(
134 "Invalid len parameter in TlsSocket.read (len: $len)"); 187 "Invalid len parameter in TlsSocket.read (len: $len)");
135 } 188 }
136 if (len < toRead) { 189 if (len < toRead) {
137 toRead = len; 190 toRead = len;
138 } 191 }
139 } 192 }
140 List<int> result = buffer.data.getRange(buffer.start, toRead); 193 List<int> result = buffer.data.getRange(buffer.start, toRead);
141 buffer.advanceStart(toRead); 194 buffer.advanceStart(toRead);
142 _setHandlersAfterRead(); 195 _setHandlersAfterRead();
143 return result; 196 return result;
144 } 197 }
145 198
146 int readList(List<int> data, int offset, int bytes) { 199 int readList(List<int> data, int offset, int bytes) {
147 if (offset < 0 || bytes < 0 || offset + bytes > data.length) { 200 if (offset < 0 || bytes < 0 || offset + bytes > data.length) {
148 throw new ArgumentError( 201 throw new ArgumentError(
149 "Invalid offset or bytes in TlsSocket.readList"); 202 "Invalid offset or bytes in TlsSocket.readList");
150 } 203 }
204 if (_status != CONNECTED && _status != CLOSED) {
205 return 0;
206 }
151 207
152 int bytesRead = 0; 208 int bytesRead = 0;
153 var buffer = _tlsFilter.buffers[READ_PLAINTEXT]; 209 var buffer = _tlsFilter.buffers[READ_PLAINTEXT];
154 // TODO(whesse): Currently this fails if the if is turned into a while loop. 210 // TODO(whesse): Currently this fails if the if is turned into a while loop.
155 // Fix it so that it can loop and read more than one buffer's worth of data. 211 // Fix it so that it can loop and read more than one buffer's worth of data.
156 if (bytes > bytesRead) { 212 if (bytes > bytesRead) {
157 _readEncryptedData(); 213 _readEncryptedData();
158 if (buffer.length > 0) { 214 if (buffer.length > 0) {
159 int toRead = min(bytes - bytesRead, buffer.length); 215 int toRead = min(bytes - bytesRead, buffer.length);
160 data.setRange(offset, toRead, buffer.data, buffer.start); 216 data.setRange(offset, toRead, buffer.data, buffer.start);
161 buffer.advanceStart(toRead); 217 buffer.advanceStart(toRead);
162 bytesRead += toRead; 218 bytesRead += toRead;
163 offset += toRead; 219 offset += toRead;
164 } 220 }
165 } 221 }
166 222
167 _setHandlersAfterRead(); 223 _setHandlersAfterRead();
168 return bytesRead; 224 return bytesRead;
169 } 225 }
170 226
171 // Write the data to the socket, and flush it as much as possible 227 // Write the data to the socket, and flush it as much as possible
172 // until it would block. If the write would block, _writeEncryptedData sets 228 // until it would block. If the write would block, _writeEncryptedData sets
173 // up handlers to flush the pipeline when possible. 229 // up handlers to flush the pipeline when possible.
174 int writeList(List<int> data, int offset, int bytes) { 230 int writeList(List<int> data, int offset, int bytes) {
231 if (_status != CONNECTED) return 0;
175 var buffer = _tlsFilter.buffers[WRITE_PLAINTEXT]; 232 var buffer = _tlsFilter.buffers[WRITE_PLAINTEXT];
176 if (bytes > buffer.free) { 233 if (bytes > buffer.free) {
177 bytes = buffer.free; 234 bytes = buffer.free;
178 } 235 }
179 if (bytes > 0) { 236 if (bytes > 0) {
180 buffer.data.setRange(buffer.start + buffer.length, bytes, data, offset); 237 buffer.data.setRange(buffer.start + buffer.length, bytes, data, offset);
181 buffer.length += bytes; 238 buffer.length += bytes;
182 } 239 }
183 _writeEncryptedData(); // Tries to flush all pipeline stages. 240 _writeEncryptedData(); // Tries to flush all pipeline stages.
184 return bytes; 241 return bytes;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 _socket.onWrite = _tlsWriteHandler; 300 _socket.onWrite = _tlsWriteHandler;
244 } 301 }
245 } 302 }
246 303
247 void _tlsHandshakeCompleteHandler() { 304 void _tlsHandshakeCompleteHandler() {
248 _status = CONNECTED; 305 _status = CONNECTED;
249 if (_connectPending && _socketConnectHandler != null) { 306 if (_connectPending && _socketConnectHandler != null) {
250 _connectPending = false; 307 _connectPending = false;
251 _socketConnectHandler(); 308 _socketConnectHandler();
252 } 309 }
310 if (_socketWriteHandler != null) {
311 _socket.onWrite = _tlsWriteHandler;
312 }
253 } 313 }
254 314
315 // True if the underlying socket is closed, the filter has been emptied of
Bill Hesse 2012/11/20 18:42:55 Should we use doc comments for private methods?
Søren Gjesse 2012/11/20 21:13:07 Normally we don't.
316 // all data, and the close event has been fired.
317 get _closed => _socketClosed && !_fireCloseEventPending;
318
255 void _fireCloseEvent() { 319 void _fireCloseEvent() {
256 _fireCloseEventPending = false; 320 _fireCloseEventPending = false;
257 _tlsFilter.destroy(); 321 _tlsFilter.destroy();
258 _tlsFilter = null; 322 _tlsFilter = null;
259 if (scheduledDataEvent != null) { 323 if (scheduledDataEvent != null) {
260 scheduledDataEvent.cancel(); 324 scheduledDataEvent.cancel();
261 } 325 }
262 if (_socketCloseHandler != null) { 326 if (_socketCloseHandler != null) {
263 _socketCloseHandler(); 327 _socketCloseHandler();
264 } 328 }
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 } 413 }
350 414
351 // _TlsSocket cannot extend _Socket and use _Socket's factory constructor. 415 // _TlsSocket cannot extend _Socket and use _Socket's factory constructor.
352 Socket _socket; 416 Socket _socket;
353 String _host; 417 String _host;
354 int _port; 418 int _port;
355 bool _is_server; 419 bool _is_server;
356 String _certificateName; 420 String _certificateName;
357 421
358 var _status = NOT_CONNECTED; 422 var _status = NOT_CONNECTED;
423 _SocketInputStream _inputStream;
424 _SocketOutputStream _outputStream;
359 bool _socketClosed = false; 425 bool _socketClosed = false;
360 bool _filterEmpty = false; 426 bool _filterEmpty = false;
361 bool _connectPending = false; 427 bool _connectPending = false;
362 bool _fireCloseEventPending = false; 428 bool _fireCloseEventPending = false;
363 Function _socketConnectHandler; 429 Function _socketConnectHandler;
364 Function _socketWriteHandler; 430 Function _socketWriteHandler;
365 Function _socketDataHandler; 431 Function _socketDataHandler;
366 Function _socketCloseHandler; 432 Function _socketCloseHandler;
367 Timer scheduledDataEvent; 433 Timer scheduledDataEvent;
368 434
(...skipping 30 matching lines...) Expand all
399 bool is_server, 465 bool is_server,
400 String certificateName); 466 String certificateName);
401 void destroy(); 467 void destroy();
402 void handshake(); 468 void handshake();
403 void init(); 469 void init();
404 int processBuffer(int bufferIndex); 470 int processBuffer(int bufferIndex);
405 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler); 471 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler);
406 472
407 List<_TlsExternalBuffer> get buffers; 473 List<_TlsExternalBuffer> get buffers;
408 } 474 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698