dropp baes64 use binary
This commit is contained in:
@@ -41,6 +41,26 @@ def ws_max_size() -> int | None:
|
||||
return None if value <= 0 else value
|
||||
|
||||
|
||||
# Binary relay frame: JSON header (request/response metadata) + raw body in one
|
||||
# WebSocket binary message. Activation bodies stay bytes end to end — no base64
|
||||
# inflation, no JSON re-encode of megabytes per hop. Text JSON frames remain the
|
||||
# control plane (gossip, peer-register, streamed SSE responses).
|
||||
BINARY_FRAME_MAGIC = b"MRF1"
|
||||
|
||||
|
||||
def encode_binary_frame(header: dict, body: bytes) -> bytes:
|
||||
header_bytes = json.dumps(header, separators=(",", ":")).encode()
|
||||
return BINARY_FRAME_MAGIC + len(header_bytes).to_bytes(4, "big") + header_bytes + body
|
||||
|
||||
|
||||
def decode_binary_frame(frame: bytes) -> tuple[dict, bytes]:
|
||||
if len(frame) < 8 or frame[:4] != BINARY_FRAME_MAGIC:
|
||||
raise ValueError("not a meshnet binary relay frame")
|
||||
header_len = int.from_bytes(frame[4:8], "big")
|
||||
header = json.loads(frame[8:8 + header_len].decode())
|
||||
return header, bytes(frame[8 + header_len:])
|
||||
|
||||
|
||||
class RelayServer:
|
||||
"""Async WebSocket relay server that runs in a background thread.
|
||||
|
||||
@@ -118,6 +138,9 @@ class RelayServer:
|
||||
self.port,
|
||||
ssl=ssl_ctx,
|
||||
max_size=ws_max_size(),
|
||||
# Bulk payloads are zstd-compressed at the pipeline layer already;
|
||||
# per-message deflate would recompress them on every hop for nothing.
|
||||
compression=None,
|
||||
)
|
||||
# Record actual port after bind
|
||||
for sock in server.sockets or []:
|
||||
@@ -162,6 +185,17 @@ class RelayServer:
|
||||
|
||||
try:
|
||||
async for raw in ws:
|
||||
# Binary frames are relay-http-response bodies from a bridge —
|
||||
# route them to the waiting rpc requester as-is, never fan out.
|
||||
if isinstance(raw, (bytes, bytearray)):
|
||||
try:
|
||||
header, _ = decode_binary_frame(bytes(raw))
|
||||
except (ValueError, json.JSONDecodeError):
|
||||
continue
|
||||
queue = self._pending_rpc.get(header.get("request_id"))
|
||||
if queue is not None:
|
||||
queue.put_nowait(bytes(raw))
|
||||
continue
|
||||
try:
|
||||
envelope = json.loads(raw)
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
@@ -252,14 +286,27 @@ class RelayServer:
|
||||
|
||||
try:
|
||||
raw = await asyncio.wait_for(ws_requester.recv(), timeout=30.0)
|
||||
payload = json.loads(raw)
|
||||
if isinstance(raw, (bytes, bytearray)):
|
||||
header, body = decode_binary_frame(bytes(raw))
|
||||
request_id = str(header.get("request_id") or uuid.uuid4())
|
||||
header["request_id"] = request_id
|
||||
header["target_peer"] = target_peer_id
|
||||
outbound: str | bytes = encode_binary_frame(header, body)
|
||||
else:
|
||||
payload = json.loads(raw)
|
||||
request_id = str(payload.get("request_id") or uuid.uuid4())
|
||||
payload["request_id"] = request_id
|
||||
payload["target_peer"] = target_peer_id
|
||||
outbound = json.dumps({
|
||||
"topic": "relay-http-request",
|
||||
"version": 1,
|
||||
"from_peer": "relay",
|
||||
"payload": payload,
|
||||
})
|
||||
except Exception:
|
||||
await ws_requester.close(1003, "invalid relay rpc request")
|
||||
return
|
||||
|
||||
request_id = str(payload.get("request_id") or uuid.uuid4())
|
||||
payload["request_id"] = request_id
|
||||
payload["target_peer"] = target_peer_id
|
||||
queue: asyncio.Queue = asyncio.Queue()
|
||||
self._pending_rpc[request_id] = queue
|
||||
overall_timeout = 310.0
|
||||
@@ -267,15 +314,11 @@ class RelayServer:
|
||||
loop = asyncio.get_running_loop()
|
||||
deadline = loop.time() + overall_timeout
|
||||
try:
|
||||
await target.ws.send(json.dumps({
|
||||
"topic": "relay-http-request",
|
||||
"version": 1,
|
||||
"from_peer": "relay",
|
||||
"payload": payload,
|
||||
}))
|
||||
await target.ws.send(outbound)
|
||||
# Forward frames until a terminal one: streamed responses (US-036)
|
||||
# end with {"stream": true, "done": true}; a frame without "stream"
|
||||
# is a complete legacy single response.
|
||||
# is a complete legacy single response. A binary frame is always a
|
||||
# complete single response.
|
||||
while True:
|
||||
remaining = deadline - loop.time()
|
||||
if remaining <= 0:
|
||||
@@ -283,6 +326,9 @@ class RelayServer:
|
||||
frame = await asyncio.wait_for(
|
||||
queue.get(), timeout=min(idle_timeout, remaining)
|
||||
)
|
||||
if isinstance(frame, (bytes, bytearray)):
|
||||
await ws_requester.send(frame)
|
||||
break
|
||||
await ws_requester.send(json.dumps(frame))
|
||||
if not frame.get("stream") or frame.get("done"):
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user