// Copyright (c) 2013, 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;

/**
 * [InternetAddressType] is the type an [InternetAddress]. Currently,
 * IP version 4 (IPv4) and IP version 6 (IPv6) are supported.
 */
class InternetAddressType {
  static const InternetAddressType IP_V4 = const InternetAddressType._(0);
  static const InternetAddressType IP_V6 = const InternetAddressType._(1);
  static const InternetAddressType ANY = const InternetAddressType._(-1);

  final int _value;

  const InternetAddressType._(this._value);

  factory InternetAddressType._from(int value) {
    if (value == 0) return IP_V4;
    if (value == 1) return IP_V6;
    throw new ArgumentError("Invalid type: $value");
  }

  /**
   * Get the name of the type, e.g. "IP_V4" or "IP_V6".
   */
  String get name {
    switch (_value) {
      case -1:
        return "ANY";
      case 0:
        return "IP_V4";
      case 1:
        return "IP_V6";
      default:
        throw new ArgumentError("Invalid InternetAddress");
    }
  }

  String toString() => "InternetAddressType: $name";
}

/**
 * An internet address.
 *
 * This object holds an internet address. If this internet address
 * is the result of a DNS lookup, the address also holds the hostname
 * used to make the lookup.
 * An Internet address combined with a port number represents an
 * endpoint to which a socket can connect or a listening socket can
 * bind.
 */
abstract class InternetAddress {
  /**
   * IP version 4 loopback address. Use this address when listening on
   * or connecting to the loopback adapter using IP version 4 (IPv4).
   */
  external static InternetAddress get LOOPBACK_IP_V4;

  /**
   * IP version 6 loopback address. Use this address when listening on
   * or connecting to the loopback adapter using IP version 6 (IPv6).
   */
  external static InternetAddress get LOOPBACK_IP_V6;

  /**
   * IP version 4 any address. Use this address when listening on
   * all adapters IP addresses using IP version 4 (IPv4).
   */
  external static InternetAddress get ANY_IP_V4;

  /**
   * IP version 6 any address. Use this address when listening on
   * all adapters IP addresses using IP version 6 (IPv6).
   */
  external static InternetAddress get ANY_IP_V6;

  /**
   * The [type] of the [InternetAddress] specified what IP protocol.
   */
  InternetAddressType get type;

  /**
   * The numeric address of the host. For IPv4 addresses this is using
   * the dotted-decimal notation. For IPv6 it is using the
   * hexadecimal representation.
   */
  String get address;

  /**
   * The host used to lookup the address. If there is no host
   * associated with the address this returns the numeric address.
   */
  String get host;

  /**
   * Get the raw address of this [InternetAddress]. The result is either a
   * 4 or 16 byte long list. The returned list is a copy, making it possible
   * to change the list without modifying the [InternetAddress].
   */
  List<int> get rawAddress;

  /**
   * Returns true if the [InternetAddress] is a loopback address.
   */
  bool get isLoopback;

  /**
   * Returns true if the [InternetAddress]s scope is a link-local.
   */
  bool get isLinkLocal;

  /**
   * Returns true if the [InternetAddress]s scope is multicast.
   */
  bool get isMulticast;

  /**
   * Creates a new [InternetAddress] from a numeric address.
   *
   * If the address in [address] is not a numeric IPv4
   * (dotted-decimal notation) or IPv6 (hexadecimal representation).
   * address [ArgumentError] is thrown.
   */
  external factory InternetAddress(String address);

  /**
   * Perform a reverse dns lookup on the [address], creating a new
   * [InternetAddress] where the host field set to the result.
   */
  Future<InternetAddress> reverse();

  /**
   * Lookup a host, returning a Future of a list of
   * [InternetAddress]s. If [type] is [InternetAddressType.ANY], it
   * will lookup both IP version 4 (IPv4) and IP version 6 (IPv6)
   * addresses. If [type] is either [InternetAddressType.IP_V4] or
   * [InternetAddressType.IP_V6] it will only lookup addresses of the
   * specified type. The order of the list can, and most likely will,
   * change over time.
   */
  external static Future<List<InternetAddress>> lookup(String host,
      {InternetAddressType type: InternetAddressType.ANY});

  /**
   * Clones the given [address] with the new [host].
   *
   * The [address] must be an [InternetAddress] that was created with one
   * of the static methods of this class.
   */
  external static InternetAddress _cloneWithNewHost(
      InternetAddress address, String host);
}

/**
 * A [NetworkInterface] represents an active network interface on the current
 * system. It contains a list of [InternetAddress]es that are bound to the
 * interface.
 */
abstract class NetworkInterface {
  /**
   * Get the name of the [NetworkInterface].
   */
  String get name;

  /**
   * Get the index of the [NetworkInterface].
   */
  int get index;

  /**
   * Get a list of [InternetAddress]es currently bound to this
   * [NetworkInterface].
   */
  List<InternetAddress> get addresses;

  /**
   * Whether [list] is supported.
   *
   * [list] is currently unsupported on Android.
   */
  external static bool get listSupported;

  /**
   * Query the system for [NetworkInterface]s.
   *
   * If [includeLoopback] is `true`, the returned list will include the
   * loopback device. Default is `false`.
   *
   * If [includeLinkLocal] is `true`, the list of addresses of the returned
   * [NetworkInterface]s, may include link local addresses. Default is `false`.
   *
   * If [type] is either [InternetAddressType.IP_V4] or
   * [InternetAddressType.IP_V6] it will only lookup addresses of the
   * specified type. Default is [InternetAddressType.ANY].
   */
  external static Future<List<NetworkInterface>> list(
      {bool includeLoopback: false,
      bool includeLinkLocal: false,
      InternetAddressType type: InternetAddressType.ANY});
}

/**
 * A [RawServerSocket] represents a listening socket, and provides a
 * stream of low-level [RawSocket] objects, one for each connection
 * made to the listening socket.
 *
 * See [RawSocket] for more info.
 */
abstract class RawServerSocket implements Stream<RawSocket> {
  /**
   * Returns a future for a [:RawServerSocket:]. 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 an IP version 6 (IPv6) address is used, both IP version 6
   * (IPv6) and version 4 (IPv4) connections will be accepted. To
   * restrict this to version 6 (IPv6) only, use [v6Only] to set
   * version 6 only.
   *
   * 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.
   *
   * The optional argument [shared] specifies whether additional RawServerSocket
   * objects can bind to the same combination of `address`, `port` and `v6Only`.
   * If `shared` is `true` and more `RawServerSocket`s from this isolate or
   * other isolates are bound to the port, then the incoming connections will be
   * distributed among all the bound `RawServerSocket`s. Connections can be
   * distributed over multiple isolates this way.
   */
  external static Future<RawServerSocket> bind(address, int port,
      {int backlog: 0, bool v6Only: false, bool shared: false});

  /**
   * Returns the port used by this socket.
   */
  int get port;

  /**
   * Returns the address used by this socket.
   */
  InternetAddress get address;

  /**
   * Closes the socket. The returned future completes when the socket
   * is fully closed and is no longer bound.
   */
  Future<RawServerSocket> close();
}

/**
 * A [ServerSocket] represents a listening socket, and provides a
 * stream of [Socket] objects, one for each connection made to the
 * listening socket.
 *
 * See [Socket] for more info.
 */
abstract class ServerSocket implements Stream<Socket> {
  /**
   * Returns a future for a [:ServerSocket:]. 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 an IP version 6 (IPv6) address is used, both IP version 6
   * (IPv6) and version 4 (IPv4) connections will be accepted. To
   * restrict this to version 6 (IPv6) only, use [v6Only] to set
   * version 6 only.
   *
   * 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.
   *
   * The optional argument [shared] specifies whether additional ServerSocket
   * objects can bind to the same combination of `address`, `port` and `v6Only`.
   * If `shared` is `true` and more `ServerSocket`s from this isolate or other
   * isolates are bound to the port, then the incoming connections will be
   * distributed among all the bound `ServerSocket`s. Connections can be
   * distributed over multiple isolates this way.
   */
  external static Future<ServerSocket> bind(address, int port,
      {int backlog: 0, bool v6Only: false, bool shared: false});

  /**
   * Returns the port used by this socket.
   */
  int get port;

  /**
   * Returns the address used by this socket.
   */
  InternetAddress get address;

  /**
   * Closes the socket. The returned future completes when the socket
   * is fully closed and is no longer bound.
   */
  Future<ServerSocket> close();
}

/**
 * The [SocketDirection] is used as a parameter to [Socket.close] and
 * [RawSocket.close] to close a socket in the specified direction(s).
 */
class SocketDirection {
  static const SocketDirection RECEIVE = const SocketDirection._(0);
  static const SocketDirection SEND = const SocketDirection._(1);
  static const SocketDirection BOTH = const SocketDirection._(2);
  final _value;

  const SocketDirection._(this._value);
}

/**
 * The [SocketOption] is used as a parameter to [Socket.setOption] and
 * [RawSocket.setOption] to set customize the behaviour of the underlying
 * socket.
 */
class SocketOption {
  /**
   * Enable or disable no-delay on the socket. If TCP_NODELAY is enabled, the
   * socket will not buffer data internally, but instead write each data chunk
   * as an individual TCP packet.
   *
   * TCP_NODELAY is disabled by default.
   */
  static const SocketOption TCP_NODELAY = const SocketOption._(0);

  static const SocketOption _IP_MULTICAST_LOOP = const SocketOption._(1);
  static const SocketOption _IP_MULTICAST_HOPS = const SocketOption._(2);
  static const SocketOption _IP_MULTICAST_IF = const SocketOption._(3);
  static const SocketOption _IP_BROADCAST = const SocketOption._(4);
  final _value;

  const SocketOption._(this._value);
}

/**
 * Events for the [RawSocket].
 */
class RawSocketEvent {
  static const RawSocketEvent READ = const RawSocketEvent._(0);
  static const RawSocketEvent WRITE = const RawSocketEvent._(1);
  static const RawSocketEvent READ_CLOSED = const RawSocketEvent._(2);
  static const RawSocketEvent CLOSED = const RawSocketEvent._(3);
  final int _value;

  const RawSocketEvent._(this._value);
  String toString() {
    return const [
      'RawSocketEvent:READ',
      'RawSocketEvent:WRITE',
      'RawSocketEvent:READ_CLOSED',
      'RawSocketEvent:CLOSED'
    ][_value];
  }
}

/**
 * The [RawSocket] is a low-level interface to a socket, exposing the raw
 * events signaled by the system. It's a [Stream] of [RawSocketEvent]s.
 */
abstract class RawSocket implements Stream<RawSocketEvent> {
  /**
   * Set or get, if the [RawSocket] should listen for [RawSocketEvent.READ]
   * events. Default is [:true:].
   */
  bool readEventsEnabled;

  /**
   * Set or get, if the [RawSocket] should listen for [RawSocketEvent.WRITE]
   * events. Default is [:true:].
   * This is a one-shot listener, and writeEventsEnabled must be set
   * to true again to receive another write event.
   */
  bool writeEventsEnabled;

  /**
   * Creates a new socket connection to the host and port and returns a [Future]
   * that will complete with either a [RawSocket] once connected or an error
   * if the host-lookup or connection failed.
   *
   * [host] can either be a [String] or an [InternetAddress]. If [host] is a
   * [String], [connect] will perform a [InternetAddress.lookup] and try
   * all returned [InternetAddress]es, until connected. Unless a
   * connection was established, the error from the first failing connection is
   * returned.
   *
   * The argument [sourceAddress] can be used to specify the local
   * address to bind when making the connection. `sourceAddress` can either
   * be a `String` or an `InternetAddress`. If a `String` is passed it must
   * hold a numeric IP address.
   *
   * The argument [timeout] is used to specify the maximum allowed time to wait
   * for a connection to be established. If [timeout] is longer than the system
   * level timeout duration, a timeout may occur sooner than specified in
   * [timeout]. On timeout, a [SocketException] is thrown and all ongoing
   * connection attempts to [host] are cancelled.
   */
  external static Future<RawSocket> connect(host, int port,
      {sourceAddress, Duration timeout});

  /**
   * Returns the number of received and non-read bytes in the socket that
   * can be read.
   */
  int available();

  /**
   * Read up to [len] bytes from the socket. This function is
   * non-blocking and will only return data if data is available. The
   * number of bytes read can be less then [len] if fewer bytes are
   * available for immediate reading. If no data is available [:null:]
   * is returned.
   */
  List<int> read([int len]);

  /**
   * Writes up to [count] bytes of the buffer from [offset] buffer offset to
   * the socket. The number of successfully written bytes is returned. This
   * function is non-blocking and will only write data if buffer space is
   * available in the socket.
   *
   * The default value for [offset] is 0, and the default value for [count] is
   * [:buffer.length - offset:].
   */
  int write(List<int> buffer, [int offset, int count]);

  /**
   * Returns the port used by this socket.
   */
  int get port;

  /**
   * Returns the remote port connected to by this socket.
   */
  int get remotePort;

  /**
   * Returns the [InternetAddress] used to connect this socket.
   */
  InternetAddress get address;

  /**
   * Returns the remote [InternetAddress] connected to by this socket.
   */
  InternetAddress get remoteAddress;

  /**
   * Closes the socket. Returns a Future that completes with [this] when the
   * underlying connection is completely destroyed.
   *
   * Calling [close] will never throw an exception
   * and calling it several times is supported. Calling [close] can result in
   * a [RawSocketEvent.READ_CLOSED] event.
   */
  Future<RawSocket> close();

  /**
   * Shutdown the socket in the [direction]. Calling [shutdown] will never
   * throw an exception and calling it several times is supported. Calling
   * shutdown with either [SocketDirection.BOTH] or [SocketDirection.RECEIVE]
   * can result in a [RawSocketEvent.READ_CLOSED] event.
   */
  void shutdown(SocketDirection direction);

  /**
   * Use [setOption] to customize the [RawSocket]. See [SocketOption] for
   * available options.
   *
   * Returns [:true:] if the option was set successfully, false otherwise.
   */
  bool setOption(SocketOption option, bool enabled);
}

/**
 * A high-level class for communicating over a TCP socket.
 *
 * The [Socket] exposes both a [Stream] and a [IOSink] interface, making it
 * ideal for using together with other [Stream]s.
 */
abstract class Socket implements Stream<List<int>>, IOSink {
  /**
   * Creates a new socket connection to the host and port and returns a [Future]
   * that will complete with either a [Socket] once connected or an error
   * if the host-lookup or connection failed.
   *
   * [host] can either be a [String] or an [InternetAddress]. If [host] is a
   * [String], [connect] will perform a [InternetAddress.lookup] and try
   * all returned [InternetAddress]es, until connected. Unless a
   * connection was established, the error from the first failing connection is
   * returned.
   *
   * The argument [sourceAddress] can be used to specify the local
   * address to bind when making the connection. `sourceAddress` can either
   * be a `String` or an `InternetAddress`. If a `String` is passed it must
   * hold a numeric IP address.
   *
   * The argument [timeout] is used to specify the maximum allowed time to wait
   * for a connection to be established. If [timeout] is longer than the system
   * level timeout duration, a timeout may occur sooner than specified in
   * [timeout]. On timeout, a [SocketException] is thrown and all ongoing
   * connection attempts to [host] are cancelled.
   */
  external static Future<Socket> connect(host, int port,
      {sourceAddress, Duration timeout});

  /**
   * Destroy the socket in both directions. Calling [destroy] will make the
   * send a close event on the stream and will no longer react on data being
   * piped to it.
   *
   * Call [close](inherited from [IOSink]) to only close the [Socket]
   * for sending data.
   */
  void destroy();

  /**
   * Use [setOption] to customize the [RawSocket]. See [SocketOption] for
   * available options.
   *
   * Returns [:true:] if the option was set successfully, false otherwise.
   */
  bool setOption(SocketOption option, bool enabled);

  /**
   * Returns the port used by this socket.
   */
  int get port;

  /**
   * Returns the remote port connected to by this socket.
   */
  int get remotePort;

  /**
   * Returns the [InternetAddress] used to connect this socket.
   */
  InternetAddress get address;

  /**
   * Returns the remote [InternetAddress] connected to by this socket.
   */
  InternetAddress get remoteAddress;

  Future close();

  Future get done;
}

/**
 * Datagram package. Data send to and received from datagram sockets
 * contains the internet address and port of the destination or source
 * togeter with the data.
 */
class Datagram {
  List<int> data;
  InternetAddress address;
  int port;

  Datagram(this.data, this.address, this.port);
}

/**
 * The [RawDatagramSocket] is a low-level interface to an UDP socket,
 * exposing the raw events signaled by the system. It's a [Stream] of
 * [RawSocketEvent]s.
 *
 * Note that the event [RawSocketEvent.READ_CLOSED] will never be
 * received as an UDP socket cannot be closed by a remote peer.
 */
abstract class RawDatagramSocket extends Stream<RawSocketEvent> {
  /**
   * Set or get, if the [RawDatagramSocket] should listen for
   * [RawSocketEvent.READ] events. Default is [:true:].
   */
  bool readEventsEnabled;

  /**
   * Set or get, if the [RawDatagramSocket] should listen for
   * [RawSocketEvent.WRITE] events. Default is [:true:].  This is a
   * one-shot listener, and writeEventsEnabled must be set to true
   * again to receive another write event.
   */
  bool writeEventsEnabled;

  /**
   * Set or get, whether multicast traffic is looped back to the host.
   *
   * By default multicast loopback is enabled.
   */
  bool multicastLoopback;

  /**
   * Set or get, the maximum network hops for multicast packages
   * originating from this socket.
   *
   * For IPv4 this is referred to as TTL (time to live).
   *
   * By default this value is 1 causing multicast traffic to stay on
   * the local network.
   */
  int multicastHops;

  /**
   * Set or get, the network interface used for outgoing multicast packages.
   *
   * A value of `null`indicate that the system chooses the network
   * interface to use.
   *
   * By default this value is `null`
   */
  NetworkInterface multicastInterface;

  /**
   * Set or get, whether IPv4 broadcast is enabled.
   *
   * IPv4 broadcast needs to be enabled by the sender for sending IPv4
   * broadcast packages. By default IPv4 broadcast is disabled.
   *
   * For IPv6 there is no general broadcast mechanism. Use multicast
   * instead.
   */
  bool broadcastEnabled;

  /**
   * Creates a new raw datagram socket binding it to an address and
   * port.
   */
  external static Future<RawDatagramSocket> bind(host, int port,
      {bool reuseAddress: true});

  /**
   * Returns the port used by this socket.
   */
  int get port;

  /**
   * Returns the address used by this socket.
   */
  InternetAddress get address;

  /**
   * Close the datagram socket.
   */
  void close();

  /**
   * Send a datagram.
   *
   * Returns the number of bytes written. This will always be either
   * the size of [buffer] or `0`.
   */
  int send(List<int> buffer, InternetAddress address, int port);

  /**
   * Receive a datagram. If there are no datagrams available `null` is
   * returned.
   *
   * The maximum length of the datagram that can be received is 65503 bytes.
   */
  Datagram receive();

  /**
   * Join a multicast group.
   *
   * If an error occur when trying to join the multicast group an
   * exception is thrown.
   */
  void joinMulticast(InternetAddress group, [NetworkInterface interface]);

  /**
   * Leave a multicast group.
   *
   * If an error occur when trying to join the multicase group an
   * exception is thrown.
   */
  void leaveMulticast(InternetAddress group, [NetworkInterface interface]);
}

class SocketException implements IOException {
  final String message;
  final OSError osError;
  final InternetAddress address;
  final int port;

  const SocketException(this.message, {this.osError, this.address, this.port});
  const SocketException.closed()
      : message = 'Socket has been closed',
        osError = null,
        address = null,
        port = null;

  String toString() {
    StringBuffer sb = new StringBuffer();
    sb.write("SocketException");
    if (!message.isEmpty) {
      sb.write(": $message");
      if (osError != null) {
        sb.write(" ($osError)");
      }
    } else if (osError != null) {
      sb.write(": $osError");
    }
    if (address != null) {
      sb.write(", address = ${address.host}");
    }
    if (port != null) {
      sb.write(", port = $port");
    }
    return sb.toString();
  }
}
