libp2p-hs-0.1.0.0: Haskell implementation of the libp2p networking stack
Safe HaskellNone
LanguageGHC2021

LibP2P.NAT

Description

NAT traversal handler registration (specsautonat, specsrelay, specsrelayDCUtR).

Wires the AutoNAT, Circuit Relay v2, and DCUtR module implementations into the Switch protocol registry, in the style of registerIdentifyHandlers:

libp2pautonat/1.0.0 — AutoNAT dial-back server libp2pcircuitrelay0.2.0/hop — Circuit Relay v2 relay server libp2pcircuitrelay0.2.0/stop — Circuit Relay v2 target (inbound relayed streams) libp2pdcutr — DCUtR hole-punch coordination (handler side)

Synopsis

Configuration

data NATConfig Source #

Configuration for the NAT traversal handlers.

Constructors

NATConfig 

Fields

defaultNATConfig :: NATConfig Source #

Default NAT configuration: default relay limits and refresh tuning.

Registration

registerNATHandlers :: Switch -> NATConfig -> IO (RelayState, CircuitState) Source #

Register the NAT protocol handlers and the circuit client transport on the Switch.

Returns the relay server state (so callers can inspect reservations/circuits) and the circuit client state, which ties transportListen on a p2p-circuit address to the inbound stop streams that arrive over the connection to that relay.

registerAutoNATHandler :: Switch -> IO () Source #

Register the AutoNAT server handler (libp2pautonat/1.0.0).

The dial-back deliberately bypasses the connection pool: reusing the requester's existing connection would always report success. Instead a fresh transport dial + upgrade verifies both reachability and identity, and the probe connection is closed immediately (go-libp2p uses a separate dialer host for the same reason).

registerRelayHopHandler :: Switch -> RelayState -> IO () Source #

Register the Circuit Relay v2 hop handler (libp2pcircuitrelay0.2.0/hop): serve RESERVE and CONNECT requests.

registerRelayStopHandler :: Switch -> CircuitState -> IO () Source #

Register the Circuit Relay v2 stop handler (libp2pcircuitrelay0.2.0/stop).

After the CONNECT/OK exchange the stop stream *is* the relayed connection (specsrelaycircuit-v2), so it is handed to the circuit transport's listener for the relay it arrived over. The Switch then upgrades it like any other inbound raw connection.

The relay's advertised limit is not yet enforced (issue #269).

registerDCUtRHandler :: Switch -> DCUtRUpgradeConfig -> IO () Source #

Register the DCUtR handler (libp2pdcutr).

Answers the CONNECT/SYNC exchange with our listen addresses and dials the initiator's addresses through the Switch for the hole punch.

registerReservationCleanup :: Switch -> RelayState -> IO () Source #

Drop a peer's relay reservation once its last connection to us goes away (specsrelaycircuit-v2): "the reservation remains valid until its expiration, as long as there is an active connection from the peer to the relay. If the peer disconnects, the reservation is no longer valid."

The reservation is bound to the peer, not to the connection the RESERVE arrived on, so a peer holding a second connection keeps it. This matches go-libp2p, whose relay returns early from its disconnect notifiee while Connectedness(p) == Connected.

closeConnection removes the connection from the pool in the same STM transaction that marks it closed, and only then runs the notifiers, so the lookup below never observes the connection being torn down.

DCUtR production integration

registerDCUtRUpgrade :: Switch -> DCUtRUpgradeConfig -> IO () Source #

Subscribe the DCUtR direct-connection upgrade to new connections.

specsrelayDCUtR: "The protocol starts with the completion of a relay connection from A to B. Upon observing the new connection, the inbound peer (here B) checks the addresses advertised by A via identify." The trigger is therefore an *inbound* connection over a circuit, the same condition go-libp2p's hole punch notifiee applies (Direction == DirInbound && isRelayAddress(RemoteMultiaddr())).

upgradeRelayedConnection :: Switch -> DCUtRUpgradeConfig -> Connection -> IO DCUtRResult Source #

Upgrade a relayed connection to a direct one (specsrelayDCUtR).

Tries the unilateral upgrade first, falling back to the /libp2p/dcutr exchange, and on success schedules the relay connection to close after the grace period. Exposed so it can be driven directly instead of through the notifier.

holePunchTargets :: Switch -> PeerId -> IO [Multiaddr] Source #

The peer's advertised addresses that are worth a unilateral direct dial: decodable, not relayed, and publicly routable.

specsrelayDCUtR: "B checks the addresses advertised by A via identify. If that set includes public addresses, then A may be reachable by a direct connection". go-libp2p applies the same pair of filters (!isRelayAddress(a) && manet.IsPublicAddr(a)).

A circuit address is never a target: dialling it would go back through the relay we are trying to get off.

dcutrOwnAddrs :: Switch -> Maybe PeerId -> IO [Multiaddr] Source #

Addresses we put in DCUtR CONNECT: the address reported by the relay that carries this connection, followed by every non-relayed listen address. Scoping the observation to that relay avoids advertising stale mappings learned from unrelated peers. Private listen addresses remain useful to peers on the same LAN and as deterministic test fallbacks.

data DCUtRUpgradeConfig Source #

Tuning for the DCUtR upgrade that runs on an inbound relayed connection.

Constructors

DCUtRUpgradeConfig 

Fields

  • ducMaxAttempts :: !Int

    Hole punch attempts, each re-running the CONNECT/SYNC exchange so RTT is re-measured. specsrelayDCUtR: inbound peers "SHOULD retry twice (thus a total of 3 attempts)".

  • ducDirectDialTimeoutMicros :: !Int

    Bound on one hole punch dial. Without it a dial whose peer never answers the handshake pins a socket and a thread forever: a simultaneous connect that fails to collide lands on the peer's ordinary listener, leaving both ends running the responder side. go-libp2p bounds the same dial with defaultDirectDialTimeout.

  • ducStreamTimeoutMicros :: !Int

    Bound on the whole /libp2p/dcutr coordination exchange. The relay carrying it can vanish mid-exchange. go-libp2p sets the same bound as a stream deadline (StreamTimeout).

  • ducRelayCloseGraceMicros :: !Int

    How long the relay connection is kept after a successful upgrade. specsrelayDCUtR: "the relay connection should be closed after a grace period". go-libp2p's holepunch package leaves this to its connection manager, which this implementation does not have, so the delay is applied here.

defaultDCUtRUpgradeConfig :: DCUtRUpgradeConfig Source #

Three hole punch attempts and a 15s grace period before the relay connection is dropped.

Circuit client

data CircuitState Source #

Per-Switch state shared between the circuit transport and the stop protocol handler: one inbound queue per relay we hold a reservation on.

data ReservationRefreshConfig Source #

Tuning for client-side reservation refresh (specsrelaycircuit-v2: "the reservation becomes invalid after this time and it's the responsibility of the client to refresh").

Values follow go-libp2p's autorelay relay finder (rsvpExpirationSlack / rsvpRefreshInterval): refresh once the reservation is within rrcMargin of its expiry, checked every rrcPollInterval.

Constructors

ReservationRefreshConfig 

Fields

defaultReservationRefreshConfig :: ReservationRefreshConfig Source #

Default refresh tuning: a 2 minute margin, checked every minute.