@@ -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,
@@ -350,11 +351,15 @@ proc new*(
350351 _: type QuicTransport ,
351352 u: Upgrade ,
352353 privateKey: PrivateKey ,
354+ rng: Rng ,
353355 connManager: ConnManager = nil ,
354356): QuicTransport =
357+ doAssert not rng.isNil, " Rng is nil"
358+
355359 let self = QuicTransport (
356360 upgrader: QuicUpgrade (ms: u.ms, connManager: connManager.toOpt ()),
357361 privateKey: privateKey,
362+ rng: rng,
358363 certGenerator: defaultCertGenerator,
359364 )
360365 procCall Transport (self).initialize ()
@@ -364,12 +369,16 @@ proc new*(
364369 _: type QuicTransport ,
365370 u: Upgrade ,
366371 privateKey: PrivateKey ,
372+ rng: Rng ,
367373 certGenerator: CertGenerator ,
368374 connManager: ConnManager = nil ,
369375): QuicTransport =
376+ doAssert not rng.isNil, " Rng is nil"
377+
370378 let self = QuicTransport (
371379 upgrader: QuicUpgrade (ms: u.ms, connManager: connManager.toOpt ()),
372380 privateKey: privateKey,
381+ rng: rng,
373382 certGenerator: certGenerator,
374383 )
375384 procCall Transport (self).initialize ()
@@ -576,6 +585,7 @@ method dial*(
576585 hostname: string ,
577586 address: MultiAddress ,
578587 peerId: Opt [PeerId ] = Opt .none (PeerId ),
588+ dir: Direction = Direction .Out ,
579589): Future [RawConn ] {.async : (raises: [transport.TransportError , CancelledError ]).} =
580590 let taAddress =
581591 try :
@@ -586,6 +596,23 @@ method dial*(
586596 )
587597
588598 try :
599+ if dir == Direction .In :
600+ let endpoint = self.listenerEndpointFor (taAddress)
601+ if endpoint.isNone ():
602+ raise newException (
603+ QuicTransportDialError ,
604+ " error in QUIC hole punch: no unique listener for address family" ,
605+ )
606+
607+ # The Sync sender is the QUIC server. Open its NAT mapping with random
608+ # UDP packets from the listener socket and let the expected inbound
609+ # connection complete the DCUtR attempt.
610+ while true :
611+ let payload = self.rng.generateBytes (64 )
612+ await endpoint.get ().datagramTransport ().sendTo (taAddress, payload)
613+ let delay = 10 + int (self.rng.generate (uint32 ) mod 191 'u32 )
614+ await sleepAsync (delay.milliseconds)
615+
589616 let endpoint = self.dialEndpointFor (taAddress)
590617 let quicConnection = await endpoint.dial (taAddress)
591618 peerId.withValue (expectedPeerId):
@@ -606,6 +633,8 @@ method dial*(
606633 )
607634 except TransportOsError as e:
608635 raise newException (QuicTransportDialError , " error in quic dial:" & e.msg, e)
636+ except chronos.TransportError as e:
637+ raise newException (QuicTransportDialError , " error in quic dial: " & e.msg, e)
609638 except DialError as e:
610639 raise newException (QuicTransportDialError , " error in quic dial:" & e.msg, e)
611640 except QuicError as e:
0 commit comments