Add relay-backed public node registration

This commit is contained in:
Dobromir Popov
2026-06-30 15:01:49 +02:00
parent a4373a6202
commit 9ca198ee1e
9 changed files with 516 additions and 2 deletions

View File

@@ -295,6 +295,61 @@ def test_relay_circuit_relay_proxies_message():
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/<peer> sends one HTTP-shaped request to a connected peer."""
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"}
# ---------------------------------------------------------------------------
# Tracker gossip fields tests
# ---------------------------------------------------------------------------
@@ -349,6 +404,41 @@ def test_tracker_accepts_registration_without_gossip_fields():
assert "node_id" in resp
def test_tracker_network_map_exposes_relay_and_registered_peer():
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["nodes"][0]["relay_addr"] == "wss://ai.neuron.d-popov.com/rpc/peer123"
assert body["nodes"][0]["peer_id"] == "peer123"
# ---------------------------------------------------------------------------
# mDNS (no-op without zeroconf installed)
# ---------------------------------------------------------------------------