mirror of
https://github.com/logos-storage/libp2p-mix-ping-example.git
synced 2026-05-18 16:59:41 +00:00
125 lines
3.3 KiB
Nim
125 lines
3.3 KiB
Nim
# SPDX-License-Identifier: MIT
|
|
|
|
## Multiple Transports Example
|
|
##
|
|
## This example demonstrates using multiple transport protocols (TCP and QUIC)
|
|
## with libp2p.
|
|
## It creates a switch that listens on both TCP and QUIC addresses,
|
|
## then performs ping operations preferring each transport protocol to
|
|
## show how to use multiple transports in a libp2p application.
|
|
|
|
{.used.}
|
|
|
|
import chronos
|
|
import std/[sequtils, strutils]
|
|
import libp2p/[
|
|
builders,
|
|
crypto/crypto,
|
|
multiaddress,
|
|
peerid,
|
|
protocols/ping,
|
|
switch,
|
|
]
|
|
|
|
proc newTcpQuicSwitch*(
|
|
privKey: Opt[PrivateKey] = Opt.none(PrivateKey),
|
|
rng: ref HmacDrbgContext = newRng()
|
|
): Switch =
|
|
## A switch that listens on TCP and QUIC addresses.
|
|
let addrs = @[
|
|
MultiAddress.init("/ip4/0.0.0.0/udp/0/quic-v1").tryGet(),
|
|
MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet(),
|
|
]
|
|
|
|
var builder = SwitchBuilder
|
|
.new()
|
|
.withRng(rng)
|
|
.withAddresses(addrs)
|
|
.withNoise()
|
|
.withMplex()
|
|
.withQuicTransport()
|
|
.withTcpTransport()
|
|
|
|
privKey.withValue(key):
|
|
builder = builder.withPrivateKey(key)
|
|
|
|
builder.build()
|
|
|
|
proc quicPreferred*(addrs: seq[MultiAddress]): seq[MultiAddress] =
|
|
## Dial order is address order, so put QUIC addresses before fallback transports.
|
|
addrs.filterIt("/quic-v1" in $it) &
|
|
addrs.filterIt("/quic-v1" notin $it)
|
|
|
|
proc tcpPreferred*(addrs: seq[MultiAddress]): seq[MultiAddress] =
|
|
## Dial order is address order, so put TCP addresses before QUIC fallback.
|
|
addrs.filterIt("/quic-v1" notin $it) &
|
|
addrs.filterIt("/quic-v1" in $it)
|
|
|
|
proc connectPreferringQuic*(
|
|
localSwitch: Switch, remotePeerId: PeerId, remoteAddrs: seq[MultiAddress]
|
|
) {.async: (raises: [CancelledError, DialFailedError]).} =
|
|
await localSwitch.connect(remotePeerId, quicPreferred(remoteAddrs))
|
|
|
|
proc pingPreferringQuic*(
|
|
localSwitch: Switch,
|
|
pingProtocol: Ping,
|
|
remotePeerId: PeerId,
|
|
remoteAddrs: seq[MultiAddress],
|
|
): Future[Duration] {.
|
|
async: (raises: [CancelledError, DialFailedError, LPStreamError,
|
|
WrongPingAckError])
|
|
.} =
|
|
let conn = await localSwitch.dial(remotePeerId, quicPreferred(remoteAddrs),
|
|
PingCodec)
|
|
defer:
|
|
await conn.close()
|
|
|
|
await pingProtocol.ping(conn)
|
|
|
|
proc pingPreferringTcp*(
|
|
localSwitch: Switch,
|
|
pingProtocol: Ping,
|
|
remotePeerId: PeerId,
|
|
remoteAddrs: seq[MultiAddress],
|
|
): Future[Duration] {.
|
|
async: (raises: [CancelledError, DialFailedError, LPStreamError,
|
|
WrongPingAckError])
|
|
.} =
|
|
let conn = await localSwitch.dial(remotePeerId, tcpPreferred(remoteAddrs),
|
|
PingCodec)
|
|
defer:
|
|
await conn.close()
|
|
|
|
await pingProtocol.ping(conn)
|
|
|
|
when isMainModule:
|
|
proc main() {.async: (raises: [CancelledError, LPError]).} =
|
|
let rng = newRng()
|
|
let pingProtocol = Ping.new(rng = rng)
|
|
let
|
|
quicClient = newTcpQuicSwitch(rng = rng)
|
|
tcpClient = newTcpQuicSwitch(rng = rng)
|
|
b = newTcpQuicSwitch(rng = rng)
|
|
|
|
b.mount(pingProtocol)
|
|
|
|
await quicClient.start()
|
|
await tcpClient.start()
|
|
await b.start()
|
|
defer:
|
|
await quicClient.stop()
|
|
await tcpClient.stop()
|
|
await b.stop()
|
|
|
|
let quicRtt = await quicClient.pingPreferringQuic(
|
|
pingProtocol, b.peerInfo.peerId, b.peerInfo.addrs
|
|
)
|
|
echo "quic ping: ", quicRtt
|
|
|
|
let tcpRtt = await tcpClient.pingPreferringTcp(
|
|
pingProtocol, b.peerInfo.peerId, b.peerInfo.addrs
|
|
)
|
|
echo "tcp ping: ", tcpRtt
|
|
|
|
waitFor main()
|