dial method
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);
}