dial method

  1. @override
Future<TransportConn> dial(
  1. MultiAddr addr, {
  2. Duration? timeout,
})
override

Dials a peer at the given multiaddress with optional timeout override Returns a connection to the peer if successful

Implementation

@override
Future<TransportConn> dial(MultiAddr addr, {Duration? timeout}) async {
  _log.info('[CircuitV2Client.dial] 🔌 Starting circuit dial to $addr');

  // 1. Parse the /p2p-circuit address.
  final addrComponents = addr.components; // Use the components getter

  String? relayIdStr;
  String? destIdStr;

  int p2pIdx = -1;
  for (int i = 0; i < addrComponents.length; i++) {
    if (addrComponents[i].$1.code == Protocols.p2p.code) {
      p2pIdx = i;
      relayIdStr = addrComponents[i].$2;
      break;
    }
  }

  if (relayIdStr == null) {
    throw ArgumentError(
        'Dial address must contain a /p2p/relayId component: $addr');
  }
  final relayId = p2p_peer.PeerId.fromString(
      relayIdStr); // Use concrete PeerId.fromString

  bool connectToRelayAsDest = false;
  PeerId destId;

  int circuitIdx = -1;
  for (int i = p2pIdx + 1; i < addrComponents.length; i++) {
    if (addrComponents[i].$1.code == Protocols.circuit.code) {
      circuitIdx = i;
      break;
    }
  }

  if (circuitIdx == -1) {
    throw ArgumentError(
        'Dial address is not a circuit address (missing /p2p-circuit): $addr');
  }

  if (circuitIdx == addrComponents.length - 1) {
    // Ends with /p2p-circuit, so destination is the relay itself
    destId = relayId;
    connectToRelayAsDest = true;
    _log.fine('Dialing relay $relayId as destination via circuit');
  } else if (circuitIdx < addrComponents.length - 1 &&
      addrComponents[circuitIdx + 1].$1.code == Protocols.p2p.code) {
    // Has /p2p/destId after /p2p-circuit
    destIdStr = addrComponents[circuitIdx + 1].$2;
    destId = p2p_peer.PeerId.fromString(
        destIdStr); // Use concrete PeerId.fromString
    _log.fine('Dialing $destId via relay $relayId');
  } else {
    throw ArgumentError(
        'Invalid circuit address format after /p2p-circuit: $addr');
  }

  // 2. Create new relayed connection
  // NOTE: We do NOT cache connections here. The Swarm handles connection caching
  // at a higher level after upgrade completes. Caching unupgraded connections here
  // causes race conditions when multiple parallel dials return the same connection
  // and both try to upgrade it concurrently.
  return await _createNewRelayedConnection(
      addr, destId, relayId, connectToRelayAsDest);
}