"""Tests for US-017: P2P gossip, relay node, and TLS infrastructure.""" from __future__ import annotations import json import threading import time from unittest.mock import MagicMock # --------------------------------------------------------------------------- # identity tests # --------------------------------------------------------------------------- def test_load_or_create_identity_generates_peer_id(tmp_path): "Load or create identity generates peer id\n\nTags: gossip, network, relay" from meshnet_p2p.identity import load_or_create_identity identity = load_or_create_identity(tmp_path / "identity.json") assert len(identity["peer_id"]) == 16 assert "public_key_pem" in identity assert "private_key_pem" in identity def test_identity_is_stable_across_loads(tmp_path): "Identity is stable across loads\n\nTags: gossip, network, relay" from meshnet_p2p.identity import load_or_create_identity path = tmp_path / "identity.json" first = load_or_create_identity(path) second = load_or_create_identity(path) assert first["peer_id"] == second["peer_id"] assert first["public_key_pem"] == second["public_key_pem"] def test_identity_different_for_different_paths(tmp_path): "Identity different for different paths\n\nTags: gossip, network, relay" from meshnet_p2p.identity import load_or_create_identity a = load_or_create_identity(tmp_path / "a.json") b = load_or_create_identity(tmp_path / "b.json") # Extremely unlikely to collide assert a["peer_id"] != b["peer_id"] def test_relay_peer_id_includes_node_name_for_shared_wallet(): "Relay peer id includes node name for shared wallet\n\nTags: gossip, network, relay, security, wallet" from meshnet_node.relay_bridge import peer_id_from_wallet wallet = "5gMLrmyBYTpkFjmyc4eGwcaWhYquyWgCBFFEqHzR5Qur" assert peer_id_from_wallet(wallet, node_name="gpu head") == "5gMLrmyBYTpkFjmy-gpu-head" assert peer_id_from_wallet(wallet, node_name="cpu-tail") == "5gMLrmyBYTpkFjmy-cpu-tail" def test_relay_peer_id_falls_back_to_endpoint_port_integer(): "Relay peer id falls back to endpoint port integer\n\nTags: gossip, network, relay" from meshnet_node.relay_bridge import peer_id_from_wallet wallet = "5gMLrmyBYTpkFjmyc4eGwcaWhYquyWgCBFFEqHzR5Qur" first = peer_id_from_wallet(wallet, advertised_addr="http://192.168.0.20:7001") second = peer_id_from_wallet(wallet, advertised_addr="http://192.168.0.20:7002") assert first == "5gMLrmyBYTpkFjmy-7001" assert second == "5gMLrmyBYTpkFjmy-7002" assert first != second # --------------------------------------------------------------------------- # TLS / certificate tests # --------------------------------------------------------------------------- def test_generate_self_signed_cert_creates_files(tmp_path): "Generate self signed cert creates files\n\nTags: gossip, network, relay" from meshnet_p2p.tls import generate_self_signed_cert cert_p, key_p = generate_self_signed_cert( cert_path=tmp_path / "cert.pem", key_path=tmp_path / "key.pem", common_name="localhost", ) assert cert_p.exists() assert key_p.exists() assert cert_p.stat().st_size > 100 assert key_p.stat().st_size > 100 def test_generate_self_signed_cert_is_idempotent(tmp_path): "Generate self signed cert is idempotent\n\nTags: gossip, network, relay" from meshnet_p2p.tls import generate_self_signed_cert args = dict(cert_path=tmp_path / "cert.pem", key_path=tmp_path / "key.pem", common_name="test") generate_self_signed_cert(**args) mtime1 = (tmp_path / "cert.pem").stat().st_mtime generate_self_signed_cert(**args) mtime2 = (tmp_path / "cert.pem").stat().st_mtime assert mtime1 == mtime2 # file not regenerated def test_cert_fingerprint_returns_sha256_prefix(tmp_path): "Cert fingerprint returns sha256 prefix\n\nTags: gossip, network, relay" from meshnet_p2p.tls import generate_self_signed_cert, cert_fingerprint cert_p, key_p = generate_self_signed_cert( cert_path=tmp_path / "cert.pem", key_path=tmp_path / "key.pem", common_name="test", ) fp = cert_fingerprint(cert_p) assert fp.startswith("sha256:") assert len(fp) == len("sha256:") + 64 # 32 bytes hex = 64 chars def test_make_server_ssl_context_loads_cert(tmp_path): "Make server ssl context loads cert\n\nTags: gossip, network, relay" import ssl from meshnet_p2p.tls import generate_self_signed_cert, make_server_ssl_context cert_p, key_p = generate_self_signed_cert( cert_path=tmp_path / "cert.pem", key_path=tmp_path / "key.pem", common_name="test", ) ctx = make_server_ssl_context(cert_p, key_p) assert isinstance(ctx, ssl.SSLContext) # --------------------------------------------------------------------------- # PeerRegistry tests # --------------------------------------------------------------------------- def test_peer_registry_register_and_list(): "Peer registry register and list\n\nTags: gossip, network, relay" from meshnet_relay.peer_registry import PeerRegistry reg = PeerRegistry() ws_mock = MagicMock() reg.register("peer1", "http://1.2.3.4:8001", ws_mock) assert len(reg) == 1 peers = reg.list_peers() assert len(peers) == 1 assert peers[0]["peer_id"] == "peer1" def test_peer_registry_all_except_excludes_sender(): "Peer registry all except excludes sender\n\nTags: gossip, network, relay" from meshnet_relay.peer_registry import PeerRegistry reg = PeerRegistry() reg.register("a", "http://a:8001", MagicMock()) reg.register("b", "http://b:8001", MagicMock()) reg.register("c", "http://c:8001", MagicMock()) others = reg.all_except("a") assert len(others) == 2 assert all(e.peer_id != "a" for e in others) def test_peer_registry_unregister_removes_peer(): "Peer registry unregister removes peer\n\nTags: gossip, network, relay" from meshnet_relay.peer_registry import PeerRegistry reg = PeerRegistry() reg.register("x", "http://x:8001", MagicMock()) reg.unregister("x") assert len(reg) == 0 assert reg.get("x") is None # --------------------------------------------------------------------------- # GossipClient + RelayServer integration test # --------------------------------------------------------------------------- def _start_relay(host="127.0.0.1", port=0): from meshnet_relay.server import RelayServer server = RelayServer(host=host, port=port) actual_port = server.start() return server, actual_port def test_gossip_fanout_through_relay(): "Node B publishes node-join; node A receives it within 2 seconds.\n\nTags: gossip, network, relay" from meshnet_p2p.gossip import GossipClient, TOPIC_NODE_JOIN relay, port = _start_relay() relay_url = f"ws://127.0.0.1:{port}/ws" client_a = GossipClient(relay_url=relay_url, peer_id="peer_a") client_b = GossipClient(relay_url=relay_url, peer_id="peer_b") received = [] client_a.subscribe(TOPIC_NODE_JOIN, lambda env: received.append(env)) client_a.start() client_b.start() assert client_a.wait_connected(timeout=5), "client_a failed to connect to relay" assert client_b.wait_connected(timeout=5), "client_b failed to connect to relay" # Give both peers time to register with relay time.sleep(0.2) client_b.publish(TOPIC_NODE_JOIN, {"addr": "http://192.168.1.10:8001", "peer_id": "peer_b"}) deadline = time.monotonic() + 2.0 while time.monotonic() < deadline and not received: time.sleep(0.05) client_a.stop() client_b.stop() relay.stop() assert received, "client_a did not receive node-join message from client_b" assert received[0]["topic"] == TOPIC_NODE_JOIN assert received[0]["from_peer"] == "peer_b" def test_gossip_dedup_prevents_processing_duplicate_message_ids(): "A message with a duplicate msg_id is only processed once.\n\nTags: gossip, network, relay" from meshnet_p2p.gossip import GossipClient, TOPIC_NODE_JOIN relay, port = _start_relay() relay_url = f"ws://127.0.0.1:{port}/ws" client_a = GossipClient(relay_url=relay_url, peer_id="peer_a2") client_b = GossipClient(relay_url=relay_url, peer_id="peer_b2") received = [] client_a.subscribe(TOPIC_NODE_JOIN, lambda env: received.append(env)) client_a.start() client_b.start() client_a.wait_connected(5) client_b.wait_connected(5) time.sleep(0.2) # Publish once client_b.publish(TOPIC_NODE_JOIN, {"test": "dedup"}) time.sleep(0.5) count = len(received) client_a.stop() client_b.stop() relay.stop() # Should have received exactly one message (not duplicated) assert count <= 1 def test_relay_server_peer_list_grows_on_connect(): "Relay registry grows when clients connect.\n\nTags: gossip, network, relay" from meshnet_p2p.gossip import GossipClient relay, port = _start_relay() relay_url = f"ws://127.0.0.1:{port}/ws" client = GossipClient(relay_url=relay_url, peer_id="solo_peer") client.start() client.wait_connected(5) time.sleep(0.3) # let peer-register message process peer_count = len(relay.registry) client.stop() relay.stop() assert peer_count >= 1 def test_relay_circuit_relay_proxies_message(): "A node behind NAT (client_a) receives a message via circuit relay from client_b.\n\nTags: gossip, network, relay" from meshnet_relay.server import RelayServer relay = RelayServer(host="127.0.0.1", port=0) port = relay.start() # client_a connects to gossip hub and registers received_via_relay = [] ready = threading.Event() def run_nat_client(): import websockets.sync.client as wsc with wsc.connect(f"ws://127.0.0.1:{port}/ws") as ws: ws.send(json.dumps({ "topic": "peer-register", "version": 1, "from_peer": "nat_peer", "msg_id": "reg-001", "timestamp": "2026-06-29T00:00:00Z", "ttl": 3, "payload": {"peer_id": "nat_peer", "addr": ""}, })) # consume peer-list response ws.recv() ready.set() # wait for a relayed message try: msg = ws.recv(timeout=3) received_via_relay.append(json.loads(msg)) except Exception: pass nat_thread = threading.Thread(target=run_nat_client, daemon=True) nat_thread.start() ready.wait(timeout=5) time.sleep(0.1) # ensure peer is in registry # client_b connects via circuit relay path def send_via_relay(): try: import websockets.sync.client as wsc with wsc.connect(f"ws://127.0.0.1:{port}/relay/nat_peer") as ws: ws.send(json.dumps({"topic": "direct-relay-test", "payload": {"hi": "there"}})) time.sleep(0.3) except Exception: pass relay_thread = threading.Thread(target=send_via_relay, daemon=True) relay_thread.start() relay_thread.join(timeout=3) nat_thread.join(timeout=3) relay.stop() assert received_via_relay, "NAT'd peer did not receive message via circuit relay" def test_relay_rpc_round_trips_http_request_to_peer(): "Relay /rpc/ sends one HTTP-shaped request to a connected peer.\n\nTags: gossip, network, relay" import websockets.sync.client as wsc # type: ignore[import] from meshnet_relay.server import RelayServer relay = RelayServer(host="127.0.0.1", port=0) port = relay.start() ready = threading.Event() def run_peer(): with wsc.connect(f"ws://127.0.0.1:{port}/ws") as ws: ws.send(json.dumps({ "topic": "peer-register", "version": 1, "from_peer": "rpc_peer", "msg_id": "rpc-reg-001", "payload": {"peer_id": "rpc_peer", "addr": ""}, })) ws.recv() ready.set() envelope = json.loads(ws.recv(timeout=3)) payload = envelope["payload"] ws.send(json.dumps({ "topic": "relay-http-response", "version": 1, "from_peer": "rpc_peer", "payload": { "request_id": payload["request_id"], "status": 200, "headers": {"Content-Type": "application/json"}, "body": json.dumps({"ok": True, "path": payload["path"]}), }, })) peer_thread = threading.Thread(target=run_peer, daemon=True) peer_thread.start() assert ready.wait(timeout=5) with wsc.connect(f"ws://127.0.0.1:{port}/rpc/rpc_peer") as ws: ws.send(json.dumps({ "request_id": "req-1", "method": "POST", "path": "/v1/chat/completions", "headers": {"Content-Type": "application/json"}, "body": "{}", })) response = json.loads(ws.recv(timeout=5)) relay.stop() peer_thread.join(timeout=3) assert response["status"] == 200 assert json.loads(response["body"]) == {"ok": True, "path": "/v1/chat/completions"} def test_relay_rpc_reuses_connection_for_sequential_requests(monkeypatch): "One route session should not repeat the WebSocket handshake per token.\n\nTags: gossip, network, relay" import websockets.sync.client as wsc # type: ignore[import] from meshnet_node.relay_bridge import decode_binary_frame, encode_binary_frame from meshnet_node.torch_server import _RelayHopClient from meshnet_relay.server import RelayServer relay = RelayServer(host="127.0.0.1", port=0) port = relay.start() ready = threading.Event() def run_peer(): with wsc.connect(f"ws://127.0.0.1:{port}/ws") as ws: ws.send(json.dumps({ "topic": "peer-register", "version": 1, "from_peer": "persistent_peer", "msg_id": "persistent-reg-001", "payload": {"peer_id": "persistent_peer", "addr": ""}, })) ws.recv() ready.set() for _ in range(2): raw = ws.recv(timeout=3) header, body = decode_binary_frame(raw) ws.send(encode_binary_frame({ "request_id": header["request_id"], "status": 200, "headers": {"Content-Type": "application/octet-stream"}, }, body)) peer_thread = threading.Thread(target=run_peer, daemon=True) peer_thread.start() assert ready.wait(timeout=5) real_connect = wsc.connect connection_attempts = 0 def tracked_connect(*args, **kwargs): nonlocal connection_attempts connection_attempts += 1 return real_connect(*args, **kwargs) monkeypatch.setattr(wsc, "connect", tracked_connect) client = _RelayHopClient(f"ws://127.0.0.1:{port}/rpc/persistent_peer", timeout=5) try: responses = [ client.request( "/forward", f"token-{index}".encode(), {"X-Meshnet-Session": "route-session"}, ) for index in range(2) ] finally: client.close() relay.stop() peer_thread.join(timeout=3) assert [status for status, _, _ in responses] == [200, 200] assert [body for _, _, body in responses] == [b"token-0", b"token-1"] assert connection_attempts == 1 def test_relay_hop_client_preserves_binary_json_and_closes_uncertain_legacy_socket(monkeypatch): "DIP-002: persistent clients correlate both frame formats and never replay a lost response.\n\nTags: gossip, network, relay" import websockets.sync.client as wsc # type: ignore[import] from meshnet_node.relay_bridge import decode_binary_frame, encode_binary_frame from meshnet_node.torch_server import _RelayHopClient, _RelayRequestUncertainError class FakeSocket: def __init__(self, responses): self.responses = iter(responses) self.sent = [] self.closed = False def send(self, frame): self.sent.append(frame) def recv(self, timeout): response = next(self.responses) if isinstance(response, BaseException): raise response request, _ = decode_binary_frame(self.sent[-1]) if isinstance(response, bytes): return encode_binary_frame({ "request_id": request["request_id"], "status": 200, "headers": {}, }, response) return json.dumps({"request_id": request["request_id"], "status": 200, "headers": {}, "body": response}) def close(self): self.closed = True healthy = FakeSocket([b"binary", "json"]) legacy = FakeSocket([b"first", TimeoutError("legacy relay closed")]) session_a = FakeSocket([b"a"]) session_b = FakeSocket([b"b"]) sockets = iter([healthy, legacy, session_a, session_b]) monkeypatch.setattr(wsc, "connect", lambda *args, **kwargs: next(sockets)) client = _RelayHopClient("ws://relay/rpc/peer", timeout=0.01) assert client.request("/forward", b"a", {})[2] == b"binary" assert client.request("/forward", b"b", {})[2] == b"json" first_id = decode_binary_frame(healthy.sent[0])[0]["request_id"] second_id = decode_binary_frame(healthy.sent[1])[0]["request_id"] assert first_id != second_id client.close() client = _RelayHopClient("ws://relay/rpc/peer", timeout=0.01) assert client.request("/forward", b"first", {})[2] == b"first" try: client.request("/forward", b"second", {}) except _RelayRequestUncertainError: pass else: raise AssertionError("a post-send disconnect must not be retried") assert legacy.closed is True assert client._ws is None # Route Sessions own their own requester socket; serialising one client's # calls must not accidentally make another session share it. first = _RelayHopClient("ws://relay/rpc/peer", timeout=0.01) second = _RelayHopClient("ws://relay/rpc/peer", timeout=0.01) assert first.request("/forward", b"a", {})[2] == b"a" assert second.request("/forward", b"b", {})[2] == b"b" assert first._ws is session_a assert second._ws is session_b def test_relay_rpc_cleans_pending_on_timeout_disconnect_and_cancellation(): "DIP-002: every terminal relay RPC path releases its pending response queue.\n\nTags: gossip, network, relay" import asyncio from meshnet_relay.server import RelayServer class Requester: def __init__(self): self.messages = [json.dumps({ "request_id": "legacy-id", "method": "POST", "path": "/forward", "headers": {}, "body": "{}", })] self.sent = [] async def recv(self): if self.messages: return self.messages.pop(0) raise EOFError async def send(self, message): self.sent.append(json.loads(message)) async def close(self, *args): pass class Target: async def send(self, message): pass async def wait_for_pending(relay): for _ in range(100): if relay._pending_rpc: return await asyncio.sleep(0) raise AssertionError("relay RPC did not register pending state") async def exercise(kind): relay = RelayServer(rpc_timeout=0.02, rpc_idle_timeout=0.01) relay.registry.register("peer", "", Target()) requester = Requester() task = asyncio.create_task(relay._handle_rpc(requester, "peer")) await wait_for_pending(relay) if kind == "disconnect": relay._fail_pending_for_peer("peer") elif kind == "cancel": task.cancel() if kind == "cancel": try: await task except asyncio.CancelledError: pass else: await task assert relay._pending_rpc == {} if kind == "timeout": assert requester.sent[-1]["status"] == 504 if kind == "disconnect": assert requester.sent[-1]["status"] == 503 for kind in ("timeout", "disconnect", "cancel"): asyncio.run(exercise(kind)) def test_binary_relay_frame_codecs_interoperate(): "Node and relay ship the same binary frame format as separate copies.\n\nTags: gossip, network, relay" import os from meshnet_node import relay_bridge from meshnet_relay import server as relay_server header = {"request_id": "r-1", "status": 200, "headers": {"X": "y"}} body = os.urandom(4096) for encoder, decoder in ( (relay_bridge.encode_binary_frame, relay_server.decode_binary_frame), (relay_server.encode_binary_frame, relay_bridge.decode_binary_frame), ): assert decoder(encoder(header, body)) == (header, body) try: relay_server.decode_binary_frame(b"not a frame") except ValueError: pass else: raise AssertionError("garbage bytes must not decode as a binary frame") def test_binary_relay_frame_layout_remains_byte_for_byte_compatible(): """Framing optimizations preserve the MRF1 header-length-body contract. Tags: gossip, network, relay, wire """ import json from meshnet_node.relay_bridge import BINARY_FRAME_MAGIC, encode_binary_frame header = {"request_id": "r-1", "headers": {"X-Meshnet-Shape": "1,1,2"}} body = b"\x01\x02\x03\x04" header_bytes = json.dumps(header, separators=(",", ":")).encode() assert encode_binary_frame(header, body) == ( BINARY_FRAME_MAGIC + len(header_bytes).to_bytes(4, "big") + header_bytes + body ) def test_activation_compression_round_trips_and_skips_small_bodies(): "Pipeline hops zstd-compress large activations; tiny decode bodies pass raw.\n\nTags: gossip, network, relay" import os from meshnet_node.server import _decompress_body from meshnet_node.torch_server import _maybe_compress_activation small = os.urandom(1024) assert _maybe_compress_activation(small) == (small, None) large = os.urandom(96 * 1024) * 2 # repetition so zstd actually shrinks it wire, encoding = _maybe_compress_activation(large) assert encoding == "zstd" assert len(wire) < len(large) assert _decompress_body(wire, encoding) == large def test_relay_rpc_carries_activation_sized_frames(): "A >1 MiB activation body must survive the full relay round trip.\n\nTags: gossip, network, relay" import http.server import os from meshnet_node.relay_bridge import RelayHttpBridge from meshnet_node.torch_server import _relay_hop from meshnet_relay.server import RelayServer body = os.urandom(2 * 1024 * 1024) # 2 MiB raw, ~2.7 MiB once base64-wrapped class EchoHandler(http.server.BaseHTTPRequestHandler): def do_POST(self): data = self.rfile.read(int(self.headers.get("Content-Length", 0))) self.send_response(200) self.send_header("Content-Type", "application/octet-stream") self.send_header("Content-Length", str(len(data))) self.end_headers() self.wfile.write(data) def log_message(self, *args): pass local = http.server.HTTPServer(("127.0.0.1", 0), EchoHandler) local_thread = threading.Thread(target=local.serve_forever, daemon=True) local_thread.start() relay = RelayServer(host="127.0.0.1", port=0) port = relay.start() bridge = RelayHttpBridge( relay_url=f"ws://127.0.0.1:{port}/ws", peer_id="big_peer", local_base_url=f"http://127.0.0.1:{local.server_address[1]}", advertised_addr="", ) try: bridge.start() assert bridge.wait_connected(timeout=5.0) time.sleep(0.2) # let peer-register land in the relay registry status, headers, resp_body = _relay_hop( f"ws://127.0.0.1:{port}/rpc/big_peer", "/forward", body, {"Content-Type": "application/octet-stream"}, timeout=30.0, ) finally: bridge.stop() relay.stop() local.shutdown() local_thread.join(timeout=3) assert status == 200 assert resp_body == body def test_node_relay_bridge_reconnects_after_failed_connection(monkeypatch): "Node-side relay bridge keeps retrying its outbound WebSocket connection.\n\nTags: gossip, network, relay" import websockets.sync.client as wsc # type: ignore[import] from meshnet_node.relay_bridge import RelayHttpBridge attempts = [] class FakeWebSocket: def __enter__(self): return self def __exit__(self, exc_type, exc, tb): return False def send(self, _message): pass def recv(self, timeout=1): raise TimeoutError def fake_connect(url, open_timeout=5, **kwargs): attempts.append((url, open_timeout)) if len(attempts) == 1: raise OSError("temporary relay outage") return FakeWebSocket() monkeypatch.setattr(wsc, "connect", fake_connect) bridge = RelayHttpBridge( relay_url="ws://relay.example/ws", peer_id="peer-reconnect", local_base_url="http://127.0.0.1:8001", advertised_addr="http://127.0.0.1:8001", reconnect_interval=0.01, ) try: info = bridge.start() assert info.relay_addr == "ws://relay.example/rpc/peer-reconnect" assert bridge.wait_connected(timeout=1.0) finally: bridge.stop() assert len(attempts) >= 2 # --------------------------------------------------------------------------- # Tracker gossip fields tests # --------------------------------------------------------------------------- def _start_tracker_and_register(extra_fields: dict) -> dict: """Helper: start tracker, register node with extra gossip fields, return response.""" import json as _json import urllib.request from meshnet_tracker.server import TrackerServer tracker = TrackerServer(host="127.0.0.1", port=0) port = tracker.start() url = f"http://127.0.0.1:{port}" payload = { "endpoint": "http://127.0.0.1:8001", "shard_start": 0, "shard_end": 7, "model": "stub-model", "hardware_profile": {}, "score": 1.0, **extra_fields, } data = _json.dumps(payload).encode() req = urllib.request.Request( f"{url}/v1/nodes/register", data=data, headers={"Content-Type": "application/json"}, method="POST", ) with urllib.request.urlopen(req, timeout=5) as r: resp = _json.loads(r.read()) tracker.stop() return resp def test_tracker_derives_relay_url_from_public_self_url(): "Tracker derives relay url from public self url\n\nTags: gossip, network, relay" from meshnet_tracker.server import TrackerServer, derive_relay_url_from_public_tracker_url assert derive_relay_url_from_public_tracker_url("https://ai.neuron.d-popov.com") == ( "wss://ai.neuron.d-popov.com/ws" ) assert derive_relay_url_from_public_tracker_url("http://127.0.0.1:8081") is None tracker = TrackerServer(cluster_self_url="https://ai.neuron.d-popov.com") port = tracker.start() try: import json as _json import urllib.request with urllib.request.urlopen(f"http://127.0.0.1:{port}/v1/network/map", timeout=5) as resp: body = _json.loads(resp.read()) assert body["relay_url"] == "wss://ai.neuron.d-popov.com/ws" assert body["relay"]["mode"] == "external" assert body["relay"]["url"] == "wss://ai.neuron.d-popov.com/ws" finally: tracker.stop() def test_tracker_accepts_relay_addr_in_registration(): "Tracker accepts relay addr in registration\n\nTags: gossip, network, relay" resp = _start_tracker_and_register({ "relay_addr": "ws://relay.meshnet.ai:8765/relay/abc123", "cert_fingerprint": "sha256:deadbeef", "peer_id": "abc123def456ef01", }) assert "node_id" in resp def test_tracker_accepts_registration_without_gossip_fields(): "Existing registrations without P2P fields still work.\n\nTags: gossip, network, relay" resp = _start_tracker_and_register({}) assert "node_id" in resp def test_tracker_network_map_exposes_relay_and_registered_peer(): "Tracker network map exposes relay and registered peer\n\nTags: gossip, network, relay" import json as _json import urllib.request from meshnet_tracker.server import TrackerServer tracker = TrackerServer(host="127.0.0.1", port=0, relay_url="wss://ai.neuron.d-popov.com/ws") port = tracker.start() url = f"http://127.0.0.1:{port}" try: req = urllib.request.Request( f"{url}/v1/nodes/register", data=_json.dumps({ "endpoint": "http://192.0.2.10:7000", "model": "stub-model", "shard_start": 0, "shard_end": 31, "relay_addr": "wss://ai.neuron.d-popov.com/rpc/peer123", "peer_id": "peer123", }).encode(), headers={"Content-Type": "application/json"}, method="POST", ) with urllib.request.urlopen(req, timeout=5): pass with urllib.request.urlopen(f"{url}/v1/network/map", timeout=5) as resp: body = _json.loads(resp.read()) finally: tracker.stop() assert body["relay_url"] == "wss://ai.neuron.d-popov.com/ws" assert body["relay"]["mode"] == "external" assert body["nodes"][0]["relay_addr"] == "wss://ai.neuron.d-popov.com/rpc/peer123" assert body["nodes"][0]["peer_id"] == "peer123" def test_tracker_can_embed_relay_server_and_advertise_it(): "Tracker can embed relay server and advertise it\n\nTags: gossip, network, relay" import json as _json import urllib.request import websockets.sync.client as wsc # type: ignore[import] from meshnet_tracker.server import TrackerServer tracker = TrackerServer( host="127.0.0.1", port=0, embedded_relay=True, embedded_relay_host="127.0.0.1", embedded_relay_port=0, ) port = tracker.start() try: with urllib.request.urlopen(f"http://127.0.0.1:{port}/v1/network/map", timeout=5) as resp: body = _json.loads(resp.read()) assert body["relay"]["mode"] == "embedded" assert body["relay_url"].startswith("ws://127.0.0.1:") assert body["relay_url"].endswith("/ws") with wsc.connect(body["relay_url"], open_timeout=5) as ws: ws.send(_json.dumps({ "topic": "peer-register", "version": 1, "from_peer": "embedded-peer", "msg_id": "embedded-reg-1", "payload": {"peer_id": "embedded-peer", "addr": ""}, })) peer_list = _json.loads(ws.recv(timeout=5)) assert peer_list["topic"] == "peer-list" finally: tracker.stop() # --------------------------------------------------------------------------- # mDNS (no-op without zeroconf installed) # --------------------------------------------------------------------------- def test_mdns_discovery_is_available_flag(): "Mdns discovery is available flag\n\nTags: gossip, network, relay" from meshnet_p2p.mdns import MdnsDiscovery disc = MdnsDiscovery(peer_id="test", port=8001) # is_available() should be bool regardless of zeroconf install status assert isinstance(disc.is_available(), bool) def test_mdns_start_and_stop_without_zeroconf(monkeypatch): "Mdns start and stop without zeroconf\n\nTags: gossip, network, relay" from meshnet_p2p import mdns as mdns_mod monkeypatch.setattr(mdns_mod, "_HAS_ZEROCONF", False) from meshnet_p2p.mdns import MdnsDiscovery disc = MdnsDiscovery(peer_id="x", port=8001) disc.start() # should not raise disc.stop() # should not raise # --------------------------------------------------------------------------- # US-036: streamed responses over relay RPC / US-037: bridge concurrency # --------------------------------------------------------------------------- def _start_local_http_server(handler_cls): from http.server import ThreadingHTTPServer server = ThreadingHTTPServer(("127.0.0.1", 0), handler_cls) thread = threading.Thread(target=server.serve_forever, daemon=True) thread.start() return server, server.server_address[1] def _run_streaming_peer(port: int, peer_id: str, ready: threading.Event): """Peer that answers one rpc request with a 4-frame streamed response.""" import websockets.sync.client as wsc # type: ignore[import] with wsc.connect(f"ws://127.0.0.1:{port}/ws") as ws: ws.send(json.dumps({ "topic": "peer-register", "version": 1, "from_peer": peer_id, "msg_id": f"{peer_id}-reg", "payload": {"peer_id": peer_id, "addr": ""}, })) ws.recv() ready.set() envelope = json.loads(ws.recv(timeout=5)) rid = envelope["payload"]["request_id"] def frame(payload): ws.send(json.dumps({ "topic": "relay-http-response", "version": 1, "from_peer": peer_id, "payload": payload, })) frame({"request_id": rid, "status": 200, "headers": {"Content-Type": "text/event-stream"}, "stream": True, "done": False}) frame({"request_id": rid, "stream": True, "chunk": 'data: {"choices": [{"delta": {"content": "hello"}}]}\n\n', "done": False}) frame({"request_id": rid, "stream": True, "chunk": "data: [DONE]\n\n", "done": False}) frame({"request_id": rid, "stream": True, "done": True}) def test_relay_rpc_forwards_streamed_frames_in_order(): "A streamed response traverses the relay as multiple frames ending with done.\n\nTags: gossip, network, relay, streaming" import websockets.sync.client as wsc # type: ignore[import] from meshnet_relay.server import RelayServer relay = RelayServer(host="127.0.0.1", port=0) port = relay.start() ready = threading.Event() peer_thread = threading.Thread( target=_run_streaming_peer, args=(port, "stream_peer", ready), daemon=True ) peer_thread.start() assert ready.wait(timeout=5) frames = [] with wsc.connect(f"ws://127.0.0.1:{port}/rpc/stream_peer") as ws: ws.send(json.dumps({ "request_id": "req-stream-1", "method": "POST", "path": "/v1/chat/completions", "headers": {}, "body": "{}", })) while True: frames.append(json.loads(ws.recv(timeout=5))) if not frames[-1].get("stream") or frames[-1].get("done"): break relay.stop() peer_thread.join(timeout=3) assert len(frames) == 4 assert frames[0]["status"] == 200 and frames[0]["stream"] is True assert frames[1]["chunk"].startswith("data:") assert frames[2]["chunk"] == "data: [DONE]\n\n" assert frames[-1]["done"] is True def test_tracker_relay_http_request_collapses_streamed_frames(): "Buffered wrapper joins chunk frames into one response body.\n\nTags: gossip, network, relay, streaming" from meshnet_relay.server import RelayServer from meshnet_tracker.server import _relay_http_request relay = RelayServer(host="127.0.0.1", port=0) port = relay.start() ready = threading.Event() peer_thread = threading.Thread( target=_run_streaming_peer, args=(port, "buffer_peer", ready), daemon=True ) peer_thread.start() assert ready.wait(timeout=5) response = _relay_http_request( f"ws://127.0.0.1:{port}/rpc/buffer_peer", path="/v1/chat/completions", body=b"{}", headers={}, ) relay.stop() peer_thread.join(timeout=3) assert response is not None assert response["status"] == 200 assert '"content": "hello"' in response["body"] assert "data: [DONE]" in response["body"] def test_stream_line_tokens_accounting(): "Stream line tokens accounting\n\nTags: gossip, network, relay, streaming" from meshnet_tracker.server import _stream_line_tokens assert _stream_line_tokens(b": comment") == (0, None) assert _stream_line_tokens(b"data: [DONE]") == (0, None) observed, reported = _stream_line_tokens( b'data: {"choices": [{"delta": {"content": "two words"}}]}' ) assert observed == 2 and reported is None observed, reported = _stream_line_tokens(b'data: {"usage": {"total_tokens": 42}}') assert reported == {"prompt": None, "completion": None, "total": 42} assert _stream_line_tokens(b"data: not-json") == (1, None) def test_relay_bridge_streams_sse_as_chunk_frames(): "Bridge forwards a local SSE response as header + chunk frames + done.\n\nTags: gossip, network, relay, streaming" from http.server import BaseHTTPRequestHandler from meshnet_node.relay_bridge import RelayHttpBridge class SSEHandler(BaseHTTPRequestHandler): def do_POST(self): self.rfile.read(int(self.headers.get("Content-Length", 0) or 0)) self.send_response(200) self.send_header("Content-Type", "text/event-stream") self.end_headers() for i in range(3): self.wfile.write(f'data: {{"i": {i}}}\n\n'.encode()) self.wfile.flush() self.wfile.write(b"data: [DONE]\n\n") def log_message(self, *args): pass server, port = _start_local_http_server(SSEHandler) try: bridge = RelayHttpBridge( relay_url="ws://unused.example/ws", peer_id="peer-sse", local_base_url=f"http://127.0.0.1:{port}", advertised_addr="", ) frames = [] bridge._send_response_frame = lambda payload: (frames.append(payload), True)[1] bridge._process_request({ "request_id": "req-sse-1", "method": "POST", "path": "/v1/chat/completions", "headers": {"Content-Type": "application/json"}, "body": "{}", }) finally: server.shutdown() assert frames[0]["stream"] is True and frames[0]["status"] == 200 chunk_frames = [f for f in frames if f.get("chunk")] assert len(chunk_frames) >= 2 assert frames[-1] == {"request_id": "req-sse-1", "stream": True, "done": True} assert "".join(f["chunk"] for f in chunk_frames).count("data:") == 4 def test_relay_bridge_non_stream_response_stays_single_frame(): "Relay bridge non stream response stays single frame\n\nTags: gossip, network, relay, streaming" from http.server import BaseHTTPRequestHandler from meshnet_node.relay_bridge import RelayHttpBridge class JSONHandler(BaseHTTPRequestHandler): def do_POST(self): self.rfile.read(int(self.headers.get("Content-Length", 0) or 0)) body = json.dumps({"ok": True}).encode() self.send_response(200) self.send_header("Content-Type", "application/json") self.send_header("Content-Length", str(len(body))) self.end_headers() self.wfile.write(body) def log_message(self, *args): pass server, port = _start_local_http_server(JSONHandler) try: bridge = RelayHttpBridge( relay_url="ws://unused.example/ws", peer_id="peer-json", local_base_url=f"http://127.0.0.1:{port}", advertised_addr="", ) frames = [] bridge._send_response_frame = lambda payload: (frames.append(payload), True)[1] bridge._process_request({ "request_id": "req-json-1", "method": "POST", "path": "/v1/chat/completions", "headers": {"Content-Type": "application/json"}, "body": "{}", }) finally: server.shutdown() assert len(frames) == 1 assert "stream" not in frames[0] assert json.loads(frames[0]["body"]) == {"ok": True} def test_relay_bridge_serves_concurrent_requests(): "US-037: a slow relayed request must not block a fast one.\n\nTags: gossip, network, relay" import websockets.sync.client as wsc # type: ignore[import] from http.server import BaseHTTPRequestHandler from meshnet_node.relay_bridge import RelayHttpBridge from meshnet_relay.server import RelayServer class Handler(BaseHTTPRequestHandler): def do_POST(self): self.rfile.read(int(self.headers.get("Content-Length", 0) or 0)) if self.path == "/slow": time.sleep(2.0) body = json.dumps({"path": self.path}).encode() self.send_response(200) self.send_header("Content-Type", "application/json") self.send_header("Content-Length", str(len(body))) self.end_headers() self.wfile.write(body) def log_message(self, *args): pass http_server, http_port = _start_local_http_server(Handler) relay = RelayServer(host="127.0.0.1", port=0) relay_port = relay.start() bridge = RelayHttpBridge( relay_url=f"ws://127.0.0.1:{relay_port}/ws", peer_id="conc_peer", local_base_url=f"http://127.0.0.1:{http_port}", advertised_addr="", ) bridge.start() results = {} try: assert bridge.wait_connected(timeout=5) deadline = time.time() + 5 while time.time() < deadline and relay.registry.get("conc_peer") is None: time.sleep(0.05) assert relay.registry.get("conc_peer") is not None def call(path, key): with wsc.connect(f"ws://127.0.0.1:{relay_port}/rpc/conc_peer") as ws: ws.send(json.dumps({ "request_id": f"req-{key}", "method": "POST", "path": path, "headers": {"Content-Type": "application/json"}, "body": "{}", })) results[key] = (json.loads(ws.recv(timeout=10)), time.monotonic()) start = time.monotonic() slow_thread = threading.Thread(target=call, args=("/slow", "slow"), daemon=True) slow_thread.start() time.sleep(0.3) # let the slow request reach the bridge first call("/fast", "fast") fast_elapsed = results["fast"][1] - start slow_thread.join(timeout=10) finally: bridge.stop() relay.stop() http_server.shutdown() assert results["fast"][0]["status"] == 200 assert results["slow"][0]["status"] == 200 # The fast request finished while the slow one was still in flight. assert fast_elapsed < 1.5 # Responses matched by request_id despite out-of-order completion. assert json.loads(results["fast"][0]["body"]) == {"path": "/fast"} assert json.loads(results["slow"][0]["body"]) == {"path": "/slow"}