| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
LibP2P.Protocol.Ping
Description
Ping protocol implementation (specs/ping).
Protocol ID: ipfsping/1.0.0
Wire format: 32 bytes random → 32 bytes echo. No framing, no protobuf. The responder runs an echo loop: reads 32 bytes, writes them back, until the initiator closes the stream, then closes its own side.
The initiator keeps at most one outbound ping stream per peer
(ping.md: "The dialing peer MUST NOT keep more than one outbound
stream for the ping protocol per peer"). A PingSession holds that
single stream and reuses it for successive pings (ping.md: the peer
"MAY send further payloads on the same stream"); the stream is closed
when the session ends or on the first failed ping. Streams are opened
through the Switch (newStream), so each session holds exactly one
stream reservation, released on close.
The listener accepts at most two concurrent ping streams per remote
peer (ping.md: "The listening peer SHOULD accept at most two streams
per peer since cross-stream behavior is non-linear and stream writes
occur asynchronously"). registerPingHandler installs a
PingLimiter that counts live inbound ping streams per peer and
resets the third and subsequent streams without serving them.
Synopsis
- pingProtocolId :: Text
- data PingError
- data PingResult = PingResult {}
- data PingSession
- handlePing :: StreamIO -> PeerId -> IO ()
- data PingLimiter
- newPingLimiter :: IO PingLimiter
- handlePingLimited :: PingLimiter -> StreamIO -> PeerId -> IO ()
- sendPing :: Switch -> Connection -> IO (Either PingError PingResult)
- openPingSession :: Switch -> Connection -> IO (Either PingError PingSession)
- ping :: PingSession -> IO (Either PingError PingResult)
- pingWithTimeout :: Int -> PingSession -> IO (Either PingError PingResult)
- closePingSession :: PingSession -> IO ()
- withPingSession :: Switch -> Connection -> (PingSession -> IO a) -> IO (Either PingError a)
- registerPingHandler :: Switch -> IO ()
- pingSize :: Int
- pingTimeoutMicros :: Int
- maxPingStreamsPerPeer :: Int
Protocol ID
pingProtocolId :: Text Source #
Ping protocol ID.
Types
Ping error types.
Constructors
| PingTimeout | No echo within the timeout |
| PingMismatch | Response doesn't match sent bytes |
| PingStreamError !String | Stream open, negotiation, or I/O error |
data PingResult Source #
Successful ping result.
Constructors
| PingResult | |
Fields
| |
Instances
| Show PingResult Source # | |
Defined in LibP2P.Protocol.Ping Methods showsPrec :: Int -> PingResult -> ShowS # show :: PingResult -> String # showList :: [PingResult] -> ShowS # | |
| Eq PingResult Source # | |
Defined in LibP2P.Protocol.Ping | |
data PingSession Source #
The single outbound ping stream to a peer, negotiated and ready.
Obtain with openPingSession (or scoped via withPingSession), send
pings with ping, and always release with closePingSession. A
session whose ping failed (timeout, mismatch, I/O error) closes its
stream immediately and rejects further pings.
Concurrent ping calls on one session are serialized on psLock:
exactly one write/echo exchange runs on the stream at a time, so
concurrent callers queue instead of interleaving their 32-byte
payloads on the wire.
Responder
handlePing :: StreamIO -> PeerId -> IO () Source #
Handle an inbound Ping request (responder / echo loop).
Reads 32 bytes, writes them back. Repeats until the initiator closes its write side (EOF), then closes this side of the stream (ping.md: the listening peer SHOULD exit the loop and close the stream).
data PingLimiter Source #
Per-peer accounting of live inbound ping streams, shared by every invocation of the registered ping handler on one Switch.
newPingLimiter :: IO PingLimiter Source #
Create an empty inbound ping stream limiter.
handlePingLimited :: PingLimiter -> StreamIO -> PeerId -> IO () Source #
Serve an inbound ping stream, enforcing the per-peer cap.
If the remote peer already has maxPingStreamsPerPeer live ping
streams, the new stream is reset (closed without serving the echo
loop). Otherwise the stream occupies a slot for the duration of
handlePing; the slot is released when the stream closes or errors.
Initiator
sendPing :: Switch -> Connection -> IO (Either PingError PingResult) Source #
Send a single Ping to a remote peer (initiator side).
Convenience wrapper: opens a ping session, pings once, and closes the
stream. For repeated pings to the same peer, use withPingSession
to reuse one stream instead of opening one per call.
openPingSession :: Switch -> Connection -> IO (Either PingError PingSession) Source #
Open a ping stream on the connection and negotiate the protocol.
The stream is opened through the Switch so it is counted against the peer's stream limits; the reservation is released when the session is closed. On any failure the stream (if opened) is closed before returning.
ping :: PingSession -> IO (Either PingError PingResult) Source #
Send one ping on the session with the default timeout
(pingTimeoutMicros). The session's stream is reused across calls.
pingWithTimeout :: Int -> PingSession -> IO (Either PingError PingResult) Source #
Send one ping on the session, waiting at most the given number of microseconds for the echo. On failure the session is closed: a stream whose echo timed out or went wrong cannot be reused, because a late echo would corrupt the next ping.
The whole exchange runs under the session lock, so concurrent callers are queued one after another on the single stream. The closed check happens under the lock too: a caller queued behind a failed ping sees the session as closed instead of writing into a poisoned stream.
closePingSession :: PingSession -> IO () Source #
Close the session's stream (signalling EOF to the responder's echo loop) and release its stream reservation. Idempotent.
withPingSession :: Switch -> Connection -> (PingSession -> IO a) -> IO (Either PingError a) Source #
Run an action with a ping session, closing it afterwards even if the action throws. Returns Left if the session could not be opened.
Registration
registerPingHandler :: Switch -> IO () Source #
Register the Ping handler on the Switch.
The installed handler shares one PingLimiter, so concurrent inbound
ping streams are capped at maxPingStreamsPerPeer per remote peer.
Constants
pingTimeoutMicros :: Int Source #
Time to wait for an echo before giving up, in microseconds. 10 seconds, mirroring go-libp2p's ping timeout.
maxPingStreamsPerPeer :: Int Source #
Maximum concurrent inbound ping streams served per remote peer (ping.md: "The listening peer SHOULD accept at most two streams per peer since cross-stream behavior is non-linear and stream writes occur asynchronously").