startConnect static method
- dynamic host,
- int port, {
- SecurityContext? context,
- bool onBadCertificate(
- X509Certificate certificate
- void keyLog()?,
- List<
String> ? supportedProtocols,
override
Like connect, but returns a Future that completes with a ConnectionTask that can be cancelled if the RawSecureSocket is no longer needed.
Implementation
static Future<ConnectionTask<RawSecureSocket>> startConnect(
host,
int port, {
SecurityContext? context,
bool Function(X509Certificate certificate)? onBadCertificate,
void Function(String line)? keyLog,
List<String>? supportedProtocols,
}) async {
final tcpTask = await RawSocket.startConnect(host, port);
final result = Completer<RawSecureSocket>();
var cancelled = false;
RawSocket? connected;
SocketException cancelledException() => SocketException(
"Connection attempt cancelled, host: $host, port: $port",
);
Future<void> connectAndSecure() async {
try {
final socket = await tcpTask.socket;
if (cancelled) {
socket.close();
throw cancelledException();
}
connected = socket;
final secureSocket = await secure(
socket,
context: context,
onBadCertificate: onBadCertificate,
keyLog: keyLog,
supportedProtocols: supportedProtocols,
);
if (result.isCompleted) {
secureSocket.close();
} else {
result.complete(secureSocket);
}
} catch (error, stackTrace) {
if (!result.isCompleted) result.completeError(error, stackTrace);
}
}
void cancel() {
cancelled = true;
tcpTask.cancel();
// Once TCP has connected, cancelling the connect does nothing, so close
// the socket too; otherwise a stalled handshake leaks it. Closing the
// socket does not complete the handshake, so complete the result here.
// After the handshake has completed, cancel does nothing.
final socket = connected;
if (socket != null && !result.isCompleted) {
socket.close();
result.completeError(cancelledException(), StackTrace.current);
}
}
unawaited(connectAndSecure());
return ConnectionTask<RawSecureSocket>._(result.future, cancel);
}