Chromium Code Reviews| Index: sdk/lib/io/secure_socket.dart |
| diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart |
| index a8b0eaafacf7ff0ba81e3d648d944444af1adcc9..95bf4a93826aa734d0b4026afb12fc95be80303e 100644 |
| --- a/sdk/lib/io/secure_socket.dart |
| +++ b/sdk/lib/io/secure_socket.dart |
| @@ -437,6 +437,9 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| bool sendClientCertificate: false, |
| bool onBadCertificate(X509Certificate certificate)}) { |
| var future; |
| + _verifyFields(host, requestedPort, certificateName, is_server, |
| + requestClientCertificate, requireClientCertificate, |
| + sendClientCertificate, onBadCertificate); |
| if (host is String) { |
| if (socket != null) { |
| future = new Future.value( |
| @@ -484,7 +487,6 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| _stream = _controller.stream; |
| // Throw an ArgumentError if any field is invalid. After this, all |
| // errors will be reported through the future or the stream. |
| - _verifyFields(); |
| _secureFilter.init(); |
| _filterPointer = _secureFilter._pointer(); |
| _secureFilter.registerHandshakeCompleteCallback( |
| @@ -499,6 +501,7 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| futureSocket = new Future.value(socket); |
| } |
| futureSocket.then((rawSocket) { |
| + _connectPending = true; |
| _socket = rawSocket; |
| _socket.readEventsEnabled = true; |
| _socket.writeEventsEnabled = false; |
| @@ -506,14 +509,13 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| // If a current subscription is provided use this otherwise |
| // create a new one. |
| _socketSubscription = _socket.listen(_eventDispatcher, |
| - onError: _errorHandler, |
| + onError: _reportError, |
| onDone: _doneHandler); |
| } else { |
| _socketSubscription.onData(_eventDispatcher); |
| - _socketSubscription.onError(_errorHandler); |
| + _socketSubscription.onError(_reportError); |
| _socketSubscription.onDone(_doneHandler); |
| } |
| - _connectPending = true; |
| _secureFilter.connect(address.host, |
| (address as dynamic)._sockaddr_storage, |
| port, |
| @@ -525,10 +527,7 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| sendClientCertificate); |
| _secureHandshake(); |
| }) |
| - .catchError((error) { |
| - _handshakeComplete.completeError(error); |
| - _close(); |
| - }); |
| + .catchError(_reportError); |
| } |
| StreamSubscription listen(void onData(RawSocketEvent data), |
| @@ -542,12 +541,22 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| cancelOnError: cancelOnError); |
| } |
| - void _verifyFields() { |
| - assert(is_server is bool); |
| - assert(_socket == null || _socket is RawSocket); |
| - if (address is! InternetAddress) { |
| - throw new ArgumentError( |
| - "RawSecureSocket constructor: host is not an InternetAddress"); |
| + static void _verifyFields(host, |
|
Søren Gjesse
2013/06/25 06:35:49
Indentation.
Bill Hesse
2013/06/25 12:41:14
Done.
|
| + int requestedPort, |
| + String certificateName, |
| + bool is_server, |
| + bool requestClientCertificate, |
| + bool requireClientCertificate, |
| + bool sendClientCertificate, |
| + Function onBadCertificate) { |
| + if (host is! String && host is! InternetAddress) { |
| + throw new ArgumentError("host is not a String or an InternetAddress"); |
| + } |
| + if (requestedPort is! int) { |
| + throw new ArgumentError("requestedPort is not an int"); |
| + } |
| + if (requestedPort < 0 || requestedPort > 65535) { |
| + throw new ArgumentError("requestedPort is not in the range 0..65535"); |
| } |
| if (certificateName != null && certificateName is! String) { |
| throw new ArgumentError("certificateName is not null or a String"); |
| @@ -693,12 +702,16 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| } |
| void _eventDispatcher(RawSocketEvent event) { |
| - if (event == RawSocketEvent.READ) { |
| - _readHandler(); |
| - } else if (event == RawSocketEvent.WRITE) { |
| - _writeHandler(); |
| - } else if (event == RawSocketEvent.READ_CLOSED) { |
| - _closeHandler(); |
| + try { |
| + if (event == RawSocketEvent.READ) { |
| + _readHandler(); |
| + } else if (event == RawSocketEvent.WRITE) { |
| + _writeHandler(); |
| + } else if (event == RawSocketEvent.READ_CLOSED) { |
| + _closeHandler(); |
| + } |
| + } catch (e) { |
| + _reportError(e); |
| } |
| } |
| @@ -718,20 +731,13 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| } |
| } |
| - void _errorHandler(e) { |
| - _reportError(e, 'Error on underlying RawSocket'); |
| - } |
| - |
| - void _reportError(e, String message) { |
| - // TODO(whesse): Call _reportError from all internal functions that throw. |
| - if (e is SocketException) { |
| - e = new SocketException('$message (${e.message})', e.osError); |
| - } else if (e is OSError) { |
| - e = new SocketException(message, e); |
| - } else { |
| - e = new SocketException('$message (${e.toString()})', null); |
| - } |
| + void _reportError(e) { |
| if (_connectPending) { |
| + // _connectPending is true after the underlying connection has been |
| + // made, but before the handshake has completed. |
| + if (e is! TlsException) { |
| + e = new HandshakeException("$e", null); |
| + } |
| _handshakeComplete.completeError(e); |
| } else { |
| _controller.addError(e); |
| @@ -756,8 +762,7 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| _socketClosedRead = true; |
| if (_filterStatus.readEmpty) { |
| _reportError( |
| - new SocketException('Connection terminated during handshake'), |
| - 'RawSecureSocket error'); |
| + new HandshakeException('Connection terminated during handshake')); |
| } else { |
| _secureHandshake(); |
| } |
| @@ -772,7 +777,7 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| _writeSocket(); |
| _scheduleFilter(); |
| } catch (e) { |
| - _reportError(e, "RawSecureSocket error"); |
| + _reportError(e); |
| } |
| } |
| @@ -838,9 +843,8 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| if (_status == HANDSHAKE) { |
| _secureFilter.handshake(); |
| if (_status == HANDSHAKE) { |
| - _reportError( |
| - new SocketException('Connection terminated during handshake'), |
| - 'RawSecureSocket error'); |
| + throw new HandshakeException( |
| + 'Connection terminated during handshake'); |
| } |
| } |
| _closeHandler(); |
| @@ -855,7 +859,7 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| if (_status == HANDSHAKE) _secureHandshake(); |
| } |
| _tryFilter(); |
| - }); |
| + }).catchError(_reportError); |
| } |
| } |
| @@ -872,12 +876,7 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| } |
| return result; |
| } else if (!_socketClosedRead) { |
| - try { |
| - return _socket.read(bytes); |
| - } catch (e) { |
| - _reportError(e, "RawSecureSocket error reading encrypted socket"); |
| - return null; |
| - } |
| + return _socket.read(bytes); |
| } else { |
| return null; |
| } |
| @@ -1161,3 +1160,56 @@ abstract class _SecureFilter { |
| List<_ExternalBuffer> get buffers; |
| } |
| + |
| +/** A secure networking exception caused by a failure in the |
| + * TLS/SSL protocol. |
| + */ |
| +class TlsException implements IOException { |
| + const TlsException([String message = "", |
| + OSError osError = null]) |
| + : this._("TlsException", message, osError); |
| + |
| + const TlsException._(String this.type, |
| + String this.message, |
| + OSError this.osError); |
| + |
| + String toString() { |
| + StringBuffer sb = new StringBuffer(); |
| + sb.write(type); |
| + if (!message.isEmpty) { |
| + sb.write(": $message"); |
| + if (osError != null) { |
| + sb.write(" ($osError)"); |
| + } |
| + } else if (osError != null) { |
| + sb.write(": $osError"); |
| + } |
| + return sb.toString(); |
| + } |
| + final String type; |
|
Anders Johnsen
2013/06/25 05:55:03
Move to top.
Bill Hesse
2013/06/25 12:41:14
Done.
|
| + final String message; |
| + final OSError osError; |
| +} |
| + |
| + |
| +/** |
| + * An exception that happens in the handshake phase of establishing |
| + * a secure network connection. |
| + */ |
|
Søren Gjesse
2013/06/25 06:35:49
As mentioned before maybe just drop HandshakeExcep
|
| +class HandshakeException extends TlsException { |
| + const HandshakeException([String message = "", |
| + OSError osError = null]) |
| + : super._("HandshakeException", message, osError); |
| +} |
| + |
| + |
| +/** |
| + * An exception that happens in the handshake phase of establishing |
| + * a secure network connection, when looking up or verifying a |
| + * certificate. |
| + */ |
|
Søren Gjesse
2013/06/25 06:35:49
Ca we add some more information to this exception
Bill Hesse
2013/06/25 12:41:14
Done.
|
| +class CertificateException extends TlsException { |
| + const CertificateException([String message = "", |
| + OSError osError = null]) |
| + : super._("CertificateException", message, osError); |
| +} |