// 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;

/// A server socket, providing a stream of high-level [Socket]s.
///
/// See [SecureSocket] for more info.
class SecureServerSocket extends Stream<SecureSocket>
    implements ServerSocketBase<SecureSocket> {
  final RawSecureServerSocket _socket;

  SecureServerSocket._(this._socket);

  /// Listens on a given address and port.
  ///
  /// When the returned 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].
  ///
  /// The [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 negotiation 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 same 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,
        );
  }

  /// The port used by this socket.
  int get port => _socket.port;

  /// The address used by this socket.
  InternetAddress get address => _socket.address;

  /// Closes this 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;
  }
}

/// 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,
    );
  }

  /// Listens on a provided address and port.
  ///
  /// When the returned 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,
    );
  }

  /// The port used by this socket.
  int get port => _socket.port;

  /// The address used by this socket.
  InternetAddress get address => _socket.address;

  /// Closes this 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 _RawSocketBase)._owner = owner;
  }
}
