Skip to content

Bugfix: Separate login and message replay timestamps to allow companion RTC differs from app clock - #2834

Open
usrflo wants to merge 3 commits into
meshcore-dev:devfrom
usrflo:bugfix/login-msg-timer
Open

Bugfix: Separate login and message replay timestamps to allow companion RTC differs from app clock#2834
usrflo wants to merge 3 commits into
meshcore-dev:devfrom
usrflo:bugfix/login-msg-timer

Conversation

@usrflo

@usrflo usrflo commented Jun 24, 2026

Copy link
Copy Markdown

Summary

Properly fixes the silent-message-rejection issue that was also addressed in #1551 and #1889.
It does so by tracking login replay and message replay in two separate per-client fields instead of sharing one to fix clock/timestamp differences at the client. This uniformly applies to room-server, repeater and sensor.

Fix

Split the two replay tracks:

  • Add a transient field ClientInfo::last_login_timestamp.
  • The login replay check and the login timestamp assignment use last_login_timestamp.
  • The message/REQ handlers are unchanged and keep using last_timestamp.

Result:

  • Login replay now runs purely on the companion RTC. Because getCurrentTimeUnique() is monotonic per device, every login's timestamp strictly exceeds the previous one → repeated logins work again (regression fixed).
  • Message replay still runs on last_timestamp, which is no longer poisoned by the login's RTC value → messages are no longer rejected when the RTC runs ahead.
  • The forward-only RTC sync (clock sync / time refuse to go backwards) no longer matters, because the two replay tracks are independent.

Backward compatibility

No wire-protocol change. Old clients keep working against a patched server (the server just tracks login and messages separately), and patched clients work against an unpatched server.

…o prevent being stuck using different timer values
@usrflo usrflo changed the title Separate login and message replay timestamps (proper fix for #1551, supersedes #1889) Bugfix: Separate login and message replay timestamps to allow companion RTC differs from app clock Jun 28, 2026
@usrflo
usrflo marked this pull request as ready for review June 28, 2026 06:57
@usrflo
usrflo marked this pull request as draft June 28, 2026 19:39
@usrflo

usrflo commented Jul 14, 2026

Copy link
Copy Markdown
Author

Proof by test case "companion RTC in the future"

Stock firmware (dev-Branch) denies messages after login with the debug log statement "possible replay attack detected"

Bug: the login-timestamp from the rtc clock is compared with the message-timestamp from the app clock, login_ts>msg_ts, error

Companion with future time (+3 months)

(venv) $ meshcli -s /dev/meshl1new
INFO:meshcore:Serial Connection started
INFO:meshcore:Connected to meshl1new running on a v1.16.0 fw.
meshl1new|* clock
Current time : 2026-10-14 21:26:08 (1792005968)
meshl1new|* quit
(venv) $ meshcli -s /dev/meshl1new login meshhtv3 [...]
INFO:meshcore:Serial Connection started
INFO:meshcore:Connected to meshl1new running on a v1.16.0 fw.
Login success
(venv) $ meshcli -s /dev/meshl1new msg meshhtv3 "A0 baseline (RTC incorrect)" wait_ack
INFO:meshcore:Serial Connection started
INFO:meshcore:Connected to meshl1new running on a v1.16.0 fw.
Timeout waiting ack
(venv) $ 

Repeater-Serial-Log

DEBUG: RadioLibWrapper: noise_floor = -92
10:52:54 - 15/5/2024 U RAW: 1E00B71C1944EF77CBD5B639451A11EDFE0039F5BEA9CFC83899D45E77C0C71F98CE947AABFC268A17EF0EE6B1C1134A404D37FF0D
10:52:54 - 15/5/2024 U: RX, len=53 (type=7, route=D, payload_len=51) SNR=11 RSSI=-24 score=1000 time=467 hash=C326FAC717A35C86
DEBUG: Login success!
DEBUG: RadioLibWrapper: noise_floor = -92
10:52:55 - 15/5/2024 U: TX, len=22 (type=1, route=F, payload_len=20) [B7 -> 1C]
10:52:57 - 15/5/2024 U RAW: 0501921CB7BEB08B637928A1CC46D89FAE45F491DB6A0B
10:52:57 - 15/5/2024 U: RX, len=23 (type=1, route=F, payload_len=20) SNR=12 RSSI=-43 score=1000 time=324 hash=BD2021EAC9EB7553 [B7 -> 1C]
DEBUG: 10:52:57 - 15/5/2024 U Dispatcher::checkRecv(), score delay below threshold (0)
DEBUG: RadioLibWrapper: noise_floor = -93
10:52:58 - 15/5/2024 U RAW: 2200B71C2CF7EB49D0E271A90242AEF0278AB00F695D
10:52:58 - 15/5/2024 U: RX, len=22 (type=8, route=D, payload_len=20) SNR=12 RSSI=-23 score=1000 time=304 hash=C8340E778B8C42DB [1C -> B7]
DEBUG: PATH to client, path_len=0
DEBUG: RadioLibWrapper: noise_floor = -92
DEBUG: RadioLibWrapper: noise_floor = -93
DEBUG: RadioLibWrapper: noise_floor = -92
10:53:03 - 15/5/2024 U RAW: 0A00B71CDE1891FF919B689CA45E060A87358F2B8CAB07877ED44ECB672C387225CF36EF08D7
10:53:03 - 15/5/2024 U: RX, len=38 (type=2, route=D, payload_len=36) SNR=11 RSSI=-24 score=1000 time=386 hash=8E180F4B9C366CE4 [1C -> B7]
DEBUG: onPeerDataRecv: possible replay attack detected
DEBUG: RadioLibWrapper: noise_floor = -93
DEBUG: RadioLibWrapper: noise_floor = -92

Firmware with this Pull-Request 2834

Comparison of login_ts with login_ts from RTC clock and msg_ts with msg_ts from app clock

Companion with future time (+3 months)

(venv) $ meshcli -s /dev/meshl1new
INFO:meshcore:Serial Connection started
INFO:meshcore:Connected to meshl1new running on a v1.16.0 fw.
meshl1new|* clock
Current time : 2026-10-14 21:19:06 (1792005546)
meshl1new|* quit
(venv) $ meshcli -s /dev/meshl1new login meshhtv3 [...]
INFO:meshcore:Serial Connection started
INFO:meshcore:Connected to meshl1new running on a v1.16.0 fw.
Login success
(venv) $ meshcli -s /dev/meshl1new msg meshhtv3 "A0 baseline (RTC correct)" wait_ack
INFO:meshcore:Serial Connection started
INFO:meshcore:Connected to meshl1new running on a v1.16.0 fw.
Msg acked
(venv) $ 

Repeater-Serial-Log

DEBUG: RadioLibWrapper: noise_floor = -91
10:53:20 - 15/5/2024 U RAW: 1E00B71C1944EF77CBD5B639451A11EDFE0039F5BEA9CFC83899D45E77C0C71F98CE94F1C0189C1D6CAB186EBCA537FA9991ACA4AD
10:53:20 - 15/5/2024 U: RX, len=53 (type=7, route=D, payload_len=51) SNR=11 RSSI=-27 score=1000 time=467 hash=3682E6825BC1DD86
DEBUG: Login success!
DEBUG: RadioLibWrapper: noise_floor = -92
10:53:21 - 15/5/2024 U: TX, len=22 (type=1, route=F, payload_len=20) [B7 -> 1C]
DEBUG: RadioLibWrapper: noise_floor = -92
10:53:24 - 15/5/2024 U RAW: 2200B71CC541AC889F86C4139451502BB8B04831BB5C
10:53:24 - 15/5/2024 U: RX, len=22 (type=8, route=D, payload_len=20) SNR=11 RSSI=-27 score=1000 time=304 hash=0749A2FCBA2A929D [1C -> B7]
DEBUG: PATH to client, path_len=0
DEBUG: RadioLibWrapper: noise_floor = -92
DEBUG: RadioLibWrapper: noise_floor = -91
DEBUG: RadioLibWrapper: noise_floor = -91
DEBUG: RadioLibWrapper: noise_floor = -91
DEBUG: RadioLibWrapper: noise_floor = -92
10:53:34 - 15/5/2024 U RAW: 0A00B71C5D10DD60488C01E467F65A8D8AC0380BF25907877ED44ECB672C387225CF36EF08D7
10:53:34 - 15/5/2024 U: RX, len=38 (type=2, route=D, payload_len=36) SNR=11 RSSI=-26 score=1000 time=386 hash=7EE044590288F8EC [1C -> B7]
DEBUG: RadioLibWrapper: noise_floor = -91
10:53:35 - 15/5/2024 U: TX, len=6 (type=3, route=D, payload_len=4)
10:53:35 - 15/5/2024 U: TX, len=38 (type=2, route=D, payload_len=36) [B7 -> 1C]
DEBUG: RadioLibWrapper: noise_floor = -91
DEBUG: RadioLibWrapper: noise_floor = -91

--> the wrong evaluation "possible replay attack detected" doesn't occur anymore with the bugfix

@usrflo
usrflo marked this pull request as ready for review July 14, 2026 20:18
@usrflo

usrflo commented Jul 22, 2026

Copy link
Copy Markdown
Author

It is always a pleasure to see how smoothly repeater/room-server logins work with this pull request.
This PR ist part of the ufo firmware, latest build at time of writing: v0.6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant