[fix](trx-server): guard APRS-IS uplink against history replays

Skip APRS packets whose ts_ms is older than 120 seconds. Live RF-decoded
packets arrive within milliseconds; history replay items can be up to 24
hours old and must not be re-uploaded to APRS-IS as live traffic.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
2026-03-14 08:45:24 +01:00
parent 5ed3e29d90
commit 945912adc1
+16
View File
@@ -4,6 +4,8 @@
//! APRS-IS IGate uplink — forwards RF-decoded APRS packets to APRS-IS (aprs.fi etc.).
use std::time::{SystemTime, UNIX_EPOCH};
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
use tokio::net::TcpStream;
use tokio::sync::broadcast;
@@ -209,6 +211,20 @@ pub async fn run_aprsfi_uplink(
stats_skipped += 1;
continue 'forward;
}
// Guard against history replays: skip packets whose timestamp
// indicates they are older than 2 minutes. Live RF-decoded
// packets arrive within milliseconds; history items can be
// up to 24 hours old.
if let Some(ts_ms) = pkt.ts_ms {
let now_ms = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_millis() as i64)
.unwrap_or(0);
if now_ms.saturating_sub(ts_ms) > 120_000 {
stats_skipped += 1;
continue 'forward;
}
}
let tnc2 = format_tnc2(&pkt);
debug!("APRS-IS: forwarded {}>{},...", pkt.src_call, pkt.dest_call);
if let Err(e) = write_half.write_all(tnc2.as_bytes()).await {