| 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 * SecureSocket provides a secure (SSL or TLS) client connection to a server. | 6 * SecureSocket 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 SecureSocket implements Socket { | 10 abstract class SecureSocket implements Socket { |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 _outputStream = new _SocketOutputStream(this); | 211 _outputStream = new _SocketOutputStream(this); |
| 212 } | 212 } |
| 213 return _outputStream; | 213 return _outputStream; |
| 214 } | 214 } |
| 215 | 215 |
| 216 int available() { | 216 int available() { |
| 217 throw new UnimplementedError("SecureSocket.available not implemented yet"); | 217 throw new UnimplementedError("SecureSocket.available not implemented yet"); |
| 218 } | 218 } |
| 219 | 219 |
| 220 void close([bool halfClose = false]) { | 220 void close([bool halfClose = false]) { |
| 221 if (_status == CLOSED) return; |
| 221 if (halfClose) { | 222 if (halfClose) { |
| 222 _closedWrite = true; | 223 _closedWrite = true; |
| 223 _writeEncryptedData(); | 224 _writeEncryptedData(); |
| 224 if (_filterWriteEmpty) { | 225 if (_filterWriteEmpty) { |
| 225 _socket.close(true); | 226 _socket.close(true); |
| 226 _socketClosedWrite = true; | 227 _socketClosedWrite = true; |
| 228 if (_closedRead) { |
| 229 close(false); |
| 230 } |
| 227 } | 231 } |
| 228 } else { | 232 } else { |
| 229 _closedWrite = true; | 233 _closedWrite = true; |
| 230 _closedRead = true; | 234 _closedRead = true; |
| 231 _socket.close(false); | 235 _socket.close(false); |
| 232 _socketClosedWrite = true; | 236 _socketClosedWrite = true; |
| 233 _socketClosedRead = true; | 237 _socketClosedRead = true; |
| 234 _secureFilter.destroy(); | 238 _secureFilter.destroy(); |
| 235 _secureFilter = null; | 239 _secureFilter = null; |
| 236 if (scheduledDataEvent != null) { | 240 if (scheduledDataEvent != null) { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 void _secureConnectHandler() { | 325 void _secureConnectHandler() { |
| 322 _connectPending = true; | 326 _connectPending = true; |
| 323 _secureFilter.connect(_host, _port, _is_server, _certificateName); | 327 _secureFilter.connect(_host, _port, _is_server, _certificateName); |
| 324 _status = HANDSHAKE; | 328 _status = HANDSHAKE; |
| 325 _secureHandshake(); | 329 _secureHandshake(); |
| 326 } | 330 } |
| 327 | 331 |
| 328 void _secureWriteHandler() { | 332 void _secureWriteHandler() { |
| 329 _writeEncryptedData(); | 333 _writeEncryptedData(); |
| 330 if (_filterWriteEmpty && _closedWrite && !_socketClosedWrite) { | 334 if (_filterWriteEmpty && _closedWrite && !_socketClosedWrite) { |
| 331 _socket.close(true); | 335 close(true); |
| 332 _sockedClosedWrite = true; | |
| 333 } | 336 } |
| 334 if (_status == HANDSHAKE) { | 337 if (_status == HANDSHAKE) { |
| 335 _secureHandshake(); | 338 _secureHandshake(); |
| 336 } else if (_status == CONNECTED && | 339 } else if (_status == CONNECTED && |
| 337 _socketWriteHandler != null && | 340 _socketWriteHandler != null && |
| 338 _secureFilter.buffers[WRITE_PLAINTEXT].free > 0) { | 341 _secureFilter.buffers[WRITE_PLAINTEXT].free > 0) { |
| 339 // We must be able to set onWrite from the onWrite callback. | 342 // We must be able to set onWrite from the onWrite callback. |
| 340 var handler = _socketWriteHandler; | 343 var handler = _socketWriteHandler; |
| 341 // Reset the one-shot handler. | 344 // Reset the one-shot handler. |
| 342 _socketWriteHandler = null; | 345 _socketWriteHandler = null; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 356 } catch (e) { _reportError(e, "SecureSocket error"); } | 359 } catch (e) { _reportError(e, "SecureSocket error"); } |
| 357 if (!_filterReadEmpty) { | 360 if (!_filterReadEmpty) { |
| 358 // Call the onData event. | 361 // Call the onData event. |
| 359 if (scheduledDataEvent != null) { | 362 if (scheduledDataEvent != null) { |
| 360 scheduledDataEvent.cancel(); | 363 scheduledDataEvent.cancel(); |
| 361 scheduledDataEvent = null; | 364 scheduledDataEvent = null; |
| 362 } | 365 } |
| 363 if (_socketDataHandler != null) { | 366 if (_socketDataHandler != null) { |
| 364 _socketDataHandler(); | 367 _socketDataHandler(); |
| 365 } | 368 } |
| 369 } else if (_socketClosedRead) { |
| 370 _secureCloseHandler(); |
| 366 } | 371 } |
| 367 } | 372 } |
| 368 } | 373 } |
| 369 | 374 |
| 370 void _secureErrorHandler(e) { | 375 void _secureErrorHandler(e) { |
| 371 _reportError(e, 'Error on underlying Socket'); | 376 _reportError(e, 'Error on underlying Socket'); |
| 372 } | 377 } |
| 373 | 378 |
| 374 void _reportError(error, String message) { | 379 void _reportError(error, String message) { |
| 375 // TODO(whesse): Call _reportError from all internal functions that throw. | 380 // TODO(whesse): Call _reportError from all internal functions that throw. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 390 if (_inputStream != null) { | 395 if (_inputStream != null) { |
| 391 reported = reported || _inputStream._onSocketError(e); | 396 reported = reported || _inputStream._onSocketError(e); |
| 392 } | 397 } |
| 393 if (_outputStream != null) { | 398 if (_outputStream != null) { |
| 394 reported = reported || _outputStream._onSocketError(e); | 399 reported = reported || _outputStream._onSocketError(e); |
| 395 } | 400 } |
| 396 if (!reported) throw e; | 401 if (!reported) throw e; |
| 397 } | 402 } |
| 398 | 403 |
| 399 void _secureCloseHandler() { | 404 void _secureCloseHandler() { |
| 405 if (_closedRead) return; |
| 400 _socketClosedRead = true; | 406 _socketClosedRead = true; |
| 401 if (_filterReadEmpty) { | 407 if (_filterReadEmpty) { |
| 402 _closedRead = true; | 408 _closedRead = true; |
| 403 _fireCloseEvent(); | 409 if (scheduledDataEvent != null) { |
| 410 scheduledDataEvent.cancel(); |
| 411 } |
| 412 if (_socketCloseHandler != null) { |
| 413 _socketCloseHandler(); |
| 414 } |
| 404 if (_socketClosedWrite) { | 415 if (_socketClosedWrite) { |
| 405 _secureFilter.destroy(); | 416 close(false); |
| 406 _secureFilter = null; | |
| 407 _status = CLOSED; | |
| 408 } | 417 } |
| 409 } | 418 } |
| 410 } | 419 } |
| 411 | 420 |
| 412 void _secureHandshake() { | 421 void _secureHandshake() { |
| 413 _readEncryptedData(); | 422 _readEncryptedData(); |
| 414 _secureFilter.handshake(); | 423 _secureFilter.handshake(); |
| 415 _writeEncryptedData(); | 424 _writeEncryptedData(); |
| 416 if (_secureFilter.buffers[WRITE_ENCRYPTED].length > 0) { | 425 if (_secureFilter.buffers[WRITE_ENCRYPTED].length > 0) { |
| 417 _socket.onWrite = _secureWriteHandler; | 426 _socket.onWrite = _secureWriteHandler; |
| 418 } | 427 } |
| 419 } | 428 } |
| 420 | 429 |
| 421 void _secureHandshakeCompleteHandler() { | 430 void _secureHandshakeCompleteHandler() { |
| 422 _status = CONNECTED; | 431 _status = CONNECTED; |
| 423 if (_connectPending && _socketConnectHandler != null) { | 432 if (_connectPending && _socketConnectHandler != null) { |
| 424 _connectPending = false; | 433 _connectPending = false; |
| 425 _socketConnectHandler(); | 434 _socketConnectHandler(); |
| 426 } | 435 } |
| 427 if (_socketWriteHandler != null) { | 436 if (_socketWriteHandler != null) { |
| 428 _socket.onWrite = _secureWriteHandler; | 437 _socket.onWrite = _secureWriteHandler; |
| 429 } | 438 } |
| 430 } | 439 } |
| 431 | 440 |
| 432 // True if the underlying socket is closed, the filter has been emptied of | 441 // True if the underlying socket is closed, the filter has been emptied of |
| 433 // all data, and the close event has been fired. | 442 // all data, and the close event has been fired. |
| 434 get _closed => _socketClosed && !_fireCloseEventPending; | 443 get _closed => _socketClosed; |
| 435 | |
| 436 void _fireCloseEvent() { | |
| 437 if (scheduledDataEvent != null) { | |
| 438 scheduledDataEvent.cancel(); | |
| 439 } | |
| 440 if (_socketCloseHandler != null) { | |
| 441 _socketCloseHandler(); | |
| 442 } | |
| 443 } | |
| 444 | 444 |
| 445 void _readEncryptedData() { | 445 void _readEncryptedData() { |
| 446 // Read from the socket, and push it through the filter as far as | 446 // Read from the socket, and push it through the filter as far as |
| 447 // possible. | 447 // possible. |
| 448 var encrypted = _secureFilter.buffers[READ_ENCRYPTED]; | 448 var encrypted = _secureFilter.buffers[READ_ENCRYPTED]; |
| 449 var plaintext = _secureFilter.buffers[READ_PLAINTEXT]; | 449 var plaintext = _secureFilter.buffers[READ_PLAINTEXT]; |
| 450 bool progress = true; | 450 bool progress = true; |
| 451 while (progress) { | 451 while (progress) { |
| 452 progress = false; | 452 progress = false; |
| 453 // Do not try to read plaintext from the filter while handshaking. | 453 // Do not try to read plaintext from the filter while handshaking. |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 // _closedRead is false, since we are in a read or readList call. | 542 // _closedRead is false, since we are in a read or readList call. |
| 543 if (!_filterReadEmpty) { | 543 if (!_filterReadEmpty) { |
| 544 // _filterReadEmpty may be out of date since read and readList empty | 544 // _filterReadEmpty may be out of date since read and readList empty |
| 545 // the plaintext buffer after calling _readEncryptedData. | 545 // the plaintext buffer after calling _readEncryptedData. |
| 546 // TODO(whesse): Fix this as part of fixing read and readList. | 546 // TODO(whesse): Fix this as part of fixing read and readList. |
| 547 _readEncryptedData(); | 547 _readEncryptedData(); |
| 548 } | 548 } |
| 549 if (_filterReadEmpty) { | 549 if (_filterReadEmpty) { |
| 550 // This can't be an else clause: the value of _filterReadEmpty changes. | 550 // This can't be an else clause: the value of _filterReadEmpty changes. |
| 551 // This must be asynchronous, because we are in a read or readList call. | 551 // This must be asynchronous, because we are in a read or readList call. |
| 552 new Timer(0, (_) => _fireCloseEvent()); | 552 new Timer(0, (_) => _secureCloseHandler()); |
| 553 } | 553 } |
| 554 } | 554 } |
| 555 } | 555 } |
| 556 | 556 |
| 557 bool get _socketClosed => _closedRead; | 557 bool get _socketClosed => _closedRead; |
| 558 | 558 |
| 559 // _SecureSocket cannot extend _Socket and use _Socket's factory constructor. | 559 // _SecureSocket cannot extend _Socket and use _Socket's factory constructor. |
| 560 Socket _socket; | 560 Socket _socket; |
| 561 String _host; | 561 String _host; |
| 562 int _port; | 562 int _port; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 614 String certificateName); | 614 String certificateName); |
| 615 void destroy(); | 615 void destroy(); |
| 616 void handshake(); | 616 void handshake(); |
| 617 void init(); | 617 void init(); |
| 618 int processBuffer(int bufferIndex); | 618 int processBuffer(int bufferIndex); |
| 619 void registerBadCertificateCallback(Function callback); | 619 void registerBadCertificateCallback(Function callback); |
| 620 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler); | 620 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler); |
| 621 | 621 |
| 622 List<_ExternalBuffer> get buffers; | 622 List<_ExternalBuffer> get buffers; |
| 623 } | 623 } |
| OLD | NEW |