Commit Graph

95 Commits

Author SHA1 Message Date
agessaman 8a776a122e fix(cli): point txdelay settings at the delays config section
The mesh CLI's get/set txdelay and direct.txdelay read and wrote
repeater.tx_delay_factor / repeater.direct_tx_delay_factor, but the
engine and web API use the delays section, so the CLI knobs were
silently dead: set appeared to succeed while changing nothing, and get
echoed the unused value back. Same defect and same fix as the recent
rxdelay repoint.
2026-07-15 22:02:18 -07:00
agessaman 3e2231f2bc fix(repeater): wire the flood reception delay base into the dispatcher
The delays.rx_delay_base config value was stored and reported but never
applied. Now that the core dispatcher implements MeshCore's flood
reception-quality delay, feed it through:

- set dispatcher.rx_delay_base from delays.rx_delay_base at startup and
  re-apply it on live config updates of the delays section (web API
  saves already pass that section)
- point the mesh CLI get/set rxdelay at the delays section; it read and
  wrote repeater.rx_delay_base, which nothing consumes, so the CLI knob
  was silently dead
- delegate RepeaterHandler.calculate_packet_score to the shared core
  packet_score (same firmware packetScoreInt formula, one impl)

Suppression works through the existing engine seen-cache because it
dedupes at process time, after the dispatcher hold. Default remains 0
(delay disabled), matching firmware.
2026-07-15 21:22:32 -07:00
agessaman b5a327b925 fix(router): defer direct payload handling 2026-07-14 21:08:42 -07:00
agessaman 62ad7424c2 fix(router): consume PATH and RESPONSE only after MAC authentication
Extend the authenticated-ownership model to the PATH and RESPONSE
routing branches so a packet is consumed (do-not-retransmit) only when
a local identity MAC-verifies it. Prefix-only collisions and forged
traffic stay eligible for the forwarding engine.

- PathHelper marks do-not-retransmit and reports authenticated only
  after a successful MAC decrypt with a valid path envelope; invalid or
  truncated envelopes remain forwardable.
- PacketRouter aggregates authenticated results across the path helper
  and companion bridges for PATH and RESPONSE, skipping the engine only
  on authenticated ownership while preserving empty-path DIRECT release
  hygiene.
2026-07-13 19:54:59 -07:00
Lloyd 8d766c8a2a Merge pull request #357 from agessaman/fix/consume-on-decrypt
fix(router): consume packets only on authenticated local handling (#353)
2026-07-13 23:02:56 +01:00
agessaman 8875177088 fix(router): consume packets only on authenticated local handling (#353)
Route login, text, and protocol-request packets through a single
_consume_via_local_candidates fan-out that offers each one to every local
candidate sharing the one-byte destination hash — the companion bridge and the
room-server/repeater identity — and consumes it only when one MAC-verifies it.
A prefix collision with a remote node (or a forged packet) is left for the
forwarding engine instead of being swallowed.

- gate processed_by_injection on the core HandlerResult.authenticated
- protocol-request now forwards on collision instead of always marking handled
- add real-crypto integration tests (text, room-server login, protocol-request)
  and router fan-out tests covering companion + room-server collisions
2026-07-13 14:46:56 -07:00
Rightup e5d72eaff9 feat: update advert packet sending with error handling and add corresponding tests 2026-07-13 21:54:16 +01:00
Rightup 1906f576bb feat: add region/default-scope / cli commands update
standardize default region on mesh.default_region (remove legacy region_default_scope usage)
add/align CLI support for owner.info, path.hash.mode, and loop.detect with validation
wire UI terminal get/set + autocomplete/help for owner.info, path.hash.mode, loop.detect
extend update_radio_config to persist owner_info for UI set owner.info
add and use shared packet utility for advert creation + default-region transport scoping
refactor repeater and room-server advert paths to reuse shared packet logic
2026-07-08 17:25:35 +01:00
Vashiru 667169c7ff feat: Bump to 168 hours to match docs.meshcore.io 2026-07-08 10:12:47 +01:00
Vashiru 17f8bcca2f feat: Allow setting max. flood interval to 50 2026-07-08 10:12:46 +01:00
agessaman 954150b2d8 merge: reconcile companion cleanup with fix-general-tidy
Merge the maintainer's fix-general-tidy branch (neighbor discovery,
keygen, API endpoints, web-asset rebuild, HTTP server config/control
commands, and an independent #286 room-server push/ACK/guest fix) into
the companion cleanup branch.

Both branches fixed #286 in parallel with byte-identical push-ACK CRC
logic. In the six overlapping files the maintainer's implementation is
kept (ACL replay-detection/session helpers, encoded path-len with legacy
fallback, expected_crc/ack_timeout_s injector API, dispatcher ACK
helpers); this branch's unique companion work is preserved on top
(sender_prefix persistence + migration, boot-state hardening /
CompanionStateLoadError, MessageQueue.max_size, older-core fallbacks).

Conflict resolution took the maintainer's side across the overlap, then
fixed two integration seams the merge introduced and updated this
branch's tests to the maintainer's API:
- room_server: timeout used undefined `hops`; aligned to `path_len`.
- packet_router: PATH helper was invoked twice (maintainer's
  unconditional call plus this branch's conditional local-identity
  call); dropped the now-redundant conditional block.

Pin openhop_core to @dev (was @feature/publish-workflow-message-handling)
so this can merge to the repeater's dev; core dev carries the required
sender_prefix and PathUtils.is_valid_path_len APIs.

Full suite green (1040 passed) against openhop_core dev and
refactor/companion-housekeeping; ruff clean.
2026-07-07 12:56:43 -07:00
Rightup 43a112ce7c feat: add HTTP server configuration and control commands 2026-07-07 20:38:22 +01:00
agessaman b2e45c2038 fix: resolve room-server push ACKs through the dispatcher
Room server pushes waited on dispatcher.wait_for_ack, but nothing in the
repeater could ever resolve it, so every push timed out and re-pushed on
the backoff schedule (issue #286's duplicate floods — worst for virtual
companions on the same instance, whose ACKs never even cross the air):

- no core AckHandler is registered (all RX lands in the router fallback),
  so received ACK CRCs were never fed to dispatcher ACK matching
- inject_packet waited on packet.get_crc(), a packet-hash CRC that no ACK
  sender produces; the crypto CRC only the room server knows was ignored
- PATH returns (how a flood-received DM is ACKed) were decrypted by
  PathHelper, but it read the encoded path_len wire byte as a raw count —
  an empty 3-byte-hash path (0x80) parsed as a 128-byte truncated
  payload — and the router's PATH branch never ran PathHelper for
  room/repeater destinations when any companion bridge existed

Fixes:
- router ACK branch feeds discrete ACK CRCs (RF and locally injected) to
  dispatcher._register_ack_received
- PATH packets addressed to a local server identity are processed by
  PathHelper regardless of companion bridges; PathHelper decodes the
  encoded path_len via PathUtils, keeps the encoded byte in out_path_len,
  and registers the embedded ACK via ack_received_fn
- inject_packet accepts expected_ack_crc/ack_timeout; the room server
  passes its crypto CRC and a hop-count-based timeout (the encoded byte
  would have produced a ~4-minute direct-push wait)

Verified live on a real mesh: push to a same-instance virtual companion
resolves via the PATH-embedded ACK (encoded path_len 0x80) and push to a
firmware client resolves via the discrete RF ACK, no re-push loops.

Fixes #286
Fixes #341
2026-07-07 11:17:54 -07:00
agessaman 9c6ea0151e fix: compute signed-post push ACK over the full signed span
push_post_to_client sent posts as TXT_TYPE_SIGNED_PLAIN (plaintext =
timestamp + flags + author_prefix + text) but computed its expected ACK
over the plain-DM span (timestamp + attempt byte + text). Signed-plain
receivers (firmware BaseChatMesh::onPeerDataRecv, and openhop_core's
text handler since it gained signed-message ACKs) reply with
sha256(decrypted[0 : 9 + strlen(text)] || client_pubkey)[:4], so the
server never recognized any push ACK: every push timed out and the same
posts were re-pushed forever (issue #286's repeating 'Push timed out'
log and duplicate unread floods).

Hash the exact plaintext span that is encrypted and sent, plus the
client pubkey. Verified against openhop_core's TextMessageHandler: the
ACK it emits for a pushed post now matches the stored pending_ack_crc.

Fixes #286
2026-07-07 10:35:28 -07:00
agessaman 0404b3ab44 fix: add blank-password read-only guests to the room ACL
A blank-password login replied success (read-only guest) without ever
creating an ACL entry or storing the ECDH shared secret. The client app
believed it was logged in, but the room server's text handler and sync
loop only see ACL members: the client's posts were dropped without a
delivery ACK (send shows failed) and posts were never pushed to it.
Rooms with only an admin password configured were fully affected since
every guest login is blank-password.

Add the guest to the ACL with guest permissions, the shared secret, and
sync_since (mirroring the password path), reject when the ACL is full,
and refresh activity timestamps on repeat blank logins.

Refs #286
2026-07-07 10:35:01 -07:00
Rightup daec7f0ebc feat: implement neighbor discovery session management and API endpoints 2026-07-04 23:41:33 +01:00
Rightup ae68112377 - Refactored ACL authentication flow with shared helpers for replay detection and session updates.
- Changed blank-password login behavior to create/manage guest sessions (when read-only is enabled), including replay protection and session timestamp tracking.
- Preserved and centralized `sync_since` handling during successful auth/session updates.
- Updated login handling to return explicit `(success, permissions)` and reset room-server sync guard state in SQLite on successful room-server login.
- Updated identity/banner output in mesh CLI from `pyMC_*` to `openHop_*` and adjusted default version fallback.
- Extended path handling to support encoded path-length semantics via `PathUtils`, with legacy fallback support for older/malformed packets.
- Added bundled ACK extraction from PATH payload extras and callback-based ACK propagation.
- Hardened room-server push logic: max-failure early skip, corrected expected ACK CRC calculation, path encoding compatibility, persisted sync/last-activity fields, and passed expected CRC + timeout into packet injection.
- Enhanced packet router ACK flow with dispatcher ACK registration helper, support for multipart ACK wrapper handling, configurable ACK wait timeout/CRC in injection, and ensured PATH helper processing always runs.
- Updated daemon wiring to pass ACK callback into `PathHelper`,
- make dispatcher dedupe configurable (prevent dbl deduping), and only register duplicate logging hook when dedupe is enabled.
- Expanded tests to cover guest blank-password replay tracking, updated room-server injector ACK expectations, and new duplicate-logging-hook gating behavior.
2026-07-02 16:32:32 +01:00
Lloyd 2b67dea96b refactor:rename-project-to-openhop 2026-06-24 23:27:49 +01:00
Lloyd 3b7a20a192 fix: add nosec comment to exception handling in CryptoUtils decryption 2026-06-23 09:13:48 +01:00
Lloyd 018f425dc1 feat: data redaction in log messages and update related tests 2026-06-23 08:52:41 +01:00
Lloyd 4a8876a95e feat: implement login throttling with exponential backoff and enforce minimum admin password length 2026-06-23 08:52:40 +01:00
Lloyd 9cff088853 feat: enhance client resolution and ACL handling in protocol request and text helpers 2026-06-23 08:52:40 +01:00
agessaman 778adb6917 feat: implement randomized response jitter in DiscoveryHelper to prevent packet collisions
- Added a default upper bound for randomized pre-send jitter in discovery responses to avoid collisions when multiple repeaters respond simultaneously.
- Introduced a new parameter `response_jitter_ms` in the `DiscoveryHelper` constructor to configure the jitter.
- Updated the `_send_packet_async` method to apply the jitter before sending responses.
- Added tests to verify the correct application of jitter and ensure functionality when jitter is disabled.
2026-05-30 18:07:23 -07:00
agessaman 5fcb6255d5 feat: enhance login handler with anonymous request support and region name formatting
- Updated the `LoginHelper` class to wrap the login handler in an `AnonRequestHandler`, allowing for proper handling of anonymous requests.
- Introduced methods for formatting region names based on flood policies and added support for retrieving transport keys from SQLite storage.
- Enhanced the constructor to accept additional parameters for SQLite handler and configuration, improving flexibility for owner-info and feature-flag replies.
- Added tests to validate the new functionality and ensure correct behavior of region name formatting and owner/features callbacks.
2026-05-30 16:19:52 -07:00
Rightup 60ca184dbd refactor: enhance security comments and error handling across multiple modules 2026-05-27 22:07:34 +01:00
Lloyd 45a44eb47b Refactor test cases and base code for consistency and readability
- Updated byte representations in tests to use lowercase hex format for consistency.
- Reformatted code for better readability, including line breaks and indentation adjustments.
- Consolidated multiple lines into single lines where appropriate to enhance clarity.
- Ensured that all test cases maintain consistent formatting and style across the test suite.
2026-05-27 20:15:10 +01:00
Zindello d597ab2ea8 fix: replace datetime.UTC attribute access in repeater_cli
Also extend the compat scanner to catch datetime.UTC used as an
attribute (datetime.datetime.now(datetime.UTC)) in addition to
direct imports, so this form cannot be reintroduced undetected.

Co-Authored-By: Zindello <josh@zindello.com.au>
2026-05-27 12:16:56 +10:00
Lloyd 37ee0e892a Add more unit tests for handler helpers, identity manager, CLI, key generation, and main functionality
- Introduced tests for TraceHelper and DiscoveryHelper to validate packet forwarding and discovery request handling.
- Implemented tests for LoginHelper to ensure identity registration and login packet processing.
- Added tests for IdentityManager to cover identity registration, lookup, and filtering.
- Created tests for MeshCLI to verify command handling, configuration setting, and error paths.
2026-05-26 13:01:38 +01:00
Lloyd eb5d971c72 fix: filter neighbors to include only zero-hop repeaters in response 2026-05-11 16:26:15 +01:00
Lloyd a36d991c78 Fix event loop handling in TextHelper for room server synchronization 2026-04-28 09:24:42 +01:00
Lloyd 1626b3f307 feat: add max flood hops configuration to repeater settings 2026-04-22 13:52:40 +01:00
TJ Downes c52ae53cc6 perf(advert): replace list with deque for _recent_drops; use islice for _known_neighbors cap
Problem 1 — _recent_drops: the list was evicted with pop(0), which is an
O(n) memmove every time a drop is recorded.  With maxlen=20 this is
negligible today, but pop(0) on a list is always O(n) and the pattern is
worth eliminating.

Problem 2 — _known_neighbors cap: the eviction path did
  set(list(self._known_neighbors)[500:])
which first materialises the entire set as a list (O(n) allocation) before
slicing.  itertools.islice works directly on the set iterator and only
allocates the 500 kept items, halving peak memory pressure during cleanup.

Changes:
* Import itertools (already absent from this file)
* Import deque from collections alongside OrderedDict
* self._recent_drops initialised as deque(maxlen=20); self._max_recent_drops
  removed (maxlen is the single source of truth)
* Drop-recording block: rebuild deque from generator (preserves pubkey dedup
  filter) then append — automatic eviction replaces the explicit pop(0) guard
* Known-neighbors cap: itertools.islice(self._known_neighbors, 500) replaces
  list(self._known_neighbors)[500:]

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 19:52:44 -07:00
Lloyd c5fd41f28a feat: enhance task management in handlers with tracking and error logging 2026-04-21 09:38:03 +01:00
Lloyd 4d49eb701b feat: add owner_info field to repeater configuration and add getter for protocol request handling 2026-04-13 16:49:02 +01:00
Lloyd 07a47523ab feat: enhance event loop handling for thread-safe scheduling in MeshCLI 2026-03-24 14:18:12 +00:00
Lloyd 400e707c3f feat: add help command and detailed command descriptions to MeshCLI 2026-03-24 14:12:32 +00:00
Lloyd 91918e7cfc feat: add CLI command endpoint and standalone CLI client for pyMC Repeater 2026-03-24 14:02:51 +00:00
agessaman 3cb27d3310 feat: enhance trace processing and path handling in RepeaterDaemon and TraceHelper
- Added local_identity parameter to RepeaterDaemon for improved trace path matching.
- Refactored trace path handling in TraceHelper to support multi-byte hashes and structured hops.
- Updated methods to ensure compatibility with new trace data formats and improved logging.
- Enhanced tests to validate new trace processing logic and path handling.
2026-03-22 14:34:04 -07:00
agessaman 7558c5604c feat: enhance repeater TX mode functionality so companion tenants can TX while in monitor mode
- Modify TX modes: forward, monitor, and add no_tx, allowing for flexible packet handling.
- Updated configuration and API endpoints to support the new modes.
- Adjusted logic in RepeaterHandler to manage packet processing based on the selected mode.
- Enhanced CLI commands to reflect the new mode settings.
- Added tests for each TX mode to ensure correct behavior.
2026-03-15 13:03:18 -07:00
Lloyd 289fdb1a16 Add warning for trace responses with RSSI=0 in TraceHelper 2026-03-12 13:50:36 +00:00
Lloyd 632f1d2d1a Merge pull request #132 from agessaman/dev-companion-v2-cleanup
Update OTA repeater stats to return correct uptime, airtime, packet counts, etc.
2026-03-10 09:32:43 +00:00
agessaman 25c2a14a81 Update OTA repeater stats to return correct uptime, airtime, packet counts, etc.
- Introduced `total_rx_airtime_ms` in `AirtimeManager` to track received packet airtime.
- Added `record_rx` method to log received airtime in `AirtimeManager`.
- Updated `RepeaterHandler` to count received packets and log RX airtime using the new method.
- Enhanced statistics reporting in `get_stats` to include total received airtime.
- Updated `ProtocolRequestHelper` to include total RX airtime in the RepeaterStats structure for better monitoring.
2026-03-09 17:27:51 -07:00
Lloyd e19ec79b49 Implement advertisement packet deduplication with configurable TTL and max hashes 2026-03-06 16:47:38 +00:00
agessaman c150b9a9bf Merge upstream/feat/newRadios into dev-companion-v2-cleanup
- Keep our Vite-built assets and index.html script (index-DyUIpN7m.js)
- Remove upstream-only asset chunks and RoomServers-BxQ-0q-x.js
- README: keep two-backend intro, add upstream CAUTION/compatibility table
- manage.sh: keep dialog/gauge UX and .[hardware]; add CH341 udev, sudoers, libusb, polkit, silent upgrade
- sqlite_handler: add crc_errors table, index, and cleanup from upstream
- engine: add validate_packet and mark_seen in direct_forward; keep our path hash_size/hop_count logic
- advert: keep comment, use current_time = now
- api_endpoints: use restart_service() from service_utils
- config merge: strip user config comments before yq merge (upstream)

Made-with: Cursor
2026-03-05 16:43:14 -08:00
Lloyd c54efa3412 add side bar display of advert blocks etc 2026-03-05 12:56:01 +00:00
Lloyd 2b7d394938 add logging for tracking advert blocking 2026-03-05 11:26:40 +00:00
Lloyd 4285023670 Implement adaptive advert rate limiting and configuration updates 2026-03-05 10:35:15 +00:00
agessaman d5fe1e637c Restore deleted AdvertHelper. 2026-02-27 22:18:56 -08:00
agessaman 6fa85a832f Update packet type labels in rrdtool_handler and sqlite_handler for consistency
- Enhanced readability by adding descriptive suffixes to packet type labels in both rrdtool_handler.py and sqlite_handler.py.
- Aligned packet type definitions with the new naming conventions from pyMC_core, ensuring consistency across the codebase.
2026-02-27 21:18:29 -08:00
agessaman 789a2f27ea Enhance PacketRouter and CompanionFrameServer for improved packet delivery and contact persistence
- Updated PacketRouter to deliver packets to all companion bridges when the destination is not recognized, ensuring better handling of ephemeral destinations.
- Refactored CompanionFrameServer to separate contact serialization and persistence logic, allowing for non-blocking database operations.
- Introduced a unique index for companion contacts in SQLite to support upsert functionality, enhancing data integrity and performance.
- Improved AdvertHelper to run database operations in a separate thread, preventing event loop blocking and maintaining responsiveness.
2026-02-24 21:51:56 -08:00