networking.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. from ipaddress import ip_address
  2. from typing import List, Sequence
  3. from multiaddr import Multiaddr
  4. from hivemind.utils.logging import TextStyle, get_logger
  5. LOCALHOST = "127.0.0.1"
  6. logger = get_logger(__name__)
  7. def choose_ip_address(
  8. maddrs: Sequence[Multiaddr], prefer_global: bool = True, protocol_priority: Sequence[str] = ("ip4", "ip6")
  9. ) -> str:
  10. """
  11. Currently, some components of hivemind are not converted to work over libp2p and use classical networking.
  12. To allow other peers reach a server when needed, these components announce a machine's IP address.
  13. This function automatically selects the best IP address to announce among publicly visible multiaddrs
  14. of this machine identified by libp2p (typically, using the ``P2P.get_visible_maddrs()`` method),
  15. so a user does not need to define this address manually (unless the user wants to).
  16. The best IP address is chosen using the following logic:
  17. - Prefer IP addresses from global address blocks
  18. (in terms of https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv4Address.is_global)
  19. - Among the IP addresses of the same globality status, prefer IPv4 addresses over IPv6
  20. If the default logic does not suit you, it is recommended to set the announced IP address manually.
  21. """
  22. for need_global in [prefer_global, not prefer_global]:
  23. for protocol in protocol_priority:
  24. for addr in maddrs:
  25. if protocol in addr.protocols():
  26. value_for_protocol = addr[protocol]
  27. if ip_address(value_for_protocol).is_global == need_global:
  28. return value_for_protocol
  29. raise ValueError(f"No IP address found among given multiaddrs: {maddrs}")
  30. def log_visible_maddrs(visible_maddrs: List[Multiaddr], only_p2p: bool) -> None:
  31. if only_p2p:
  32. unique_addrs = {addr["p2p"] for addr in visible_maddrs}
  33. initial_peers = " ".join(f"/p2p/{addr}" for addr in unique_addrs)
  34. else:
  35. available_ips = [Multiaddr(addr) for addr in visible_maddrs if "ip4" in addr or "ip6" in addr]
  36. if available_ips:
  37. preferred_ip = choose_ip_address(available_ips)
  38. selected_maddrs = [addr for addr in visible_maddrs if preferred_ip in str(addr)]
  39. else:
  40. selected_maddrs = visible_maddrs
  41. initial_peers = " ".join(str(addr) for addr in selected_maddrs)
  42. logger.info(
  43. f"Running a DHT instance. To connect other peers to this one, use "
  44. f"{TextStyle.BOLD}{TextStyle.BLUE}--initial_peers {initial_peers}{TextStyle.RESET}"
  45. )
  46. logger.info(f"Full list of visible multiaddresses: {' '.join(str(addr) for addr in visible_maddrs)}")