// 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.loopbackIPv4] or
   * [InternetAddress.loopbackIPv6]. To allow for incoming
   * connection from the network use either one of the values
   * [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] 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.
   *
   * [supportedProtocols] is an optional list of protocols (in decreasing
   * order of preference) to use during the ALPN protocol negogiation with
   * clients.  Example values are "http/1.1" or "h2".  The selected protocol
   * can be obtained via [SecureSocket.selectedProtocol].
   *
   * 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;
  late 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.loopbackIPv4] or
   * [InternetAddress.loopbackIPv6]. To allow for incoming
   * connection from the network use either one of the values
   * [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] 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.
   *
   * [supportedProtocols] is an optional list of protocols (in decreasing
   * order of preference) to use during the ALPN protocol negotiation with
   * clients.  Example values are "http/1.1" or "h2".  The selected protocol
   * can be obtained via [RawSecureSocket.selectedProtocol].
   *
   * 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, true, connection,
            context: _context,
            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;
  }
}
