Skip to content

Commit 5f0f56e

Browse files
tridgeclaude
andcommitted
mavlink: clamp persisted timestamp at save time too, to prevent +15s drift
The previous fix raised signing.timestamp on load to max(saved+15s, now) but the save path still persisted whatever signing.timestamp held — and in a session with no successful send_message (e.g. a child where the first incoming packet gets rejected and so nothing is forwarded onward), signing.timestamp stays at the loaded value of saved+15s and gets written straight back. Each load+save cycle then ratchets the stored key.timestamp by another 15s ahead of real time. After enough sequential short-lived sessions the stored value parks far enough in the future that the next session's first incoming packet is below signing.timestamp - MAVLINK_SIGNING_TIMESTAMP_LIMIT seconds and the helper rejects it with MAVLINK_SIGNING_STATUS_OLD_TIMESTAMP. Once that happens nothing forwards on that link for the lifetime of the test suite. Cap the persisted value at current wall clock. The +15s buffer is a load-time replay guard against advancement lost between the previous save and a crash; it isn't supposed to round-trip through the next save. With the cap, the stored key.timestamp tracks real time, the +15s buffer is reapplied fresh on each load, and per-session drift is bounded at ~15s — never compounds across sessions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 1dc0e22 commit 5f0f56e

1 file changed

Lines changed: 24 additions & 3 deletions

File tree

mavlink.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -380,12 +380,33 @@ void MAVLink::save_signing_timestamp(void)
380380
}
381381
bool need_save = false;
382382

383+
// Cap saved value at current real time. The +15s buffer added in
384+
// load_signing_key() is a per-load replay guard; allowing it to
385+
// round-trip through this save would let the buffer compound across
386+
// sequential short-lived sessions until signing.timestamp parks far
387+
// enough in the future that incoming packets get rejected as
388+
// MAVLINK_SIGNING_STATUS_OLD_TIMESTAMP. Using the legitimate
389+
// wall-clock advancement here keeps the stored timestamp in sync
390+
// with reality.
391+
double now_s = time_seconds();
392+
const uint64_t epoch_offset = 1420070400ULL;
393+
uint64_t now_mavlink = 0;
394+
if (now_s > epoch_offset) {
395+
now_mavlink = uint64_t(now_s - epoch_offset) * 100ULL * 1000ULL;
396+
}
397+
383398
for (uint8_t i=0; i<MAVLINK_COMM_NUM_BUFFERS; i++) {
384399
mavlink_channel_t _chan = (mavlink_channel_t)(MAVLINK_COMM_0 + i);
385400
const mavlink_status_t *status = mavlink_get_channel_status(_chan);
386-
if (status && status->signing && status->signing->timestamp > key.timestamp) {
387-
key.timestamp = status->signing->timestamp;
388-
need_save = true;
401+
if (status && status->signing) {
402+
uint64_t v = status->signing->timestamp;
403+
if (v > now_mavlink) {
404+
v = now_mavlink;
405+
}
406+
if (v > key.timestamp) {
407+
key.timestamp = v;
408+
need_save = true;
409+
}
389410
}
390411
}
391412
if (need_save) {

0 commit comments

Comments
 (0)