mirror of
https://github.com/torlando-tech/pyxis.git
synced 2026-08-28 05:24:22 +00:00
213 lines
8.7 KiB
Python
213 lines
8.7 KiB
Python
#!/usr/bin/env python3
|
|
import argparse
|
|
import hashlib
|
|
import os
|
|
from pathlib import Path
|
|
import sys
|
|
import tempfile
|
|
import time
|
|
|
|
import RNS
|
|
|
|
RNS_VERSION = "1.4.2"
|
|
RNS_TREE_SHA256 = "b5398e7bae0cdd47212e0c6bff3f3a51b21012db0c23cb20d43b5103612f6c5e"
|
|
if getattr(RNS, "__version__", None) != RNS_VERSION:
|
|
raise SystemExit(f"wrong RNS reference version: {getattr(RNS, '__version__', None)}")
|
|
if RNS.__file__ is None:
|
|
raise SystemExit("RNS reference has no source path")
|
|
reference_root = Path(RNS.__file__).resolve().parent
|
|
reference_hash = hashlib.sha256()
|
|
for reference_file in sorted(reference_root.rglob("*.py")):
|
|
relative = reference_file.relative_to(reference_root).as_posix().encode()
|
|
content = reference_file.read_bytes()
|
|
reference_hash.update(len(relative).to_bytes(4, "big"))
|
|
reference_hash.update(relative)
|
|
reference_hash.update(len(content).to_bytes(8, "big"))
|
|
reference_hash.update(content)
|
|
if reference_hash.hexdigest() != RNS_TREE_SHA256:
|
|
raise SystemExit(f"wrong RNS reference tree: {reference_hash.hexdigest()}")
|
|
print(f"REFERENCE RNS {RNS_VERSION}")
|
|
print(f"REFERENCE RNS tree {RNS_TREE_SHA256}")
|
|
|
|
state = {
|
|
"request_seen": False,
|
|
"request_count": 0,
|
|
"anonymous": False,
|
|
"link": None,
|
|
"link_closed": False,
|
|
"form_valid": False,
|
|
"form_sequence": [],
|
|
}
|
|
|
|
|
|
def micron_page(title: str, target_bytes: int) -> bytes:
|
|
prefix = f">{title}\n\nThis page traversed a real encrypted Reticulum Link.\n".encode()
|
|
line = b"Deterministic x86 NomadNet integration payload.\n"
|
|
result = bytearray(prefix)
|
|
while len(result) + len(line) <= target_bytes:
|
|
result.extend(line)
|
|
if len(result) < target_bytes:
|
|
result.extend(b"x" * (target_bytes - len(result)))
|
|
return bytes(result)
|
|
|
|
|
|
PAGES = {
|
|
"/page/immediate.mu": micron_page("Immediate page", 220),
|
|
"/page/resource.mu": micron_page("Resource-backed page", 12_000),
|
|
"/page/near-limit.mu": micron_page("Resource-backed page", 40_000),
|
|
"/page/oversized.mu": micron_page("Resource-backed page", 70_000),
|
|
"/page/cancel.mu": micron_page("Resource-backed page", 60_000),
|
|
"/page/reuse-first.mu": micron_page("Immediate page", 220),
|
|
"/page/reuse-second.mu": micron_page("Resource-backed page", 12_000),
|
|
"/page/form.mu": micron_page("Form response", 220),
|
|
"/page/partial.mu": b">Peer-refreshed fragment\n\nReal partial response.\n",
|
|
}
|
|
|
|
EXPECTED_FORM_DATA = {
|
|
"var_fixed": "yes",
|
|
"field_name": "Example User",
|
|
"field_password": "example-pass",
|
|
"field_color": "red,blue",
|
|
}
|
|
|
|
|
|
def page_handler(path, data, request_id, link_id, remote_identity, requested_at):
|
|
state["request_seen"] = True
|
|
state["request_count"] += 1
|
|
state["anonymous"] = remote_identity is None
|
|
if path == "/page/form.mu":
|
|
state["form_valid"] = data == EXPECTED_FORM_DATA
|
|
state["form_sequence"].append(data)
|
|
print(f"SERVER request count={state['request_count']} path={path} bytes={len(PAGES[path])} anonymous={state['anonymous']}", flush=True)
|
|
return PAGES[path]
|
|
|
|
|
|
def on_link_established(link):
|
|
state["link"] = link
|
|
link.set_link_closed_callback(on_link_closed)
|
|
print("SERVER link established", flush=True)
|
|
|
|
|
|
def on_link_closed(link):
|
|
state["link_closed"] = True
|
|
print("SERVER link closed", flush=True)
|
|
|
|
|
|
def write_config(config_dir: str):
|
|
config = """
|
|
[reticulum]
|
|
enable_transport = No
|
|
share_instance = No
|
|
panic_on_interface_error = No
|
|
|
|
[logging]
|
|
loglevel = 3
|
|
|
|
[interfaces]
|
|
[[PyxisNomadNetX86]]
|
|
type = UDPInterface
|
|
interface_enabled = True
|
|
listen_ip = 127.0.0.1
|
|
listen_port = 14356
|
|
forward_ip = 127.0.0.1
|
|
forward_port = 14357
|
|
"""
|
|
with open(os.path.join(config_dir, "config"), "w") as handle:
|
|
handle.write(config)
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("scenario", choices=("immediate", "resource", "near-limit", "oversized", "timeout", "cancel", "reuse", "form-anonymous", "form-identified", "owner-form-history", "partial"))
|
|
parser.add_argument("--timeout", type=float, default=20.0)
|
|
args = parser.parse_args()
|
|
|
|
config_dir = tempfile.mkdtemp(prefix=f"pyxis-nomadnet-{args.scenario}-")
|
|
os.makedirs(os.path.join(config_dir, "storage", "resources"), exist_ok=True)
|
|
write_config(config_dir)
|
|
RNS.Reticulum(config_dir)
|
|
identity = RNS.Identity()
|
|
destination = RNS.Destination(identity, RNS.Destination.IN,
|
|
RNS.Destination.SINGLE, "nomadnetwork", "node")
|
|
destination.set_proof_strategy(RNS.Destination.PROVE_ALL)
|
|
destination.set_link_established_callback(on_link_established)
|
|
if args.scenario == "reuse":
|
|
for path in ("/page/reuse-first.mu", "/page/reuse-second.mu"):
|
|
destination.register_request_handler(path, page_handler,
|
|
allow=RNS.Destination.ALLOW_ALL,
|
|
auto_compress=False)
|
|
elif args.scenario != "timeout":
|
|
path = ("/page/form.mu" if args.scenario.startswith("form-") or
|
|
args.scenario == "owner-form-history" else f"/page/{args.scenario}.mu")
|
|
destination.register_request_handler(path, page_handler,
|
|
allow=RNS.Destination.ALLOW_ALL,
|
|
auto_compress=False)
|
|
destination.announce(app_data=b"Pyxis x86 NomadNet peer")
|
|
print(f"SERVER announced {destination.hash.hex()}", flush=True)
|
|
|
|
started = time.time()
|
|
last_announce = started
|
|
owner_response_deadline = None
|
|
while time.time() - started < args.timeout:
|
|
now = time.time()
|
|
if now - last_announce >= 2.0 and not state["request_seen"]:
|
|
destination.announce(app_data=b"Pyxis x86 NomadNet peer")
|
|
last_announce = now
|
|
if state["request_seen"] and not state["anonymous"] and args.scenario != "form-identified":
|
|
print("SERVER FAIL client identified unexpectedly", flush=True)
|
|
return 1
|
|
if args.scenario == "form-anonymous" and state["request_seen"]:
|
|
if state["anonymous"] and state["form_valid"]:
|
|
print("SERVER PASS exact form request data anonymous=True", flush=True)
|
|
return 0
|
|
print("SERVER FAIL form data or anonymous identity mismatch", flush=True)
|
|
return 1
|
|
if args.scenario == "form-identified" and state["request_seen"]:
|
|
if not state["anonymous"] and state["form_valid"]:
|
|
print("SERVER PASS exact form request data anonymous=False", flush=True)
|
|
return 0
|
|
print("SERVER FAIL form data or identified identity mismatch", flush=True)
|
|
return 1
|
|
if args.scenario == "owner-form-history" and state["request_count"] == 3:
|
|
expected_changed = dict(EXPECTED_FORM_DATA)
|
|
expected_changed["field_name"] = "Changed User"
|
|
if (state["anonymous"] and state["form_sequence"] ==
|
|
[EXPECTED_FORM_DATA, expected_changed, EXPECTED_FORM_DATA]):
|
|
if owner_response_deadline is None:
|
|
owner_response_deadline = now + 2.0
|
|
print("SERVER owner response 3 queued; awaiting client receipt", flush=True)
|
|
if state["link_closed"]:
|
|
print("SERVER PASS exact form request data owner-history=True delivery-settled=True", flush=True)
|
|
return 0
|
|
if now >= owner_response_deadline:
|
|
print("SERVER FAIL owner response delivery did not settle", flush=True)
|
|
return 1
|
|
time.sleep(0.02)
|
|
continue
|
|
print("SERVER FAIL owner form/history request sequence", flush=True)
|
|
return 1
|
|
if args.scenario in ("immediate", "resource", "near-limit", "oversized", "partial") and state["request_seen"]:
|
|
time.sleep(1.0)
|
|
print("SERVER PASS", flush=True)
|
|
return 0
|
|
if args.scenario == "reuse" and state["request_count"] == 2:
|
|
time.sleep(1.0)
|
|
print("SERVER PASS reused one Link for two anonymous requests", flush=True)
|
|
return 0
|
|
if args.scenario == "cancel" and state["request_seen"] and state["link_closed"]:
|
|
print("SERVER PASS cancellation observed", flush=True)
|
|
return 0
|
|
if args.scenario == "timeout" and state["link"] is not None:
|
|
# The missing handler is intentional; the client receipt must fail.
|
|
time.sleep(3.0)
|
|
print("SERVER PASS missing-handler timeout exercised", flush=True)
|
|
return 0
|
|
time.sleep(0.02)
|
|
|
|
print(f"SERVER FAIL deadline request={state['request_seen']} closed={state['link_closed']}", flush=True)
|
|
return 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|