dialBack method
Requests a peer providing AutoNAT services to test dial back and report the address on a successful connection.
Implementation
@override
Future<void> dialBack(PeerId peer) async {
P2PStream? stream;
try {
final ctx = Context(timeout: _requestTimeout); // Use the configured request timeout
stream = await _host.newStream(peer, [autoNATV1Proto], ctx);
await stream.scope().setService(serviceName);
await stream.scope().reserveMemory(_autoNATClientMaxMessageScopeReservation, ReservationPriority.always);
// Determine the effective deadline: earlier of context timeout and stream I/O timeout
final now = DateTime.now();
final contextAbsoluteDeadline = now.add(_requestTimeout);
final streamIoAbsoluteDeadline = now.add(streamTimeout); // streamTimeout is the 60s constant
final effectiveDeadline = contextAbsoluteDeadline.isBefore(streamIoAbsoluteDeadline)
? contextAbsoluteDeadline
: streamIoAbsoluteDeadline;
await stream.setDeadline(effectiveDeadline);
final localPeerInfo = AddrInfo(_host.id, _addrFunc()); // Used _host.id
final req = _newDialMessage(localPeerInfo);
await writeDelimited(stream, req); // Pass stream directly, and await
// Read the response using the delimited reader
final res = await readDelimited(stream, pb.Message.fromBuffer); // Pass stream directly
if (res.type != pb.Message_MessageType.DIAL_RESPONSE) {
throw Exception('Unexpected response: ${res.type}');
}
final status = res.dialResponse.status;
_metricsTracer?.receivedDialResponse(status);
switch (status) {
case pb.Message_ResponseStatus.OK:
return;
default:
throw AutoNATError(status, res.dialResponse.statusText);
}
} catch (e) {
// In Go, s.Reset() is called in several error paths.
// In Dart, closing the stream or letting it be garbage collected is typical.
// If specific reset logic is needed, it would be part of P2PStream.
rethrow;
} finally {
if (stream != null) {
stream.scope().releaseMemory(_autoNATClientMaxMessageScopeReservation);
await stream.close();
}
}
}