| Index: tool/input_sdk/lib/io/secure_server_socket.dart
|
| diff --git a/tool/input_sdk/lib/io/secure_server_socket.dart b/tool/input_sdk/lib/io/secure_server_socket.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..2fbc5b1224792b61f8db10365028889fc6073388
|
| --- /dev/null
|
| +++ b/tool/input_sdk/lib/io/secure_server_socket.dart
|
| @@ -0,0 +1,295 @@
|
| +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +part of dart.io;
|
| +
|
| +/**
|
| + * The [SecureServerSocket] is a server socket, providing a stream of high-level
|
| + * [Socket]s.
|
| + *
|
| + * See [SecureSocket] for more info.
|
| + */
|
| +class SecureServerSocket extends Stream<SecureSocket> {
|
| + final RawSecureServerSocket _socket;
|
| +
|
| + SecureServerSocket._(this._socket);
|
| +
|
| + /**
|
| + * Returns a future for a [SecureServerSocket]. When the future
|
| + * completes the server socket is bound to the given [address] and
|
| + * [port] and has started listening on it.
|
| + *
|
| + * The [address] can either be a [String] or an
|
| + * [InternetAddress]. If [address] is a [String], [bind] will
|
| + * perform a [InternetAddress.lookup] and use the first value in the
|
| + * list. To listen on the loopback adapter, which will allow only
|
| + * incoming connections from the local host, use the value
|
| + * [InternetAddress.LOOPBACK_IP_V4] or
|
| + * [InternetAddress.LOOPBACK_IP_V6]. To allow for incoming
|
| + * connection from the network use either one of the values
|
| + * [InternetAddress.ANY_IP_V4] or [InternetAddress.ANY_IP_V6] to
|
| + * bind to all interfaces or the IP address of a specific interface.
|
| + *
|
| + * If [port] has the value [:0:] an ephemeral port will be chosen by
|
| + * the system. The actual port used can be retrieved using the
|
| + * [port] getter.
|
| + *
|
| + * The optional argument [backlog] can be used to specify the listen
|
| + * backlog for the underlying OS listen setup. If [backlog] has the
|
| + * value of [:0:] (the default) a reasonable value will be chosen by
|
| + * the system.
|
| + *
|
| + * Incoming client connections are promoted to secure connections, using
|
| + * the server certificate and key set in [context].
|
| + *
|
| + * [address] must be given as a numeric address, not a host name.
|
| + *
|
| + * To request or require that clients authenticate by providing an SSL (TLS)
|
| + * client certificate, set the optional parameter [requestClientCertificate]
|
| + * or [requireClientCertificate] to true. Requiring a certificate implies
|
| + * requesting a certificate, so setting both is redundant.
|
| + * To check whether a client certificate was received, check
|
| + * SecureSocket.peerCertificate after connecting. If no certificate
|
| + * was received, the result will be null.
|
| + *
|
| + * The optional argument [shared] specifies whether additional
|
| + * SecureServerSocket objects can bind to the same combination of `address`,
|
| + * `port` and `v6Only`. If `shared` is `true` and more `SecureServerSocket`s
|
| + * from this isolate or other isolates are bound to the port, then the
|
| + * incoming connections will be distributed among all the bound
|
| + * `SecureServerSocket`s. Connections can be distributed over multiple
|
| + * isolates this way.
|
| + */
|
| + static Future<SecureServerSocket> bind(
|
| + address,
|
| + int port,
|
| + SecurityContext context,
|
| + {int backlog: 0,
|
| + bool v6Only: false,
|
| + bool requestClientCertificate: false,
|
| + bool requireClientCertificate: false,
|
| + List<String> supportedProtocols,
|
| + bool shared: false}) {
|
| + return RawSecureServerSocket.bind(
|
| + address,
|
| + port,
|
| + context,
|
| + backlog: backlog,
|
| + v6Only: v6Only,
|
| + requestClientCertificate: requestClientCertificate,
|
| + requireClientCertificate: requireClientCertificate,
|
| + supportedProtocols: supportedProtocols,
|
| + shared: shared).then(
|
| + (serverSocket) => new SecureServerSocket._(serverSocket));
|
| + }
|
| +
|
| + StreamSubscription<SecureSocket> listen(void onData(SecureSocket socket),
|
| + {Function onError,
|
| + void onDone(),
|
| + bool cancelOnError}) {
|
| + return _socket.map((rawSocket) => new SecureSocket._(rawSocket))
|
| + .listen(onData,
|
| + onError: onError,
|
| + onDone: onDone,
|
| + cancelOnError: cancelOnError);
|
| + }
|
| +
|
| + /**
|
| + * Returns the port used by this socket.
|
| + */
|
| + int get port => _socket.port;
|
| +
|
| + /**
|
| + * Returns the address used by this socket.
|
| + */
|
| + InternetAddress get address => _socket.address;
|
| +
|
| + /**
|
| + * Closes the socket. The returned future completes when the socket
|
| + * is fully closed and is no longer bound.
|
| + */
|
| + Future<SecureServerSocket> close() => _socket.close().then((_) => this);
|
| +
|
| + void set _owner(owner) { _socket._owner = owner; }
|
| +}
|
| +
|
| +
|
| +/**
|
| + * The RawSecureServerSocket is a server socket, providing a stream of low-level
|
| + * [RawSecureSocket]s.
|
| + *
|
| + * See [RawSecureSocket] for more info.
|
| + */
|
| +class RawSecureServerSocket extends Stream<RawSecureSocket> {
|
| + final RawServerSocket _socket;
|
| + StreamController<RawSecureSocket> _controller;
|
| + StreamSubscription<RawSocket> _subscription;
|
| + final SecurityContext _context;
|
| + final bool requestClientCertificate;
|
| + final bool requireClientCertificate;
|
| + final List<String> supportedProtocols;
|
| + bool _closed = false;
|
| +
|
| + RawSecureServerSocket._(this._socket,
|
| + this._context,
|
| + this.requestClientCertificate,
|
| + this.requireClientCertificate,
|
| + this.supportedProtocols) {
|
| + _controller = new StreamController<RawSecureSocket>(
|
| + sync: true,
|
| + onListen: _onSubscriptionStateChange,
|
| + onPause: _onPauseStateChange,
|
| + onResume: _onPauseStateChange,
|
| + onCancel: _onSubscriptionStateChange);
|
| + }
|
| +
|
| + /**
|
| + * Returns a future for a [RawSecureServerSocket]. When the future
|
| + * completes the server socket is bound to the given [address] and
|
| + * [port] and has started listening on it.
|
| + *
|
| + * The [address] can either be a [String] or an
|
| + * [InternetAddress]. If [address] is a [String], [bind] will
|
| + * perform a [InternetAddress.lookup] and use the first value in the
|
| + * list. To listen on the loopback adapter, which will allow only
|
| + * incoming connections from the local host, use the value
|
| + * [InternetAddress.LOOPBACK_IP_V4] or
|
| + * [InternetAddress.LOOPBACK_IP_V6]. To allow for incoming
|
| + * connection from the network use either one of the values
|
| + * [InternetAddress.ANY_IP_V4] or [InternetAddress.ANY_IP_V6] to
|
| + * bind to all interfaces or the IP address of a specific interface.
|
| + *
|
| + * If [port] has the value [:0:] an ephemeral port will be chosen by
|
| + * the system. The actual port used can be retrieved using the
|
| + * [port] getter.
|
| + *
|
| + * The optional argument [backlog] can be used to specify the listen
|
| + * backlog for the underlying OS listen setup. If [backlog] has the
|
| + * value of [:0:] (the default) a reasonable value will be chosen by
|
| + * the system.
|
| + *
|
| + * Incoming client connections are promoted to secure connections,
|
| + * using the server certificate and key set in [context].
|
| + *
|
| + * [address] must be given as a numeric address, not a host name.
|
| + *
|
| + * To request or require that clients authenticate by providing an SSL (TLS)
|
| + * client certificate, set the optional parameters requestClientCertificate or
|
| + * requireClientCertificate to true. Require implies request, so one doesn't
|
| + * need to specify both. To check whether a client certificate was received,
|
| + * check SecureSocket.peerCertificate after connecting. If no certificate
|
| + * was received, the result will be null.
|
| + *
|
| + * The optional argument [shared] specifies whether additional
|
| + * RawSecureServerSocket objects can bind to the same combination of
|
| + * `address`, `port` and `v6Only`. If `shared` is `true` and more
|
| + * `RawSecureServerSocket`s from this isolate or other isolates are bound to
|
| + * the port, then the incoming connections will be distributed among all the
|
| + * bound `RawSecureServerSocket`s. Connections can be distributed over
|
| + * multiple isolates this way.
|
| + */
|
| + static Future<RawSecureServerSocket> bind(
|
| + address,
|
| + int port,
|
| + SecurityContext context,
|
| + {int backlog: 0,
|
| + bool v6Only: false,
|
| + bool requestClientCertificate: false,
|
| + bool requireClientCertificate: false,
|
| + List<String> supportedProtocols,
|
| + bool shared: false}) {
|
| + return RawServerSocket.bind(
|
| + address, port, backlog: backlog, v6Only: v6Only, shared: shared)
|
| + .then((serverSocket) => new RawSecureServerSocket._(
|
| + serverSocket,
|
| + context,
|
| + requestClientCertificate,
|
| + requireClientCertificate,
|
| + supportedProtocols));
|
| + }
|
| +
|
| + StreamSubscription<RawSecureSocket> listen(void onData(RawSecureSocket s),
|
| + {Function onError,
|
| + void onDone(),
|
| + bool cancelOnError}) {
|
| + return _controller.stream.listen(onData,
|
| + onError: onError,
|
| + onDone: onDone,
|
| + cancelOnError: cancelOnError);
|
| + }
|
| +
|
| + /**
|
| + * Returns the port used by this socket.
|
| + */
|
| + int get port => _socket.port;
|
| +
|
| + /**
|
| + * Returns the address used by this socket.
|
| + */
|
| + InternetAddress get address => _socket.address;
|
| +
|
| + /**
|
| + * Closes the socket. The returned future completes when the socket
|
| + * is fully closed and is no longer bound.
|
| + */
|
| + Future<RawSecureServerSocket> close() {
|
| + _closed = true;
|
| + return _socket.close().then((_) => this);
|
| + }
|
| +
|
| + void _onData(RawSocket connection) {
|
| + var remotePort;
|
| + try {
|
| + remotePort = connection.remotePort;
|
| + } catch (e) {
|
| + // If connection is already closed, remotePort throws an exception.
|
| + // Do nothing - connection is closed.
|
| + return;
|
| + }
|
| + _RawSecureSocket.connect(
|
| + connection.address,
|
| + remotePort,
|
| + context: _context,
|
| + is_server: true,
|
| + socket: connection,
|
| + requestClientCertificate: requestClientCertificate,
|
| + requireClientCertificate: requireClientCertificate,
|
| + supportedProtocols: supportedProtocols)
|
| + .then((RawSecureSocket secureConnection) {
|
| + if (_closed) {
|
| + secureConnection.close();
|
| + } else {
|
| + _controller.add(secureConnection);
|
| + }
|
| + }).catchError((e, s) {
|
| + if (!_closed) {
|
| + _controller.addError(e, s);
|
| + }
|
| + });
|
| + }
|
| +
|
| + void _onPauseStateChange() {
|
| + if (_controller.isPaused) {
|
| + _subscription.pause();
|
| + } else {
|
| + _subscription.resume();
|
| + }
|
| + }
|
| +
|
| + void _onSubscriptionStateChange() {
|
| + if (_controller.hasListener) {
|
| + _subscription = _socket.listen(_onData,
|
| + onError: _controller.addError,
|
| + onDone: _controller.close);
|
| + } else {
|
| + close();
|
| + }
|
| + }
|
| +
|
| + void set _owner(owner) {
|
| + (_socket as dynamic)._owner = owner;
|
| + }
|
| +}
|
| +
|
| +
|
|
|