@@ -5,6 +5,7 @@ import std/[hashes, sets, sequtils]
55import chronos, chronicles, metrics, results
66import lsquic
77import
8+ ../ crypto/ rng,
89 ../ wire,
910 ../ connmanager,
1011 ../ multiaddress,
@@ -25,6 +26,8 @@ export transport
2526logScope:
2627 topics = " libp2p quictransport"
2728
29+ const QuicHolePunchPacketSize * = 64
30+
2831type
2932 P2PConnection = connection.Connection
3033 QuicConnection = lsquic.Connection
@@ -353,11 +356,15 @@ proc new*(
353356 _: type QuicTransport ,
354357 u: Upgrade ,
355358 privateKey: PrivateKey ,
359+ rng: Rng ,
356360 connManager: ConnManager = nil ,
357361): QuicTransport =
362+ doAssert not rng.isNil, " Rng is nil"
363+
358364 let self = QuicTransport (
359365 upgrader: QuicUpgrade (ms: u.ms, connManager: connManager.toOpt ()),
360366 privateKey: privateKey,
367+ rng: rng,
361368 certGenerator: defaultCertGenerator,
362369 )
363370 procCall Transport (self).initialize ()
@@ -367,12 +374,16 @@ proc new*(
367374 _: type QuicTransport ,
368375 u: Upgrade ,
369376 privateKey: PrivateKey ,
377+ rng: Rng ,
370378 certGenerator: CertGenerator ,
371379 connManager: ConnManager = nil ,
372380): QuicTransport =
381+ doAssert not rng.isNil, " Rng is nil"
382+
373383 let self = QuicTransport (
374384 upgrader: QuicUpgrade (ms: u.ms, connManager: connManager.toOpt ()),
375385 privateKey: privateKey,
386+ rng: rng,
376387 certGenerator: certGenerator,
377388 )
378389 procCall Transport (self).initialize ()
@@ -583,6 +594,7 @@ method dial*(
583594 hostname: string ,
584595 address: MultiAddress ,
585596 peerId: Opt [PeerId ] = Opt .none (PeerId ),
597+ dir: Direction = Direction .Out ,
586598): Future [RawConn ] {.async : (raises: [transport.TransportError , CancelledError ]).} =
587599 let taAddress =
588600 try :
@@ -593,6 +605,23 @@ method dial*(
593605 )
594606
595607 try :
608+ if dir == Direction .In :
609+ let endpoint = self.listenerEndpointFor (taAddress)
610+ if endpoint.isNone ():
611+ raise newException (
612+ QuicTransportDialError ,
613+ " error in QUIC hole punch: no unique listener for address family" ,
614+ )
615+
616+ # The Sync sender is the QUIC server. Open its NAT mapping with random
617+ # UDP packets from the listener socket and let the expected inbound
618+ # connection complete the DCUtR attempt.
619+ while true :
620+ let payload = self.rng.generateBytes (QuicHolePunchPacketSize )
621+ await endpoint.get ().datagramTransport ().sendTo (taAddress, payload)
622+ let delay = self.rng.rand (10 , 200 )
623+ await sleepAsync (delay.milliseconds)
624+
596625 let endpoint = self.dialEndpointFor (taAddress)
597626 let quicConnection = await endpoint.dial (taAddress)
598627 peerId.withValue (expectedPeerId):
@@ -613,6 +642,8 @@ method dial*(
613642 )
614643 except TransportOsError as e:
615644 raise newException (QuicTransportDialError , " error in quic dial:" & e.msg, e)
645+ except chronos.TransportError as e:
646+ raise newException (QuicTransportDialError , " error in quic dial: " & e.msg, e)
616647 except DialError as e:
617648 raise newException (QuicTransportDialError , " error in quic dial:" & e.msg, e)
618649 except QuicError as e:
0 commit comments