Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
60ed1fa
Add TLS example under examples/doc-examples (follow-up to PR #831)
Fatumayattani Oct 6, 2025
c33f3c1
Merge branch 'main' into feature/tls-example
yashksaini-coder Oct 6, 2025
0e01c0a
Merge branch 'main' into feature/tls-example
yashksaini-coder Oct 6, 2025
5a8a8ac
Merge branch 'main' into feature/tls-example
seetadev Oct 10, 2025
378d4b2
Merge branch 'main' into feature/tls-example
yashksaini-coder Oct 12, 2025
9b556ff
Merge branch 'main' into feature/tls-example
yashksaini-coder Oct 14, 2025
7b63377
Enhance TLS example by generating a new RSA key pair for the host
yashksaini-coder Oct 14, 2025
d0910b1
Add TLS client example with echo and chat modes
yashksaini-coder Oct 14, 2025
dbfe1f7
Enhance TLS server example with improved message handling and logging…
yashksaini-coder Oct 14, 2025
b857741
Refactor TLS example scripts for improved readability and logging; en…
yashksaini-coder Oct 14, 2025
93e92e9
Refactor TLS example scripts to use TProtocol for protocol IDs; impro…
yashksaini-coder Oct 14, 2025
288b513
Update TLS example scripts to use union type for return values; clean…
yashksaini-coder Oct 14, 2025
a79f691
Enhance TLS example scripts by integrating utility functions for opti…
yashksaini-coder Oct 14, 2025
d30745c
Remove unused import of multiaddr in TLS example script to streamline…
yashksaini-coder Oct 14, 2025
aaad0d9
Add type ignore comments for TLS transport and Mplex options in examp…
yashksaini-coder Oct 15, 2025
ac0ef65
Revert "Remove unused import of multiaddr in TLS example script to st…
yashksaini-coder Oct 19, 2025
a2b830b
Merge branch 'main' into feature/tls-example
yashksaini-coder Oct 20, 2025
c438f43
Merge branch 'main' into feature/tls-example
yashksaini-coder Oct 20, 2025
c5dada9
Merge branch 'feature/tls-example' of https://github.com/guha-rahul/p…
yashksaini-coder Oct 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 155 additions & 0 deletions examples/doc-examples/example_tls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
#!/usr/bin/env python3
"""
TLS Server Example

This example demonstrates how to create a TLS-enabled py-libp2p host that accepts
connections and responds to messages from clients. The server will print out its
listen addresses, which can be used by clients to connect.

Usage:
python example_tls.py [--port PORT]
"""

import argparse
from datetime import datetime

import multiaddr
import trio

from libp2p import generate_new_rsa_identity, new_host
from libp2p.custom_types import TProtocol
from libp2p.security.tls.transport import (
PROTOCOL_ID as TLS_PROTOCOL_ID,
TLSTransport,
)
from libp2p.stream_muxer.mplex.mplex import MPLEX_PROTOCOL_ID, Mplex
from libp2p.utils import get_available_interfaces, get_optimal_binding_address

# Define a protocol ID for our example
PROTOCOL_ID = TProtocol("/tls-example/1.0.0")


async def handle_echo(stream):
"""
Handle an incoming stream from a client.

Args:
stream: The incoming stream

"""
peer_id = stream.muxed_conn.peer_id
remote_addr = stream.muxed_conn.remote_multiaddr
timestamp = datetime.now().strftime("%H:%M:%S")

print(f"[{timestamp}] Received new stream from peer: {peer_id} at {remote_addr}")

# Get connection security details if available
conn = stream.muxed_conn
if hasattr(conn, "secured_conn") and hasattr(conn.secured_conn, "tls_version"):
print(f"[{timestamp}] Connection secured with: {conn.secured_conn.tls_version}")

try:
# Read the client's message
message = await stream.read(4096)
print(f"[{timestamp}] Received message: {message.decode()}")

# Send a response back
response = (
f"Server received your message of length {len(message)}. "
f"Your message was: {message.decode()}"
).encode()
await stream.write(response)
print(f"[{timestamp}] Sent response to peer: {peer_id}")
except Exception as e:
print(f"[{timestamp}] Error handling stream: {e}")
finally:
# Close the stream when done
await stream.close()
print(f"[{timestamp}] Closed stream with peer: {peer_id}")


async def main(host_str="0.0.0.0", port=8000) -> None:
"""
Run a TLS-enabled server that accepts connections and handles messages.

Args:
host_str: The host address to listen on (0.0.0.0 for all interfaces)
port: The port to listen on (0 for random port)

"""
# Generate a new key pair for this host
key_pair = generate_new_rsa_identity()

# Use the new address paradigm to get optimal binding addresses
if host_str == "0.0.0.0":
# Use available interfaces for wildcard binding
listen_addrs = get_available_interfaces(port, "tcp")
else:
# Use optimal binding address for specific host
listen_addrs = [get_optimal_binding_address(port, "tcp")]

timestamp = datetime.now().strftime("%H:%M:%S")
print(f"[{timestamp}] Starting TLS-enabled libp2p host...")

# Create a TLS transport with our key pair and explicit muxer preference
tls_transport = TLSTransport(key_pair, muxers=[MPLEX_PROTOCOL_ID])

# Create a host with TLS security transport
host = new_host(
key_pair=key_pair,
sec_opt={TLS_PROTOCOL_ID: tls_transport}, # type: ignore
muxer_opt={MPLEX_PROTOCOL_ID: Mplex}, # Using MPLEX for stream multiplexing
)

# Set up a handler for the echo protocol
host.set_stream_handler(PROTOCOL_ID, handle_echo) # type: ignore

async with host.run(listen_addrs=listen_addrs):
timestamp = datetime.now().strftime("%H:%M:%S")
print(f"[{timestamp}] Host started with Peer ID: {host.get_id()}")

# Create a connection string with our configured host/port
peer_id = host.get_id()
connection_addr = f"/ip4/{host_str}/tcp/{port}/p2p/{peer_id}"

print(f"Server listening on: {host_str}:{port}")
print(f"Server peer ID: {peer_id}")

print(f"\nProtocol: {PROTOCOL_ID}")
print("Security: TLS 1.3")
print("Stream Multiplexing: MPLEX")

print("\nUse example_tls_client.py to connect to this server:")
print(f" python example_tls_client.py --server {connection_addr}")

print("\nTLS is now active. Waiting for connections. Press Ctrl+C to stop.")
try:
# Keep the server running until interrupted
await trio.sleep_forever()
except KeyboardInterrupt:
pass

timestamp = datetime.now().strftime("%H:%M:%S")
print(f"[{timestamp}] Host shut down cleanly.")


def parse_args():
parser = argparse.ArgumentParser(description="TLS Server Example")
parser.add_argument("--host", default="0.0.0.0", help="Host address to listen on")
parser.add_argument(
"-p", "--port", type=int, default=8000, help="Port to listen on"
)
parser.add_argument("--debug", action="store_true", help="Enable debug logging")
return parser.parse_args()


if __name__ == "__main__":
args = parse_args()

# Set up logging if debug is enabled
if args.debug:
import logging

logging.basicConfig(level=logging.DEBUG)

trio.run(main, args.host, args.port)
Loading