negotiate method
Negotiate will return the registered protocol handler to use for a given inbound stream, returning after the protocol has been determined and the Negotiator has finished using the stream for negotiation. Returns an error if negotiation fails.
Implementation
@override
Future<(ProtocolID, HandlerFunc)> negotiate(P2PStream<dynamic> stream) async {
try {
// 1. Read the initiator's multistream protocol ID
_log.fine("[multistreamMuxer - negotiate] Waiting to read initiator's protocol ID.");
final initiatorProtoID = await _readNextToken(stream);
_log.fine("[multistreamMuxer - negotiate] Read initiator's protocol ID: $initiatorProtoID");
if (initiatorProtoID != protocolID) {
_log.warning("[multistreamMuxer - negotiate] Initiator sent wrong protocol ID: $initiatorProtoID. Expected: $protocolID");
await stream.reset();
throw IncorrectVersionException('Initiator sent wrong protocol ID: $initiatorProtoID');
}
// 2. Send our multistream protocol ID back
_log.fine("[multistreamMuxer - negotiate] Sending our protocol ID: $protocolID");
await _writeDelimited(stream, utf8.encode(protocolID));
_log.fine("[multistreamMuxer - negotiate] Sent our protocol ID.");
// Now proceed with protocol selection
while (true) {
_log.fine('[multistreamMuxer - negotiate] Waiting to read next protocol offer from initiator.');
final tok = await _readNextToken(stream);
_log.fine('[multistreamMuxer - negotiate] Received protocol offer from initiator: "$tok"');
// Find a handler for this protocol
_log.fine('[multistreamMuxer - negotiate] Finding handler for token: "$tok"');
final h = await _findHandler(tok);
if (h == null) {
// No handler found, send "na" (not available)
_log.warning('[multistreamMuxer - negotiate] No handler for "$tok". Sending "na".');
await _writeDelimited(stream, utf8.encode('na'));
_log.fine('[multistreamMuxer - negotiate] Sent "na" for "$tok". Continuing loop.');
continue;
}
// Handler found, send the protocol name back
_log.fine('[multistreamMuxer - negotiate] Handler found for "$tok". Sending acknowledgment: "$tok".');
await _writeDelimited(stream, utf8.encode(tok));
_log.fine('[multistreamMuxer - negotiate] Sent acknowledgment for "$tok".');
// Return the protocol and handler
_log.fine('[multistreamMuxer - negotiate] Returning protocol "$tok" and its handler.');
return (tok, h.handle);
}
} catch (e) {
_log.severe('[multistreamMuxer - negotiate] Error during negotiation: $e');
await stream.reset();
rethrow;
}
}