Skip to content

Commit 0038ef9

Browse files
authored
Merge branch 'main' into main
2 parents 4d8afa6 + 4c739f6 commit 0038ef9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1685
-109
lines changed

docs/examples.mDNS.rst

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
mDNS Peer Discovery Example
2+
===========================
3+
4+
This example demonstrates how to use mDNS (Multicast DNS) for peer discovery in py-libp2p.
5+
6+
Prerequisites
7+
-------------
8+
9+
First, ensure you have py-libp2p installed and your environment is activated:
10+
11+
.. code-block:: console
12+
13+
$ python -m pip install libp2p
14+
15+
Running the Example
16+
-------------------
17+
18+
The mDNS demo script allows you to discover peers on your local network using mDNS. To start a peer, run:
19+
20+
.. code-block:: console
21+
22+
$ mdns-demo
23+
24+
You should see output similar to:
25+
26+
.. code-block:: console
27+
28+
Run this from another console to start another peer on a different port:
29+
30+
python mdns-demo -p <ANOTHER_PORT>
31+
32+
Waiting for mDNS peer discovery events...
33+
34+
2025-06-20 23:28:12,052 - libp2p.example.discovery.mdns - INFO - Starting peer Discovery
35+
36+
To discover peers, open another terminal and run the same command with a different port:
37+
38+
.. code-block:: console
39+
40+
$ python mdns-demo -p 9001
41+
42+
You should see output indicating that a new peer has been discovered:
43+
44+
.. code-block:: console
45+
46+
Run this from the same folder in another console to start another peer on a different port:
47+
48+
python mdns-demo -p <ANOTHER_PORT>
49+
50+
Waiting for mDNS peer discovery events...
51+
52+
2025-06-20 23:43:43,786 - libp2p.example.discovery.mdns - INFO - Starting peer Discovery
53+
2025-06-20 23:43:43,790 - libp2p.example.discovery.mdns - INFO - Discovered: 16Uiu2HAmGxy5NdQEjZWtrYUMrzdp3Syvg7MB2E5Lx8weA9DanYxj
54+
55+
When a new peer is discovered, its peer ID will be printed in the console output.
56+
57+
How it Works
58+
------------
59+
60+
- Each node advertises itself on the local network using mDNS.
61+
- When a new peer is discovered, the handler prints its peer ID.
62+
- This is useful for local peer discovery without requiring a DHT or bootstrap nodes.
63+
64+
You can modify the script to perform additional actions when peers are discovered, such as opening streams or exchanging messages.

docs/examples.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ Examples
1313
examples.pubsub
1414
examples.circuit_relay
1515
examples.kademlia
16+
examples.mDNS

docs/libp2p.discovery.events.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
libp2p.discovery.events package
2+
===============================
3+
4+
Submodules
5+
----------
6+
7+
libp2p.discovery.events.peerDiscovery module
8+
--------------------------------------------
9+
10+
.. automodule:: libp2p.discovery.events.peerDiscovery
11+
:members:
12+
:undoc-members:
13+
:show-inheritance:
14+
15+
Module contents
16+
---------------
17+
18+
.. automodule:: libp2p.discovery.events
19+
:members:
20+
:undoc-members:
21+
:show-inheritance:

docs/libp2p.discovery.mdns.rst

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
libp2p.discovery.mdns package
2+
=============================
3+
4+
Submodules
5+
----------
6+
7+
libp2p.discovery.mdns.broadcaster module
8+
----------------------------------------
9+
10+
.. automodule:: libp2p.discovery.mdns.broadcaster
11+
:members:
12+
:undoc-members:
13+
:show-inheritance:
14+
15+
libp2p.discovery.mdns.listener module
16+
-------------------------------------
17+
18+
.. automodule:: libp2p.discovery.mdns.listener
19+
:members:
20+
:undoc-members:
21+
:show-inheritance:
22+
23+
libp2p.discovery.mdns.mdns module
24+
---------------------------------
25+
26+
.. automodule:: libp2p.discovery.mdns.mdns
27+
:members:
28+
:undoc-members:
29+
:show-inheritance:
30+
31+
libp2p.discovery.mdns.utils module
32+
----------------------------------
33+
34+
.. automodule:: libp2p.discovery.mdns.utils
35+
:members:
36+
:undoc-members:
37+
:show-inheritance:
38+
39+
Module contents
40+
---------------
41+
42+
.. automodule:: libp2p.discovery.mdns
43+
:members:
44+
:undoc-members:
45+
:show-inheritance:

docs/libp2p.discovery.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
libp2p.discovery package
2+
========================
3+
4+
Subpackages
5+
-----------
6+
7+
.. toctree::
8+
:maxdepth: 4
9+
10+
libp2p.discovery.events
11+
libp2p.discovery.mdns
12+
13+
Submodules
14+
----------
15+
16+
Module contents
17+
---------------
18+
19+
.. automodule:: libp2p.discovery
20+
:members:
21+
:undoc-members:
22+
:show-inheritance:

docs/libp2p.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Subpackages
88
:maxdepth: 4
99

1010
libp2p.crypto
11+
libp2p.discovery
1112
libp2p.host
1213
libp2p.identity
1314
libp2p.io

examples/mDNS/mDNS.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import argparse
2+
import logging
3+
import secrets
4+
5+
import multiaddr
6+
import trio
7+
8+
from libp2p import (
9+
new_host,
10+
)
11+
from libp2p.abc import PeerInfo
12+
from libp2p.crypto.secp256k1 import (
13+
create_new_key_pair,
14+
)
15+
from libp2p.discovery.events.peerDiscovery import peerDiscovery
16+
17+
logger = logging.getLogger("libp2p.discovery.mdns")
18+
logger.setLevel(logging.INFO)
19+
handler = logging.StreamHandler()
20+
handler.setFormatter(
21+
logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
22+
)
23+
logger.addHandler(handler)
24+
25+
# Set root logger to DEBUG to capture all logs from dependencies
26+
logging.getLogger().setLevel(logging.DEBUG)
27+
28+
29+
def onPeerDiscovery(peerinfo: PeerInfo):
30+
logger.info(f"Discovered: {peerinfo.peer_id}")
31+
32+
33+
async def run(port: int) -> None:
34+
secret = secrets.token_bytes(32)
35+
key_pair = create_new_key_pair(secret)
36+
listen_addr = multiaddr.Multiaddr(f"/ip4/0.0.0.0/tcp/{port}")
37+
38+
peerDiscovery.register_peer_discovered_handler(onPeerDiscovery)
39+
40+
print(
41+
"Run this from the same folder in another console to "
42+
"start another peer on a different port:\n\n"
43+
"mdns-demo -p <ANOTHER_PORT>\n"
44+
)
45+
print("Waiting for mDNS peer discovery events...\n")
46+
47+
logger.info("Starting peer Discovery")
48+
host = new_host(key_pair=key_pair, enable_mDNS=True)
49+
async with host.run(listen_addrs=[listen_addr]):
50+
await trio.sleep_forever()
51+
52+
53+
def main() -> None:
54+
description = """
55+
This program demonstrates mDNS peer discovery using libp2p.
56+
To use it, run 'mdns-demo -p <PORT>', where <PORT> is the port number.
57+
Start multiple peers on different ports to see discovery in action.
58+
"""
59+
parser = argparse.ArgumentParser(description=description)
60+
parser.add_argument("-p", "--port", default=0, type=int, help="source port number")
61+
parser.add_argument(
62+
"-v", "--verbose", action="store_true", help="Enable verbose output"
63+
)
64+
args = parser.parse_args()
65+
if args.verbose:
66+
logger.setLevel(logging.DEBUG)
67+
try:
68+
trio.run(run, args.port)
69+
except KeyboardInterrupt:
70+
logger.info("Exiting...")
71+
72+
73+
if __name__ == "__main__":
74+
main()

libp2p/__init__.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
TProtocol,
3333
TSecurityOptions,
3434
)
35+
from libp2p.discovery.mdns.mdns import (
36+
MDNSDiscovery,
37+
)
3538
from libp2p.host.basic_host import (
3639
BasicHost,
3740
)
@@ -245,6 +248,7 @@ def new_host(
245248
disc_opt: IPeerRouting | None = None,
246249
muxer_preference: Literal["YAMUX", "MPLEX"] | None = None,
247250
listen_addrs: Sequence[multiaddr.Multiaddr] | None = None,
251+
enable_mDNS: bool = False,
248252
) -> IHost:
249253
"""
250254
Create a new libp2p host based on the given parameters.
@@ -256,6 +260,7 @@ def new_host(
256260
:param disc_opt: optional discovery
257261
:param muxer_preference: optional explicit muxer preference
258262
:param listen_addrs: optional list of multiaddrs to listen on
263+
:param enable_mDNS: whether to enable mDNS discovery
259264
:return: return a host instance
260265
"""
261266
swarm = new_swarm(
@@ -268,8 +273,7 @@ def new_host(
268273
)
269274

270275
if disc_opt is not None:
271-
return RoutedHost(swarm, disc_opt)
272-
return BasicHost(swarm)
273-
276+
return RoutedHost(swarm, disc_opt, enable_mDNS)
277+
return BasicHost(swarm, enable_mDNS)
274278

275279
__version__ = __version("libp2p")

libp2p/discovery/__init__.py

Whitespace-only changes.

libp2p/discovery/events/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)