negotiate method

  1. @override
Future<(ProtocolID, HandlerFunc)> negotiate(
  1. P2PStream stream
)
override

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;
  }
}