2022-11-04 09:52:27 +00:00
|
|
|
|
when (NimMajor, NimMinor) < (1, 4):
|
|
|
|
|
{.push raises: [Defect].}
|
|
|
|
|
else:
|
|
|
|
|
{.push raises: [].}
|
2021-03-26 08:49:51 +00:00
|
|
|
|
|
|
|
|
|
import
|
2023-12-20 14:23:41 +00:00
|
|
|
|
std/[tables, sequtils, sets, options, times, strutils],
|
2023-01-23 20:24:46 +00:00
|
|
|
|
chronos,
|
2023-03-09 18:05:50 +00:00
|
|
|
|
eth/p2p/discoveryv5/enr,
|
2021-06-09 14:37:08 +00:00
|
|
|
|
libp2p/builders,
|
2021-03-26 08:49:51 +00:00
|
|
|
|
libp2p/peerstore
|
|
|
|
|
|
2022-11-24 13:11:23 +00:00
|
|
|
|
import
|
2023-04-24 14:37:54 +00:00
|
|
|
|
../../waku_core,
|
2023-08-09 17:11:50 +00:00
|
|
|
|
../../common/utils/sequence
|
2022-11-24 13:11:23 +00:00
|
|
|
|
|
2021-06-09 14:37:08 +00:00
|
|
|
|
export peerstore, builders
|
2021-03-26 08:49:51 +00:00
|
|
|
|
|
|
|
|
|
type
|
2022-11-29 16:35:25 +00:00
|
|
|
|
|
2022-11-24 13:11:23 +00:00
|
|
|
|
# Keeps track of the Connectedness state of a peer
|
2022-06-01 09:49:41 +00:00
|
|
|
|
ConnectionBook* = ref object of PeerBook[Connectedness]
|
2021-03-26 08:49:51 +00:00
|
|
|
|
|
2023-01-23 20:24:46 +00:00
|
|
|
|
# Last failed connection attemp timestamp
|
|
|
|
|
LastFailedConnBook* = ref object of PeerBook[Moment]
|
|
|
|
|
|
|
|
|
|
# Failed connection attempts
|
|
|
|
|
NumberFailedConnBook* = ref object of PeerBook[int]
|
|
|
|
|
|
2022-11-24 13:11:23 +00:00
|
|
|
|
# Keeps track of when peers were disconnected in Unix timestamps
|
|
|
|
|
DisconnectBook* = ref object of PeerBook[int64]
|
|
|
|
|
|
|
|
|
|
# Keeps track of the origin of a peer
|
|
|
|
|
SourceBook* = ref object of PeerBook[PeerOrigin]
|
2021-04-21 09:36:56 +00:00
|
|
|
|
|
2022-11-29 16:35:25 +00:00
|
|
|
|
# Direction
|
2023-01-23 20:24:46 +00:00
|
|
|
|
DirectionBook* = ref object of PeerBook[PeerDirection]
|
2022-11-29 16:35:25 +00:00
|
|
|
|
|
2023-03-09 18:05:50 +00:00
|
|
|
|
# ENR Book
|
|
|
|
|
ENRBook* = ref object of PeerBook[enr.Record]
|
2021-03-26 08:49:51 +00:00
|
|
|
|
|
2022-11-24 13:11:23 +00:00
|
|
|
|
##################
|
2021-06-15 08:55:47 +00:00
|
|
|
|
# Peer Store API #
|
|
|
|
|
##################
|
|
|
|
|
|
2023-01-23 20:24:46 +00:00
|
|
|
|
proc delete*(peerStore: PeerStore,
|
|
|
|
|
peerId: PeerId) =
|
|
|
|
|
# Delete all the information of a given peer.
|
|
|
|
|
peerStore.del(peerId)
|
|
|
|
|
|
2022-11-24 13:11:23 +00:00
|
|
|
|
proc get*(peerStore: PeerStore,
|
2023-03-09 18:05:50 +00:00
|
|
|
|
peerId: PeerID): RemotePeerInfo =
|
2021-06-15 08:55:47 +00:00
|
|
|
|
## Get the stored information of a given peer.
|
2023-03-09 18:05:50 +00:00
|
|
|
|
RemotePeerInfo(
|
2021-06-15 08:55:47 +00:00
|
|
|
|
peerId: peerId,
|
2022-11-24 13:11:23 +00:00
|
|
|
|
addrs: peerStore[AddressBook][peerId],
|
2023-03-09 18:05:50 +00:00
|
|
|
|
enr: if peerStore[ENRBook][peerId] != default(enr.Record): some(peerStore[ENRBook][peerId]) else: none(enr.Record),
|
|
|
|
|
protocols: peerStore[ProtoBook][peerId],
|
2022-11-24 13:11:23 +00:00
|
|
|
|
agent: peerStore[AgentBook][peerId],
|
|
|
|
|
protoVersion: peerStore[ProtoVersionBook][peerId],
|
2023-03-09 18:05:50 +00:00
|
|
|
|
publicKey: peerStore[KeyBook][peerId],
|
2022-11-24 13:11:23 +00:00
|
|
|
|
|
|
|
|
|
# Extended custom fields
|
|
|
|
|
connectedness: peerStore[ConnectionBook][peerId],
|
|
|
|
|
disconnectTime: peerStore[DisconnectBook][peerId],
|
|
|
|
|
origin: peerStore[SourceBook][peerId],
|
2022-11-29 16:35:25 +00:00
|
|
|
|
direction: peerStore[DirectionBook][peerId],
|
2023-01-23 20:24:46 +00:00
|
|
|
|
lastFailedConn: peerStore[LastFailedConnBook][peerId],
|
|
|
|
|
numberFailedConn: peerStore[NumberFailedConnBook][peerId]
|
2021-06-15 08:55:47 +00:00
|
|
|
|
)
|
|
|
|
|
|
2023-04-12 11:05:34 +00:00
|
|
|
|
proc getWakuProtos*(peerStore: PeerStore): seq[string] =
|
|
|
|
|
## Get the waku protocols of all the stored peers.
|
|
|
|
|
let wakuProtocols = toSeq(peerStore[ProtoBook].book.values())
|
|
|
|
|
.flatten()
|
|
|
|
|
.deduplicate()
|
|
|
|
|
.filterIt(it.startsWith("/vac/waku"))
|
|
|
|
|
return wakuProtocols
|
|
|
|
|
|
2022-11-29 16:35:25 +00:00
|
|
|
|
# TODO: Rename peers() to getPeersByProtocol()
|
2023-03-09 18:05:50 +00:00
|
|
|
|
proc peers*(peerStore: PeerStore): seq[RemotePeerInfo] =
|
2021-06-15 08:55:47 +00:00
|
|
|
|
## Get all the stored information of every peer.
|
2022-11-24 13:11:23 +00:00
|
|
|
|
let allKeys = concat(toSeq(peerStore[AddressBook].book.keys()),
|
|
|
|
|
toSeq(peerStore[ProtoBook].book.keys()),
|
|
|
|
|
toSeq(peerStore[KeyBook].book.keys())).toHashSet()
|
2021-06-15 08:55:47 +00:00
|
|
|
|
|
|
|
|
|
return allKeys.mapIt(peerStore.get(it))
|
2022-11-24 13:11:23 +00:00
|
|
|
|
|
2023-03-09 18:05:50 +00:00
|
|
|
|
proc peers*(peerStore: PeerStore, proto: string): seq[RemotePeerInfo] =
|
2022-11-24 13:11:23 +00:00
|
|
|
|
# Return the known info for all peers registered on the specified protocol
|
2023-03-09 18:05:50 +00:00
|
|
|
|
peerStore.peers.filterIt(it.protocols.contains(proto))
|
2022-11-24 13:11:23 +00:00
|
|
|
|
|
2023-03-09 18:05:50 +00:00
|
|
|
|
proc peers*(peerStore: PeerStore, protocolMatcher: Matcher): seq[RemotePeerInfo] =
|
2022-11-24 13:11:23 +00:00
|
|
|
|
# Return the known info for all peers matching the provided protocolMatcher
|
2023-03-09 18:05:50 +00:00
|
|
|
|
peerStore.peers.filterIt(it.protocols.anyIt(protocolMatcher(it)))
|
2022-11-24 13:11:23 +00:00
|
|
|
|
|
|
|
|
|
proc connectedness*(peerStore: PeerStore, peerId: PeerID): Connectedness =
|
2023-12-20 14:23:41 +00:00
|
|
|
|
# Return the connection state of the given, managed peer
|
|
|
|
|
# TODO: the PeerManager should keep and update local connectedness state for peers, redial on disconnect, etc.
|
|
|
|
|
# TODO: richer return than just bool, e.g. add enum "CanConnect", "CannotConnect", etc. based on recent connection attempts
|
|
|
|
|
return peerStore[ConnectionBook].book.getOrDefault(peerId, NotConnected)
|
2022-11-24 13:11:23 +00:00
|
|
|
|
|
2023-01-26 09:20:20 +00:00
|
|
|
|
proc isConnected*(peerStore: PeerStore, peerId: PeerID): bool =
|
|
|
|
|
# Returns `true` if the peer is connected
|
|
|
|
|
peerStore.connectedness(peerId) == Connected
|
|
|
|
|
|
2022-11-24 13:11:23 +00:00
|
|
|
|
proc hasPeer*(peerStore: PeerStore, peerId: PeerID, proto: string): bool =
|
|
|
|
|
# Returns `true` if peer is included in manager for the specified protocol
|
|
|
|
|
# TODO: What if peer does not exist in the peerStore?
|
2023-03-09 18:05:50 +00:00
|
|
|
|
peerStore.get(peerId).protocols.contains(proto)
|
2022-11-24 13:11:23 +00:00
|
|
|
|
|
|
|
|
|
proc hasPeers*(peerStore: PeerStore, proto: string): bool =
|
|
|
|
|
# Returns `true` if the peerstore has any peer for the specified protocol
|
|
|
|
|
toSeq(peerStore[ProtoBook].book.values()).anyIt(it.anyIt(it == proto))
|
|
|
|
|
|
|
|
|
|
proc hasPeers*(peerStore: PeerStore, protocolMatcher: Matcher): bool =
|
|
|
|
|
# Returns `true` if the peerstore has any peer matching the protocolMatcher
|
|
|
|
|
toSeq(peerStore[ProtoBook].book.values()).anyIt(it.anyIt(protocolMatcher(it)))
|
|
|
|
|
|
2023-03-09 18:05:50 +00:00
|
|
|
|
proc getPeersByDirection*(peerStore: PeerStore, direction: PeerDirection): seq[RemotePeerInfo] =
|
2023-01-18 14:17:56 +00:00
|
|
|
|
return peerStore.peers.filterIt(it.direction == direction)
|
|
|
|
|
|
2023-03-09 18:05:50 +00:00
|
|
|
|
proc getNotConnectedPeers*(peerStore: PeerStore): seq[RemotePeerInfo] =
|
2023-01-18 14:17:56 +00:00
|
|
|
|
return peerStore.peers.filterIt(it.connectedness != Connected)
|
2023-01-26 09:20:20 +00:00
|
|
|
|
|
2023-03-09 18:05:50 +00:00
|
|
|
|
proc getConnectedPeers*(peerStore: PeerStore): seq[RemotePeerInfo] =
|
2023-02-09 15:59:29 +00:00
|
|
|
|
return peerStore.peers.filterIt(it.connectedness == Connected)
|
|
|
|
|
|
2023-03-09 18:05:50 +00:00
|
|
|
|
proc getPeersByProtocol*(peerStore: PeerStore, proto: string): seq[RemotePeerInfo] =
|
|
|
|
|
return peerStore.peers.filterIt(it.protocols.contains(proto))
|
2023-04-19 14:12:00 +00:00
|
|
|
|
|
|
|
|
|
proc getReachablePeers*(peerStore: PeerStore): seq[RemotePeerInfo] =
|
|
|
|
|
return peerStore.peers.filterIt(it.connectedness == CanConnect or it.connectedness == Connected)
|