selectOneOf method
Selects one of the given protocols with the remote peer.
This method implements the initiator side of the multistream-select protocol.
It will try each protocol in protocolsToSelect
in order until the remote
peer acknowledges one or indicates it does not support any of them.
Returns the selected ProtocolID or null
if no protocol could be agreed upon.
Implementation
Future<ProtocolID?> selectOneOf(P2PStream<dynamic> stream, List<ProtocolID> protocolsToSelect) async {
final startTime = DateTime.now();
final streamId = stream.id();
// Safely get peer ID - during negotiation, conn might not be available
String peerInfo;
try {
peerInfo = stream.conn.remotePeer.toString();
} catch (e) {
peerInfo = 'unknown_peer';
}
try {
// 1. Send our multistream protocol ID
await _writeDelimited(stream, utf8.encode(protocolID));
// 2. Read their multistream protocol ID
final remoteProtoID = await _readNextToken(stream);
if (remoteProtoID != protocolID) {
await stream.reset();
throw IncorrectVersionException(
'Remote peer responded with wrong multistream version: $remoteProtoID, expected $protocolID');
}
// 3. Iterate through the protocols we want to select
for (int i = 0; i < protocolsToSelect.length; i++) {
final p = protocolsToSelect[i];
final protocolStart = DateTime.now();
await _writeDelimited(stream, utf8.encode(p));
final response = await _readNextToken(stream);
if (response == p) {
// Protocol selected
final totalDuration = DateTime.now().difference(startTime);
return p;
} else if (response == 'na') {
// Protocol not available, try next
continue;
} else {
// Unexpected response
await stream.reset();
throw IncorrectVersionException(
'Remote peer sent unexpected response: "$response" when trying to negotiate protocol "$p"');
}
}
// No protocol was selected
final totalDuration = DateTime.now().difference(startTime);
await stream.reset(); // Ensure stream is reset if no protocol is selected
return null;
} catch (e, st) {
final totalDuration = DateTime.now().difference(startTime);
await stream.reset();
rethrow;
}
}