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

patch class RawServerSocket {
  /* patch */ static Future<RawServerSocket> bind(address,
                                                  int port,
                                                  {int backlog: 0,
                                                   bool v6Only: false,
                                                   bool shared: false}) {
    return _RawServerSocket.bind(address, port, backlog, v6Only, shared);
  }
}


patch class RawSocket {
  /* patch */ static Future<RawSocket> connect(
      host, int port, {sourceAddress}) {
    return _RawSocket.connect(host, port, sourceAddress);
  }
}


patch class InternetAddress {
  /* patch */ static InternetAddress get LOOPBACK_IP_V4 {
    return _InternetAddress.LOOPBACK_IP_V4;
  }

  /* patch */ static InternetAddress get LOOPBACK_IP_V6 {
    return _InternetAddress.LOOPBACK_IP_V6;
  }

  /* patch */ static InternetAddress get ANY_IP_V4 {
    return _InternetAddress.ANY_IP_V4;
  }

  /* patch */ static InternetAddress get ANY_IP_V6 {
    return _InternetAddress.ANY_IP_V6;
  }

  /* patch */ factory InternetAddress(String address) {
    return new _InternetAddress.parse(address);
  }

  /* patch */ static Future<List<InternetAddress>> lookup(
      String host, {InternetAddressType type: InternetAddressType.ANY}) {
    return _NativeSocket.lookup(host, type: type);
  }
}

patch class NetworkInterface {
  /* patch */ static Future<List<NetworkInterface>> list({
      bool includeLoopback: false,
      bool includeLinkLocal: false,
      InternetAddressType type: InternetAddressType.ANY}) {
    return _NativeSocket.listInterfaces(includeLoopback: includeLoopback,
                                        includeLinkLocal: includeLinkLocal,
                                        type: type);
  }
}

class _InternetAddress implements InternetAddress {
  static const int _ADDRESS_LOOPBACK_IP_V4 = 0;
  static const int _ADDRESS_LOOPBACK_IP_V6 = 1;
  static const int _ADDRESS_ANY_IP_V4 = 2;
  static const int _ADDRESS_ANY_IP_V6 = 3;
  static const int _IPV4_ADDR_LENGTH = 4;
  static const int _IPV6_ADDR_LENGTH = 16;

  static _InternetAddress LOOPBACK_IP_V4 =
      new _InternetAddress.fixed(_ADDRESS_LOOPBACK_IP_V4);
  static _InternetAddress LOOPBACK_IP_V6 =
      new _InternetAddress.fixed(_ADDRESS_LOOPBACK_IP_V6);
  static _InternetAddress ANY_IP_V4 =
      new _InternetAddress.fixed(_ADDRESS_ANY_IP_V4);
  static _InternetAddress ANY_IP_V6 =
      new _InternetAddress.fixed(_ADDRESS_ANY_IP_V6);

  final String address;
  final String _host;
  final Uint8List _in_addr;

  InternetAddressType get type =>
      _in_addr.length == _IPV4_ADDR_LENGTH ? InternetAddressType.IP_V4
                                           : InternetAddressType.IP_V6;

  String get host => _host != null ? _host : address;

  List<int> get rawAddress => new Uint8List.fromList(_in_addr);

  bool get isLoopback {
    switch (type) {
      case InternetAddressType.IP_V4:
        return _in_addr[0] == 127;

      case InternetAddressType.IP_V6:
        for (int i = 0; i < _IPV6_ADDR_LENGTH - 1; i++) {
          if (_in_addr[i] != 0) return false;
        }
        return _in_addr[_IPV6_ADDR_LENGTH - 1] == 1;
    }
  }

  bool get isLinkLocal {
    switch (type) {
      case InternetAddressType.IP_V4:
        // Checking for 169.254.0.0/16.
        return _in_addr[0] == 169 && _in_addr[1] == 254;

      case InternetAddressType.IP_V6:
        // Checking for fe80::/10.
        return _in_addr[0] == 0xFE && (_in_addr[1] & 0xB0) == 0x80;
    }
  }

  bool get isMulticast {
    switch (type) {
      case InternetAddressType.IP_V4:
        // Checking for 224.0.0.0 through 239.255.255.255.
        return _in_addr[0] >= 224 && _in_addr[0] < 240;

      case InternetAddressType.IP_V6:
        // Checking for ff00::/8.
        return _in_addr[0] == 0xFF;
    }
  }

  Future<InternetAddress> reverse() => _NativeSocket.reverseLookup(this);

  _InternetAddress(String this.address,
                   String this._host,
                   List<int> this._in_addr);

  factory _InternetAddress.parse(String address) {
    if (address is !String) {
      throw new ArgumentError("Invalid internet address $address");
    }
    var in_addr = _parse(address);
    if (in_addr == null) {
      throw new ArgumentError("Invalid internet address $address");
    }
    return new _InternetAddress(address, null, in_addr);
  }

  factory _InternetAddress.fixed(int id) {
    switch (id) {
      case _ADDRESS_LOOPBACK_IP_V4:
        var in_addr = new Uint8List(_IPV4_ADDR_LENGTH);
        in_addr[0] = 127;
        in_addr[_IPV4_ADDR_LENGTH - 1] = 1;
        return new _InternetAddress("127.0.0.1", null, in_addr);
      case _ADDRESS_LOOPBACK_IP_V6:
        var in_addr = new Uint8List(_IPV6_ADDR_LENGTH);
        in_addr[_IPV6_ADDR_LENGTH - 1] = 1;
        return new _InternetAddress("::1", null, in_addr);
      case _ADDRESS_ANY_IP_V4:
        var in_addr = new Uint8List(_IPV4_ADDR_LENGTH);
        return new _InternetAddress("0.0.0.0", "0.0.0.0", in_addr);
      case _ADDRESS_ANY_IP_V6:
        var in_addr = new Uint8List(_IPV6_ADDR_LENGTH);
        return new _InternetAddress("::", "::", in_addr);
      default:
        assert(false);
        throw new ArgumentError();
    }
  }

  // Create a clone of this _InternetAddress replacing the host.
  _InternetAddress _cloneWithNewHost(String host) {
    return new _InternetAddress(
        address, host, new Uint8List.fromList(_in_addr));
  }

  bool operator ==(other) {
    if (!(other is _InternetAddress)) return false;
    if (other.type != type) return false;
    bool equals = true;
    for (int i = 0; i < _in_addr.length && equals; i++) {
      equals = other._in_addr[i] == _in_addr[i];
    }
    return equals;
  }

  int get hashCode {
    int result = 1;
    for (int i = 0; i < _in_addr.length; i++) {
      result = (result * 31 + _in_addr[i]) & 0x3FFFFFFF;
    }
    return result;
  }

  String toString() {
    return "InternetAddress('$address', ${type.name})";
  }

  static Uint8List _parse(String address) native "InternetAddress_Parse";
}

class _NetworkInterface implements NetworkInterface {
  final String name;
  final int index;
  final List<InternetAddress> addresses = [];

  _NetworkInterface(this.name, this.index);

  String toString() {
    return "NetworkInterface('$name', $addresses)";
  }
}


// The NativeFieldWrapperClass1 can not be used with a mixin, due to missing
// implicit constructor.
class _NativeSocketNativeWrapper extends NativeFieldWrapperClass1 {}


// The _NativeSocket class encapsulates an OS socket.
class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
  // Bit flags used when communicating between the eventhandler and
  // dart code. The EVENT flags are used to indicate events of
  // interest when sending a message from dart code to the
  // eventhandler. When receiving a message from the eventhandler the
  // EVENT flags indicate the events that actually happened. The
  // COMMAND flags are used to send commands from dart to the
  // eventhandler. COMMAND flags are never received from the
  // eventhandler. Additional flags are used to communicate other
  // information.
  static const int READ_EVENT = 0;
  static const int WRITE_EVENT = 1;
  static const int ERROR_EVENT = 2;
  static const int CLOSED_EVENT = 3;
  static const int DESTROYED_EVENT = 4;
  static const int FIRST_EVENT = READ_EVENT;
  static const int LAST_EVENT = DESTROYED_EVENT;
  static const int EVENT_COUNT = LAST_EVENT - FIRST_EVENT + 1;

  static const int CLOSE_COMMAND = 8;
  static const int SHUTDOWN_READ_COMMAND = 9;
  static const int SHUTDOWN_WRITE_COMMAND = 10;
  // The lower bits of RETURN_TOKEN_COMMAND messages contains the number
  // of tokens returned.
  static const int RETURN_TOKEN_COMMAND = 11;
  static const int SET_EVENT_MASK_COMMAND = 12;
  static const int FIRST_COMMAND = CLOSE_COMMAND;
  static const int LAST_COMMAND = SET_EVENT_MASK_COMMAND;

  // Type flag send to the eventhandler providing additional
  // information on the type of the file descriptor.
  static const int LISTENING_SOCKET = 16;
  static const int PIPE_SOCKET = 17;
  static const int TYPE_NORMAL_SOCKET = 0;
  static const int TYPE_LISTENING_SOCKET = 1 << LISTENING_SOCKET;
  static const int TYPE_PIPE = 1 << PIPE_SOCKET;
  static const int TYPE_TYPE_MASK = TYPE_LISTENING_SOCKET | PIPE_SOCKET;

  // Protocol flags.
  static const int TCP_SOCKET = 18;
  static const int UDP_SOCKET = 19;
  static const int INTERNAL_SOCKET = 20;
  static const int TYPE_TCP_SOCKET = 1 << TCP_SOCKET;
  static const int TYPE_UDP_SOCKET = 1 << UDP_SOCKET;
  static const int TYPE_INTERNAL_SOCKET = 1 << INTERNAL_SOCKET;
  static const int TYPE_PROTOCOL_MASK =
      TYPE_TCP_SOCKET | TYPE_UDP_SOCKET | TYPE_INTERNAL_SOCKET;


  // Native port messages.
  static const HOST_NAME_LOOKUP = 0;
  static const LIST_INTERFACES = 1;
  static const REVERSE_LOOKUP = 2;

  // Protocol flags.
  static const int PROTOCOL_IPV4 = 1 << 0;
  static const int PROTOCOL_IPV6 = 1 << 1;

  static const int NORMAL_TOKEN_BATCH_SIZE = 8;
  static const int LISTENING_TOKEN_BATCH_SIZE = 2;

  static const Duration _RETRY_DURATION = const Duration(milliseconds: 250);
  static const Duration _RETRY_DURATION_LOOPBACK =
      const Duration(milliseconds: 25);

  // Use default Map so we keep order.
  static Map<int, _NativeSocket> _sockets = new Map<int, _NativeSocket>();

  // Socket close state
  bool isClosed = false;
  bool isClosing = false;
  bool isClosedRead = false;
  bool closedReadEventSent = false;
  bool isClosedWrite = false;
  Completer closeCompleter = new Completer.sync();

  // Handlers and receive port for socket events from the event handler.
  final List eventHandlers = new List(EVENT_COUNT + 1);
  RawReceivePort eventPort;
  bool flagsSent = false;

  // The type flags for this socket.
  final int typeFlags;

  // Holds the port of the socket, 0 if not known.
  int localPort = 0;

  // Holds the address used to connect or bind the socket.
  InternetAddress localAddress;

  int available = 0;

  int tokens = 0;

  bool sendReadEvents = false;
  bool readEventIssued = false;

  bool sendWriteEvents = false;
  bool writeEventIssued = false;
  bool writeAvailable = false;

  static final Stopwatch sw = new Stopwatch()..start();
  // Statistics.
  int totalRead = 0;
  int totalWritten = 0;
  int readCount = 0;
  int writeCount = 0;
  double lastRead;
  double lastWrite;

  // The owner object is the object that the Socket is being used by, e.g.
  // a HttpServer, a WebSocket connection, a process pipe, etc.
  Object owner;

  static double get timestamp => sw.elapsedMicroseconds / 1000000.0;

  static Future<List<InternetAddress>> lookup(
      String host, {InternetAddressType type: InternetAddressType.ANY}) {
    return _IOService._dispatch(_SOCKET_LOOKUP, [host, type._value])
        .then((response) {
          if (isErrorResponse(response)) {
            throw createError(response, "Failed host lookup: '$host'");
          } else {
            return response.skip(1).map((result) {
              var type = new InternetAddressType._from(result[0]);
              return new _InternetAddress(result[1], host, result[2]);
            }).toList();
          }
        });
  }

  static Future<InternetAddress> reverseLookup(InternetAddress addr) {
    return _IOService._dispatch(_SOCKET_REVERSE_LOOKUP, [addr._in_addr])
        .then((response) {
          if (isErrorResponse(response)) {
            throw createError(response, "Failed reverse host lookup", addr);
          } else {
            return addr._cloneWithNewHost(response);
          }
        });
  }

  static Future<List<NetworkInterface>> listInterfaces({
      bool includeLoopback: false,
      bool includeLinkLocal: false,
      InternetAddressType type: InternetAddressType.ANY}) {
    return _IOService._dispatch(_SOCKET_LIST_INTERFACES, [type._value])
        .then((response) {
          if (isErrorResponse(response)) {
            throw createError(response, "Failed listing interfaces");
          } else {
            var map = response.skip(1)
                .fold(new Map<String, NetworkInterface>(), (map, result) {
                  var type = new InternetAddressType._from(result[0]);
                  var name = result[3];
                  var index = result[4];
                  var address = new _InternetAddress(result[1], "", result[2]);
                  if (!includeLinkLocal && address.isLinkLocal) return map;
                  if (!includeLoopback && address.isLoopback) return map;
                  map.putIfAbsent(
                      name, () => new _NetworkInterface(name, index));
                  map[name].addresses.add(address);
                  return map;
                });
            return map.values.toList();
          }
        });
  }

  static Future<_NativeSocket> connect(host, int port, sourceAddress) {
    if (sourceAddress != null && sourceAddress is! _InternetAddress) {
      if (sourceAddress is String) {
        sourceAddress = new InternetAddress(sourceAddress);
      }
    }
    return new Future.value(host)
        .then((host) {
          if (host is _InternetAddress) return [host];
          return lookup(host)
              .then((addresses) {
                if (addresses.isEmpty) {
                  throw createError(response, "Failed host lookup: '$host'");
                }
                return addresses;
              });
        })
        .then((addresses) {
          assert(addresses is List);
          var completer = new Completer();
          var it = addresses.iterator;
          var error = null;
          var connecting = new HashMap();
          void connectNext() {
            if (!it.moveNext()) {
              if (connecting.isEmpty) {
                assert(error != null);
                completer.completeError(error);
              }
              return;
            }
            var address = it.current;
            var socket = new _NativeSocket.normal();
            socket.localAddress = address;
            var result;
            if (sourceAddress == null) {
              result = socket.nativeCreateConnect(address._in_addr, port);
            } else {
              assert(sourceAddress is _InternetAddress);
              result = socket.nativeCreateBindConnect(
                  address._in_addr, port, sourceAddress._in_addr);
            }
            if (result is OSError) {
              // Keep first error, if present.
              if (error == null) {
                error = createError(result, "Connection failed", address, port);
              }
              connectNext();
            } else {
              // Query the local port, for error messages.
              socket.port;
              // Set up timer for when we should retry the next address
              // (if any).
              var duration = address.isLoopback ?
                  _RETRY_DURATION_LOOPBACK :
                  _RETRY_DURATION;
              var timer = new Timer(duration, connectNext);
              connecting[socket] = timer;
              // Setup handlers for receiving the first write event which
              // indicate that the socket is fully connected.
              socket.setHandlers(
                  write: () {
                    timer.cancel();
                    socket.setListening(read: false, write: false);
                    completer.complete(socket);
                    connecting.remove(socket);
                    connecting.forEach((s, t) {
                      t.cancel();
                      s.close();
                      s.setHandlers();
                      s.setListening(read: false, write: false);
                    });
                  },
                  error: (e) {
                    timer.cancel();
                    socket.close();
                    // Keep first error, if present.
                    if (error == null) error = e;
                    connecting.remove(socket);
                    if (connecting.isEmpty) connectNext();
                  });
              socket.setListening(read: false, write: true);
            }
          }
          connectNext();
          return completer.future;
        });
  }

  static Future<_NativeSocket> bind(host,
                                    int port,
                                    int backlog,
                                    bool v6Only,
                                    bool shared) {
    return new Future.value(host)
        .then((host) {
          if (host is _InternetAddress) return host;
          return lookup(host)
              .then((list) {
                if (list.length == 0) {
                  throw createError(response, "Failed host lookup: '$host'");
                }
                return list[0];
              });
        })
        .then((address) {
          var socket = new _NativeSocket.listen();
          socket.localAddress = address;

          var result = socket.nativeCreateBindListen(address._in_addr,
                                                     port,
                                                     backlog,
                                                     v6Only,
                                                     shared);
          if (result is OSError) {
            throw new SocketException("Failed to create server socket",
                                      osError: result,
                                      address: address,
                                      port: port);
          }
          if (port != 0) socket.localPort = port;
          socket.connectToEventHandler();
          return socket;
        });
  }

  static Future<_NativeSocket> bindDatagram(
      host, int port, bool reuseAddress) {
    return new Future.value(host)
        .then((host) {
          if (host is _InternetAddress) return host;
          return lookup(host)
              .then((list) {
                if (list.length == 0) {
                  throw createError(response, "Failed host lookup: '$host'");
                }
                return list[0];
              });
        })
        .then((address) {
          var socket = new _NativeSocket.datagram(address);
          var result = socket.nativeCreateBindDatagram(
              address._in_addr, port, reuseAddress);
          if (result is OSError) {
            throw new SocketException("Failed to create datagram socket",
                                      osError: result,
                                      address: address,
                                      port: port);
          }
          if (port != 0) socket.localPort = port;
          return socket;
        });
  }

  _NativeSocket.datagram(this.localAddress)
    : typeFlags = TYPE_NORMAL_SOCKET | TYPE_UDP_SOCKET;

  _NativeSocket.normal() : typeFlags = TYPE_NORMAL_SOCKET | TYPE_TCP_SOCKET;

  _NativeSocket.listen() : typeFlags = TYPE_LISTENING_SOCKET | TYPE_TCP_SOCKET {
    isClosedWrite = true;
  }

  _NativeSocket.pipe() : typeFlags = TYPE_PIPE;

  _NativeSocket.watch(int id)
      : typeFlags = TYPE_NORMAL_SOCKET | TYPE_INTERNAL_SOCKET {
    isClosedWrite = true;
    nativeSetSocketId(id);
  }

  bool get isListening => (typeFlags & TYPE_LISTENING_SOCKET) != 0;
  bool get isPipe => (typeFlags & TYPE_PIPE) != 0;
  bool get isInternal => (typeFlags & TYPE_INTERNAL_SOCKET) != 0;
  bool get isTcp => (typeFlags & TYPE_TCP_SOCKET) != 0;
  bool get isUdp => (typeFlags & TYPE_UDP_SOCKET) != 0;

  List<int> read(int len) {
    if (len != null && len <= 0) {
      throw new ArgumentError("Illegal length $len");
    }
    if (isClosing || isClosed) return null;
    len = min(available, len == null ? available : len);
    if (len == 0) return null;
    var result = nativeRead(len);
    if (result is OSError) {
      reportError(result, "Read failed");
      return null;
    }
    if (result != null) {
      available -= result.length;
      totalRead += result.length;
    }
    readCount++;
    lastRead = timestamp;
    return result;
  }

  Datagram receive() {
    if (isClosing || isClosed) return null;
    var result = nativeRecvFrom();
    if (result is OSError) {
      reportError(result, "Receive failed");
      return null;
    }
    if (result != null) {
      // Read the next available. Available is only for the next datagram, not
      // the sum of all datagrams pending, so we need to call after each
      // receive. If available becomes > 0, the _NativeSocket will continue to
      // emit read events.
      available = nativeAvailable();
      totalRead += result.data.length;
    }
    readCount++;
    lastRead = timestamp;
    return result;
  }

  int write(List<int> buffer, int offset, int bytes) {
    if (buffer is! List) throw new ArgumentError();
    if (offset == null) offset = 0;
    if (bytes == null) {
      if (offset > buffer.length) {
        throw new RangeError.value(offset);
      }
      bytes = buffer.length - offset;
    }
    if (offset < 0) throw new RangeError.value(offset);
    if (bytes < 0) throw new RangeError.value(bytes);
    if ((offset + bytes) > buffer.length) {
      throw new RangeError.value(offset + bytes);
    }
    if (offset is! int || bytes is! int) {
      throw new ArgumentError("Invalid arguments to write on Socket");
    }
    if (isClosing || isClosed) return 0;
    if (bytes == 0) return 0;
    _BufferAndStart bufferAndStart =
        _ensureFastAndSerializableByteData(buffer, offset, offset + bytes);
    var result =
        nativeWrite(bufferAndStart.buffer, bufferAndStart.start, bytes);
    if (result is OSError) {
      scheduleMicrotask(() => reportError(result, "Write failed"));
      result = 0;
    }
    // The result may be negative, if we forced a short write for testing
    // purpose. In such case, don't mark writeAvailable as false, as we don't
    // know if we'll receive an event. It's better to just retry.
    if (result >= 0 && result < bytes) {
      writeAvailable = false;
    }
    // Negate the result, as stated above.
    if (result < 0) result = -result;
    totalWritten += result;
    writeCount++;
    lastWrite = timestamp;
    return result;
  }

  int send(List<int> buffer, int offset, int bytes,
           InternetAddress address, int port) {
    if (isClosing || isClosed) return 0;
    _BufferAndStart bufferAndStart =
        _ensureFastAndSerializableByteData(
            buffer, offset, bytes);
    var result = nativeSendTo(
        bufferAndStart.buffer, bufferAndStart.start, bytes,
        address._in_addr, port);
    if (result is OSError) {
      scheduleMicrotask(() => reportError(result, "Send failed"));
      result = 0;
    }
    totalWritten += result;
    writeCount++;
    lastWrite = timestamp;
    return result;
  }

  _NativeSocket accept() {
    // Don't issue accept if we're closing.
    if (isClosing || isClosed) return null;
    assert(available > 0);
    available--;
    tokens++;
    returnTokens(LISTENING_TOKEN_BATCH_SIZE);
    var socket = new _NativeSocket.normal();
    if (nativeAccept(socket) != true) return null;
    socket.localPort = localPort;
    socket.localAddress = address;
    totalRead += 1;
    lastRead = timestamp;
    return socket;
  }

  int get port {
    if (localPort != 0) return localPort;
    if (isClosing || isClosed) throw const SocketException.closed();
    var result = nativeGetPort();
    if (result is OSError) throw result;
    return localPort = result;
  }

  int get remotePort {
    if (isClosing || isClosed) throw const SocketException.closed();
    var result = nativeGetRemotePeer();
    if (result is OSError) throw result;
    return result[1];
  }

  InternetAddress get address => localAddress;

  InternetAddress get remoteAddress {
    if (isClosing || isClosed) throw const SocketException.closed();
    var result = nativeGetRemotePeer();
    if (result is OSError) throw result;
    var addr = result[0];
    var type = new InternetAddressType._from(addr[0]);
    return new _InternetAddress(addr[1], null, addr[2]);
  }

  void issueReadEvent() {
    if (closedReadEventSent) return;
    if (readEventIssued) return;
    readEventIssued = true;
    void issue() {
      readEventIssued = false;
      if (isClosing) return;
      if (!sendReadEvents) return;
      if (available == 0) {
        if (isClosedRead && !closedReadEventSent) {
          if (isClosedWrite) close();
          var handler = eventHandlers[CLOSED_EVENT];
          if (handler == null) return;
          closedReadEventSent = true;
          handler();
        }
        return;
      }
      var handler = eventHandlers[READ_EVENT];
      if (handler == null) return;
      readEventIssued = true;
      handler();
      scheduleMicrotask(issue);
    }
    scheduleMicrotask(issue);
  }

  void issueWriteEvent({bool delayed: true}) {
    if (writeEventIssued) return;
    if (!writeAvailable) return;
    void issue() {
      writeEventIssued = false;
      if (!writeAvailable) return;
      if (isClosing) return;
      if (!sendWriteEvents) return;
      sendWriteEvents = false;
      var handler = eventHandlers[WRITE_EVENT];
      if (handler == null) return;
      handler();
    }
    if (delayed) {
      writeEventIssued = true;
      scheduleMicrotask(issue);
    } else {
      issue();
    }
  }

  // Multiplexes socket events to the socket handlers.
  void multiplex(int events) {
    for (int i = FIRST_EVENT; i <= LAST_EVENT; i++) {
      if (((events & (1 << i)) != 0)) {
        if ((i == CLOSED_EVENT || i == READ_EVENT) && isClosedRead) continue;
        if (isClosing && i != DESTROYED_EVENT) continue;
        if (i == CLOSED_EVENT &&
            !isListening  &&
            !isClosing &&
            !isClosed) {
          isClosedRead = true;
          issueReadEvent();
          continue;
        }

        if (i == WRITE_EVENT) {
          writeAvailable = true;
          issueWriteEvent(delayed: false);
          continue;
        }

        if (i == READ_EVENT) {
          if (isListening) {
            available++;
          } else {
            available = nativeAvailable();
            issueReadEvent();
            continue;
          }
        }

        var handler = eventHandlers[i];
        if (i == DESTROYED_EVENT) {
          assert(isClosing);
          assert(!isClosed);
          isClosed = true;
          closeCompleter.complete();
          disconnectFromEventHandler();
          if (handler != null) handler();
          continue;
        }

        if (i == ERROR_EVENT) {
          if (!isClosing) {
            reportError(nativeGetError(), "");
          }
        } else if (!isClosed) {
          // If the connection is closed right after it's accepted, there's a
          // chance the close-handler is not set.
          if (handler != null) handler();
        }
      }
    }
    if (!isListening) {
      tokens++;
      returnTokens(NORMAL_TOKEN_BATCH_SIZE);
    }
  }

  void returnTokens(int tokenBatchSize) {
    if (!isClosing && !isClosed) {
      assert(eventPort != null);
      // Return in batches.
      if (tokens == tokenBatchSize) {
        assert(tokens < (1 << FIRST_COMMAND));
        sendToEventHandler((1 << RETURN_TOKEN_COMMAND) | tokens);
        tokens = 0;
      }
    }
  }

  void setHandlers({read, write, error, closed, destroyed}) {
    eventHandlers[READ_EVENT] = read;
    eventHandlers[WRITE_EVENT] = write;
    eventHandlers[ERROR_EVENT] = error;
    eventHandlers[CLOSED_EVENT] = closed;
    eventHandlers[DESTROYED_EVENT] = destroyed;
  }

  void setListening({read: true, write: true}) {
    sendReadEvents = read;
    sendWriteEvents = write;
    if (read) issueReadEvent();
    if (write) issueWriteEvent();
    if (!flagsSent && !isClosing) {
      flagsSent = true;
      int flags = 1 << SET_EVENT_MASK_COMMAND;
      if (!isClosedRead) flags |= 1 << READ_EVENT;
      if (!isClosedWrite) flags |= 1 << WRITE_EVENT;
      sendToEventHandler(flags);
    }
  }

  Future close() {
    if (!isClosing && !isClosed) {
      sendToEventHandler(1 << CLOSE_COMMAND);
      isClosing = true;
    }
    return closeCompleter.future;
  }

  void shutdown(SocketDirection direction) {
    if (!isClosing && !isClosed) {
      switch (direction) {
        case SocketDirection.RECEIVE:
          shutdownRead();
          break;
        case SocketDirection.SEND:
          shutdownWrite();
          break;
        case SocketDirection.BOTH:
          close();
          break;
        default:
          throw new ArgumentError(direction);
      }
    }
  }

  void shutdownWrite() {
    if (!isClosing && !isClosed) {
      if (closedReadEventSent) {
        close();
      } else {
        sendToEventHandler(1 << SHUTDOWN_WRITE_COMMAND);
      }
      isClosedWrite = true;
    }
  }

  void shutdownRead() {
    if (!isClosing && !isClosed) {
      if (isClosedWrite) {
        close();
      } else {
        sendToEventHandler(1 << SHUTDOWN_READ_COMMAND);
      }
      isClosedRead = true;
    }
  }

  void sendToEventHandler(int data) {
    int fullData = (typeFlags & TYPE_TYPE_MASK) | data;
    assert(!isClosing);
    connectToEventHandler();
    _EventHandler._sendData(this, eventPort.sendPort, fullData);
  }

  void connectToEventHandler() {
    assert(!isClosed);
    if (eventPort == null) {
      eventPort = new RawReceivePort(multiplex);
      _sockets[_serviceId] = this;
    }
  }

  void disconnectFromEventHandler() {
    assert(eventPort != null);
    eventPort.close();
    eventPort = null;
    _sockets.remove(_serviceId);
    // Now that we don't track this Socket anymore, we can clear the owner
    // field.
    owner = null;
  }

  // Check whether this is an error response from a native port call.
  static bool isErrorResponse(response) {
    return response is List && response[0] != _SUCCESS_RESPONSE;
  }

  // Create the appropriate error/exception from different returned
  // error objects.
  static createError(error,
                     String message,
                     [InternetAddress address,
                      int port]) {
    if (error is OSError) {
      return new SocketException(
          message, osError: error, address: address, port: port);
    } else if (error is List) {
      assert(isErrorResponse(error));
      switch (error[0]) {
        case _ILLEGAL_ARGUMENT_RESPONSE:
          return new ArgumentError();
        case _OSERROR_RESPONSE:
          return new SocketException(message,
                                     osError: new OSError(error[2], error[1]),
                                     address: address,
                                     port: port);
        default:
          return new Exception("Unknown error");
      }
    } else {
      return new SocketException(message, address: address, port: port);
    }
  }

  void reportError(error, String message) {
    var e = createError(error, message, address, localPort);
    // Invoke the error handler if any.
    if (eventHandlers[ERROR_EVENT] != null) {
      eventHandlers[ERROR_EVENT](e);
    }
    // For all errors we close the socket
    close();
  }

  getOption(SocketOption option) {
    if (option is! SocketOption) throw new ArgumentError(options);
    var result = nativeGetOption(option._value, address.type._value);
    if (result is OSError) throw result;
    return result;
  }

  bool setOption(SocketOption option, value) {
    if (option is! SocketOption) throw new ArgumentError(options);
    var result = nativeSetOption(option._value, address.type._value, value);
    if (result is OSError) throw result;
  }

  InternetAddress multicastAddress(
      InternetAddress addr, NetworkInterface interface) {
    // On Mac OS using the interface index for joining IPv4 multicast groups
    // is not supported. Here the IP address of the interface is needed.
    if (Platform.isMacOS && addr.type == InternetAddressType.IP_V4) {
      if (interface != null) {
        for (int i = 0; i < interface.addresses.length; i++) {
          if (interface.addresses[i].type == InternetAddressType.IP_V4) {
            return interface.addresses[i];
          }
        }
        // No IPv4 address found on the interface.
        throw new SocketException(
            "The network interface does not have an address "
            "of the same family as the multicast address");
      } else {
        // Default to the ANY address if no iterface is specified.
        return InternetAddress.ANY_IP_V4;
      }
    } else {
      return null;
    }
  }

  void joinMulticast(InternetAddress addr, NetworkInterface interface) {
    var interfaceAddr = multicastAddress(addr, interface);
    var interfaceIndex = interface == null ? 0 : interface.index;
    var result = nativeJoinMulticast(
        addr._in_addr,
        interfaceAddr == null ? null : interfaceAddr._in_addr,
        interfaceIndex);
    if (result is OSError) throw result;
  }

  void leaveMulticast(InternetAddress addr, NetworkInterface interface) {
    var interfaceAddr = multicastAddress(addr, interface);
    var interfaceIndex = interface == null ? 0 : interface.index;
    var result = nativeLeaveMulticast(
        addr._in_addr,
        interfaceAddr == null ? null : interfaceAddr._in_addr,
        interfaceIndex);
    if (result is OSError) throw result;
  }

  String get _serviceTypePath => 'io/sockets';
  String get _serviceTypeName => 'Socket';

  String _JSONKind() {
    return isListening ? "Listening" :
           isPipe ? "Pipe" :
           isInternal ? "Internal" : "Normal";
  }

  Map _toJSONPipe(bool ref) {
    var name = 'Anonymous Pipe';
    var r = {
      'id': _servicePath,
      'type': _serviceType(ref),
      'name': name,
      'user_name': name,
      'kind': _JSONKind(),
    };
    if (ref) {
      return r;
    }
    r['readClosed'] = isClosedRead;
    r['writeClosed'] = isClosedWrite;
    r['closing'] = isClosing;
    r['fd'] = nativeGetSocketId();
    if (owner != null) {
      r['owner'] = owner._toJSON(true);
    }
    return r;
  }

  Map _toJSONInternal(bool ref) {
    var name = 'Internal';
    var r = {
      'id': _servicePath,
      'type': _serviceType(ref),
      'name': name,
      'user_name': name,
      'kind': _JSONKind(),
    };
    if (ref) {
      return r;
    }
    r['closing'] = isClosing;
    r['fd'] = nativeGetSocketId();
    if (owner != null) {
      r['owner'] = owner._toJSON(true);
    }
    return r;
  }

  Map _toJSONNetwork(bool ref) {
    var name = '${address.host}:$port';
    if (isTcp && !isListening) name += " <-> ${remoteAddress.host}:$remotePort";
    var r = {
      'id': _servicePath,
      'type': _serviceType(ref),
      'name': name,
      'user_name': name,
      'kind': _JSONKind(),
    };
    if (ref) {
      return r;
    }
    var protocol = isTcp ? "TCP" : isUdp ? "UDP" : null;
    var localAddress;
    var localPort;
    var rAddress;
    var rPort;
    try {
      localAddress = address.address;
    } catch (e) { }
    try {
      localPort = port;
    } catch (e) { }
    try {
      rAddress = this.remoteAddress.address;
    } catch (e) { }
    try {
      rPort = remotePort;
    } catch (e) { }
    r['localAddress'] = localAddress;
    r['localPort'] = localPort;
    r['remoteAddress'] = rAddress;
    r['remotePort'] = rPort;
    r['protocol'] = protocol;
    r['readClosed'] = isClosedRead;
    r['writeClosed'] = isClosedWrite;
    r['closing'] = isClosing;
    r['listening'] = isListening;
    r['fd'] = nativeGetSocketId();
    if (owner != null) {
      r['owner'] = owner._toJSON(true);
    }
    return r;
  }

  Map _toJSON(bool ref) {
    var map;
    if (isPipe) {
      map =  _toJSONPipe(ref);
    } else if (isInternal) {
      map = _toJSONInternal(ref);
    } else {
      map = _toJSONNetwork(ref);
    }
    if (!ref) {
      map['available'] = available;
      map['totalRead'] = totalRead;
      map['totalWritten'] = totalWritten;
      map['readCount'] = totalWritten;
      map['writeCount'] = writeCount;
      map['lastRead'] = lastRead;
      map['lastWrite'] = lastWrite;
    }
    return map;
  }

  void nativeSetSocketId(int id) native "Socket_SetSocketId";
  nativeAvailable() native "Socket_Available";
  nativeRead(int len) native "Socket_Read";
  nativeRecvFrom() native "Socket_RecvFrom";
  nativeWrite(List<int> buffer, int offset, int bytes)
      native "Socket_WriteList";
  nativeSendTo(List<int> buffer, int offset, int bytes,
               List<int> address, int port)
      native "Socket_SendTo";
  nativeCreateConnect(List<int> addr,
                      int port) native "Socket_CreateConnect";
  nativeCreateBindConnect(
      List<int> addr, int port, List<int> sourceAddr)
      native "Socket_CreateBindConnect";
  nativeCreateBindListen(List<int> addr, int port, int backlog, bool v6Only,
                         bool shared)
      native "ServerSocket_CreateBindListen";
  nativeCreateBindDatagram(List<int> addr, int port, bool reuseAddress)
      native "Socket_CreateBindDatagram";
  nativeAccept(_NativeSocket socket) native "ServerSocket_Accept";
  int nativeGetPort() native "Socket_GetPort";
  List nativeGetRemotePeer() native "Socket_GetRemotePeer";
  int nativeGetSocketId() native "Socket_GetSocketId";
  OSError nativeGetError() native "Socket_GetError";
  nativeGetOption(int option, int protocol) native "Socket_GetOption";
  bool nativeSetOption(int option, int protocol, value)
      native "Socket_SetOption";
  bool nativeJoinMulticast(
      List<int> addr, List<int> interfaceAddr, int interfaceIndex)
          native "Socket_JoinMulticast";
  bool nativeLeaveMulticast(
      List<int> addr, List<int> interfaceAddr, int interfaceIndex)
      native "Socket_LeaveMulticast";
  bool _nativeMarkSocketAsSharedHack()
      native "Socket_MarkSocketAsSharedHack";
}


class _RawServerSocket extends Stream<RawSocket>
                       implements RawServerSocket {
  final _NativeSocket _socket;
  StreamController<RawSocket> _controller;
  ReceivePort _referencePort;
  bool _v6Only;

  static Future<_RawServerSocket> bind(address,
                                       int port,
                                       int backlog,
                                       bool v6Only,
                                       bool shared) {
    if (port < 0 || port > 0xFFFF)
      throw new ArgumentError("Invalid port $port");
    if (backlog < 0) throw new ArgumentError("Invalid backlog $backlog");
    return _NativeSocket.bind(address, port, backlog, v6Only, shared)
        .then((socket) => new _RawServerSocket(socket, v6Only));
  }

  _RawServerSocket(this._socket, this._v6Only);

  StreamSubscription<RawSocket> listen(void onData(RawSocket event),
                                       {Function onError,
                                        void onDone(),
                                        bool cancelOnError}) {
    if (_controller != null) {
      throw new StateError("Stream was already listened to");
    }
    var zone = Zone.current;
    _controller = new StreamController(sync: true,
        onListen: _onSubscriptionStateChange,
        onCancel: _onSubscriptionStateChange,
        onPause: _onPauseStateChange,
        onResume: _onPauseStateChange);
    _socket.setHandlers(
      read: zone.bindCallback(() {
        while (_socket.available > 0) {
          var socket = _socket.accept();
          if (socket == null) return;
          _controller.add(new _RawSocket(socket));
          if (_controller.isPaused) return;
        }
      }),
      error: zone.bindUnaryCallback((e) {
        _controller.addError(e);
        _controller.close();
      }),
      destroyed: () {
        _controller.close();
        if (_referencePort != null) {
          _referencePort.close();
          _referencePort = null;
        }
      });
    return _controller.stream.listen(
        onData,
        onError: onError,
        onDone: onDone,
        cancelOnError: cancelOnError);
  }

  int get port => _socket.port;

  InternetAddress get address => _socket.address;

  Future close() {
    return _socket.close().then((_) {
      if (_referencePort != null) {
        _referencePort.close();
        _referencePort = null;
      }
      return this;
    });
  }

  void _pause() {
    _socket.setListening(read: false, write: false);
  }

  void _resume() {
    _socket.setListening(read: true, write: false);
  }

  void _onSubscriptionStateChange() {
    if (_controller.hasListener) {
      _resume();
    } else {
      _socket.close();
    }
  }

  void _onPauseStateChange() {
    if (_controller.isPaused) {
      _pause();
    } else {
      _resume();
    }
  }

  RawServerSocketReference get reference {
    if (_referencePort == null) {
      bool successfull = _socket._nativeMarkSocketAsSharedHack();
      _referencePort = new ReceivePort();
      _referencePort.listen((sendPort) {
        sendPort.send(
          [_socket.address,
           _socket.port,
           _v6Only]);
      });
    }
    return new _RawServerSocketReference(_referencePort.sendPort);
  }

  Map _toJSON(bool ref) => _socket._toJSON(ref);

  void set _owner(owner) { _socket.owner = owner; }
}


class _RawServerSocketReference implements RawServerSocketReference {
  final SendPort _sendPort;

  _RawServerSocketReference(this._sendPort);

  Future<RawServerSocket> create() {
    var port = new ReceivePort();
    _sendPort.send(port.sendPort);
    return port.first.then((List args) {
      port.close();

      InternetAddress address = args[0];
      int tcpPort = args[1];
      bool v6Only = args[2];
      return
          RawServerSocket.bind(address, tcpPort, v6Only: v6Only, shared: true);
    });
  }

  int get hashCode => _sendPort.hashCode;

  bool operator==(Object other)
      => other is _RawServerSocketReference && _sendPort == other._sendPort;
}


class _RawSocket extends Stream<RawSocketEvent>
                 implements RawSocket {
  final _NativeSocket _socket;
  StreamController<RawSocketEvent> _controller;
  bool _readEventsEnabled = true;
  bool _writeEventsEnabled = true;

  // Flag to handle Ctrl-D closing of stdio on Mac OS.
  bool _isMacOSTerminalInput = false;

  static Future<RawSocket> connect(host, int port, sourceAddress) {
    return _NativeSocket.connect(host, port, sourceAddress)
        .then((socket) => new _RawSocket(socket));
  }

  _RawSocket(this._socket) {
    var zone = Zone.current;
    _controller = new StreamController(sync: true,
        onListen: _onSubscriptionStateChange,
        onCancel: _onSubscriptionStateChange,
        onPause: _onPauseStateChange,
        onResume: _onPauseStateChange);
    _socket.setHandlers(
      read: () => _controller.add(RawSocketEvent.READ),
      write: () {
        // The write event handler is automatically disabled by the
        // event handler when it fires.
        _writeEventsEnabled = false;
        _controller.add(RawSocketEvent.WRITE);
      },
      closed: () => _controller.add(RawSocketEvent.READ_CLOSED),
      destroyed: () {
        _controller.add(RawSocketEvent.CLOSED);
        _controller.close();
      },
      error: zone.bindUnaryCallback((e) {
        _controller.addError(e);
        _socket.close();
      })
    );
  }

  factory _RawSocket._writePipe() {
    var native = new _NativeSocket.pipe();
    native.isClosedRead = true;
    native.closedReadEventSent = true;
    return new _RawSocket(native);
  }

  factory _RawSocket._readPipe(int fd) {
    var native = new _NativeSocket.pipe();
    native.isClosedWrite = true;
    if (fd != null) _getStdioHandle(native, fd);
    var result = new _RawSocket(native);
    result._isMacOSTerminalInput =
        Platform.isMacOS &&
        _StdIOUtils._socketType(result._socket) == _STDIO_HANDLE_TYPE_TERMINAL;
    return result;
  }

  StreamSubscription<RawSocketEvent> listen(void onData(RawSocketEvent event),
                                            {Function onError,
                                             void onDone(),
                                             bool cancelOnError}) {
    return _controller.stream.listen(
        onData,
        onError: onError,
        onDone: onDone,
        cancelOnError: cancelOnError);
  }

  int available() => _socket.available;

  List<int> read([int len]) {
    if (_isMacOSTerminalInput) {
      var available = this.available();
      if (available == 0) return null;
      var data = _socket.read(len);
      if (data == null || data.length < available) {
        // Reading less than available from a Mac OS terminal indicate Ctrl-D.
        // This is interpreted as read closed.
        scheduleMicrotask(() => _controller.add(RawSocketEvent.READ_CLOSED));
      }
      return data;
    } else {
      return _socket.read(len);
    }
  }

  int write(List<int> buffer, [int offset, int count]) =>
      _socket.write(buffer, offset, count);

  Future close() => _socket.close().then((_) => this);

  void shutdown(SocketDirection direction) => _socket.shutdown(direction);

  int get port => _socket.port;

  int get remotePort => _socket.remotePort;

  InternetAddress get address => _socket.address;

  InternetAddress get remoteAddress => _socket.remoteAddress;

  bool get readEventsEnabled => _readEventsEnabled;
  void set readEventsEnabled(bool value) {
    if (value != _readEventsEnabled) {
      _readEventsEnabled = value;
      if (!_controller.isPaused) _resume();
    }
  }

  bool get writeEventsEnabled => _writeEventsEnabled;
  void set writeEventsEnabled(bool value) {
    if (value != _writeEventsEnabled) {
      _writeEventsEnabled = value;
      if (!_controller.isPaused) _resume();
    }
  }

  bool setOption(SocketOption option, bool enabled) =>
      _socket.setOption(option, enabled);

  _pause() {
    _socket.setListening(read: false, write: false);
  }

  void _resume() {
    _socket.setListening(read: _readEventsEnabled, write: _writeEventsEnabled);
  }

  void _onPauseStateChange() {
    if (_controller.isPaused) {
      _pause();
    } else {
      _resume();
    }
  }

  void _onSubscriptionStateChange() {
    if (_controller.hasListener) {
      _resume();
    } else {
      _socket.close();
    }
  }

  Map _toJSON(bool ref) => _socket._toJSON(ref);
  void set _owner(owner) { _socket.owner = owner; }
}


patch class ServerSocket {
  /* patch */ static Future<ServerSocket> bind(address,
                                               int port,
                                               {int backlog: 0,
                                                bool v6Only: false,
                                                bool shared: false}) {
    return _ServerSocket.bind(address, port, backlog, v6Only, shared);
  }
}


class _ServerSocketReference implements ServerSocketReference {
  final RawServerSocketReference _rawReference;

  _ServerSocketReference(this._rawReference);

  Future<ServerSocket> create() {
    return _rawReference.create().then((raw) => new _ServerSocket(raw));
  }
}


class _ServerSocket extends Stream<Socket>
                    implements ServerSocket {
  final _socket;

  static Future<_ServerSocket> bind(address,
                                    int port,
                                    int backlog,
                                    bool v6Only,
                                    bool shared) {
    return _RawServerSocket.bind(address, port, backlog, v6Only, shared)
        .then((socket) => new _ServerSocket(socket));
  }

  _ServerSocket(this._socket);

  StreamSubscription<Socket> listen(void onData(Socket event),
                                    {Function onError,
                                     void onDone(),
                                     bool cancelOnError}) {
    return _socket.map((rawSocket) => new _Socket(rawSocket)).listen(
        onData,
        onError: onError,
        onDone: onDone,
        cancelOnError: cancelOnError);
  }

  int get port => _socket.port;

  InternetAddress get address => _socket.address;

  Future close() => _socket.close().then((_) => this);

  ServerSocketReference get reference {
    return new _ServerSocketReference(_socket.reference);
  }

  Map _toJSON(bool ref) => _socket._toJSON(ref);

  void set _owner(owner) { _socket._owner = owner; }
}


patch class Socket {
  /* patch */ static Future<Socket> connect(host, int port, {sourceAddress}) {
    return RawSocket.connect(host, port, sourceAddress: sourceAddress).then(
        (socket) => new _Socket(socket));
  }
}


class _SocketStreamConsumer extends StreamConsumer<List<int>> {
  StreamSubscription subscription;
  final _Socket socket;
  int offset;
  List<int> buffer;
  bool paused = false;
  Completer streamCompleter;

  _SocketStreamConsumer(this.socket);

  Future<Socket> addStream(Stream<List<int>> stream) {
    socket._ensureRawSocketSubscription();
    streamCompleter = new Completer<Socket>();
    if (socket._raw != null) {
      subscription = stream.listen(
          (data) {
            assert(!paused);
            assert(buffer == null);
            buffer = data;
            offset = 0;
            try {
              write();
            } catch (e) {
              socket.destroy();
              stop();
              done(e);
            }
          },
          onError: (error, [stackTrace]) {
            socket.destroy();
            done(error, stackTrace);
          },
          onDone: () {
            done();
          },
          cancelOnError: true);
    }
    return streamCompleter.future;
  }

  Future<Socket> close() {
    socket._consumerDone();
    return new Future.value(socket);
  }

  void write() {
    if (subscription == null) return;
    assert(buffer != null);
    // Write as much as possible.
    offset += socket._write(buffer, offset, buffer.length - offset);
    if (offset < buffer.length) {
      if (!paused) {
        paused = true;
        subscription.pause();
      }
      socket._enableWriteEvent();
    } else {
      buffer = null;
      if (paused) {
        paused = false;
        subscription.resume();
      }
    }
  }

  void done([error, stackTrace]) {
    if (streamCompleter != null) {
      if (error != null) {
        streamCompleter.completeError(error, stackTrace);
      } else {
        streamCompleter.complete(socket);
      }
      streamCompleter = null;
    }
  }

  void stop() {
    if (subscription == null) return;
    subscription.cancel();
    subscription = null;
    paused = false;
    socket._disableWriteEvent();
  }
}


class _Socket extends Stream<List<int>> implements Socket {
  RawSocket _raw;  // Set to null when the raw socket is closed.
  bool _closed = false;  // Set to true when the raw socket is closed.
  StreamController _controller;
  bool _controllerClosed = false;
  _SocketStreamConsumer _consumer;
  IOSink _sink;
  var _subscription;
  var _detachReady;

  _Socket(RawSocket this._raw) {
    _controller = new StreamController<List<int>>(sync: true,
        onListen: _onSubscriptionStateChange,
        onCancel: _onSubscriptionStateChange,
        onPause: _onPauseStateChange,
        onResume: _onPauseStateChange);
    _consumer = new _SocketStreamConsumer(this);
    _sink = new IOSink(_consumer);

    // Disable read events until there is a subscription.
    _raw.readEventsEnabled = false;

    // Disable write events until the consumer needs it for pending writes.
    _raw.writeEventsEnabled = false;
  }

  factory _Socket._writePipe() {
    return new _Socket(new _RawSocket._writePipe());
  }

  factory _Socket._readPipe([int fd]) {
    return new _Socket(new _RawSocket._readPipe(fd));
  }

  _NativeSocket get _nativeSocket => _raw._socket;

  StreamSubscription<List<int>> listen(void onData(List<int> event),
                                       {Function onError,
                                        void onDone(),
                                        bool cancelOnError}) {
    return _controller.stream.listen(
        onData,
        onError: onError,
        onDone: onDone,
        cancelOnError: cancelOnError);
  }

  Encoding get encoding => _sink.encoding;

  void set encoding(Encoding value) {
    _sink.encoding = value;
  }

  void write(Object obj) => _sink.write(obj);

  void writeln([Object obj = ""]) => _sink.writeln(obj);

  void writeCharCode(int charCode) => _sink.writeCharCode(charCode);

  void writeAll(Iterable objects, [sep = ""]) => _sink.writeAll(objects, sep);

  void add(List<int> bytes) => _sink.add(bytes);

  Future<Socket> addStream(Stream<List<int>> stream) {
    return _sink.addStream(stream);
  }

  Future<Socket> flush() => _sink.flush();

  Future<Socket> close() => _sink.close();

  Future<Socket> get done => _sink.done;

  void destroy() {
    // Destroy can always be called to get rid of a socket.
    if (_raw == null) return;
    _consumer.stop();
    _closeRawSocket();
    _controllerClosed = true;
    _controller.close();
  }

  bool setOption(SocketOption option, bool enabled) {
    if (_raw == null) return false;
    return _raw.setOption(option, enabled);
  }

  int get port {
    if (_raw == null) throw const SocketException.closed();;
    return _raw.port;
  }

  InternetAddress get address {
    if (_raw == null) throw const SocketException.closed();;
    return _raw.address;
  }

  int get remotePort {
    if (_raw == null) throw const SocketException.closed();;
    return _raw.remotePort;
  }

  InternetAddress get remoteAddress {
    if (_raw == null) throw const SocketException.closed();;
    return _raw.remoteAddress;
  }

  Future _detachRaw() {
    _detachReady = new Completer();
    _sink.close();
    return _detachReady.future.then((_) {
      assert(_consumer.buffer == null);
      var raw = _raw;
      _raw = null;
      return [raw, _subscription];
    });
  }

  // Ensure a subscription on the raw socket. Both the stream and the
  // consumer needs a subscription as they share the error and done
  // events from the raw socket.
  void _ensureRawSocketSubscription() {
    if (_subscription == null && _raw != null) {
      _subscription = _raw.listen(_onData,
                                  onError: _onError,
                                  onDone: _onDone,
                                  cancelOnError: true);
    }
  }

  _closeRawSocket() {
    var tmp = _raw;
    _raw = null;
    _closed = true;
    tmp.close();
  }

  void _onSubscriptionStateChange() {
    if (_controller.hasListener) {
      _ensureRawSocketSubscription();
      // Enable read events for providing data to subscription.
      if (_raw != null) {
        _raw.readEventsEnabled = true;
      }
    } else {
      _controllerClosed = true;
      if (_raw != null) {
        _raw.shutdown(SocketDirection.RECEIVE);
      }
    }
  }

  void _onPauseStateChange() {
    if (_raw != null) {
      _raw.readEventsEnabled = !_controller.isPaused;
    }
  }

  void _onData(event) {
    switch (event) {
      case RawSocketEvent.READ:
        var buffer = _raw.read();
        if (buffer != null) _controller.add(buffer);
        break;
      case RawSocketEvent.WRITE:
        _consumer.write();
        break;
      case RawSocketEvent.READ_CLOSED:
        _controllerClosed = true;
        _controller.close();
        break;
    }
  }

  void _onDone() {
    if (!_controllerClosed) {
      _controllerClosed = true;
      _controller.close();
    }
    _consumer.done();
  }

  void _onError(error, stackTrace) {
    if (!_controllerClosed) {
      _controllerClosed = true;
      _controller.addError(error, stackTrace);
      _controller.close();
    }
    _consumer.done(error, stackTrace);
  }

  int _write(List<int> data, int offset, int length) =>
      _raw.write(data, offset, length);

  void _enableWriteEvent() {
    _raw.writeEventsEnabled = true;
  }

  void _disableWriteEvent() {
    if (_raw != null) {
      _raw.writeEventsEnabled = false;
    }
  }

  void _consumerDone() {
    if (_detachReady != null) {
      _detachReady.complete(null);
    } else {
      if (_raw != null) {
        _raw.shutdown(SocketDirection.SEND);
        _disableWriteEvent();
      }
    }
  }

  Map _toJSON(bool ref) => _raw._toJSON(ref);
  void set _owner(owner) { _raw._owner = owner; }
}


patch class RawDatagramSocket {
  /* patch */ static Future<RawDatagramSocket> bind(
      host, int port, {bool reuseAddress: true}) {
    return _RawDatagramSocket.bind(host, port, reuseAddress);
  }
}

class _RawDatagramSocket extends Stream implements RawDatagramSocket {
  _NativeSocket _socket;
  StreamController<RawSocketEvent> _controller;
  bool _readEventsEnabled = true;
  bool _writeEventsEnabled = true;

  _RawDatagramSocket(this._socket) {
    var zone = Zone.current;
    _controller = new StreamController(sync: true,
        onListen: _onSubscriptionStateChange,
        onCancel: _onSubscriptionStateChange,
        onPause: _onPauseStateChange,
        onResume: _onPauseStateChange);
    _socket.setHandlers(
      read: () => _controller.add(RawSocketEvent.READ),
      write: () {
        // The write event handler is automatically disabled by the
        // event handler when it fires.
        _writeEventsEnabled = false;
        _controller.add(RawSocketEvent.WRITE);
      },
      closed: () => _controller.add(RawSocketEvent.READ_CLOSED),
      destroyed: () {
        _controller.add(RawSocketEvent.CLOSED);
        _controller.close();
      },
      error: zone.bindUnaryCallback((e) {
        _controller.addError(e);
        _socket.close();
      })
    );
  }

  static Future<RawDatagramSocket> bind(
      host, int port, bool reuseAddress) {
    if (port < 0 || port > 0xffff)
      throw new ArgumentError("Invalid port $port");
    return _NativeSocket.bindDatagram(host, port, reuseAddress)
        .then((socket) => new _RawDatagramSocket(socket));
  }

  StreamSubscription<RawSocketEvent> listen(void onData(RawSocketEvent event),
                                            {Function onError,
                                             void onDone(),
                                             bool cancelOnError}) {
    return _controller.stream.listen(
        onData,
        onError: onError,
        onDone: onDone,
        cancelOnError: cancelOnError);
  }

  Future close() => _socket.close().then((_) => this);

  int send(List<int> buffer, InternetAddress address, int port) =>
      _socket.send(buffer, 0, buffer.length, address, port);

  Datagram receive() {
    return _socket.receive();
  }

  void joinMulticast(InternetAddress group, [NetworkInterface interface]) {
    _socket.joinMulticast(group, interface);
  }

  void leaveMulticast(InternetAddress group, [NetworkInterface interface]) {
    _socket.leaveMulticast(group, interface);
  }

  bool get readEventsEnabled => _readEventsEnabled;
  void set readEventsEnabled(bool value) {
    if (value != _readEventsEnabled) {
      _readEventsEnabled = value;
      if (!_controller.isPaused) _resume();
    }
  }

  bool get writeEventsEnabled => _writeEventsEnabled;
  void set writeEventsEnabled(bool value) {
    if (value != _writeEventsEnabled) {
      _writeEventsEnabled = value;
      if (!_controller.isPaused) _resume();
    }
  }

  bool get multicastLoopback =>
      _socket.getOption(SocketOption._IP_MULTICAST_LOOP);
  void set multicastLoopback(bool value) =>
      _socket.setOption(SocketOption._IP_MULTICAST_LOOP, value);

  int get multicastHops =>
      _socket.getOption(SocketOption._IP_MULTICAST_HOPS);
  void set multicastHops(int value) =>
      _socket.setOption(SocketOption._IP_MULTICAST_HOPS, value);

  NetworkInterface get multicastInterface =>
      throw "Not implemented";
  void set multicastInterface(NetworkInterface value) =>
      throw "Not implemented";

  bool get broadcastEnabled =>
      _socket.getOption(SocketOption._IP_BROADCAST);
  void set broadcastEnabled(bool value) =>
      _socket.setOption(SocketOption._IP_BROADCAST, value);

  int get port => _socket.port;

  InternetAddress get address => _socket.address;

  _pause() {
    _socket.setListening(read: false, write: false);
  }

  void _resume() {
    _socket.setListening(read: _readEventsEnabled, write: _writeEventsEnabled);
  }

  void _onPauseStateChange() {
    if (_controller.isPaused) {
      _pause();
    } else {
      _resume();
    }
  }

  void _onSubscriptionStateChange() {
    if (_controller.hasListener) {
      _resume();
    } else {
      _socket.close();
    }
  }
}

Datagram _makeDatagram(List<int> data,
                       String address,
                       List<int> in_addr,
                       int port) {
  return new Datagram(
      data,
      new _InternetAddress(address, null, in_addr),
      port);
}

String _socketsStats() => _SocketsObservatory.toJSON();
