- packages/p2p: identity (peer_id from sha256 of RSA pubkey), TLS cert generation with SHA-256 fingerprint, GossipClient (WSS PubSub with per-topic handlers, dedup by msg_id, auto-reconnect), MdnsDiscovery (zeroconf optional dependency, graceful no-op fallback) - packages/relay: new meshnet-relay package — RelayServer (asyncio + websockets) with gossip fanout hub, circuit relay proxy for NAT traversal, peer registry; meshnet-relay CLI - packages/p2p/relay_bootstrap.json: team relay bootstrap list - Tracker: _NodeEntry gains relay_addr, cert_fingerprint, peer_id; both register and heartbeat handlers read and store these optional fields - docs/adr/0010 already written (previous commit) - conftest.py: packages/relay added to sys.path - 18 new tests; 115 passed total, 1 skipped (no regressions) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
61 lines
1.9 KiB
Python
61 lines
1.9 KiB
Python
"""meshnet-relay CLI entry point."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import logging
|
|
import sys
|
|
import time
|
|
from pathlib import Path
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(
|
|
prog="meshnet-relay",
|
|
description="Meshnet NAT-traversal relay and gossip hub",
|
|
)
|
|
parser.add_argument("--host", default="0.0.0.0", help="Interface to bind")
|
|
parser.add_argument("--port", type=int, default=8765, help="WebSocket port")
|
|
parser.add_argument("--cert", metavar="PATH", help="TLS certificate (PEM)")
|
|
parser.add_argument("--key", metavar="PATH", help="TLS private key (PEM)")
|
|
parser.add_argument("--max-peers", type=int, default=500, help="Max concurrent peers")
|
|
parser.add_argument("--log-level", default="INFO", choices=["DEBUG", "INFO", "WARNING", "ERROR"])
|
|
|
|
args = parser.parse_args()
|
|
logging.basicConfig(
|
|
level=getattr(logging, args.log_level),
|
|
format="%(asctime)s %(levelname)-8s %(name)s %(message)s",
|
|
)
|
|
|
|
from .server import RelayServer
|
|
|
|
ssl_cert = Path(args.cert) if args.cert else None
|
|
ssl_key = Path(args.key) if args.key else None
|
|
|
|
server = RelayServer(
|
|
host=args.host,
|
|
port=args.port,
|
|
ssl_cert=ssl_cert,
|
|
ssl_key=ssl_key,
|
|
max_peers=args.max_peers,
|
|
)
|
|
port = server.start()
|
|
scheme = "wss" if ssl_cert else "ws"
|
|
print(f"meshnet-relay listening on {scheme}://{args.host}:{port}", flush=True)
|
|
print(" /ws gossip PubSub", flush=True)
|
|
print(" /relay/<id> circuit relay to peer", flush=True)
|
|
print(" /health health check", flush=True)
|
|
print(" /v1/peers peer list", flush=True)
|
|
print("Press Ctrl-C to stop.", flush=True)
|
|
|
|
try:
|
|
while True:
|
|
time.sleep(1)
|
|
except KeyboardInterrupt:
|
|
print("\nStopping relay…", flush=True)
|
|
server.stop()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|