connect method

  1. @override
Future<SshHandshakeInfo> connect({
  1. required SshEndpoint endpoint,
  2. required SshTransportSettings settings,
})
override

Implementation

@override
Future<SshHandshakeInfo> connect({
  required SshEndpoint endpoint,
  required SshTransportSettings settings,
}) async {
  if (_state == SshTransportState.connecting ||
      _state == SshTransportState.connected) {
    throw StateError('SSH socket transport is already connected.');
  }

  _state = SshTransportState.connecting;
  Socket? socket;
  SshTransportStream? transportStream;

  try {
    socket = await Socket.connect(
      endpoint.host,
      endpoint.port,
      timeout: settings.connectTimeout,
    );

    if (tcpNoDelay) {
      socket.setOption(SocketOption.tcpNoDelay, true);
    }

    transportStream = SshTransportStream(
      incoming: socket,
      onWrite: (List<int> bytes) {
        socket!.add(bytes);
        return socket.flush();
      },
      onClose: () async {
        await socket!.close();
        socket.destroy();
      },
      bannerExchange: bannerExchange,
      packetCodec: packetCodec,
    );

    final SshBannerExchangeResult exchange =
        await transportStream.exchangeBanners(
      localIdentification: settings.clientIdentification,
    );

    final SshHandshakeInfo handshake = SshHandshakeInfo.fromBannerExchange(
      exchange,
    );

    _socket = socket;
    _transportStream = transportStream;
    _handshake = handshake;
    _state = SshTransportState.connected;

    return handshake;
  } catch (_) {
    _handshake = null;
    _transportStream = null;
    _socket = null;
    _state = SshTransportState.disconnected;

    if (transportStream != null) {
      await transportStream.close();
    } else if (socket != null) {
      await socket.close();
      socket.destroy();
    }

    rethrow;
  }
}