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

const int _OUTGOING_BUFFER_SIZE = 8 * 1024;

class _HttpIncoming extends Stream<List<int>> {
  final int _transferLength;
  final Completer _dataCompleter = new Completer();
  Stream<List<int>> _stream;

  bool fullBodyRead = false;

  // Common properties.
  final _HttpHeaders headers;
  bool upgraded = false;

  // ClientResponse properties.
  int statusCode;
  String reasonPhrase;

  // Request properties.
  String method;
  Uri uri;

  bool hasSubscriber = false;

  // The transfer length if the length of the message body as it
  // appears in the message (RFC 2616 section 4.4). This can be -1 if
  // the length of the massage body is not known due to transfer
  // codings.
  int get transferLength => _transferLength;

  _HttpIncoming(this.headers, this._transferLength, this._stream);

  StreamSubscription<List<int>> listen(void onData(List<int> event),
                                       {Function onError,
                                        void onDone(),
                                        bool cancelOnError}) {
    hasSubscriber = true;
    return _stream
        .handleError((error) {
          throw new HttpException(error.message, uri: uri);
        })
        .listen(onData,
                onError: onError,
                onDone: onDone,
                cancelOnError: cancelOnError);
  }

  // Is completed once all data have been received.
  Future get dataDone => _dataCompleter.future;

  void close(bool closing) {
    fullBodyRead = true;
    hasSubscriber = true;
    _dataCompleter.complete(closing);
  }
}

abstract class _HttpInboundMessage extends Stream<List<int>> {
  final _HttpIncoming _incoming;
  List<Cookie> _cookies;

  _HttpInboundMessage(this._incoming);

  List<Cookie> get cookies {
    if (_cookies != null) return _cookies;
    return _cookies = headers._parseCookies();
  }

  _HttpHeaders get headers => _incoming.headers;
  String get protocolVersion => headers.protocolVersion;
  int get contentLength => headers.contentLength;
  bool get persistentConnection => headers.persistentConnection;
}


class _HttpRequest extends _HttpInboundMessage implements HttpRequest {
  final HttpResponse response;

  final _HttpServer _httpServer;

  final _HttpConnection _httpConnection;

  _HttpSession _session;

  Uri _requestedUri;

  _HttpRequest(this.response, _HttpIncoming _incoming, this._httpServer,
               this._httpConnection) : super(_incoming) {
    if (headers.protocolVersion == "1.1") {
      response.headers
          ..chunkedTransferEncoding = true
          ..persistentConnection = headers.persistentConnection;
    }

    if (_httpServer._sessionManagerInstance != null) {
      // Map to session if exists.
      var sessionIds = cookies
          .where((cookie) => cookie.name.toUpperCase() == _DART_SESSION_ID)
          .map((cookie) => cookie.value);
      for (var sessionId in sessionIds) {
        _session = _httpServer._sessionManager.getSession(sessionId);
        if (_session != null) {
          _session._markSeen();
          break;
        }
      }
    }
  }

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

  Uri get uri => _incoming.uri;

  Uri get requestedUri {
    if (_requestedUri == null) {
      var proto = headers['x-forwarded-proto'];
      var scheme = proto != null ? proto.first :
          _httpConnection._socket is SecureSocket ? "https" : "http";
      var hostList = headers['x-forwarded-host'];
      String host;
      if (hostList != null) {
        host = hostList.first;
      } else {
        hostList = headers['host'];
        if (hostList != null) {
          host = hostList.first;
        } else {
          host = "${_httpServer.address.host}:${_httpServer.port}";
        }
      }
      _requestedUri = Uri.parse("$scheme://$host$uri");
    }
    return _requestedUri;
  }

  String get method => _incoming.method;

  HttpSession get session {
    if (_session != null) {
      if (_session._destroyed) {
        // It's destroyed, clear it.
        _session = null;
        // Create new session object by calling recursive.
        return session;
      }
      // It's already mapped, use it.
      return _session;
    }
    // Create session, store it in connection, and return.
    return _session = _httpServer._sessionManager.createSession();
  }

  HttpConnectionInfo get connectionInfo => _httpConnection.connectionInfo;

  X509Certificate get certificate {
    var socket = _httpConnection._socket;
    if (socket is SecureSocket) return socket.peerCertificate;
    return null;
  }
}


class _HttpClientResponse
    extends _HttpInboundMessage implements HttpClientResponse {
  List<RedirectInfo> get redirects => _httpRequest._responseRedirects;

  // The HttpClient this response belongs to.
  final _HttpClient _httpClient;

  // The HttpClientRequest of this response.
  final _HttpClientRequest _httpRequest;

  _HttpClientResponse(_HttpIncoming _incoming, this._httpRequest,
                      this._httpClient) : super(_incoming) {
    // Set uri for potential exceptions.
    _incoming.uri = _httpRequest.uri;
  }

  int get statusCode => _incoming.statusCode;
  String get reasonPhrase => _incoming.reasonPhrase;

  X509Certificate get certificate {
    var socket = _httpRequest._httpClientConnection._socket;
    if (socket is SecureSocket) return socket.peerCertificate;
    throw new UnsupportedError("Socket is not a SecureSocket");
  }

  List<Cookie> get cookies {
    if (_cookies != null) return _cookies;
    _cookies = new List<Cookie>();
    List<String> values = headers[HttpHeaders.SET_COOKIE];
    if (values != null) {
      values.forEach((value) {
        _cookies.add(new Cookie.fromSetCookieValue(value));
      });
    }
    return _cookies;
  }

  bool get isRedirect {
    if (_httpRequest.method == "GET" || _httpRequest.method == "HEAD") {
      return statusCode == HttpStatus.MOVED_PERMANENTLY ||
             statusCode == HttpStatus.FOUND ||
             statusCode == HttpStatus.SEE_OTHER ||
             statusCode == HttpStatus.TEMPORARY_REDIRECT;
    } else if (_httpRequest.method == "POST") {
      return statusCode == HttpStatus.SEE_OTHER;
    }
    return false;
  }

  Future<HttpClientResponse> redirect([String method,
                                       Uri url,
                                       bool followLoops]) {
    if (method == null) {
      // Set method as defined by RFC 2616 section 10.3.4.
      if (statusCode == HttpStatus.SEE_OTHER && _httpRequest.method == "POST") {
        method = "GET";
      } else {
        method = _httpRequest.method;
      }
    }
    if (url == null) {
      String location = headers.value(HttpHeaders.LOCATION);
      if (location == null) {
        throw new StateError("Response has no Location header for redirect");
      }
      url = Uri.parse(location);
    }
    if (followLoops != true) {
      for (var redirect in redirects) {
        if (redirect.location == url) {
          return new Future.error(
              new RedirectException("Redirect loop detected", redirects));
        }
      }
    }
    return _httpClient._openUrlFromRequest(method, url, _httpRequest)
        .then((request) {
          request._responseRedirects
              ..addAll(this.redirects)
              ..add(new _RedirectInfo(statusCode, method, url));
          return request.close();
        });
  }

  StreamSubscription<List<int>> listen(void onData(List<int> event),
                                       {Function onError,
                                        void onDone(),
                                        bool cancelOnError}) {
    if (_incoming.upgraded) {
      // If upgraded, the connection is already 'removed' form the client.
      // Since listening to upgraded data is 'bogus', simply close and
      // return empty stream subscription.
      _httpRequest._httpClientConnection.destroy();
      return new Stream.fromIterable([]).listen(null, onDone: onDone);
    }
    var stream = _incoming;
    if (_httpClient.autoUncompress &&
        headers.value(HttpHeaders.CONTENT_ENCODING) == "gzip") {
      stream = stream.transform(GZIP.decoder);
    }
    return stream.listen(onData,
                         onError: onError,
                         onDone: onDone,
                         cancelOnError: cancelOnError);
  }

  Future<Socket> detachSocket() {
    _httpClient._connectionClosed(_httpRequest._httpClientConnection);
    return _httpRequest._httpClientConnection.detachSocket();
  }

  HttpConnectionInfo get connectionInfo => _httpRequest.connectionInfo;

  bool get _shouldAuthenticateProxy {
    // Only try to authenticate if there is a challenge in the response.
    List<String> challenge = headers[HttpHeaders.PROXY_AUTHENTICATE];
    return statusCode == HttpStatus.PROXY_AUTHENTICATION_REQUIRED &&
        challenge != null && challenge.length == 1;
  }

  bool get _shouldAuthenticate {
    // Only try to authenticate if there is a challenge in the response.
    List<String> challenge = headers[HttpHeaders.WWW_AUTHENTICATE];
    return statusCode == HttpStatus.UNAUTHORIZED &&
        challenge != null && challenge.length == 1;
  }

  Future<HttpClientResponse> _authenticate(bool proxyAuth) {
    Future<HttpClientResponse> retry() {
      // Drain body and retry.
      return drain().then((_) {
          return _httpClient._openUrlFromRequest(_httpRequest.method,
                                                 _httpRequest.uri,
                                                 _httpRequest)
              .then((request) => request.close());
          });
    }

    List<String> authChallenge() {
      return proxyAuth ? headers[HttpHeaders.PROXY_AUTHENTICATE]
                       : headers[HttpHeaders.WWW_AUTHENTICATE];
    }

    _Credentials findCredentials(_AuthenticationScheme scheme) {
      return proxyAuth ? _httpClient._findProxyCredentials(_httpRequest._proxy,
                                                           scheme)
                       : _httpClient._findCredentials(_httpRequest.uri, scheme);
    }

    void removeCredentials(_Credentials cr) {
      if (proxyAuth) {
        _httpClient._removeProxyCredentials(cr);
      } else {
        _httpClient._removeCredentials(cr);
      }
    }

    Future requestAuthentication(_AuthenticationScheme scheme, String realm) {
      if (proxyAuth) {
        if (_httpClient._authenticateProxy == null) {
          return new Future.value(false);
        }
        var proxy = _httpRequest._proxy;
        return _httpClient._authenticateProxy(proxy.host,
                                              proxy.port,
                                              scheme.toString(),
                                              realm);
      } else {
        if (_httpClient._authenticate == null) {
          return new Future.value(false);
        }
        return _httpClient._authenticate(_httpRequest.uri,
                                         scheme.toString(),
                                         realm);
      }
    }

    List<String> challenge = authChallenge();
    assert(challenge != null || challenge.length == 1);
    _HeaderValue header =
        _HeaderValue.parse(challenge[0], parameterSeparator: ",");
    _AuthenticationScheme scheme =
        new _AuthenticationScheme.fromString(header.value);
    String realm = header.parameters["realm"];

    // See if any matching credentials are available.
    _Credentials cr = findCredentials(scheme);
    if (cr != null) {
      // For basic authentication don't retry already used credentials
      // as they must have already been added to the request causing
      // this authenticate response.
      if (cr.scheme == _AuthenticationScheme.BASIC && !cr.used) {
        // Credentials where found, prepare for retrying the request.
        return retry();
      }

      // Digest authentication only supports the MD5 algorithm.
      if (cr.scheme == _AuthenticationScheme.DIGEST &&
          (header.parameters["algorithm"] == null ||
           header.parameters["algorithm"].toLowerCase() == "md5")) {
        if (cr.nonce == null || cr.nonce == header.parameters["nonce"]) {
          // If the nonce is not set then this is the first authenticate
          // response for these credentials. Set up authentication state.
          if (cr.nonce == null) {
            cr..nonce = header.parameters["nonce"]
              ..algorithm = "MD5"
              ..qop = header.parameters["qop"]
              ..nonceCount = 0;
          }
          // Credentials where found, prepare for retrying the request.
          return retry();
        } else if (header.parameters["stale"] != null &&
                   header.parameters["stale"].toLowerCase() == "true") {
          // If stale is true retry with new nonce.
          cr.nonce = header.parameters["nonce"];
          // Credentials where found, prepare for retrying the request.
          return retry();
        }
      }
    }

    // Ask for more credentials if none found or the one found has
    // already been used. If it has already been used it must now be
    // invalid and is removed.
    if (cr != null) {
      removeCredentials(cr);
      cr = null;
    }
    return requestAuthentication(scheme, realm).then((credsAvailable) {
      if (credsAvailable) {
        cr = _httpClient._findCredentials(_httpRequest.uri, scheme);
        return retry();
      } else {
        // No credentials available, complete with original response.
        return this;
      }
    });
  }
}


abstract class _HttpOutboundMessage<T> extends _IOSinkImpl {
  // Used to mark when the body should be written. This is used for HEAD
  // requests and in error handling.
  bool _encodingSet = false;

  bool _bufferOutput = true;

  final Uri _uri;
  final _HttpOutgoing _outgoing;

  final _HttpHeaders headers;

  _HttpOutboundMessage(Uri uri,
                       String protocolVersion,
                       _HttpOutgoing outgoing,
                       {_HttpHeaders initialHeaders})
      : _uri = uri,
        headers = new _HttpHeaders(
            protocolVersion,
            defaultPortForScheme: uri.scheme == 'https' ?
                HttpClient.DEFAULT_HTTPS_PORT :
                HttpClient.DEFAULT_HTTP_PORT,
            initialHeaders: initialHeaders),
        _outgoing = outgoing,
        super(outgoing, null) {
    _outgoing.outbound = this;
    _encodingMutable = false;
  }

  int get contentLength => headers.contentLength;
  void set contentLength(int contentLength) {
    headers.contentLength = contentLength;
  }

  bool get persistentConnection => headers.persistentConnection;
  void set persistentConnection(bool p) {
    headers.persistentConnection = p;
  }

  bool get bufferOutput => _bufferOutput;
  void set bufferOutput(bool bufferOutput) {
    if (_outgoing.headersWritten) throw new StateError("Header already sent");
    _bufferOutput = bufferOutput;
  }


  Encoding get encoding {
    if (_encodingSet && _outgoing.headersWritten) {
      return _encoding;
    }
    var charset;
    if (headers.contentType != null && headers.contentType.charset != null) {
      charset = headers.contentType.charset;
    } else {
      charset = "iso-8859-1";
    }
    return Encoding.getByName(charset);
  }

  void add(List<int> data) {
    if (data.length == 0) return;
    super.add(data);
  }

  void write(Object obj) {
    if (!_encodingSet) {
      _encoding = encoding;
      _encodingSet = true;
    }
    super.write(obj);
  }

  void _writeHeader();

  bool get _isConnectionClosed => false;
}


class _HttpResponse extends _HttpOutboundMessage<HttpResponse>
    implements HttpResponse {
  int _statusCode = 200;
  String _reasonPhrase;
  List<Cookie> _cookies;
  _HttpRequest _httpRequest;
  Duration _deadline;
  Timer _deadlineTimer;

  _HttpResponse(Uri uri,
                String protocolVersion,
                _HttpOutgoing outgoing,
                HttpHeaders defaultHeaders,
                String serverHeader)
      : super(uri, protocolVersion, outgoing, initialHeaders: defaultHeaders) {
    if (serverHeader != null) headers.set('server', serverHeader);
  }

  bool get _isConnectionClosed => _httpRequest._httpConnection._isClosing;

  List<Cookie> get cookies {
    if (_cookies == null) _cookies = new List<Cookie>();
    return _cookies;
  }

  int get statusCode => _statusCode;
  void set statusCode(int statusCode) {
    if (_outgoing.headersWritten) throw new StateError("Header already sent");
    _statusCode = statusCode;
  }

  String get reasonPhrase => _findReasonPhrase(statusCode);
  void set reasonPhrase(String reasonPhrase) {
    if (_outgoing.headersWritten) throw new StateError("Header already sent");
    _reasonPhrase = reasonPhrase;
  }

  Future redirect(Uri location, {int status: HttpStatus.MOVED_TEMPORARILY}) {
    if (_outgoing.headersWritten) throw new StateError("Header already sent");
    statusCode = status;
    headers.set("location", location.toString());
    return close();
  }

  Future<Socket> detachSocket({bool writeHeaders: true}) {
    if (_outgoing.headersWritten) throw new StateError("Headers already sent");
    deadline = null;  // Be sure to stop any deadline.
    var future = _httpRequest._httpConnection.detachSocket();
    if (writeHeaders) {
      var headersFuture = _outgoing.writeHeaders(drainRequest: false,
                                                 setOutgoing: false);
      assert(headersFuture == null);
    } else {
      // Imitate having written the headers.
      _outgoing.headersWritten = true;
    }
    // Close connection so the socket is 'free'.
    close();
    done.catchError((_) {
      // Catch any error on done, as they automatically will be
      // propagated to the websocket.
    });
    return future;
  }

  HttpConnectionInfo get connectionInfo => _httpRequest.connectionInfo;

  Duration get deadline => _deadline;

  void set deadline(Duration d) {
    if (_deadlineTimer != null) _deadlineTimer.cancel();
    _deadline = d;

    if (_deadline == null) return;
    _deadlineTimer = new Timer(_deadline, () {
      _httpRequest._httpConnection.destroy();
    });
  }

  void _writeHeader() {
    Uint8List buffer = new Uint8List(_OUTGOING_BUFFER_SIZE);
    int offset = 0;

    void write(List<int> bytes) {
      int len = bytes.length;
      for (int i = 0; i < len; i++) {
        buffer[offset + i] = bytes[i];
      }
      offset += len;
    }

    // Write status line.
    if (headers.protocolVersion == "1.1") {
      write(_Const.HTTP11);
    } else {
      write(_Const.HTTP10);
    }
    buffer[offset++] = _CharCode.SP;
    write(statusCode.toString().codeUnits);
    buffer[offset++] = _CharCode.SP;
    write(reasonPhrase.codeUnits);
    buffer[offset++] = _CharCode.CR;
    buffer[offset++] = _CharCode.LF;

    var session = _httpRequest._session;
    if (session != null && !session._destroyed) {
      // Mark as not new.
      session._isNew = false;
      // Make sure we only send the current session id.
      bool found = false;
      for (int i = 0; i < cookies.length; i++) {
        if (cookies[i].name.toUpperCase() == _DART_SESSION_ID) {
          cookies[i]
              ..value = session.id
              ..httpOnly = true
              ..path = "/";
          found = true;
        }
      }
      if (!found) {
        var cookie = new Cookie(_DART_SESSION_ID, session.id);
        cookies.add(cookie
            ..httpOnly = true
            ..path = "/");
      }
    }
    // Add all the cookies set to the headers.
    if (_cookies != null) {
      _cookies.forEach((cookie) {
        headers.add(HttpHeaders.SET_COOKIE, cookie);
      });
    }

    headers._finalize();

    // Write headers.
    offset = headers._write(buffer, offset);
    buffer[offset++] = _CharCode.CR;
    buffer[offset++] = _CharCode.LF;
    _outgoing.setHeader(buffer, offset);
  }

  String _findReasonPhrase(int statusCode) {
    if (_reasonPhrase != null) {
      return _reasonPhrase;
    }

    switch (statusCode) {
      case HttpStatus.CONTINUE: return "Continue";
      case HttpStatus.SWITCHING_PROTOCOLS: return "Switching Protocols";
      case HttpStatus.OK: return "OK";
      case HttpStatus.CREATED: return "Created";
      case HttpStatus.ACCEPTED: return "Accepted";
      case HttpStatus.NON_AUTHORITATIVE_INFORMATION:
        return "Non-Authoritative Information";
      case HttpStatus.NO_CONTENT: return "No Content";
      case HttpStatus.RESET_CONTENT: return "Reset Content";
      case HttpStatus.PARTIAL_CONTENT: return "Partial Content";
      case HttpStatus.MULTIPLE_CHOICES: return "Multiple Choices";
      case HttpStatus.MOVED_PERMANENTLY: return "Moved Permanently";
      case HttpStatus.FOUND: return "Found";
      case HttpStatus.SEE_OTHER: return "See Other";
      case HttpStatus.NOT_MODIFIED: return "Not Modified";
      case HttpStatus.USE_PROXY: return "Use Proxy";
      case HttpStatus.TEMPORARY_REDIRECT: return "Temporary Redirect";
      case HttpStatus.BAD_REQUEST: return "Bad Request";
      case HttpStatus.UNAUTHORIZED: return "Unauthorized";
      case HttpStatus.PAYMENT_REQUIRED: return "Payment Required";
      case HttpStatus.FORBIDDEN: return "Forbidden";
      case HttpStatus.NOT_FOUND: return "Not Found";
      case HttpStatus.METHOD_NOT_ALLOWED: return "Method Not Allowed";
      case HttpStatus.NOT_ACCEPTABLE: return "Not Acceptable";
      case HttpStatus.PROXY_AUTHENTICATION_REQUIRED:
        return "Proxy Authentication Required";
      case HttpStatus.REQUEST_TIMEOUT: return "Request Time-out";
      case HttpStatus.CONFLICT: return "Conflict";
      case HttpStatus.GONE: return "Gone";
      case HttpStatus.LENGTH_REQUIRED: return "Length Required";
      case HttpStatus.PRECONDITION_FAILED: return "Precondition Failed";
      case HttpStatus.REQUEST_ENTITY_TOO_LARGE:
        return "Request Entity Too Large";
      case HttpStatus.REQUEST_URI_TOO_LONG: return "Request-URI Too Large";
      case HttpStatus.UNSUPPORTED_MEDIA_TYPE: return "Unsupported Media Type";
      case HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE:
        return "Requested range not satisfiable";
      case HttpStatus.EXPECTATION_FAILED: return "Expectation Failed";
      case HttpStatus.INTERNAL_SERVER_ERROR: return "Internal Server Error";
      case HttpStatus.NOT_IMPLEMENTED: return "Not Implemented";
      case HttpStatus.BAD_GATEWAY: return "Bad Gateway";
      case HttpStatus.SERVICE_UNAVAILABLE: return "Service Unavailable";
      case HttpStatus.GATEWAY_TIMEOUT: return "Gateway Time-out";
      case HttpStatus.HTTP_VERSION_NOT_SUPPORTED:
        return "Http Version not supported";
      default: return "Status $statusCode";
    }
  }
}


class _HttpClientRequest extends _HttpOutboundMessage<HttpClientResponse>
    implements HttpClientRequest {
  final String method;
  final Uri uri;
  final List<Cookie> cookies = new List<Cookie>();

  // The HttpClient this request belongs to.
  final _HttpClient _httpClient;
  final _HttpClientConnection _httpClientConnection;

  final Completer<HttpClientResponse> _responseCompleter
      = new Completer<HttpClientResponse>();

  final _Proxy _proxy;

  Future<HttpClientResponse> _response;

  // TODO(ajohnsen): Get default value from client?
  bool _followRedirects = true;

  int _maxRedirects = 5;

  List<RedirectInfo> _responseRedirects = [];

  _HttpClientRequest(_HttpOutgoing outgoing, Uri uri, this.method, this._proxy,
                     this._httpClient, this._httpClientConnection)
      : uri = uri,
        super(uri, "1.1", outgoing) {
    // GET and HEAD have 'content-length: 0' by default.
    if (method == "GET" || method == "HEAD") {
      contentLength = 0;
    } else {
      headers.chunkedTransferEncoding = true;
    }
  }

  Future<HttpClientResponse> get done {
    if (_response == null) {
      _response = Future.wait([_responseCompleter.future, super.done],
                              eagerError: true)
        .then((list) => list[0]);
    }
    return _response;
  }

  Future<HttpClientResponse> close() {
    super.close();
    return done;
  }

  int get maxRedirects => _maxRedirects;
  void set maxRedirects(int maxRedirects) {
    if (_outgoing.headersWritten) throw new StateError("Request already sent");
    _maxRedirects = maxRedirects;
  }

  bool get followRedirects => _followRedirects;
  void set followRedirects(bool followRedirects) {
    if (_outgoing.headersWritten) throw new StateError("Request already sent");
    _followRedirects = followRedirects;
  }

  HttpConnectionInfo get connectionInfo => _httpClientConnection.connectionInfo;

  void _onIncoming(_HttpIncoming incoming) {
    var response = new _HttpClientResponse(incoming, this, _httpClient);
    Future<HttpClientResponse> future;
    if (followRedirects && response.isRedirect) {
      if (response.redirects.length < maxRedirects) {
        // Redirect and drain response.
        future = response.drain().then((_) => response.redirect());
      } else {
        // End with exception, too many redirects.
        future = response.drain()
            .then((_) => new Future.error(
                new RedirectException("Redirect limit exceeded",
                                      response.redirects)));
      }
    } else if (response._shouldAuthenticateProxy) {
      future = response._authenticate(true);
    } else if (response._shouldAuthenticate) {
      future = response._authenticate(false);
    } else {
      future = new Future<HttpClientResponse>.value(response);
    }
    future.then(
        (v) => _responseCompleter.complete(v),
        onError: _responseCompleter.completeError);
  }

  void _onError(error, StackTrace stackTrace) {
    _responseCompleter.completeError(error, stackTrace);
  }

  // Generate the request URI based on the method and proxy.
  String _requestUri() {
    // Generate the request URI starting from the path component.
    String uriStartingFromPath() {
      String result = uri.path;
      if (result.isEmpty) result = "/";
      if (uri.hasQuery) {
        result = "${result}?${uri.query}";
      }
      return result;
    }

    if (_proxy.isDirect) {
      return uriStartingFromPath();
    } else {
      if (method == "CONNECT") {
        // For the connect method the request URI is the host:port of
        // the requested destination of the tunnel (see RFC 2817
        // section 5.2)
        return "${uri.host}:${uri.port}";
      } else {
        if (_httpClientConnection._proxyTunnel) {
          return uriStartingFromPath();
        } else {
          return uri.removeFragment().toString();
        }
      }
    }
  }

  void _writeHeader() {
    Uint8List buffer = new Uint8List(_OUTGOING_BUFFER_SIZE);
    int offset = 0;

    void write(List<int> bytes) {
      int len = bytes.length;
      for (int i = 0; i < len; i++) {
        buffer[offset + i] = bytes[i];
      }
      offset += len;
    }

    // Write the request method.
    write(method.codeUnits);
    buffer[offset++] = _CharCode.SP;
    // Write the request URI.
    write(_requestUri().codeUnits);
    buffer[offset++] = _CharCode.SP;
    // Write HTTP/1.1.
    write(_Const.HTTP11);
    buffer[offset++] = _CharCode.CR;
    buffer[offset++] = _CharCode.LF;

    // Add the cookies to the headers.
    if (!cookies.isEmpty) {
      StringBuffer sb = new StringBuffer();
      for (int i = 0; i < cookies.length; i++) {
        if (i > 0) sb.write("; ");
        sb..write(cookies[i].name)..write("=")..write(cookies[i].value);
      }
      headers.add(HttpHeaders.COOKIE, sb.toString());
    }

    headers._finalize();

    // Write headers.
    offset = headers._write(buffer, offset);
    buffer[offset++] = _CharCode.CR;
    buffer[offset++] = _CharCode.LF;
    _outgoing.setHeader(buffer, offset);
  }
}

// Used by _HttpOutgoing as a target of a chunked converter for gzip
// compression.
class _HttpGZipSink extends ByteConversionSink {
  final Function _consume;
  _HttpGZipSink(this._consume);

  void add(List<int> chunk) {
    _consume(chunk);
  }

  void addSlice(List<int> chunk, int start, int end, bool isLast) {
    if (chunk is Uint8List) {
      _consume(new Uint8List.view(chunk.buffer, start, end - start));
    } else {
      _consume(chunk.sublist(start, end - start));
    }
  }

  void close() {}
}


// The _HttpOutgoing handles all of the following:
//  - Buffering
//  - GZip compressionm
//  - Content-Length validation.
//  - Errors.
//
// Most notable is the GZip compression, that uses a double-buffering system,
// one before gzip (_gzipBuffer) and one after (_buffer).
class _HttpOutgoing implements StreamConsumer<List<int>> {
  static const List<int> _footerAndChunk0Length =
      const [_CharCode.CR, _CharCode.LF, 0x30, _CharCode.CR, _CharCode.LF,
             _CharCode.CR, _CharCode.LF];

  static const List<int> _chunk0Length =
      const [0x30, _CharCode.CR, _CharCode.LF, _CharCode.CR, _CharCode.LF];

  final Completer _doneCompleter = new Completer();
  final Socket socket;

  bool ignoreBody = false;
  bool headersWritten = false;

  Uint8List _buffer;
  int _length = 0;

  Future _closeFuture;

  bool chunked = false;
  int _pendingChunkedFooter = 0;

  int contentLength;
  int _bytesWritten = 0;

  bool _gzip = false;
  ByteConversionSink _gzipSink;
  // _gzipAdd is set iff the sink is being added to. It's used to specify where
  // gzipped data should be taken (sometimes a controller, sometimes a socket).
  Function _gzipAdd;
  Uint8List _gzipBuffer;
  int _gzipBufferLength = 0;

  bool _socketError = false;

  _HttpOutboundMessage outbound;

  _HttpOutgoing(this.socket);

  // Returns either a future or 'null', if it was able to write headers
  // immediately.
  Future writeHeaders({bool drainRequest: true, bool setOutgoing: true}) {
    Future write() {
      try {
        outbound._writeHeader();
      } catch (_) {
        // Headers too large.
        return new Future.error(new HttpException(
            "Headers size exceeded the of '$_OUTGOING_BUFFER_SIZE'"
            " bytes"));
      }
      return null;
    }

    if (headersWritten) return null;
    headersWritten = true;
    Future drainFuture;
    bool gzip = false;
    if (outbound is _HttpResponse) {
      // Server side.
      _HttpResponse response = outbound;
      if (response._httpRequest._httpServer.autoCompress &&
          outbound.bufferOutput &&
          outbound.headers.chunkedTransferEncoding) {
        List acceptEncodings =
            response._httpRequest.headers[HttpHeaders.ACCEPT_ENCODING];
        List contentEncoding = outbound.headers[HttpHeaders.CONTENT_ENCODING];
        if (acceptEncodings != null &&
            acceptEncodings
                .expand((list) => list.split(","))
                .any((encoding) => encoding.trim().toLowerCase() == "gzip") &&
            contentEncoding == null) {
          outbound.headers.set(HttpHeaders.CONTENT_ENCODING, "gzip");
          gzip = true;
        }
      }
      if (drainRequest && !response._httpRequest._incoming.hasSubscriber) {
        drainFuture = response._httpRequest.drain().catchError((_) {});
      }
    } else {
      drainRequest = false;
    }
    if (ignoreBody) {
      return write();
    }
    if (setOutgoing) {
      int contentLength = outbound.headers.contentLength;
      if (outbound.headers.chunkedTransferEncoding) {
        chunked = true;
        if (gzip) this.gzip = true;
      } else if (contentLength >= 0) {
        this.contentLength = contentLength;
      }
    }
    if (drainFuture != null) {
      return drainFuture.then((_) => write());
    }
    return write();
  }


  Future addStream(Stream<List<int>> stream) {
    if (_socketError) {
      stream.listen(null).cancel();
      return new Future.value(outbound);
    }
    if (ignoreBody) {
      stream.drain().catchError((_) {});
      var future = writeHeaders();
      if (future != null) {
        return future.then((_) => close());
      }
      return close();
    }
    var sub;
    // Use new stream so we are able to pause (see below listen). The
    // alternative is to use stream.extand, but that won't give us a way of
    // pausing.
    var controller = new StreamController(
        onPause: () => sub.pause(),
        onResume: () => sub.resume(),
        sync: true);

    void onData(data) {
      if (_socketError) return;
      if (data.length == 0) return;
      if (chunked) {
        if (_gzip) {
          _gzipAdd = controller.add;
          _addGZipChunk(data, _gzipSink.add);
          _gzipAdd = null;
          return;
        }
        _addChunk(_chunkHeader(data.length), controller.add);
        _pendingChunkedFooter = 2;
      } else {
        if (contentLength != null) {
          _bytesWritten += data.length;
          if (_bytesWritten > contentLength) {
            controller.addError(new HttpException(
                "Content size exceeds specified contentLength. "
                "$_bytesWritten bytes written while expected "
                "$contentLength. "
                "[${new String.fromCharCodes(data)}]"));
            return;
          }
        }
      }
      _addChunk(data, controller.add);
    }

    sub = stream.listen(
        onData,
        onError: controller.addError,
        onDone: controller.close,
        cancelOnError: true);
    // Write headers now that we are listening to the stream.
    if (!headersWritten) {
      var future = writeHeaders();
      if (future != null) {
        // While incoming is being drained, the pauseFuture is non-null. Pause
        // output until it's drained.
        sub.pause(future);
      }
    }
    return socket.addStream(controller.stream)
        .then((_) {
          return outbound;
        }, onError: (error, stackTrace) {
          // Be sure to close it in case of an error.
          if (_gzip) _gzipSink.close();
          _socketError = true;
          _doneCompleter.completeError(error, stackTrace);
          if (_ignoreError(error)) {
            return outbound;
          } else {
            throw error;
          }
        });
  }

  Future close() {
    // If we are already closed, return that future.
    if (_closeFuture != null) return _closeFuture;
    // If we earlier saw an error, return immediate. The notification to
    // _Http*Connection is already done.
    if (_socketError) return new Future.value(outbound);
    if (outbound._isConnectionClosed) return new Future.value(outbound);
    if (!headersWritten && !ignoreBody) {
      if (outbound.headers.contentLength == -1) {
        // If no body was written, ignoreBody is false (it's not a HEAD
        // request) and the content-length is unspecified, set contentLength to
        // 0.
        outbound.headers.chunkedTransferEncoding = false;
        outbound.headers.contentLength = 0;
      } else if (outbound.headers.contentLength > 0) {
        var error = new HttpException(
              "No content even though contentLength was specified to be "
              "greater than 0: ${outbound.headers.contentLength}.",
              uri: outbound._uri);
        _doneCompleter.completeError(error);
        return _closeFuture = new Future.error(error);
      }
    }
    // If contentLength was specified, validate it.
    if (contentLength != null) {
      if (_bytesWritten < contentLength) {
        var error = new HttpException(
            "Content size below specified contentLength. "
            " $_bytesWritten bytes written but expected "
            "$contentLength.",
            uri: outbound._uri);
        _doneCompleter.completeError(error);
        return _closeFuture = new Future.error(error);
      }
    }

    Future finalize() {
      // In case of chunked encoding (and gzip), handle remaining gzip data and
      // append the 'footer' for chunked encoding.
      if (chunked) {
        if (_gzip) {
          _gzipAdd = socket.add;
          if (_gzipBufferLength > 0) {
            _gzipSink.add(new Uint8List.view(
                _gzipBuffer.buffer, 0, _gzipBufferLength));
          }
          _gzipBuffer = null;
          _gzipSink.close();
          _gzipAdd = null;
        }
        _addChunk(_chunkHeader(0), socket.add);
      }
      // Add any remaining data in the buffer.
      if (_length > 0) {
        socket.add(new Uint8List.view(_buffer.buffer, 0, _length));
      }
      // Clear references, for better GC.
      _buffer = null;
      // And finally flush it. As we support keep-alive, never close it from
      // here. Once the socket is flushed, we'll be able to reuse it (signaled
      // by the 'done' future).
      return socket.flush()
        .then((_) {
          _doneCompleter.complete(socket);
          return outbound;
        }, onError: (error, stackTrace) {
          _doneCompleter.completeError(error, stackTrace);
          if (_ignoreError(error)) {
            return outbound;
          } else {
            throw error;
          }
        });
    }

    var future = writeHeaders();
    if (future != null) {
      return _closeFuture = future.whenComplete(finalize);
    }
    return _closeFuture = finalize();
  }

  Future get done => _doneCompleter.future;

  void setHeader(List<int> data, int length) {
    assert(_length == 0);
    assert(data.length == _OUTGOING_BUFFER_SIZE);
    _buffer = data;
    _length = length;
  }

  void set gzip(bool value) {
    _gzip = value;
    if (_gzip) {
      _gzipBuffer = new Uint8List(_OUTGOING_BUFFER_SIZE);
      assert(_gzipSink == null);
      _gzipSink = new ZLibEncoder(gzip: true)
          .startChunkedConversion(
              new _HttpGZipSink((data) {
                // We are closing down prematurely, due to an error. Discard.
                if (_gzipAdd == null) return;
                _addChunk(_chunkHeader(data.length), _gzipAdd);
                _pendingChunkedFooter = 2;
                _addChunk(data, _gzipAdd);
              }));
    }
  }

  bool _ignoreError(error)
    => (error is SocketException || error is TlsException) &&
       outbound is HttpResponse;

  void _addGZipChunk(chunk, void add(List<int> data)) {
    if (!outbound.bufferOutput) {
      add(chunk);
      return;
    }
    if (chunk.length > _gzipBuffer.length - _gzipBufferLength) {
      add(new Uint8List.view(
          _gzipBuffer.buffer, 0, _gzipBufferLength));
      _gzipBuffer = new Uint8List(_OUTGOING_BUFFER_SIZE);
      _gzipBufferLength = 0;
    }
    if (chunk.length > _OUTGOING_BUFFER_SIZE) {
      add(chunk);
    } else {
      _gzipBuffer.setRange(_gzipBufferLength,
                           _gzipBufferLength + chunk.length,
                           chunk);
      _gzipBufferLength += chunk.length;
    }
  }

  void _addChunk(chunk, void add(List<int> data)) {
    if (!outbound.bufferOutput) {
      if (_buffer != null) {
        // If _buffer is not null, we have not written the header yet. Write
        // it now.
        add(new Uint8List.view(_buffer.buffer, 0, _length));
        _buffer = null;
        _length = 0;
      }
      add(chunk);
      return;
    }
    if (chunk.length > _buffer.length - _length) {
      add(new Uint8List.view(_buffer.buffer, 0, _length));
      _buffer = new Uint8List(_OUTGOING_BUFFER_SIZE);
      _length = 0;
    }
    if (chunk.length > _OUTGOING_BUFFER_SIZE) {
      add(chunk);
    } else {
      _buffer.setRange(_length, _length + chunk.length, chunk);
      _length += chunk.length;
    }
  }

  List<int> _chunkHeader(int length) {
    const hexDigits = const [0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
                             0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46];
    if (length == 0) {
      if (_pendingChunkedFooter == 2) return _footerAndChunk0Length;
      return _chunk0Length;
    }
    int size = _pendingChunkedFooter;
    int len = length;
    // Compute a fast integer version of (log(length + 1) / log(16)).ceil().
    while (len > 0) {
      size++;
      len >>= 4;
    }
    var footerAndHeader = new Uint8List(size + 2);
    if (_pendingChunkedFooter == 2) {
      footerAndHeader[0] = _CharCode.CR;
      footerAndHeader[1] = _CharCode.LF;
    }
    int index = size;
    while (index > _pendingChunkedFooter) {
      footerAndHeader[--index] = hexDigits[length & 15];
      length = length >> 4;
    }
    footerAndHeader[size + 0] = _CharCode.CR;
    footerAndHeader[size + 1] = _CharCode.LF;
    return footerAndHeader;
  }
}

class _HttpClientConnection {
  final String key;
  final Socket _socket;
  final bool _proxyTunnel;
  final SecurityContext _context;
  final _HttpParser _httpParser;
  StreamSubscription _subscription;
  final _HttpClient _httpClient;
  bool _dispose = false;
  Timer _idleTimer;
  bool closed = false;
  Uri _currentUri;

  Completer<_HttpIncoming> _nextResponseCompleter;
  Future _streamFuture;

  _HttpClientConnection(this.key, this._socket, this._httpClient,
                        [this._proxyTunnel = false, this._context])
      : _httpParser = new _HttpParser.responseParser() {
    _httpParser.listenToStream(_socket);

    // Set up handlers on the parser here, so we are sure to get 'onDone' from
    // the parser.
    _subscription = _httpParser.listen(
        (incoming) {
          // Only handle one incoming response at the time. Keep the
          // stream paused until the response have been processed.
          _subscription.pause();
          // We assume the response is not here, until we have send the request.
          if (_nextResponseCompleter == null) {
            throw new HttpException(
                "Unexpected response (unsolicited response without request).",
                uri: _currentUri);
          }

          // Check for status code '100 Continue'. In that case just
          // consume that response as the final response will follow
          // it. There is currently no API for the client to wait for
          // the '100 Continue' response.
          if (incoming.statusCode == 100) {
            incoming.drain().then((_) {
              _subscription.resume();
            }).catchError((error, [StackTrace stackTrace]) {
              _nextResponseCompleter.completeError(
                  new HttpException(error.message, uri: _currentUri),
                  stackTrace);
              _nextResponseCompleter = null;
            });
          } else {
            _nextResponseCompleter.complete(incoming);
            _nextResponseCompleter = null;
          }
        },
        onError: (error, [StackTrace stackTrace]) {
          if (_nextResponseCompleter != null) {
            _nextResponseCompleter.completeError(
                new HttpException(error.message, uri: _currentUri),
                stackTrace);
            _nextResponseCompleter = null;
          }
        },
        onDone: () {
          if (_nextResponseCompleter != null) {
            _nextResponseCompleter.completeError(new HttpException(
                "Connection closed before response was received",
                uri: _currentUri));
            _nextResponseCompleter = null;
          }
          close();
        });
  }

  _HttpClientRequest send(Uri uri, int port, String method, _Proxy proxy) {
    if (closed) {
      throw new HttpException(
          "Socket closed before request was sent", uri: uri);
    }
    _currentUri = uri;
    // Start with pausing the parser.
    _subscription.pause();
    _ProxyCredentials proxyCreds;  // Credentials used to authorize proxy.
    _SiteCredentials creds;  // Credentials used to authorize this request.
    var outgoing = new _HttpOutgoing(_socket);
    // Create new request object, wrapping the outgoing connection.
    var request = new _HttpClientRequest(outgoing,
                                         uri,
                                         method,
                                         proxy,
                                         _httpClient,
                                         this);
    // For the Host header an IPv6 address must be enclosed in []'s.
    var host = uri.host;
    if (host.contains(':')) host = "[$host]";
    request.headers
        ..host = host
        ..port = port
        .._add(HttpHeaders.ACCEPT_ENCODING, "gzip");
    if (_httpClient.userAgent != null) {
      request.headers._add('user-agent', _httpClient.userAgent);
    }
    if (proxy.isAuthenticated) {
      // If the proxy configuration contains user information use that
      // for proxy basic authorization.
      String auth = _CryptoUtils.bytesToBase64(
          UTF8.encode("${proxy.username}:${proxy.password}"));
      request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth");
    } else if (!proxy.isDirect && _httpClient._proxyCredentials.length > 0) {
      proxyCreds = _httpClient._findProxyCredentials(proxy);
      if (proxyCreds != null) {
        proxyCreds.authorize(request);
      }
    }
    if (uri.userInfo != null && !uri.userInfo.isEmpty) {
      // If the URL contains user information use that for basic
      // authorization.
      String auth =
          _CryptoUtils.bytesToBase64(UTF8.encode(uri.userInfo));
      request.headers.set(HttpHeaders.AUTHORIZATION, "Basic $auth");
    } else {
      // Look for credentials.
      creds = _httpClient._findCredentials(uri);
      if (creds != null) {
        creds.authorize(request);
      }
    }
    // Start sending the request (lazy, delayed until the user provides
    // data).
    _httpParser.isHead = method == "HEAD";
    _streamFuture = outgoing.done
        .then((s) {
          // Request sent, set up response completer.
          _nextResponseCompleter = new Completer();

          // Listen for response.
          _nextResponseCompleter.future
              .then((incoming) {
                _currentUri = null;
                incoming.dataDone.then((closing) {
                  if (incoming.upgraded) {
                    _httpClient._connectionClosed(this);
                    startTimer();
                    return;
                  }
                  if (closed) return;
                  if (!closing &&
                      !_dispose &&
                      incoming.headers.persistentConnection &&
                      request.persistentConnection) {
                    // Return connection, now we are done.
                    _httpClient._returnConnection(this);
                    _subscription.resume();
                  } else {
                    destroy();
                  }
                });
                // For digest authentication if proxy check if the proxy
                // requests the client to start using a new nonce for proxy
                // authentication.
                if (proxyCreds != null &&
                    proxyCreds.scheme == _AuthenticationScheme.DIGEST) {
                  var authInfo = incoming.headers["proxy-authentication-info"];
                  if (authInfo != null && authInfo.length == 1) {
                    var header =
                        _HeaderValue.parse(
                            authInfo[0], parameterSeparator: ',');
                    var nextnonce = header.parameters["nextnonce"];
                    if (nextnonce != null) proxyCreds.nonce = nextnonce;
                  }
                }
                // For digest authentication check if the server requests the
                // client to start using a new nonce.
                if (creds != null &&
                    creds.scheme == _AuthenticationScheme.DIGEST) {
                  var authInfo = incoming.headers["authentication-info"];
                  if (authInfo != null && authInfo.length == 1) {
                    var header =
                        _HeaderValue.parse(
                            authInfo[0], parameterSeparator: ',');
                    var nextnonce = header.parameters["nextnonce"];
                    if (nextnonce != null) creds.nonce = nextnonce;
                  }
                }
                request._onIncoming(incoming);
              })
              // If we see a state error, we failed to get the 'first'
              // element.
              .catchError((error) {
                throw new HttpException(
                    "Connection closed before data was received", uri: uri);
              }, test: (error) => error is StateError)
              .catchError((error, stackTrace) {
                // We are done with the socket.
                destroy();
                request._onError(error, stackTrace);
              });

          // Resume the parser now we have a handler.
          _subscription.resume();
          return s;
        }, onError: (e) {
          destroy();
        });
    return request;
  }

  Future<Socket> detachSocket() {
    return _streamFuture.then(
        (_) => new _DetachedSocket(_socket, _httpParser.detachIncoming()));
  }

  void destroy() {
    closed = true;
    _httpClient._connectionClosed(this);
    _socket.destroy();
  }

  void close() {
    closed = true;
    _httpClient._connectionClosed(this);
    _streamFuture
          // TODO(ajohnsen): Add timeout.
        .then((_) => _socket.destroy());
  }

  Future<_HttpClientConnection> createProxyTunnel(host, port, proxy, callback) {
    _HttpClientRequest request =
        send(new Uri(host: host, port: port),
             port,
             "CONNECT",
             proxy);
    if (proxy.isAuthenticated) {
      // If the proxy configuration contains user information use that
      // for proxy basic authorization.
      String auth = _CryptoUtils.bytesToBase64(
          UTF8.encode("${proxy.username}:${proxy.password}"));
      request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth");
    }
    return request.close()
        .then((response) {
          if (response.statusCode != HttpStatus.OK) {
            throw "Proxy failed to establish tunnel "
                  "(${response.statusCode} ${response.reasonPhrase})";
          }
          var socket = (response as _HttpClientResponse)._httpRequest
              ._httpClientConnection._socket;
          return SecureSocket.secure(
              socket,
              host: host,
              context: _context,
              onBadCertificate: callback);
        })
        .then((secureSocket) {
          String key = _HttpClientConnection.makeKey(true, host, port);
          return new _HttpClientConnection(
              key, secureSocket, request._httpClient, true);
        });
  }

  HttpConnectionInfo get connectionInfo => _HttpConnectionInfo.create(_socket);

  static makeKey(bool isSecure, String host, int port) {
    return isSecure ? "ssh:$host:$port" : "$host:$port";
  }

  void stopTimer() {
    if (_idleTimer != null) {
      _idleTimer.cancel();
      _idleTimer = null;
    }
  }

  void startTimer() {
    assert(_idleTimer == null);
    _idleTimer = new Timer(
        _httpClient.idleTimeout,
        () {
          _idleTimer = null;
          close();
        });
  }
}

class _ConnectionInfo {
  final _HttpClientConnection connection;
  final _Proxy proxy;

  _ConnectionInfo(this.connection, this.proxy);
}


class _ConnectionTarget {
  // Unique key for this connection target.
  final String key;
  final String host;
  final int port;
  final bool isSecure;
  final SecurityContext context;
  final Set<_HttpClientConnection> _idle = new HashSet();
  final Set<_HttpClientConnection> _active = new HashSet();
  final Queue _pending = new ListQueue();
  int _connecting = 0;

  _ConnectionTarget(this.key,
                    this.host,
                    this.port,
                    this.isSecure,
                    this.context);

  bool get isEmpty => _idle.isEmpty && _active.isEmpty && _connecting == 0;

  bool get hasIdle => _idle.isNotEmpty;

  bool get hasActive => _active.isNotEmpty || _connecting > 0;

  _HttpClientConnection takeIdle() {
    assert(hasIdle);
    _HttpClientConnection connection = _idle.first;
    _idle.remove(connection);
    connection.stopTimer();
    _active.add(connection);
    return connection;
  }

  _checkPending() {
    if (_pending.isNotEmpty) {
      _pending.removeFirst()();
    }
  }

  void addNewActive(_HttpClientConnection connection) {
    _active.add(connection);
  }

  void returnConnection(_HttpClientConnection connection) {
    assert(_active.contains(connection));
    _active.remove(connection);
    _idle.add(connection);
    connection.startTimer();
    _checkPending();
  }

  void connectionClosed(_HttpClientConnection connection) {
    assert(!_active.contains(connection) || !_idle.contains(connection));
    _active.remove(connection);
    _idle.remove(connection);
    _checkPending();
  }

  void close(bool force) {
    for (var c in _idle.toList()) {
      c.close();
    }
    if (force) {
      for (var c in _active.toList()) {
        c.destroy();
      }
    }
  }

  Future<_ConnectionInfo> connect(String uriHost,
                                  int uriPort,
                                  _Proxy proxy,
                                  _HttpClient client) {
    if (hasIdle) {
      var connection = takeIdle();
      client._connectionsChanged();
      return new Future.value(new _ConnectionInfo(connection, proxy));
    }
    if (client.maxConnectionsPerHost != null &&
        _active.length + _connecting >= client.maxConnectionsPerHost) {
      var completer = new Completer();
      _pending.add(() {
        connect(uriHost, uriPort, proxy, client)
            .then(completer.complete, onError: completer.completeError);
      });
      return completer.future;
    }
    var currentBadCertificateCallback = client._badCertificateCallback;

    bool callback(X509Certificate certificate) {
      if (currentBadCertificateCallback == null) return false;
      return currentBadCertificateCallback(certificate, uriHost, uriPort);
    }

    Future socketFuture = (isSecure && proxy.isDirect
        ? SecureSocket.connect(host,
                               port,
                               context: context,
                               onBadCertificate: callback)
        : Socket.connect(host, port));
    _connecting++;
    return socketFuture.then((socket) {
        _connecting--;
        socket.setOption(SocketOption.TCP_NODELAY, true);
        var connection =
            new _HttpClientConnection(key, socket, client, false, context);
        if (isSecure && !proxy.isDirect) {
          connection._dispose = true;
          return connection.createProxyTunnel(uriHost, uriPort, proxy, callback)
              .then((tunnel) {
                client._getConnectionTarget(uriHost, uriPort, true)
                    .addNewActive(tunnel);
                return new _ConnectionInfo(tunnel, proxy);
              });
        } else {
          addNewActive(connection);
          return new _ConnectionInfo(connection, proxy);
        }
      }, onError: (error) {
        _connecting--;
        _checkPending();
        throw error;
      });
  }
}

typedef bool BadCertificateCallback(X509Certificate cr, String host, int port);

class _HttpClient implements HttpClient {
  bool _closing = false;
  bool _closingForcefully = false;
  final Map<String, _ConnectionTarget> _connectionTargets
      = new HashMap<String, _ConnectionTarget>();
  final List<_Credentials> _credentials = [];
  final List<_ProxyCredentials> _proxyCredentials = [];
  final SecurityContext _context;
  Function _authenticate;
  Function _authenticateProxy;
  Function _findProxy = HttpClient.findProxyFromEnvironment;
  Duration _idleTimeout = const Duration(seconds: 15);
  BadCertificateCallback _badCertificateCallback;

  Duration get idleTimeout => _idleTimeout;

  int maxConnectionsPerHost;

  bool autoUncompress = true;

  String userAgent = _getHttpVersion();

  _HttpClient(SecurityContext this._context);

  void set idleTimeout(Duration timeout) {
    _idleTimeout = timeout;
    for (var c in _connectionTargets.values) {
      for (var idle in c._idle) {
        // Reset timer. This is fine, as it's not happening often.
        idle.stopTimer();
        idle.startTimer();
      }
    }
  }

  set badCertificateCallback(bool callback(X509Certificate cert,
                                           String host,
                                           int port)) {
    _badCertificateCallback = callback;
  }


  Future<HttpClientRequest> open(String method,
                                 String host,
                                 int port,
                                 String path) {
    const int hashMark = 0x23;
    const int questionMark = 0x3f;
    int fragmentStart = path.length;
    int queryStart = path.length;
    for (int i = path.length - 1; i >= 0; i--) {
      var char = path.codeUnitAt(i);
      if (char == hashMark) {
        fragmentStart = i;
        queryStart = i;
      } else if (char == questionMark) {
        queryStart = i;
      }
    }
    String query = null;
    if (queryStart < fragmentStart) {
      query = path.substring(queryStart + 1, fragmentStart);
      path = path.substring(0, queryStart);
    }
    Uri uri = new Uri(scheme: "http", host: host, port: port,
                      path: path, query: query);
    return _openUrl(method, uri);
  }

  Future<HttpClientRequest> openUrl(String method, Uri url)
      => _openUrl(method, url);

  Future<HttpClientRequest> get(String host, int port, String path)
      => open("get", host, port, path);

  Future<HttpClientRequest> getUrl(Uri url) => _openUrl("get", url);

  Future<HttpClientRequest> post(String host, int port, String path)
      => open("post", host, port, path);

  Future<HttpClientRequest> postUrl(Uri url) => _openUrl("post", url);

  Future<HttpClientRequest> put(String host, int port, String path)
      => open("put", host, port, path);

  Future<HttpClientRequest> putUrl(Uri url) => _openUrl("put", url);

  Future<HttpClientRequest> delete(String host, int port, String path)
      => open("delete", host, port, path);

  Future<HttpClientRequest> deleteUrl(Uri url) => _openUrl("delete", url);

  Future<HttpClientRequest> head(String host, int port, String path)
      => open("head", host, port, path);

  Future<HttpClientRequest> headUrl(Uri url) => _openUrl("head", url);

  Future<HttpClientRequest> patch(String host, int port, String path)
      => open("patch", host, port, path);

  Future<HttpClientRequest> patchUrl(Uri url) => _openUrl("patch", url);

  void close({bool force: false}) {
    _closing = true;
    _closingForcefully = force;
    _closeConnections(_closingForcefully);
    assert(!_connectionTargets.values.any((s) => s.hasIdle));
    assert(!force ||
        !_connectionTargets.values.any((s) => s._active.isNotEmpty));
  }

  set authenticate(Future<bool> f(Uri url, String scheme, String realm)) {
    _authenticate = f;
  }

  void addCredentials(Uri url, String realm, HttpClientCredentials cr) {
    _credentials.add(new _SiteCredentials(url, realm, cr));
  }

  set authenticateProxy(
      Future<bool> f(String host, int port, String scheme, String realm)) {
    _authenticateProxy = f;
  }

  void addProxyCredentials(String host,
                           int port,
                           String realm,
                           HttpClientCredentials cr) {
    _proxyCredentials.add(new _ProxyCredentials(host, port, realm, cr));
  }

  set findProxy(String f(Uri uri)) => _findProxy = f;

  Future<_HttpClientRequest> _openUrl(String method, Uri uri) {
    // Ignore any fragments on the request URI.
    uri = uri.removeFragment();

    if (method == null) {
      throw new ArgumentError(method);
    }
    if (method != "CONNECT") {
      if (uri.host.isEmpty) {
        throw new ArgumentError("No host specified in URI $uri");
      } else if (uri.scheme != "http" && uri.scheme != "https") {
        throw new ArgumentError(
            "Unsupported scheme '${uri.scheme}' in URI $uri");
      }
    }

    bool isSecure = (uri.scheme == "https");
    int port = uri.port;
    if (port == 0) {
      port = isSecure ?
          HttpClient.DEFAULT_HTTPS_PORT :
          HttpClient.DEFAULT_HTTP_PORT;
    }
    // Check to see if a proxy server should be used for this connection.
    var proxyConf = const _ProxyConfiguration.direct();
    if (_findProxy != null) {
      // TODO(sgjesse): Keep a map of these as normally only a few
      // configuration strings will be used.
      try {
        proxyConf = new _ProxyConfiguration(_findProxy(uri));
      } catch (error, stackTrace) {
        return new Future.error(error, stackTrace);
      }
    }
    return _getConnection(uri.host, port, proxyConf, isSecure)
        .then((_ConnectionInfo info) {

          _HttpClientRequest send(_ConnectionInfo info) {
            return info.connection.send(uri,
                                        port,
                                        method.toUpperCase(),
                                        info.proxy);
          }

          // If the connection was closed before the request was sent, create
          // and use another connection.
          if (info.connection.closed) {
            return _getConnection(uri.host, port, proxyConf, isSecure)
                .then(send);
          }
          return send(info);
        });
  }

  Future<_HttpClientRequest> _openUrlFromRequest(String method,
                                                Uri uri,
                                                _HttpClientRequest previous) {
    // If the new URI is relative (to either '/' or some sub-path),
    // construct a full URI from the previous one.
    Uri resolved = previous.uri.resolveUri(uri);
    return _openUrl(method, resolved).then((_HttpClientRequest request) {

          request
              // Only follow redirects if initial request did.
              ..followRedirects = previous.followRedirects
              // Allow same number of redirects.
              ..maxRedirects = previous.maxRedirects;
          // Copy headers.
          for (var header in previous.headers._headers.keys) {
            if (request.headers[header] == null) {
              request.headers.set(header, previous.headers[header]);
            }
          }
          return request
              ..headers.chunkedTransferEncoding = false
              ..contentLength = 0;
        });
  }

  // Return a live connection to the idle pool.
  void _returnConnection(_HttpClientConnection connection) {
    _connectionTargets[connection.key].returnConnection(connection);
    _connectionsChanged();
  }

  // Remove a closed connnection from the active set.
  void _connectionClosed(_HttpClientConnection connection) {
    connection.stopTimer();
    var connectionTarget = _connectionTargets[connection.key];
    if (connectionTarget != null) {
      connectionTarget.connectionClosed(connection);
      if (connectionTarget.isEmpty) {
        _connectionTargets.remove(connection.key);
      }
      _connectionsChanged();
    }
  }

  void _connectionsChanged() {
    if (_closing) {
      _closeConnections(_closingForcefully);
    }
  }

  void _closeConnections(bool force) {
    for (var connectionTarget in _connectionTargets.values.toList()) {
      connectionTarget.close(force);
    }
  }

  _ConnectionTarget _getConnectionTarget(String host, int port, bool isSecure) {
    String key = _HttpClientConnection.makeKey(isSecure, host, port);
    return _connectionTargets.putIfAbsent(key, () {
      return new _ConnectionTarget(key, host, port, isSecure, _context);
    });
  }

  // Get a new _HttpClientConnection, from the matching _ConnectionTarget.
  Future<_ConnectionInfo> _getConnection(String uriHost,
                                          int uriPort,
                                          _ProxyConfiguration proxyConf,
                                          bool isSecure) {
    Iterator<_Proxy> proxies = proxyConf.proxies.iterator;

    Future<_ConnectionInfo> connect(error) {
      if (!proxies.moveNext()) return new Future.error(error);
      _Proxy proxy = proxies.current;
      String host = proxy.isDirect ? uriHost: proxy.host;
      int port = proxy.isDirect ? uriPort: proxy.port;
      return _getConnectionTarget(host, port, isSecure)
          .connect(uriHost, uriPort, proxy, this)
          // On error, continue with next proxy.
          .catchError(connect);
    }
    // Make sure we go through the event loop before taking a
    // connection from the pool. For long-running synchronous code the
    // server might have closed the connection, so this lowers the
    // probability of getting a connection that was already closed.
    return new Future(() => connect(new HttpException("No proxies given")));
  }

  _SiteCredentials _findCredentials(Uri url, [_AuthenticationScheme scheme]) {
    // Look for credentials.
    _SiteCredentials cr =
        _credentials.fold(null, (_SiteCredentials prev, value) {
          var siteCredentials = value as _SiteCredentials;
          if (siteCredentials.applies(url, scheme)) {
            if (prev == null) return value;
            return siteCredentials.uri.path.length > prev.uri.path.length
                ? siteCredentials
                : prev;
          } else {
            return prev;
          }
        });
    return cr;
  }

  _ProxyCredentials _findProxyCredentials(_Proxy proxy,
                                          [_AuthenticationScheme scheme]) {
    // Look for credentials.
    var it = _proxyCredentials.iterator;
    while (it.moveNext()) {
      if (it.current.applies(proxy, scheme)) {
        return it.current;
      }
    }
    return null;
  }

  void _removeCredentials(_Credentials cr) {
    int index = _credentials.indexOf(cr);
    if (index != -1) {
      _credentials.removeAt(index);
    }
  }

  void _removeProxyCredentials(_Credentials cr) {
    int index = _proxyCredentials.indexOf(cr);
    if (index != -1) {
      _proxyCredentials.removeAt(index);
    }
  }

  static String _findProxyFromEnvironment(Uri url,
                                          Map<String, String> environment) {
    checkNoProxy(String option) {
      if (option == null) return null;
      Iterator<String> names = option.split(",").map((s) => s.trim()).iterator;
      while (names.moveNext()) {
        var name = names.current;
        if ((name.startsWith("[") &&
             name.endsWith("]") &&
             "[${url.host}]" == name) ||
            (name.isNotEmpty &&
             url.host.endsWith(name))) {
          return "DIRECT";
        }
      }
      return null;
    }

    checkProxy(String option) {
      if (option == null) return null;
      option = option.trim();
      if (option.isEmpty) return null;
      int pos = option.indexOf("://");
      if (pos >= 0) {
        option = option.substring(pos + 3);
      }
      pos = option.indexOf("/");
      if (pos >= 0) {
        option = option.substring(0, pos);
      }
      // Add default port if no port configured.
      if (option.indexOf("[") == 0) {
        var pos = option.lastIndexOf(":");
        if (option.indexOf("]") > pos) option = "$option:1080";
      } else {
        if (option.indexOf(":") == -1) option = "$option:1080";
      }
      return "PROXY $option";
    }

    // Default to using the process current environment.
    if (environment == null) environment = _platformEnvironmentCache;

    String proxyCfg;

    String noProxy = environment["no_proxy"];
    if (noProxy == null) noProxy = environment["NO_PROXY"];
    if ((proxyCfg = checkNoProxy(noProxy)) != null) {
      return proxyCfg;
    }

    if (url.scheme == "http") {
      String proxy = environment["http_proxy"];
      if (proxy == null) proxy = environment["HTTP_PROXY"];
      if ((proxyCfg = checkProxy(proxy)) != null) {
        return proxyCfg;
      }
    } else if (url.scheme == "https") {
      String proxy = environment["https_proxy"];
      if (proxy == null) proxy = environment["HTTPS_PROXY"];
      if ((proxyCfg = checkProxy(proxy)) != null) {
        return proxyCfg;
      }
    }
    return "DIRECT";
  }

  static Map<String, String> _platformEnvironmentCache = Platform.environment;
}


class _HttpConnection
    extends LinkedListEntry<_HttpConnection> with _ServiceObject {
  static const _ACTIVE = 0;
  static const _IDLE = 1;
  static const _CLOSING = 2;
  static const _DETACHED = 3;

  // Use HashMap, as we don't need to keep order.
  static Map<int, _HttpConnection> _connections =
      new HashMap<int, _HttpConnection>();

  final _socket;
  final _HttpServer _httpServer;
  final _HttpParser _httpParser;
  int _state = _IDLE;
  StreamSubscription _subscription;
  bool _idleMark = false;
  Future _streamFuture;

  _HttpConnection(this._socket, this._httpServer)
      : _httpParser = new _HttpParser.requestParser() {
    try { _socket._owner = this; } catch (_) { print(_); }
    _connections[_serviceId] = this;
    _httpParser.listenToStream(_socket);
    _subscription = _httpParser.listen(
        (incoming) {
          _httpServer._markActive(this);
          // If the incoming was closed, close the connection.
          incoming.dataDone.then((closing) {
            if (closing) destroy();
          });
          // Only handle one incoming request at the time. Keep the
          // stream paused until the request has been send.
          _subscription.pause();
          _state = _ACTIVE;
          var outgoing = new _HttpOutgoing(_socket);
          var response = new _HttpResponse(incoming.uri,
                                           incoming.headers.protocolVersion,
                                           outgoing,
                                           _httpServer.defaultResponseHeaders,
                                           _httpServer.serverHeader);
          var request = new _HttpRequest(response, incoming, _httpServer, this);
          _streamFuture = outgoing.done
              .then((_) {
                response.deadline = null;
                if (_state == _DETACHED) return;
                if (response.persistentConnection &&
                    request.persistentConnection &&
                    incoming.fullBodyRead &&
                    !_httpParser.upgrade &&
                    !_httpServer.closed) {
                  _state = _IDLE;
                  _idleMark = false;
                  _httpServer._markIdle(this);
                  // Resume the subscription for incoming requests as the
                  // request is now processed.
                  _subscription.resume();
                } else {
                  // Close socket, keep-alive not used or body sent before
                  // received data was handled.
                  destroy();
                }
              }, onError: (_) {
                destroy();
              });
          outgoing.ignoreBody = request.method == "HEAD";
          response._httpRequest = request;
          _httpServer._handleRequest(request);
        },
        onDone: () {
          destroy();
        },
        onError: (error) {
          // Ignore failed requests that was closed before headers was received.
          destroy();
        });
  }

  void markIdle() {
    _idleMark = true;
  }

  bool get isMarkedIdle => _idleMark;

  void destroy() {
    if (_state == _CLOSING || _state == _DETACHED) return;
    _state = _CLOSING;
    _socket.destroy();
    _httpServer._connectionClosed(this);
    _connections.remove(_serviceId);
  }

  Future<Socket> detachSocket() {
    _state = _DETACHED;
    // Remove connection from server.
    _httpServer._connectionClosed(this);

    _HttpDetachedIncoming detachedIncoming = _httpParser.detachIncoming();

    return _streamFuture.then((_) {
      _connections.remove(_serviceId);
      return new _DetachedSocket(_socket, detachedIncoming);
    });
  }

  HttpConnectionInfo get connectionInfo => _HttpConnectionInfo.create(_socket);

  bool get _isActive => _state == _ACTIVE;
  bool get _isIdle => _state == _IDLE;
  bool get _isClosing => _state == _CLOSING;
  bool get _isDetached => _state == _DETACHED;

  String get _serviceTypePath => 'io/http/serverconnections';
  String get _serviceTypeName => 'HttpServerConnection';

  Map _toJSON(bool ref) {
    var name = "${_socket.address.host}:${_socket.port} <-> "
        "${_socket.remoteAddress.host}:${_socket.remotePort}";
    var r = <String, dynamic>{
      'id': _servicePath,
      'type': _serviceType(ref),
      'name': name,
      'user_name': name,
    };
    if (ref) {
      return r;
    }
    r['server'] = _httpServer._toJSON(true);
    try {
      r['socket'] = _socket._toJSON(true);
    } catch (_) {
      r['socket'] = {
        'id': _servicePath,
        'type': '@Socket',
        'name': 'UserSocket',
        'user_name': 'UserSocket',
      };
    }
    switch (_state) {
      case _ACTIVE: r['state'] = "Active"; break;
      case _IDLE: r['state'] = "Idle"; break;
      case _CLOSING: r['state'] = "Closing"; break;
      case _DETACHED: r['state'] = "Detached"; break;
      default: r['state'] = 'Unknown'; break;
    }
    return r;
  }
}


// HTTP server waiting for socket connections.
class _HttpServer
    extends Stream<HttpRequest> with _ServiceObject
    implements HttpServer {
  // Use default Map so we keep order.
  static Map<int, _HttpServer> _servers = new Map<int, _HttpServer>();

  String serverHeader;
  final HttpHeaders defaultResponseHeaders = _initDefaultResponseHeaders();
  bool autoCompress = false;

  Duration _idleTimeout;
  Timer _idleTimer;

  static Future<HttpServer> bind(
      address, int port, int backlog, bool v6Only, bool shared) {
    return ServerSocket.bind(
        address, port, backlog: backlog, v6Only: v6Only, shared: shared)
            .then((socket) {
              return new _HttpServer._(socket, true);
            });
  }

  static Future<HttpServer> bindSecure(address,
                                       int port,
                                       SecurityContext context,
                                       int backlog,
                                       bool v6Only,
                                       bool requestClientCertificate,
                                       bool shared) {
    return SecureServerSocket.bind(
        address,
        port,
        context,
        backlog: backlog,
        v6Only: v6Only,
        requestClientCertificate: requestClientCertificate,
        shared: shared)
            .then((socket) {
              return new _HttpServer._(socket, true);
            });
  }

  _HttpServer._(this._serverSocket, this._closeServer) {
    _controller = new StreamController<HttpRequest>(sync: true,
                                                    onCancel: close);
    idleTimeout = const Duration(seconds: 120);
    _servers[_serviceId] = this;
    _serverSocket._owner = this;
  }

  _HttpServer.listenOn(this._serverSocket) : _closeServer = false {
    _controller = new StreamController<HttpRequest>(sync: true,
                                                    onCancel: close);
    idleTimeout = const Duration(seconds: 120);
    _servers[_serviceId] = this;
    try { _serverSocket._owner = this; } catch (_) {}
  }

  static HttpHeaders _initDefaultResponseHeaders() {
    var defaultResponseHeaders = new _HttpHeaders('1.1');
    defaultResponseHeaders.contentType = ContentType.TEXT;
    defaultResponseHeaders.set('X-Frame-Options', 'SAMEORIGIN');
    defaultResponseHeaders.set('X-Content-Type-Options', 'nosniff');
    defaultResponseHeaders.set('X-XSS-Protection', '1; mode=block');
    return defaultResponseHeaders;
  }

  Duration get idleTimeout => _idleTimeout;

  void set idleTimeout(Duration duration) {
    if (_idleTimer != null) {
      _idleTimer.cancel();
      _idleTimer = null;
    }
    _idleTimeout = duration;
    if (_idleTimeout != null) {
      _idleTimer = new Timer.periodic(_idleTimeout, (_) {
        for (var idle in _idleConnections.toList()) {
          if (idle.isMarkedIdle) {
            idle.destroy();
          } else {
            idle.markIdle();
          }
        }
      });
    }
  }

  StreamSubscription<HttpRequest> listen(void onData(HttpRequest event),
                                         {Function onError,
                                         void onDone(),
                                         bool cancelOnError}) {
    _serverSocket.listen(
        (Socket socket) {
          socket.setOption(SocketOption.TCP_NODELAY, true);
          // Accept the client connection.
          _HttpConnection connection = new _HttpConnection(socket, this);
          _idleConnections.add(connection);
        },
        onError: (error, stackTrace) {
          // Ignore HandshakeExceptions as they are bound to a single request,
          // and are not fatal for the server.
          if (error is! HandshakeException) {
            _controller.addError(error, stackTrace);
          }
        },
        onDone: _controller.close);
    return _controller.stream.listen(onData,
                                     onError: onError,
                                     onDone: onDone,
                                     cancelOnError: cancelOnError);
  }

  Future close({bool force: false}) {
    closed = true;
    Future result;
    if (_serverSocket != null && _closeServer) {
      result = _serverSocket.close();
    } else {
      result = new Future.value();
    }
    idleTimeout = null;
    if (force) {
      for (var c in _activeConnections.toList()) {
        c.destroy();
      }
      assert(_activeConnections.isEmpty);
    }
    for (var c in _idleConnections.toList()) {
      c.destroy();
    }
    _maybePerformCleanup();
    return result;
  }

  void _maybePerformCleanup() {
    if (closed &&
        _idleConnections.isEmpty &&
        _activeConnections.isEmpty &&
        _sessionManagerInstance != null) {
      _sessionManagerInstance.close();
      _sessionManagerInstance = null;
      _servers.remove(_serviceId);
    }
  }

  int get port {
    if (closed) throw new HttpException("HttpServer is not bound to a socket");
    return _serverSocket.port;
  }

  InternetAddress get address {
    if (closed) throw new HttpException("HttpServer is not bound to a socket");
    return _serverSocket.address;
  }

  set sessionTimeout(int timeout) {
    _sessionManager.sessionTimeout = timeout;
  }

  void _handleRequest(_HttpRequest request) {
    if (!closed) {
      _controller.add(request);
    } else {
      request._httpConnection.destroy();
    }
  }

  void _connectionClosed(_HttpConnection connection) {
    // Remove itself from either idle or active connections.
    connection.unlink();
    _maybePerformCleanup();
  }

  void _markIdle(_HttpConnection connection) {
    _activeConnections.remove(connection);
    _idleConnections.add(connection);
  }

  void _markActive(_HttpConnection connection) {
    _idleConnections.remove(connection);
    _activeConnections.add(connection);
  }

  _HttpSessionManager get _sessionManager {
    // Lazy init.
    if (_sessionManagerInstance == null) {
      _sessionManagerInstance = new _HttpSessionManager();
    }
    return _sessionManagerInstance;
  }

  HttpConnectionsInfo connectionsInfo() {
    HttpConnectionsInfo result = new HttpConnectionsInfo();
    result.total = _activeConnections.length + _idleConnections.length;
    _activeConnections.forEach((_HttpConnection conn) {
      if (conn._isActive) {
        result.active++;
      } else {
        assert(conn._isClosing);
        result.closing++;
      }
    });
    _idleConnections.forEach((_HttpConnection conn) {
      result.idle++;
      assert(conn._isIdle);
    });
    return result;
  }

  String get _serviceTypePath => 'io/http/servers';
  String get _serviceTypeName => 'HttpServer';

  Map<String, dynamic> _toJSON(bool ref) {
    var r = <String, dynamic>{
      'id': _servicePath,
      'type': _serviceType(ref),
      'name': '${address.host}:$port',
      'user_name': '${address.host}:$port',
    };
    if (ref) {
      return r;
    }
    try {
      r['socket'] = _serverSocket._toJSON(true);
    } catch (_) {
      r['socket'] = {
        'id': _servicePath,
        'type': '@Socket',
        'name': 'UserSocket',
        'user_name': 'UserSocket',
      };
    }
    r['port'] = port;
    r['address'] = address.host;
    r['active'] = _activeConnections.map((c) => c._toJSON(true)).toList();
    r['idle'] = _idleConnections.map((c) => c._toJSON(true)).toList();
    r['closed'] = closed;
    return r;
  }

  _HttpSessionManager _sessionManagerInstance;

  // Indicated if the http server has been closed.
  bool closed = false;

  // The server listen socket. Untyped as it can be both ServerSocket and
  // SecureServerSocket.
  final _serverSocket;
  final bool _closeServer;

  // Set of currently connected clients.
  final LinkedList<_HttpConnection> _activeConnections
      = new LinkedList<_HttpConnection>();
  final LinkedList<_HttpConnection> _idleConnections
      = new LinkedList<_HttpConnection>();
  StreamController<HttpRequest> _controller;
}


class _ProxyConfiguration {
  static const String PROXY_PREFIX = "PROXY ";
  static const String DIRECT_PREFIX = "DIRECT";

  _ProxyConfiguration(String configuration) : proxies = new List<_Proxy>() {
    if (configuration == null) {
      throw new HttpException("Invalid proxy configuration $configuration");
    }
    List<String> list = configuration.split(";");
    list.forEach((String proxy) {
      proxy = proxy.trim();
      if (!proxy.isEmpty) {
        if (proxy.startsWith(PROXY_PREFIX)) {
          String username;
          String password;
          // Skip the "PROXY " prefix.
          proxy = proxy.substring(PROXY_PREFIX.length).trim();
          // Look for proxy authentication.
          int at = proxy.indexOf("@");
          if (at != -1) {
            String userinfo = proxy.substring(0, at).trim();
            proxy = proxy.substring(at + 1).trim();
            int colon = userinfo.indexOf(":");
            if (colon == -1 || colon == 0 || colon == proxy.length - 1) {
              throw new HttpException(
                  "Invalid proxy configuration $configuration");
            }
            username = userinfo.substring(0, colon).trim();
            password = userinfo.substring(colon + 1).trim();
          }
          // Look for proxy host and port.
          int colon = proxy.lastIndexOf(":");
          if (colon == -1 || colon == 0 || colon == proxy.length - 1) {
            throw new HttpException(
                "Invalid proxy configuration $configuration");
          }
          String host = proxy.substring(0, colon).trim();
          if (host.startsWith("[") && host.endsWith("]")) {
            host = host.substring(1, host.length - 1);
          }
          String portString = proxy.substring(colon + 1).trim();
          int port;
          try {
            port = int.parse(portString);
          } on FormatException catch (e) {
            throw new HttpException(
                "Invalid proxy configuration $configuration, "
                "invalid port '$portString'");
          }
          proxies.add(new _Proxy(host, port, username, password));
        } else if (proxy.trim() == DIRECT_PREFIX) {
          proxies.add(new _Proxy.direct());
        } else {
          throw new HttpException("Invalid proxy configuration $configuration");
        }
      }
    });
  }

  const _ProxyConfiguration.direct()
      : proxies = const [const _Proxy.direct()];

  final List<_Proxy> proxies;
}


class _Proxy {
  final String host;
  final int port;
  final String username;
  final String password;
  final bool isDirect;

  const _Proxy(this.host, this.port, this.username, this.password)
      : isDirect = false;
  const _Proxy.direct() : host = null, port = null,
                          username = null, password = null, isDirect = true;

  bool get isAuthenticated => username != null;
}


class _HttpConnectionInfo implements HttpConnectionInfo {
  InternetAddress remoteAddress;
  int remotePort;
  int localPort;

  static _HttpConnectionInfo create(Socket socket) {
    if (socket == null) return null;
    try {
      _HttpConnectionInfo info = new _HttpConnectionInfo();
      return info
          ..remoteAddress = socket.remoteAddress
          ..remotePort = socket.remotePort
          ..localPort = socket.port;
    } catch (e) { }
    return null;
  }
}


class _DetachedSocket extends Stream<List<int>> implements Socket {
  final Stream<List<int>> _incoming;
  final _socket;

  _DetachedSocket(this._socket, this._incoming);

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

  Encoding get encoding => _socket.encoding;

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

  void write(Object obj) { _socket.write(obj); }

  void writeln([Object obj = ""]) { _socket.writeln(obj); }

  void writeCharCode(int charCode) { _socket.writeCharCode(charCode); }

  void writeAll(Iterable objects, [String separator = ""]) {
    _socket.writeAll(objects, separator);
  }

  void add(List<int> bytes) { _socket.add(bytes); }

  void addError(error, [StackTrace stackTrace]) =>
      _socket.addError(error, stackTrace);

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

  void destroy() { _socket.destroy(); }

  Future flush() => _socket.flush();

  Future close() => _socket.close();

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

  int get port => _socket.port;

  InternetAddress get address => _socket.address;

  InternetAddress get remoteAddress => _socket.remoteAddress;

  int get remotePort => _socket.remotePort;

  bool setOption(SocketOption option, bool enabled) {
    return _socket.setOption(option, enabled);
  }

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


class _AuthenticationScheme {
  final int _scheme;

  static const UNKNOWN = const _AuthenticationScheme(-1);
  static const BASIC = const _AuthenticationScheme(0);
  static const DIGEST = const _AuthenticationScheme(1);

  const _AuthenticationScheme(this._scheme);

  factory _AuthenticationScheme.fromString(String scheme) {
    if (scheme.toLowerCase() == "basic") return BASIC;
    if (scheme.toLowerCase() == "digest") return DIGEST;
    return UNKNOWN;
  }

  String toString() {
    if (this == BASIC) return "Basic";
    if (this == DIGEST) return "Digest";
    return "Unknown";
  }
}


abstract class _Credentials {
  _HttpClientCredentials credentials;
  String realm;
  bool used = false;

  // Digest specific fields.
  String ha1;
  String nonce;
  String algorithm;
  String qop;
  int nonceCount;

  _Credentials(this.credentials, this.realm) {
    if (credentials.scheme == _AuthenticationScheme.DIGEST) {
      // Calculate the H(A1) value once. There is no mentioning of
      // username/password encoding in RFC 2617. However there is an
      // open draft for adding an additional accept-charset parameter to
      // the WWW-Authenticate and Proxy-Authenticate headers, see
      // http://tools.ietf.org/html/draft-reschke-basicauth-enc-06. For
      // now always use UTF-8 encoding.
      _HttpClientDigestCredentials creds = credentials;
      var hasher = new _MD5()
          ..add(UTF8.encode(creds.username))
          ..add([_CharCode.COLON])
          ..add(realm.codeUnits)
          ..add([_CharCode.COLON])
          ..add(UTF8.encode(creds.password));
      ha1 = _CryptoUtils.bytesToHex(hasher.close());
    }
  }

  _AuthenticationScheme get scheme => credentials.scheme;

  void authorize(HttpClientRequest request);
}

class _SiteCredentials extends _Credentials {
  Uri uri;

  _SiteCredentials(this.uri, realm, _HttpClientCredentials creds)
      : super(creds, realm);

  bool applies(Uri uri, _AuthenticationScheme scheme) {
    if (scheme != null && credentials.scheme != scheme) return false;
    if (uri.host != this.uri.host) return false;
    int thisPort =
        this.uri.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : this.uri.port;
    int otherPort = uri.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : uri.port;
    if (otherPort != thisPort) return false;
    return uri.path.startsWith(this.uri.path);
  }

  void authorize(HttpClientRequest request) {
    // Digest credentials cannot be used without a nonce from the
    // server.
    if (credentials.scheme == _AuthenticationScheme.DIGEST &&
        nonce == null) {
      return;
    }
    credentials.authorize(this, request);
    used = true;
  }
}


class _ProxyCredentials extends _Credentials {
  String host;
  int port;

  _ProxyCredentials(this.host,
                    this.port,
                    realm,
                    _HttpClientCredentials creds)
      : super(creds, realm);

  bool applies(_Proxy proxy, _AuthenticationScheme scheme) {
    if (scheme != null && credentials.scheme != scheme) return false;
    return proxy.host == host && proxy.port == port;
  }

  void authorize(HttpClientRequest request) {
    // Digest credentials cannot be used without a nonce from the
    // server.
    if (credentials.scheme == _AuthenticationScheme.DIGEST &&
        nonce == null) {
      return;
    }
    credentials.authorizeProxy(this, request);
  }
}


abstract class _HttpClientCredentials implements HttpClientCredentials {
  _AuthenticationScheme get scheme;
  void authorize(_Credentials credentials, HttpClientRequest request);
  void authorizeProxy(_ProxyCredentials credentials, HttpClientRequest request);
}


class _HttpClientBasicCredentials
    extends _HttpClientCredentials
    implements HttpClientBasicCredentials {
  String username;
  String password;

  _HttpClientBasicCredentials(this.username, this.password);

  _AuthenticationScheme get scheme => _AuthenticationScheme.BASIC;

  String authorization() {
    // There is no mentioning of username/password encoding in RFC
    // 2617. However there is an open draft for adding an additional
    // accept-charset parameter to the WWW-Authenticate and
    // Proxy-Authenticate headers, see
    // http://tools.ietf.org/html/draft-reschke-basicauth-enc-06. For
    // now always use UTF-8 encoding.
    String auth =
        _CryptoUtils.bytesToBase64(UTF8.encode("$username:$password"));
    return "Basic $auth";
  }

  void authorize(_Credentials _, HttpClientRequest request) {
    request.headers.set(HttpHeaders.AUTHORIZATION, authorization());
  }

  void authorizeProxy(_ProxyCredentials _, HttpClientRequest request) {
    request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, authorization());
  }
}


class _HttpClientDigestCredentials
    extends _HttpClientCredentials
    implements HttpClientDigestCredentials {
  String username;
  String password;

  _HttpClientDigestCredentials(this.username, this.password);

  _AuthenticationScheme get scheme => _AuthenticationScheme.DIGEST;

  String authorization(_Credentials credentials, _HttpClientRequest request) {
    String requestUri = request._requestUri();
    _MD5 hasher = new _MD5()
        ..add(request.method.codeUnits)
        ..add([_CharCode.COLON])
        ..add(requestUri.codeUnits);
    var ha2 = _CryptoUtils.bytesToHex(hasher.close());

    String qop;
    String cnonce;
    String nc;
    var x;
    hasher = new _MD5()
        ..add(credentials.ha1.codeUnits)
        ..add([_CharCode.COLON]);
    if (credentials.qop == "auth") {
      qop = credentials.qop;
      cnonce = _CryptoUtils.bytesToHex(_IOCrypto.getRandomBytes(4));
      ++credentials.nonceCount;
      nc = credentials.nonceCount.toRadixString(16);
      nc = "00000000".substring(0, 8 - nc.length + 1) + nc;
      hasher
          ..add(credentials.nonce.codeUnits)
          ..add([_CharCode.COLON])
          ..add(nc.codeUnits)
          ..add([_CharCode.COLON])
          ..add(cnonce.codeUnits)
          ..add([_CharCode.COLON])
          ..add(credentials.qop.codeUnits)
          ..add([_CharCode.COLON])
          ..add(ha2.codeUnits);
    } else {
      hasher
          ..add(credentials.nonce.codeUnits)
          ..add([_CharCode.COLON])
          ..add(ha2.codeUnits);
    }
    var response = _CryptoUtils.bytesToHex(hasher.close());

    StringBuffer buffer = new StringBuffer()
        ..write('Digest ')
        ..write('username="$username"')
        ..write(', realm="${credentials.realm}"')
        ..write(', nonce="${credentials.nonce}"')
        ..write(', uri="$requestUri"')
        ..write(', algorithm="${credentials.algorithm}"');
    if (qop == "auth") {
      buffer
          ..write(', qop="$qop"')
          ..write(', cnonce="$cnonce"')
          ..write(', nc="$nc"');
    }
    buffer.write(', response="$response"');
    return buffer.toString();
  }

  void authorize(_Credentials credentials, HttpClientRequest request) {
    request.headers.set(HttpHeaders.AUTHORIZATION,
                        authorization(credentials, request));
  }

  void authorizeProxy(_ProxyCredentials credentials,
                      HttpClientRequest request) {
    request.headers.set(HttpHeaders.PROXY_AUTHORIZATION,
                        authorization(credentials, request));
  }
}


class _RedirectInfo implements RedirectInfo {
  final int statusCode;
  final String method;
  final Uri location;
  const _RedirectInfo(this.statusCode, this.method, this.location);
}

String _getHttpVersion() {
  var version = Platform.version;
  // Only include major and minor version numbers.
  int index = version.indexOf('.', version.indexOf('.') + 1);
  version = version.substring(0, index);
  return 'Dart/$version (dart:io)';
}
