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


