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 41fdf59a81d0a1c8e77f8432e5a925d4c7978167..1b9f4fb3cb522fe703bbfa9fbd36ed7783e7a710 100644 |
| --- a/sdk/lib/io/secure_socket.dart |
| +++ b/sdk/lib/io/secure_socket.dart |
| @@ -144,6 +144,78 @@ abstract class RawSecureSocket implements RawSocket { |
| } |
| /** |
| + * Takes an already connected [socket] and starts client side TLS |
| + * handshake to make the communication secure. When the returned |
| + * future completes the [RawSecureSocket] has completed the TLS |
| + * handshake. Using this function requires that the other end of the |
| + * connection is prepared for TLS handshake. |
| + * |
| + * If the [socket] is already subscribed to pass the existing |
| + * subscription in the [subscription] parameter. The secure socket |
| + * will take over the subscription and process any subsequent |
| + * events. |
| + * |
| + * See [connect] for more information on the arguments. |
| + * |
| + */ |
| + static Future<RawSecureSocket> secure( |
| + RawSocket socket, |
| + {StreamSubscription subscription, |
| + bool sendClientCertificate: false, |
| + String certificateName, |
| + bool onBadCertificate(X509Certificate certificate)}) { |
| + return _RawSecureSocket.connect( |
| + socket.host, |
| + socket.port, |
| + certificateName, |
| + is_server: false, |
| + socket: socket, |
| + subscription: subscription, |
| + sendClientCertificate: sendClientCertificate, |
| + onBadCertificate: onBadCertificate); |
| + } |
| + |
| + /** |
| + * Takes an already connected [socket] and starts server side TLS |
| + * handshake to make the communication secure. When the returned |
| + * future completes the [RawSecureSocket] has completed the TLS |
| + * handshake. Using this function requires that the other end of the |
| + * connection is going to start the TLS handshake. |
| + * |
| + * If the [socket] is already subscribed to pass the existing |
|
Mads Ager (google)
2013/04/19 05:28:19
is already subscribed to -> already has a subscrip
|
| + * subscription in the [subscription] parameter. The secure socket |
| + * will take over the subscription and process any subsequent |
| + * events. |
| + * |
| + * If some of the data of the TLS handshake has already been read |
| + * from the socket this data can be passed in the [carryOverData] |
| + * parameter. This data will be processed before any other data |
| + * available on the socket. |
| + * |
| + * See [RawSecureServerSocket.bind] for more information on the |
| + * arguments. |
| + * |
| + */ |
| + static Future<RawSecureSocket> secureServer( |
| + RawSocket socket, |
| + String certificateName, |
| + {StreamSubscription subscription, |
| + List<int> carryOverData, |
| + bool requestClientCertificate: false, |
| + bool requireClientCertificate: false}) { |
| + return _RawSecureSocket.connect( |
| + socket.remoteHost, |
| + socket.remotePort, |
| + certificateName, |
| + is_server: true, |
| + socket: socket, |
| + subscription: subscription, |
| + carryOverData: carryOverData, |
| + requestClientCertificate: requestClientCertificate, |
| + requireClientCertificate: requireClientCertificate); |
| + } |
| + |
| + /** |
| * Get the peer certificate for a connected RawSecureSocket. If this |
| * RawSecureSocket is the server end of a secure socket connection, |
| * [peerCertificate] will return the client certificate, or null, if no |
| @@ -192,6 +264,8 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| StreamController<RawSocketEvent> _controller; |
| Stream<RawSocketEvent> _stream; |
| StreamSubscription<RawSocketEvent> _socketSubscription; |
| + List<int> _carryOverData; |
| + int _carryOverDataIndex = 0; |
| final String host; |
| final bool is_server; |
| final String certificateName; |
| @@ -218,6 +292,8 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| String certificateName, |
| {bool is_server, |
| RawSocket socket, |
| + StreamSubscription subscription, |
| + List<int> carryOverData, |
| bool requestClientCertificate: false, |
| bool requireClientCertificate: false, |
| bool sendClientCertificate: false, |
| @@ -227,6 +303,8 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| certificateName, |
| is_server, |
| socket, |
| + subscription, |
| + carryOverData, |
| requestClientCertificate, |
| requireClientCertificate, |
| sendClientCertificate, |
| @@ -240,6 +318,8 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| String this.certificateName, |
| bool this.is_server, |
| RawSocket socket, |
| + StreamSubscription this._socketSubscription, |
| + List<int> this._carryOverData, |
| bool this.requestClientCertificate, |
| bool this.requireClientCertificate, |
| bool this.sendClientCertificate, |
| @@ -252,6 +332,7 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| // errors will be reported through the future or the stream. |
| _verifyFields(); |
| _secureFilter.init(); |
| + if (_carryOverData != null) _readFromCarryOver(); |
| _secureFilter.registerHandshakeCompleteCallback( |
| _secureHandshakeCompleteHandler); |
| if (onBadCertificate != null) { |
| @@ -266,9 +347,17 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| futureSocket.then((rawSocket) { |
| rawSocket.writeEventsEnabled = false; |
| _socket = rawSocket; |
| - _socketSubscription = _socket.listen(_eventDispatcher, |
| - onError: _errorHandler, |
| - onDone: _doneHandler); |
| + if (_socketSubscription == null) { |
| + // If a current subscription is provided use this otherwise |
|
Mads Ager (google)
2013/04/19 05:28:19
indentation
|
| + // create a new one. |
| + _socketSubscription = _socket.listen(_eventDispatcher, |
| + onError: _errorHandler, |
| + onDone: _doneHandler); |
| + } else { |
| + _socketSubscription.onData(_eventDispatcher); |
| + _socketSubscription.onError(_errorHandler); |
| + _socketSubscription.onDone(_doneHandler); |
| + } |
| _connectPending = true; |
| _secureFilter.connect(host, |
| port, |
| @@ -520,6 +609,21 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| } |
| } |
| + void _readFromCarryOver() { |
| + assert(_carryOverData != null); |
| + var encrypted = _secureFilter.buffers[READ_ENCRYPTED]; |
| + var len = 1;//_carryOverData.length - _carryOverDataIndex; |
| + encrypted.data.setRange(encrypted.start + encrypted.length, |
| + len, |
| + _carryOverData, |
| + _carryOverDataIndex); |
| + encrypted.length = len; |
| + _carryOverDataIndex += len; |
| + if (_carryOverData.length == _carryOverDataIndex) { |
| + _carryOverData = null; |
| + } |
| + } |
| + |
| void _readHandler() { |
| if (_status == CLOSED) { |
| return; |
| @@ -657,14 +761,19 @@ class _RawSecureSocket extends Stream<RawSocketEvent> |
| } |
| } |
| if (!_socketClosedRead && encrypted.free > 0) { |
| - List<int> data = _socket.read(encrypted.free); |
| - if (data != null) { |
| - int bytes = data.length; |
| - encrypted.data.setRange(encrypted.start + encrypted.length, |
| - bytes, |
| - data); |
| - encrypted.length += bytes; |
| + if (_carryOverData != null) { |
| + _readFromCarryOver(); |
| progress = true; |
| + } else { |
| + List<int> data = _socket.read(encrypted.free); |
| + if (data != null) { |
| + int bytes = data.length; |
| + encrypted.data.setRange(encrypted.start + encrypted.length, |
| + bytes, |
| + data); |
| + encrypted.length += bytes; |
| + progress = true; |
| + } |
| } |
| } |
| } |