getReachability method
Check reachability for the given addresses with a specific peer
Implementation
@override
Future<Result> getReachability(PeerId peerId, List<Request> requests) async {
// Create a stream to the peer
final context = Context();
final protocols = [AutoNATv2Protocols.dialProtocol];
final stream = await host.newStream(peerId, protocols, context);
try {
await stream.scope().setService(AutoNATv2Protocols.serviceName);
} catch (ex) {
stream.reset();
throw Exception(
'Failed to attach stream ${AutoNATv2Protocols.dialProtocol} to service ${AutoNATv2Protocols.serviceName}');
}
try {
await stream
.scope()
.reserveMemory(maxMsgSize, ReservationPriority.always);
// Reserve memory
} catch (ex) {
stream.reset();
throw Exception(
'Failed to reserve memory for stream ${AutoNATv2Protocols.dialProtocol}');
}
// Set deadline
stream.setDeadline(DateTime.now().add(streamTimeout));
// Generate a random nonce
final nonce = Random().nextInt(1 << 32);
// Create a completer for the dial-back
final completer = Completer<MultiAddr>();
_dialBackQueues[nonce] = completer;
try {
// Create and send the dial request (varint-length-prefixed)
final request = _createDialRequest(requests, nonce);
await writeDelimited(stream, request);
// Read the response (varint-length-prefixed)
Message response;
try {
response = await readDelimited(stream, Message.fromBuffer);
} catch (e) {
stream.reset();
throw Exception('Dial message read failed: $e');
}
// Handle the response
if (response.hasDialResponse()) {
// Process the dial response
return await _processDialResponse(
response.dialResponse, requests, completer);
} else if (response.hasDialDataRequest()) {
// Handle dial data request
try {
await _validateAndSendDialData(requests, response, stream);
} catch (e) {
stream.reset();
throw Exception('Invalid dial data request: $e');
}
// Read the dial response after sending dial data
// (varint-length-prefixed)
try {
response = await readDelimited(stream, Message.fromBuffer);
} catch (e) {
stream.reset();
throw Exception('Dial response read failed: $e');
}
if (!response.hasDialResponse()) {
stream.reset();
throw Exception('Invalid response type after dial data');
}
// Process the dial response
return await _processDialResponse(
response.dialResponse, requests, completer);
} else {
stream.reset();
throw Exception('Invalid message type: ${response.whichMsg()}');
}
} finally {
_dialBackQueues.remove(nonce);
stream.close();
}
}