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
final request = _createDialRequest(requests, nonce);
await stream.write(request.writeToBuffer());
// Read the response
Message response;
try {
final responseData = await stream.read();
response = Message.fromBuffer(responseData);
} catch (e) {
stream.reset();
throw Exception('Dial message read failed: $e');
}
// Handle the response
if (response.hasDialResponse()) {
// Process the dial response
return _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
try {
final responseData = await stream.read();
response = Message.fromBuffer(responseData);
} 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 _processDialResponse(response.dialResponse, requests, completer);
} else {
stream.reset();
throw Exception('Invalid message type: ${response.whichMsg()}');
}
} finally {
_dialBackQueues.remove(nonce);
stream.close();
}
}