11import argparse
2+ import random
3+ import secrets
24
35import multiaddr
46import trio
1214from libp2p .custom_types import (
1315 TProtocol ,
1416)
17+ from libp2p .network .stream .exceptions import (
18+ StreamEOF ,
19+ )
1520from libp2p .network .stream .net_stream import (
1621 INetStream ,
1722)
1823from libp2p .peer .peerinfo import (
1924 info_from_p2p_addr ,
2025)
26+ from libp2p .utils .address_validation import (
27+ find_free_port ,
28+ get_available_interfaces ,
29+ )
2130
2231PROTOCOL_ID = TProtocol ("/echo/1.0.0" )
2332MAX_READ_LEN = 2 ** 32 - 1
2433
2534
2635async def _echo_stream_handler (stream : INetStream ) -> None :
27- # Wait until EOF
28- msg = await stream .read (MAX_READ_LEN )
29- await stream .write (msg )
30- await stream .close ()
36+ try :
37+ peer_id = stream .muxed_conn .peer_id
38+ print (f"Received connection from { peer_id } " )
39+ # Wait until EOF
40+ msg = await stream .read (MAX_READ_LEN )
41+ print (f"Echoing message: { msg .decode ('utf-8' )} " )
42+ await stream .write (msg )
43+ except StreamEOF :
44+ print ("Stream closed by remote peer." )
45+ except Exception as e :
46+ print (f"Error in echo handler: { e } " )
47+ finally :
48+ await stream .close ()
3149
3250
3351async def run (port : int , destination : str , seed : int | None = None ) -> None :
34- listen_addr = multiaddr .Multiaddr (f"/ip4/0.0.0.0/tcp/{ port } " )
52+ if port <= 0 :
53+ port = find_free_port ()
54+ listen_addr = get_available_interfaces (port )
3555
3656 if seed :
37- import random
38-
3957 random .seed (seed )
4058 secret_number = random .getrandbits (32 * 8 )
4159 secret = secret_number .to_bytes (length = 32 , byteorder = "big" )
4260 else :
43- import secrets
44-
4561 secret = secrets .token_bytes (32 )
4662
4763 host = new_host (key_pair = create_new_key_pair (secret ))
48- async with host .run (listen_addrs = [ listen_addr ] ), trio .open_nursery () as nursery :
64+ async with host .run (listen_addrs = listen_addr ), trio .open_nursery () as nursery :
4965 # Start the peer-store cleanup task
5066 nursery .start_soon (host .get_peerstore ().start_cleanup_task , 60 )
5167
@@ -54,10 +70,15 @@ async def run(port: int, destination: str, seed: int | None = None) -> None:
5470 if not destination : # its the server
5571 host .set_stream_handler (PROTOCOL_ID , _echo_stream_handler )
5672
73+ # Print all listen addresses with peer ID (JS parity)
74+ print ("Listener ready, listening on:\n " )
75+ peer_id = host .get_id ().to_string ()
76+ for addr in listen_addr :
77+ print (f"{ addr } /p2p/{ peer_id } " )
78+
5779 print (
58- "Run this from the same folder in another console:\n \n "
59- f"echo-demo "
60- f"-d { host .get_addrs ()[0 ]} \n "
80+ "\n Run this from the same folder in another console:\n \n "
81+ f"echo-demo -d { host .get_addrs ()[0 ]} \n "
6182 )
6283 print ("Waiting for incoming connections..." )
6384 await trio .sleep_forever ()
0 commit comments