A Python port of the Invisible Internet Project (I2P)
1"""Floodfill router tracking for efficient NetDB lookups.
2
3Floodfill routers are peers that participate in the Kademlia-like
4distributed hash table, storing and serving NetDB entries. This manager
5tracks known floodfill routers so lookup and store operations can
6target them directly.
7
8Ported from net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade.
9"""
10
11from __future__ import annotations
12
13import random
14from typing import Optional
15
16
17class FloodfillManager:
18 """Tracks floodfill routers for efficient NetDB lookups."""
19
20 def __init__(self) -> None:
21 self._floodfills: dict[bytes, dict] = {}
22
23 def add_floodfill(self, peer_hash: bytes, info: dict) -> None:
24 """Register a peer as a floodfill router."""
25 self._floodfills[peer_hash] = info
26
27 def remove_floodfill(self, peer_hash: bytes) -> None:
28 """Remove a peer from the floodfill set."""
29 self._floodfills.pop(peer_hash, None)
30
31 def select_floodfill(self, exclude: Optional[set[bytes]] = None) -> Optional[bytes]:
32 """Select a random floodfill router, optionally excluding some peers.
33
34 Returns None if no eligible floodfill is available.
35 """
36 exclude = exclude or set()
37 candidates = [h for h in self._floodfills if h not in exclude]
38 if not candidates:
39 return None
40 return random.choice(candidates)
41
42 def is_floodfill(self, peer_hash: bytes) -> bool:
43 """Check whether a peer is a known floodfill router."""
44 return peer_hash in self._floodfills
45
46 def get_all(self) -> list[bytes]:
47 """Return a list of all known floodfill peer hashes."""
48 return list(self._floodfills.keys())
49
50 @property
51 def count(self) -> int:
52 """Number of known floodfill routers."""
53 return len(self._floodfills)