| OLD | NEW |
| 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 Loading... |
| 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 if (halfClose) { | 172 if (halfClose) { |
| 125 _closedWrite = true; | 173 _closedWrite = true; |
| 126 _writeEncryptedData(); | 174 _writeEncryptedData(); |
| 127 if (_filterWriteEmpty) { | 175 if (_filterWriteEmpty) { |
| 128 _socket.close(true); | 176 _socket.close(true); |
| 129 _socketClosedWrite = true; | 177 _socketClosedWrite = true; |
| 130 } | 178 } |
| 131 } else { | 179 } else { |
| 132 _closedWrite = true; | 180 _closedWrite = true; |
| 133 _closedRead = true; | 181 _closedRead = true; |
| 134 _socket.close(false); | 182 _socket.close(false); |
| 135 _socketClosedWrite = true; | 183 _socketClosedWrite = true; |
| 136 _socketClosedRead = true; | 184 _socketClosedRead = true; |
| 137 _tlsFilter.destroy(); | 185 _tlsFilter.destroy(); |
| 138 _tlsFilter = null; | 186 _tlsFilter = null; |
| 139 if (scheduledDataEvent != null) { | 187 if (scheduledDataEvent != null) { |
| 140 scheduledDataEvent.cancel(); | 188 scheduledDataEvent.cancel(); |
| 141 } | 189 } |
| 142 _status = CLOSED; | 190 _status = CLOSED; |
| 143 } | 191 } |
| 144 } | 192 } |
| 145 | 193 |
| 194 void _closeWrite() => close(true); |
| 195 |
| 146 List<int> read([int len]) { | 196 List<int> read([int len]) { |
| 147 if (_closedRead) { | 197 if (_closedRead) { |
| 148 throw new SocketException("Reading from a closed socket"); | 198 throw new SocketException("Reading from a closed socket"); |
| 149 } | 199 } |
| 200 if (_status != CONNECTED) { |
| 201 return new List<int>(0); |
| 202 } |
| 150 var buffer = _tlsFilter.buffers[READ_PLAINTEXT]; | 203 var buffer = _tlsFilter.buffers[READ_PLAINTEXT]; |
| 151 _readEncryptedData(); | 204 _readEncryptedData(); |
| 152 int toRead = buffer.length; | 205 int toRead = buffer.length; |
| 153 if (len != null) { | 206 if (len != null) { |
| 154 if (len is! int || len < 0) { | 207 if (len is! int || len < 0) { |
| 155 throw new ArgumentError( | 208 throw new ArgumentError( |
| 156 "Invalid len parameter in TlsSocket.read (len: $len)"); | 209 "Invalid len parameter in TlsSocket.read (len: $len)"); |
| 157 } | 210 } |
| 158 if (len < toRead) { | 211 if (len < toRead) { |
| 159 toRead = len; | 212 toRead = len; |
| 160 } | 213 } |
| 161 } | 214 } |
| 162 List<int> result = buffer.data.getRange(buffer.start, toRead); | 215 List<int> result = buffer.data.getRange(buffer.start, toRead); |
| 163 buffer.advanceStart(toRead); | 216 buffer.advanceStart(toRead); |
| 164 _setHandlersAfterRead(); | 217 _setHandlersAfterRead(); |
| 165 return result; | 218 return result; |
| 166 } | 219 } |
| 167 | 220 |
| 168 int readList(List<int> data, int offset, int bytes) { | 221 int readList(List<int> data, int offset, int bytes) { |
| 169 if (_closedRead) { | 222 if (_closedRead) { |
| 170 throw new SocketException("Reading from a closed socket"); | 223 throw new SocketException("Reading from a closed socket"); |
| 171 } | 224 } |
| 172 if (offset < 0 || bytes < 0 || offset + bytes > data.length) { | 225 if (offset < 0 || bytes < 0 || offset + bytes > data.length) { |
| 173 throw new ArgumentError( | 226 throw new ArgumentError( |
| 174 "Invalid offset or bytes in TlsSocket.readList"); | 227 "Invalid offset or bytes in TlsSocket.readList"); |
| 175 } | 228 } |
| 229 if (_status != CONNECTED && _status != CLOSED) { |
| 230 return 0; |
| 231 } |
| 176 | 232 |
| 177 int bytesRead = 0; | 233 int bytesRead = 0; |
| 178 var buffer = _tlsFilter.buffers[READ_PLAINTEXT]; | 234 var buffer = _tlsFilter.buffers[READ_PLAINTEXT]; |
| 179 // TODO(whesse): Currently this fails if the if is turned into a while loop. | 235 // TODO(whesse): Currently this fails if the if is turned into a while loop. |
| 180 // Fix it so that it can loop and read more than one buffer's worth of data. | 236 // Fix it so that it can loop and read more than one buffer's worth of data. |
| 181 if (bytes > bytesRead) { | 237 if (bytes > bytesRead) { |
| 182 _readEncryptedData(); | 238 _readEncryptedData(); |
| 183 if (buffer.length > 0) { | 239 if (buffer.length > 0) { |
| 184 int toRead = min(bytes - bytesRead, buffer.length); | 240 int toRead = min(bytes - bytesRead, buffer.length); |
| 185 data.setRange(offset, toRead, buffer.data, buffer.start); | 241 data.setRange(offset, toRead, buffer.data, buffer.start); |
| 186 buffer.advanceStart(toRead); | 242 buffer.advanceStart(toRead); |
| 187 bytesRead += toRead; | 243 bytesRead += toRead; |
| 188 offset += toRead; | 244 offset += toRead; |
| 189 } | 245 } |
| 190 } | 246 } |
| 191 | 247 |
| 192 _setHandlersAfterRead(); | 248 _setHandlersAfterRead(); |
| 193 return bytesRead; | 249 return bytesRead; |
| 194 } | 250 } |
| 195 | 251 |
| 196 // Write the data to the socket, and flush it as much as possible | 252 // Write the data to the socket, and flush it as much as possible |
| 197 // until it would block. If the write would block, _writeEncryptedData sets | 253 // until it would block. If the write would block, _writeEncryptedData sets |
| 198 // up handlers to flush the pipeline when possible. | 254 // up handlers to flush the pipeline when possible. |
| 199 int writeList(List<int> data, int offset, int bytes) { | 255 int writeList(List<int> data, int offset, int bytes) { |
| 200 if (_closedWrite) { | 256 if (_closedWrite) { |
| 201 throw new SocketException("Writing to a closed socket"); | 257 throw new SocketException("Writing to a closed socket"); |
| 202 } | 258 } |
| 259 if (_status != CONNECTED) return 0; |
| 203 var buffer = _tlsFilter.buffers[WRITE_PLAINTEXT]; | 260 var buffer = _tlsFilter.buffers[WRITE_PLAINTEXT]; |
| 204 if (bytes > buffer.free) { | 261 if (bytes > buffer.free) { |
| 205 bytes = buffer.free; | 262 bytes = buffer.free; |
| 206 } | 263 } |
| 207 if (bytes > 0) { | 264 if (bytes > 0) { |
| 208 buffer.data.setRange(buffer.start + buffer.length, bytes, data, offset); | 265 buffer.data.setRange(buffer.start + buffer.length, bytes, data, offset); |
| 209 buffer.length += bytes; | 266 buffer.length += bytes; |
| 210 } | 267 } |
| 211 _writeEncryptedData(); // Tries to flush all pipeline stages. | 268 _writeEncryptedData(); // Tries to flush all pipeline stages. |
| 212 return bytes; | 269 return bytes; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 _socket.onWrite = _tlsWriteHandler; | 335 _socket.onWrite = _tlsWriteHandler; |
| 279 } | 336 } |
| 280 } | 337 } |
| 281 | 338 |
| 282 void _tlsHandshakeCompleteHandler() { | 339 void _tlsHandshakeCompleteHandler() { |
| 283 _status = CONNECTED; | 340 _status = CONNECTED; |
| 284 if (_connectPending && _socketConnectHandler != null) { | 341 if (_connectPending && _socketConnectHandler != null) { |
| 285 _connectPending = false; | 342 _connectPending = false; |
| 286 _socketConnectHandler(); | 343 _socketConnectHandler(); |
| 287 } | 344 } |
| 345 if (_socketWriteHandler != null) { |
| 346 _socket.onWrite = _tlsWriteHandler; |
| 347 } |
| 288 } | 348 } |
| 289 | 349 |
| 350 // True if the underlying socket is closed, the filter has been emptied of |
| 351 // all data, and the close event has been fired. |
| 352 get _closed => _socketClosed && !_fireCloseEventPending; |
| 353 |
| 290 void _fireCloseEvent() { | 354 void _fireCloseEvent() { |
| 291 if (scheduledDataEvent != null) { | 355 if (scheduledDataEvent != null) { |
| 292 scheduledDataEvent.cancel(); | 356 scheduledDataEvent.cancel(); |
| 293 } | 357 } |
| 294 if (_socketCloseHandler != null) { | 358 if (_socketCloseHandler != null) { |
| 295 _socketCloseHandler(); | 359 _socketCloseHandler(); |
| 296 } | 360 } |
| 297 } | 361 } |
| 298 | 362 |
| 299 void _readEncryptedData() { | 363 void _readEncryptedData() { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 _readEncryptedData(); | 465 _readEncryptedData(); |
| 402 } | 466 } |
| 403 if (_filterReadEmpty) { | 467 if (_filterReadEmpty) { |
| 404 // This can't be an else clause: the value of _filterReadEmpty changes. | 468 // This can't be an else clause: the value of _filterReadEmpty changes. |
| 405 // This must be asynchronous, because we are in a read or readList call. | 469 // This must be asynchronous, because we are in a read or readList call. |
| 406 new Timer(0, (_) => _fireCloseEvent()); | 470 new Timer(0, (_) => _fireCloseEvent()); |
| 407 } | 471 } |
| 408 } | 472 } |
| 409 } | 473 } |
| 410 | 474 |
| 475 bool get _socketClosed => _closedRead; |
| 476 |
| 411 // _TlsSocket cannot extend _Socket and use _Socket's factory constructor. | 477 // _TlsSocket cannot extend _Socket and use _Socket's factory constructor. |
| 412 Socket _socket; | 478 Socket _socket; |
| 413 String _host; | 479 String _host; |
| 414 int _port; | 480 int _port; |
| 415 bool _is_server; | 481 bool _is_server; |
| 416 String _certificateName; | 482 String _certificateName; |
| 417 | 483 |
| 418 var _status = NOT_CONNECTED; | 484 var _status = NOT_CONNECTED; |
| 419 bool _socketClosedRead = false; // The network socket is closed for reading. | 485 bool _socketClosedRead = false; // The network socket is closed for reading. |
| 420 bool _socketClosedWrite = false; // The network socket is closed for writing. | 486 bool _socketClosedWrite = false; // The network socket is closed for writing. |
| 421 bool _closedRead = false; // The secure socket has fired an onClosed event. | 487 bool _closedRead = false; // The secure socket has fired an onClosed event. |
| 422 bool _closedWrite = false; // The secure socket has been closed for writing. | 488 bool _closedWrite = false; // The secure socket has been closed for writing. |
| 423 bool _filterReadEmpty = true; // There is no buffered data to read. | 489 bool _filterReadEmpty = true; // There is no buffered data to read. |
| 424 bool _filterWriteEmpty = true; // There is no buffered data to be written. | 490 bool _filterWriteEmpty = true; // There is no buffered data to be written. |
| 491 _SocketInputStream _inputStream; |
| 492 _SocketOutputStream _outputStream; |
| 425 bool _connectPending = false; | 493 bool _connectPending = false; |
| 426 Function _socketConnectHandler; | 494 Function _socketConnectHandler; |
| 427 Function _socketWriteHandler; | 495 Function _socketWriteHandler; |
| 428 Function _socketDataHandler; | 496 Function _socketDataHandler; |
| 429 Function _socketCloseHandler; | 497 Function _socketCloseHandler; |
| 430 Timer scheduledDataEvent; | 498 Timer scheduledDataEvent; |
| 431 | 499 |
| 432 _TlsFilter _tlsFilter; | 500 _TlsFilter _tlsFilter; |
| 433 } | 501 } |
| 434 | 502 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 462 bool is_server, | 530 bool is_server, |
| 463 String certificateName); | 531 String certificateName); |
| 464 void destroy(); | 532 void destroy(); |
| 465 void handshake(); | 533 void handshake(); |
| 466 void init(); | 534 void init(); |
| 467 int processBuffer(int bufferIndex); | 535 int processBuffer(int bufferIndex); |
| 468 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler); | 536 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler); |
| 469 | 537 |
| 470 List<_TlsExternalBuffer> get buffers; | 538 List<_TlsExternalBuffer> get buffers; |
| 471 } | 539 } |
| OLD | NEW |