remoteRF-server 0.1.73__tar.gz → 0.1.74__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/PKG-INFO +1 -1
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/pyproject.toml +1 -1
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/server/grpc_server.py +188 -1
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server.egg-info/PKG-INFO +1 -1
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/README.md +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/setup.cfg +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/__init__.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/__init__.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/grpc/__init__.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/grpc/grpc_host_pb2.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/grpc/grpc_host_pb2_grpc.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/grpc/grpc_pb2.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/grpc/grpc_pb2_grpc.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/utils/__init__.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/utils/ansi_codes.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/utils/api_token.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/utils/db_connection.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/utils/db_location.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/utils/list_string.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/utils/process_arg.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/drivers/__init__.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/drivers/adalm_pluto/__init__.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/drivers/adalm_pluto/pluto_remote_server.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/host/__init__.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/host/host_directory_store.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/host/host_tunnel_server.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/server/__init__.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/server/acc_perms.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/server/cert_provider.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/server/device_manager.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/server/reservation.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/server/rpc_manager.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/server/user_group_cli.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/server/user_group_handler.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/serverrf_cli.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/tools/__init__.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/tools/gen_certs.py +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server.egg-info/SOURCES.txt +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server.egg-info/dependency_links.txt +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server.egg-info/entry_points.txt +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server.egg-info/requires.txt +0 -0
- {remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server.egg-info/top_level.txt +0 -0
|
@@ -445,6 +445,187 @@ def _cmd_devices_status() -> None:
|
|
|
445
445
|
" online=", Sty.DEFAULT, f"{ds.online}", Sty.GREEN if ds.online else Sty.RED,
|
|
446
446
|
" last_seen=", Sty.DEFAULT, f"{_fmt_ms_ago(ds.last_seen_ms)} ago", Sty.BLUE
|
|
447
447
|
)
|
|
448
|
+
|
|
449
|
+
from typing import Iterable
|
|
450
|
+
import contextlib
|
|
451
|
+
|
|
452
|
+
def _repo_root_guess() -> Path:
|
|
453
|
+
"""
|
|
454
|
+
Best-effort: find <repo>/src/... and return <repo>.
|
|
455
|
+
Fallback: walk up a few levels from this file.
|
|
456
|
+
"""
|
|
457
|
+
p = Path(__file__).resolve()
|
|
458
|
+
for parent in p.parents:
|
|
459
|
+
if parent.name == "src":
|
|
460
|
+
return parent.parent
|
|
461
|
+
# fallback
|
|
462
|
+
return p.parents[3] if len(p.parents) >= 4 else p.parent
|
|
463
|
+
|
|
464
|
+
def _host_state_dirs() -> list[Path]:
|
|
465
|
+
"""
|
|
466
|
+
Places host-directory persistence might live in your codebase:
|
|
467
|
+
- User config dir: ~/.config/remoterf (REMOTERF_CONFIG_DIR override)
|
|
468
|
+
- Repo-local: <repo>/.config
|
|
469
|
+
- Server config dir you referenced: <repo>/src/remoteRF_server/config (because of .env.host_directory)
|
|
470
|
+
"""
|
|
471
|
+
cands = [
|
|
472
|
+
_cfg_dir(),
|
|
473
|
+
_repo_root_guess() / ".config",
|
|
474
|
+
(Path(__file__).resolve().parent.parent / "config"), # <repo>/src/remoteRF_server/config
|
|
475
|
+
]
|
|
476
|
+
|
|
477
|
+
out: list[Path] = []
|
|
478
|
+
seen: set[str] = set()
|
|
479
|
+
for d in cands:
|
|
480
|
+
try:
|
|
481
|
+
rp = str(d.resolve())
|
|
482
|
+
except Exception:
|
|
483
|
+
rp = str(d)
|
|
484
|
+
if rp not in seen:
|
|
485
|
+
seen.add(rp)
|
|
486
|
+
out.append(d)
|
|
487
|
+
return out
|
|
488
|
+
|
|
489
|
+
def _host_state_files() -> list[Path]:
|
|
490
|
+
"""
|
|
491
|
+
Exact files your HostTunnelRegistry has historically used.
|
|
492
|
+
Also includes a conservative glob for future additions.
|
|
493
|
+
"""
|
|
494
|
+
files: list[Path] = []
|
|
495
|
+
for d in _host_state_dirs():
|
|
496
|
+
files.append(d / "host_directory.env")
|
|
497
|
+
files.append(d / "host_directory_meta.env")
|
|
498
|
+
# If you later add more persisted host-dir files, keep them discoverable.
|
|
499
|
+
try:
|
|
500
|
+
for p in sorted(d.glob("host_directory*.env")):
|
|
501
|
+
files.append(p)
|
|
502
|
+
except Exception:
|
|
503
|
+
pass
|
|
504
|
+
|
|
505
|
+
out: list[Path] = []
|
|
506
|
+
seen: set[str] = set()
|
|
507
|
+
for p in files:
|
|
508
|
+
try:
|
|
509
|
+
rp = str(p.resolve())
|
|
510
|
+
except Exception:
|
|
511
|
+
rp = str(p)
|
|
512
|
+
if rp not in seen:
|
|
513
|
+
seen.add(rp)
|
|
514
|
+
out.append(p)
|
|
515
|
+
return out
|
|
516
|
+
|
|
517
|
+
def _cmd_hosts_persisted() -> None:
|
|
518
|
+
files = _host_state_files()
|
|
519
|
+
found_any = False
|
|
520
|
+
printf("Host directory (persisted) state files:", Sty.BOLD)
|
|
521
|
+
for p in files:
|
|
522
|
+
if p.exists():
|
|
523
|
+
found_any = True
|
|
524
|
+
try:
|
|
525
|
+
size = p.stat().st_size
|
|
526
|
+
except Exception:
|
|
527
|
+
size = -1
|
|
528
|
+
printf(" - ", Sty.DEFAULT, f"{p}", Sty.MAGENTA, f" ({size} bytes)", Sty.GRAY)
|
|
529
|
+
else:
|
|
530
|
+
printf(" - ", Sty.DEFAULT, f"{p}", Sty.GRAY, " (missing)", Sty.GRAY)
|
|
531
|
+
if not found_any:
|
|
532
|
+
printf(" (none found)", Sty.GRAY)
|
|
533
|
+
|
|
534
|
+
def _try_clear_registry_in_memory(reg: object) -> list[str]:
|
|
535
|
+
"""
|
|
536
|
+
Best-effort in-memory wipe without knowing exact internals.
|
|
537
|
+
Uses registry lock if present.
|
|
538
|
+
"""
|
|
539
|
+
cleared: list[str] = []
|
|
540
|
+
|
|
541
|
+
lock = getattr(reg, "_lock", None)
|
|
542
|
+
acquired = False
|
|
543
|
+
try:
|
|
544
|
+
if lock is not None and hasattr(lock, "acquire") and hasattr(lock, "release"):
|
|
545
|
+
lock.acquire()
|
|
546
|
+
acquired = True
|
|
547
|
+
|
|
548
|
+
# common private dict fields
|
|
549
|
+
for attr in (
|
|
550
|
+
"_hosts",
|
|
551
|
+
"_devices",
|
|
552
|
+
"_host_by_id",
|
|
553
|
+
"_device_by_id",
|
|
554
|
+
"_device_routes",
|
|
555
|
+
"_routes",
|
|
556
|
+
"_sessions",
|
|
557
|
+
"_host_sessions",
|
|
558
|
+
):
|
|
559
|
+
d = getattr(reg, attr, None)
|
|
560
|
+
if isinstance(d, dict):
|
|
561
|
+
d.clear()
|
|
562
|
+
cleared.append(attr)
|
|
563
|
+
|
|
564
|
+
# common private sets/lists
|
|
565
|
+
for attr in ("_connected", "_online_hosts"):
|
|
566
|
+
s = getattr(reg, attr, None)
|
|
567
|
+
if isinstance(s, set):
|
|
568
|
+
s.clear()
|
|
569
|
+
cleared.append(attr)
|
|
570
|
+
|
|
571
|
+
# if there is an explicit method, prefer it (won’t hurt if absent)
|
|
572
|
+
for meth in ("clear", "reset", "wipe", "wipe_all", "wipe_state"):
|
|
573
|
+
fn = getattr(reg, meth, None)
|
|
574
|
+
if callable(fn):
|
|
575
|
+
try:
|
|
576
|
+
fn()
|
|
577
|
+
cleared.append(f"{meth}()")
|
|
578
|
+
except Exception:
|
|
579
|
+
pass
|
|
580
|
+
|
|
581
|
+
finally:
|
|
582
|
+
if acquired:
|
|
583
|
+
try:
|
|
584
|
+
lock.release()
|
|
585
|
+
except Exception:
|
|
586
|
+
pass
|
|
587
|
+
|
|
588
|
+
return cleared
|
|
589
|
+
|
|
590
|
+
def _cmd_hosts_wipe(*, yes: bool = False) -> None:
|
|
591
|
+
# confirm
|
|
592
|
+
if not yes:
|
|
593
|
+
try:
|
|
594
|
+
resp = session.prompt(stylize("Type 'wipe-hosts' to confirm wiping persisted host state: ", Sty.RED))
|
|
595
|
+
except KeyboardInterrupt:
|
|
596
|
+
printf("Cancelled.", Sty.GRAY)
|
|
597
|
+
return
|
|
598
|
+
if (resp or "").strip().lower() != "wipe-hosts":
|
|
599
|
+
printf("Wipe aborted.", Sty.GRAY)
|
|
600
|
+
return
|
|
601
|
+
|
|
602
|
+
# delete persisted files
|
|
603
|
+
files = [p for p in _host_state_files() if p.exists()]
|
|
604
|
+
if not files:
|
|
605
|
+
printf("No persisted host directory files found to wipe.", Sty.GRAY)
|
|
606
|
+
else:
|
|
607
|
+
for p in files:
|
|
608
|
+
try:
|
|
609
|
+
p.unlink()
|
|
610
|
+
printf("Deleted: ", Sty.DEFAULT, f"{p}", Sty.MAGENTA)
|
|
611
|
+
except Exception as e:
|
|
612
|
+
printf("ERROR deleting: ", Sty.RED, f"{p} -> {e}", Sty.DEFAULT)
|
|
613
|
+
return
|
|
614
|
+
|
|
615
|
+
# clear in-memory registry (so you don’t have to restart for live state)
|
|
616
|
+
global TUNNEL_REGISTRY
|
|
617
|
+
reg = TUNNEL_REGISTRY
|
|
618
|
+
if reg is None:
|
|
619
|
+
printf("Host tunnel registry not initialized; persisted files wiped only.", Sty.GRAY)
|
|
620
|
+
else:
|
|
621
|
+
cleared = _try_clear_registry_in_memory(reg)
|
|
622
|
+
if cleared:
|
|
623
|
+
printf("Cleared in-memory registry fields: ", Sty.DEFAULT, ", ".join(cleared), Sty.GRAY)
|
|
624
|
+
else:
|
|
625
|
+
printf("WARNING: Could not confirm in-memory registry clear (unknown internals). Restart server if needed.", Sty.YELLOW)
|
|
626
|
+
|
|
627
|
+
printf("Host state wipe complete.", Sty.GREEN)
|
|
628
|
+
printf("NOTE: If hosts reconnect, persisted files will be recreated.", Sty.GRAY)
|
|
448
629
|
|
|
449
630
|
# def help():
|
|
450
631
|
# printf("/------- HELP -------/", Sty.BOLD)
|
|
@@ -571,6 +752,7 @@ def help() -> None:
|
|
|
571
752
|
|
|
572
753
|
printf("Host Tunnel (live):", Sty.BOLD)
|
|
573
754
|
printf(" hosts status ", Sty.MAGENTA, "- Live host online/last_seen/devices", Sty.DEFAULT)
|
|
755
|
+
printf(" hosts wipe ", Sty.MAGENTA, "- Wipe persisted host directory state (and clear in-memory)", Sty.DEFAULT)
|
|
574
756
|
printf(" devices status ", Sty.MAGENTA, "- Live device online/last_seen/route", Sty.DEFAULT)
|
|
575
757
|
print()
|
|
576
758
|
|
|
@@ -669,7 +851,6 @@ def server_input(inpu: str) -> bool:
|
|
|
669
851
|
# ---- host tunnel ----
|
|
670
852
|
"hosts status": lambda: _stay(_cmd_hosts_status),
|
|
671
853
|
"host status": lambda: _stay(_cmd_hosts_status),
|
|
672
|
-
"tunnel hosts": lambda: _stay(_cmd_hosts_status),
|
|
673
854
|
|
|
674
855
|
"devices status": lambda: _stay(_cmd_devices_status),
|
|
675
856
|
"tunnel devices": lambda: _stay(_cmd_devices_status),
|
|
@@ -679,6 +860,12 @@ def server_input(inpu: str) -> bool:
|
|
|
679
860
|
|
|
680
861
|
fn = DISPATCH.get(cmd)
|
|
681
862
|
if fn is None:
|
|
863
|
+
# allow: "hosts wipe" and "hosts wipe -y"
|
|
864
|
+
if cmd.startswith("hosts wipe"):
|
|
865
|
+
yes = ("-y" in cmd.split()) or ("--yes" in cmd.split())
|
|
866
|
+
_cmd_hosts_wipe(yes=yes)
|
|
867
|
+
return True
|
|
868
|
+
|
|
682
869
|
printf("Unknown command: ", Sty.RED, f"{inpu}", Sty.DEFAULT)
|
|
683
870
|
printf("Type ", Sty.DEFAULT, "help", Sty.MAGENTA, " to see commands.", Sty.DEFAULT)
|
|
684
871
|
return True
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/grpc/__init__.py
RENAMED
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/grpc/grpc_host_pb2.py
RENAMED
|
File without changes
|
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/grpc/grpc_pb2.py
RENAMED
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/grpc/grpc_pb2_grpc.py
RENAMED
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/utils/__init__.py
RENAMED
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/utils/ansi_codes.py
RENAMED
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/utils/api_token.py
RENAMED
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/utils/db_connection.py
RENAMED
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/utils/db_location.py
RENAMED
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/utils/list_string.py
RENAMED
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/common/utils/process_arg.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/host/host_directory_store.py
RENAMED
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/host/host_tunnel_server.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/server/cert_provider.py
RENAMED
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/server/device_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/server/user_group_cli.py
RENAMED
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server/server/user_group_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
{remoterf_server-0.1.73 → remoterf_server-0.1.74}/src/remoteRF_server.egg-info/top_level.txt
RENAMED
|
File without changes
|