From f3ec20b14e4e38b597af7f2ccee6cc16bfb5d6c7 Mon Sep 17 00:00:00 2001 From: Sudo-Ivan Date: Sun, 4 Jan 2026 15:00:16 -0600 Subject: [PATCH] feat(rnpath): improve get_path_table method with filtering, sorting, and pagination; include additional stats for path entries --- meshchatx/src/backend/rnpath_handler.py | 78 ++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/meshchatx/src/backend/rnpath_handler.py b/meshchatx/src/backend/rnpath_handler.py index 92b54d5..032528c 100644 --- a/meshchatx/src/backend/rnpath_handler.py +++ b/meshchatx/src/backend/rnpath_handler.py @@ -5,10 +5,46 @@ class RNPathHandler: def __init__(self, reticulum_instance: RNS.Reticulum): self.reticulum = reticulum_instance - def get_path_table(self, max_hops: int = None): + def get_path_table( + self, + max_hops: int = None, + search: str = None, + interface: str = None, + hops: int = None, + page: int = 1, + limit: int = 0, + ): table = self.reticulum.get_path_table(max_hops=max_hops) formatted_table = [] for entry in table: + # Get additional data directly from Transport.path_table if available + # to provide more stats as requested. + dst_hash = entry["hash"] + announce_hash = None + state = RNS.Transport.STATE_UNKNOWN + + if dst_hash in RNS.Transport.path_table: + pt_entry = RNS.Transport.path_table[dst_hash] + if len(pt_entry) > 6: + announce_hash = pt_entry[6].hex() if pt_entry[6] else None + + if dst_hash in RNS.Transport.path_states: + state = RNS.Transport.path_states[dst_hash] + + # Filtering + if search: + search = search.lower() + hash_str = entry["hash"].hex().lower() + via_str = entry["via"].hex().lower() + if search not in hash_str and search not in via_str: + continue + + if interface and entry["interface"] != interface: + continue + + if hops is not None and entry["hops"] != hops: + continue + formatted_table.append( { "hash": entry["hash"].hex(), @@ -16,9 +52,47 @@ class RNPathHandler: "via": entry["via"].hex(), "interface": entry["interface"], "expires": entry["expires"], + "timestamp": entry.get("timestamp"), + "announce_hash": announce_hash, + "state": state, } ) - return sorted(formatted_table, key=lambda e: (e["interface"], e["hops"])) + + # Sort: Responsive first, then by hops, then by interface + formatted_table.sort( + key=lambda e: ( + 0 if e["state"] == RNS.Transport.STATE_RESPONSIVE else 1, + e["hops"], + e["interface"], + ) + ) + + total = len(formatted_table) + responsive_count = len( + [e for e in formatted_table if e["state"] == RNS.Transport.STATE_RESPONSIVE] + ) + unresponsive_count = len( + [ + e + for e in formatted_table + if e["state"] == RNS.Transport.STATE_UNRESPONSIVE + ] + ) + + # Pagination + if limit > 0: + start = (page - 1) * limit + end = start + limit + formatted_table = formatted_table[start:end] + + return { + "table": formatted_table, + "total": total, + "responsive": responsive_count, + "unresponsive": unresponsive_count, + "page": page, + "limit": limit, + } def get_rate_table(self): table = self.reticulum.get_rate_table()