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); |
+} |