125 lines
3.9 KiB
Nim
125 lines
3.9 KiB
Nim
# Nim-LibP2P
|
|
# Copyright (c) 2023 Status Research & Development GmbH
|
|
# Licensed under either of
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
|
# at your option.
|
|
# This file may not be copied, modified, or distributed except according to
|
|
# those terms.
|
|
|
|
{.push raises: [].}
|
|
{.push public.}
|
|
|
|
import std/sequtils
|
|
import pkg/[chronos, chronicles, stew/results]
|
|
import peerid, multiaddress, multicodec, crypto/crypto, routing_record, errors, utility
|
|
|
|
export peerid, multiaddress, crypto, routing_record, errors, results
|
|
|
|
## Our local peer info
|
|
|
|
type
|
|
PeerInfoError* = object of LPError
|
|
|
|
AddressMapper* =
|
|
proc(listenAddrs: seq[MultiAddress]): Future[seq[MultiAddress]]
|
|
{.gcsafe, raises: [].}
|
|
## A proc that expected to resolve the listen addresses into dialable addresses
|
|
|
|
PeerInfo* {.public.} = ref object
|
|
peerId*: PeerId
|
|
listenAddrs*: seq[MultiAddress]
|
|
## contains addresses the node listens on, which may include wildcard and private addresses (not directly reachable).
|
|
addrs*: seq[MultiAddress]
|
|
## contains resolved addresses that other peers can use to connect, including public-facing NAT and port-forwarded addresses.
|
|
addressMappers*: seq[AddressMapper]
|
|
## contains a list of procs that can be used to resolve the listen addresses into dialable addresses.
|
|
protocols*: seq[string]
|
|
protoVersion*: string
|
|
agentVersion*: string
|
|
privateKey*: PrivateKey
|
|
publicKey*: PublicKey
|
|
signedPeerRecord*: SignedPeerRecord
|
|
|
|
func shortLog*(p: PeerInfo): auto =
|
|
(
|
|
peerId: $p.peerId,
|
|
listenAddrs: mapIt(p.listenAddrs, $it),
|
|
addrs: mapIt(p.addrs, $it),
|
|
protocols: mapIt(p.protocols, $it),
|
|
protoVersion: p.protoVersion,
|
|
agentVersion: p.agentVersion,
|
|
)
|
|
chronicles.formatIt(PeerInfo): shortLog(it)
|
|
|
|
proc update*(p: PeerInfo) {.async.} =
|
|
# p.addrs.len == 0 overrides addrs only if it is the first time update is being executed or if the field is empty.
|
|
# p.addressMappers.len == 0 is for when all addressMappers have been removed,
|
|
# and we wish to have addrs in its initial state, i.e., a copy of listenAddrs.
|
|
if p.addrs.len == 0 or p.addressMappers.len == 0:
|
|
p.addrs = p.listenAddrs
|
|
for mapper in p.addressMappers:
|
|
p.addrs = await mapper(p.addrs)
|
|
|
|
p.signedPeerRecord = SignedPeerRecord.init(
|
|
p.privateKey,
|
|
PeerRecord.init(p.peerId, p.addrs)
|
|
).valueOr():
|
|
info "Can't update the signed peer record"
|
|
return
|
|
|
|
proc addrs*(p: PeerInfo): seq[MultiAddress] =
|
|
p.addrs
|
|
|
|
proc fullAddrs*(p: PeerInfo): MaResult[seq[MultiAddress]] =
|
|
let peerIdPart = ? MultiAddress.init(multiCodec("p2p"), p.peerId.data)
|
|
var res: seq[MultiAddress]
|
|
for address in p.addrs:
|
|
res.add(? concat(address, peerIdPart))
|
|
ok(res)
|
|
|
|
proc parseFullAddress*(ma: MultiAddress): MaResult[(PeerId, MultiAddress)] =
|
|
let p2pPart = ? ma[^1]
|
|
if ? p2pPart.protoCode != multiCodec("p2p"):
|
|
return err("Missing p2p part from multiaddress!")
|
|
|
|
let res = (
|
|
? PeerId.init(? p2pPart.protoArgument()).orErr("invalid peerid"),
|
|
? ma[0 .. ^2]
|
|
)
|
|
ok(res)
|
|
|
|
proc parseFullAddress*(ma: string | seq[byte]): MaResult[(PeerId, MultiAddress)] =
|
|
parseFullAddress(? MultiAddress.init(ma))
|
|
|
|
proc new*(
|
|
p: typedesc[PeerInfo],
|
|
key: PrivateKey,
|
|
listenAddrs: openArray[MultiAddress] = [],
|
|
protocols: openArray[string] = [],
|
|
protoVersion: string = "",
|
|
agentVersion: string = "",
|
|
addressMappers = newSeq[AddressMapper](),
|
|
): PeerInfo
|
|
{.raises: [LPError].} =
|
|
|
|
let pubkey = try:
|
|
key.getPublicKey().tryGet()
|
|
except CatchableError:
|
|
raise newException(PeerInfoError, "invalid private key")
|
|
|
|
let peerId = PeerId.init(key).tryGet()
|
|
|
|
let peerInfo = PeerInfo(
|
|
peerId: peerId,
|
|
publicKey: pubkey,
|
|
privateKey: key,
|
|
protoVersion: protoVersion,
|
|
agentVersion: agentVersion,
|
|
listenAddrs: @listenAddrs,
|
|
protocols: @protocols,
|
|
addressMappers: addressMappers
|
|
)
|
|
|
|
return peerInfo
|