| 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..f23f267cc9f052e618d55e8d175b90160352bcd5 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] already has a subscription, 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] already has a subscription, pass the existing
|
| + * 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
|
| + // 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;
|
| + }
|
| }
|
| }
|
| }
|
|
|