diff --git a/docs/examples.mDNS.rst b/docs/examples.mDNS.rst new file mode 100644 index 00000000..26dc8b17 --- /dev/null +++ b/docs/examples.mDNS.rst @@ -0,0 +1,64 @@ +mDNS Peer Discovery Example +========================== + +This example demonstrates how to use mDNS (Multicast DNS) for peer discovery in py-libp2p. + +Prerequisites +------------- + +First, ensure you have py-libp2p installed and your environment is activated: + +.. code-block:: console + + $ python -m pip install libp2p + +Running the Example +------------------- + +The mDNS demo script allows you to discover peers on your local network using mDNS. To start a peer, run: + +.. code-block:: console + + $ mdns-demo + +You should see output similar to: + +.. code-block:: console + + Run this from another console to start another peer on a different port: + + python mdns-demo -p + + Waiting for mDNS peer discovery events... + + 2025-06-20 23:28:12,052 - libp2p.example.discovery.mdns - INFO - Starting peer Discovery + +To discover peers, open another terminal and run the same command with a different port: + +.. code-block:: console + + $ python mdns-demo -p 9001 + +You should see output indicating that a new peer has been discovered: + +.. code-block:: console + + Run this from the same folder in another console to start another peer on a different port: + + python mdns-demo -p + + Waiting for mDNS peer discovery events... + + 2025-06-20 23:43:43,786 - libp2p.example.discovery.mdns - INFO - Starting peer Discovery + 2025-06-20 23:43:43,790 - libp2p.example.discovery.mdns - INFO - Discovered: 16Uiu2HAmGxy5NdQEjZWtrYUMrzdp3Syvg7MB2E5Lx8weA9DanYxj + +When a new peer is discovered, its peer ID will be printed in the console output. + +How it Works +------------ + +- Each node advertises itself on the local network using mDNS. +- When a new peer is discovered, the handler prints its peer ID. +- This is useful for local peer discovery without requiring a DHT or bootstrap nodes. + +You can modify the script to perform additional actions when peers are discovered, such as opening streams or exchanging messages. diff --git a/docs/examples.rst b/docs/examples.rst index 676216a9..b20d0e63 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -13,3 +13,4 @@ Examples examples.pubsub examples.circuit_relay examples.kademlia + examples.mDNS diff --git a/examples/discovery/__init__.py b/examples/discovery/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/examples/discovery/mDNS/mDNS.py b/examples/discovery/mDNS/mDNS.py deleted file mode 100644 index 28d2c9ea..00000000 --- a/examples/discovery/mDNS/mDNS.py +++ /dev/null @@ -1,50 +0,0 @@ -import logging -import secrets - -import multiaddr -import trio - -from libp2p import ( - new_host, -) -from libp2p.abc import PeerInfo -from libp2p.crypto.secp256k1 import ( - create_new_key_pair, -) -from libp2p.discovery.events.peerDiscovery import peerDiscovery - -logger = logging.getLogger("libp2p.example.discovery.mdns") -logger.setLevel(logging.INFO) -handler = logging.StreamHandler() -handler.setFormatter( - logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") -) -logger.addHandler(handler) - - -def onPeerDiscovery(peerinfo: PeerInfo): - logger.info(f"Discovered: {peerinfo.peer_id}") - - -async def main(): - # Generate a key pair for the host - secret = secrets.token_bytes(32) - key_pair = create_new_key_pair(secret) - - # Listen on a random TCP port - listen_addr = multiaddr.Multiaddr("/ip4/0.0.0.0/tcp/0") - peerDiscovery.register_peer_discovered_handler(onPeerDiscovery) - # Enable mDNS discovery - logger.info("Starting peer Discovery") - host = new_host(key_pair=key_pair, enable_mDNS=True) - await trio.sleep(5) - async with host.run(listen_addrs=[listen_addr]): - try: - while True: - await trio.sleep(100) - except KeyboardInterrupt: - logger.info("Exiting...") - - -if __name__ == "__main__": - trio.run(main) diff --git a/examples/mDNS/mDNS.py b/examples/mDNS/mDNS.py new file mode 100644 index 00000000..ad5c8fd3 --- /dev/null +++ b/examples/mDNS/mDNS.py @@ -0,0 +1,67 @@ +import argparse +import logging +import secrets + +import multiaddr +import trio + +from libp2p import ( + new_host, +) +from libp2p.abc import PeerInfo +from libp2p.crypto.secp256k1 import ( + create_new_key_pair, +) +from libp2p.discovery.events.peerDiscovery import peerDiscovery + +logger = logging.getLogger("libp2p.example.discovery.mdns") +logger.setLevel(logging.INFO) +handler = logging.StreamHandler() +handler.setFormatter( + logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") +) +logger.addHandler(handler) + + +def onPeerDiscovery(peerinfo: PeerInfo): + logger.info(f"Discovered: {peerinfo.peer_id}") + + +async def run(port: int) -> None: + secret = secrets.token_bytes(32) + key_pair = create_new_key_pair(secret) + listen_addr = multiaddr.Multiaddr(f"/ip4/0.0.0.0/tcp/{port}") + + peerDiscovery.register_peer_discovered_handler(onPeerDiscovery) + + print( + "Run this from the same folder in another console to " + "start another peer on a different port:\n\n" + "python mdns-demo -p \n" + ) + print("Waiting for mDNS peer discovery events...\n") + + logger.info("Starting peer Discovery") + host = new_host(key_pair=key_pair, enable_mDNS=True) + async with host.run(listen_addrs=[listen_addr]): + await trio.sleep_forever() + + +def main() -> None: + description = """ + This program demonstrates mDNS peer discovery using libp2p. + To use it, run 'mdns-demo -p ', where is the port number. + Start multiple peers on different ports to see discovery in action. + """ + parser = argparse.ArgumentParser(description=description) + parser.add_argument("-p", "--port", default=0, type=int, help="source port number") + + args = parser.parse_args() + try: + trio.run(run, args.port) + except KeyboardInterrupt: + logger.info("Exiting...") + + +if __name__ == "__main__": + main() diff --git a/pyproject.toml b/pyproject.toml index 7ca235fb..cf000156 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,6 +55,7 @@ identify-demo = "examples.identify.identify:main" identify-push-demo = "examples.identify_push.identify_push_demo:run_main" identify-push-listener-dialer-demo = "examples.identify_push.identify_push_listener_dialer:main" pubsub-demo = "examples.pubsub.pubsub:main" +mdns-demo = "examples.mDNS.mDNS:main" [project.optional-dependencies] dev = [