Future connect()

in lib/src/http_impl.dart [1844:1909]


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

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

    Future<ConnectionTask> connectionTask = (isSecure && proxy.isDirect
        ? SecureSocket.startConnect(host, port,
            context: context, onBadCertificate: callback)
        : Socket.startConnect(host, port));
    _connecting++;
    return connectionTask.then((ConnectionTask task) {
      _socketTasks.add(task);
      Future socketFuture = task.socket;
      if (client.connectionTimeout != null) {
        socketFuture =
            socketFuture.timeout(client.connectionTimeout, onTimeout: () {
          _socketTasks.remove(task);
          task.cancel();
        });
      }
      return socketFuture.then((socket) {
        _connecting--;
        socket.setOption(SocketOption.tcpNoDelay, true);
        var connection =
            _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);
            _socketTasks.remove(task);
            return _ConnectionInfo(tunnel, proxy);
          });
        } else {
          addNewActive(connection);
          _socketTasks.remove(task);
          return _ConnectionInfo(connection, proxy);
        }
      }, onError: (error) {
        _connecting--;
        _socketTasks.remove(task);
        _checkPending();
        throw error;
      });
    });
  }