← Back to list

Float Protocols: A Memory-Safe Rust Gateway for Heterogeneous Satellite IoT Protocol Translation…

The proliferation of low-Earth orbit (LEO) satellite constellations is driving a rapid fragmentation of satellite IoT protocols. Iridium…

Theo Wolfenden · 2026-05-28 03:52 · 1 claps · 12.2 min read
#satellite-technology #satellite #ast #rust #5g-technology
Open on Medium ↗
Wiki topics: RAG · RAG & Retrieval LNG · Linguistics & Language 📟 · Gadgets & IoT 🔭 · Astronomy & Space

Float Protocols: A Memory-Safe Rust Gateway for Heterogeneous Satellite IoT Protocol Translation with Bi-Temporal Audit Semantics

[embed]crates.io: Rust Package Registry crates.io serves as a central registry for sharing crates, which are packages or libraries written in Rust that you can…crates.io

[embed]GitHub - theoddden/Float-Protocols: Lightweight (1.1MB), low-latency async protocol-translation… Lightweight (1.1MB), low-latency async protocol-translation bridge for dead zone communication systems with future…github.com

The proliferation of low-Earth orbit (LEO) satellite constellations is driving a rapid fragmentation of satellite IoT protocols. Iridium Short Burst Data (SBD), Inmarsat C, Non-IP Data Delivery (NIDD) over 3GPP NTN NB-IoT, VSAT, and emerging direct-to-device networks such as AST SpaceMobile each impose distinct message formats, payload limits, cadence constraints, and reliability semantics. No open-source protocol gateway currently normalises across this stack. We present

Float, an Apache-licensed Rust library and gateway that translates between eight+ satellite and terrestrial IoT protocols, maintains a bi-temporal message store with valid-time and transaction-time dimensions, and uses the bi-temporal spread (t_system − t_event) as an active routing signal for reconnect-burst recovery. Float introduces a pre-allocated deadzone shard architecture inspired by NUMA-aware memory partitioning, a per-protocol exponentially weighted moving average (EWMA) adaptive threshold for burst classification, and a cadence translator that reconciles the order-of-magnitude differences in heartbeat frequency across bearers. All parsers are zero-allocation and verified with CRC-16-CCITT checksums. We evaluate Float’s latency across the five critical paths — parse-to-queue, queue-to-translate, cache-hit translation, emergency bypass, and reconnect-burst drain — using Criterion microbenchmarks. Float is available at https://github.com/theoddden/float-protocols.

  1. Introduction

Satellite IoT connectivity is expanding rapidly, but the market is structurally fragmented. As of 2024, more than 100 vendors are active in the satellite IoT space, with the top-7 satellite network operators (SNOs) — including Iridium, Inmarsat, ORBCOMM, Globalstar, and Eutelsat OneWeb — collectively holding over 80% of connections [1]. This dominance is expected to erode through 2030 as Starlink, Amazon Kuiper, Sateliot, and AST SpaceMobile enter at scale [1]. Each operator uses a distinct protocol stack, message framing, and reliability model.

The consequence for system integrators is acute. A maritime fleet tracking system may route emergency distress messages over Iridium SBD (maximum payload 340 bytes, end-to-end latency 5–20 seconds [2]), aggregate operational telemetry over VSAT (64 KB payloads, ~600 ms RTT), and forward real-time tracking via AST SpaceMobile’s direct-to-cell network (near-terrestrial latency) when in coverage. Each path has a different clock source, different reliability contract, and different maximum cadence. No open-source Rust library handles this combination.

A 2026 review of Direct-to-Satellite IoT architectures identifies ”interoperability with terrestrial IoT standards” as a first-tier open research challenge, alongside Doppler correction and massive access — and notes that ”a unified IoT stack spanning terrestrial and non-terrestrial domains is still an open goal” [3]. Float is a practical step toward that goal at the gateway layer.

Three design properties distinguish Float from generic message brokers:

  1. Zero-allocation parsers. All protocol decoders — Iridium SBD, NIDD, Inmarsat C — operate on stack-allocated fixed-size buffers. No heap allocation occurs on the hot path.

  2. Bi-temporal routing. Every message carries two timestamps: t_event (when the sensor observed the event in the physical world) and t_system (when the gateway first received it). The spread between these is used not just for audit logging, but as a real-time routing signal: messages with spread above a per-protocol threshold are classified as reconnect-burst candidates and routed to a dedicated pre-allocated shard for immediate draining.

  3. Memory-safe implementation. Float is written in Rust (stable toolchain), relying on ownership and the type system to eliminate classes of defects — buffer overflow, use-after-free, data races — that are endemic in C-based satellite middleware. Prior work on Rust for embedded and safety-critical systems confirms these guarantees are maintained even at the protocol-parsing level [4].

The remainder of this paper is structured as follows. Section 2 presents the system architecture. Section 3 describes the protocol parsers. Section 4 describes the bi-temporal store and spread-based routing. Section 5 presents the reconnect-burst recovery mechanism. Section 6 covers reliability primitives. Section 7 reports latency benchmarks. Section 8 discusses open challenges and future work. Section 9 concludes.

— -

  1. Architecture

Float’s gateway (Gateway) is an async Rust struct that composes eight functional subsystems connected through typed channels and shared-memory primitives (Figure 1).

  1. Protocol Parsers

3.1 Iridium SBD

The Iridium SBD parser implements zero-allocation frame parsing on a [u8; 340] stack buffer. Frame format: [protocol (1)][length (2 BE)][payload (N)][CRC-16-CCITT (2 BE)]. A prior defect — observed in production satellite middleware — is that many open implementations compute the CRC over only the payload, discarding the header contribution. This allows corrupt frames with valid payloads to pass silently. Float chains the CRC state across header and payload using crc16_ccitt_continue, a single-pass continuation function that avoids slice concatenation:


pub fn compute_crc(&self) -> u16 {

let header_data = [

self.header.protocol,

(self.header.length >> 8) as u8,

(self.header.length & 0xFF) as u8,

];

let crc = crc16_ccitt(&header_data);

crc16_ccitt_continue(crc, &self.payload[..self.payload_len as usize])

}

validate_checksum compares compute_crc() against the stored field, rejecting frames where the computed and stored values differ.

3.2 NIDD (3GPP TS 24.582)

The NIDD parser handles Non-IP Data Delivery frames for NTN NB-IoT as specified in 3GPP TS 24.582. Frame format: [pdu_type (1)][qos_priority (1)][reliability (1)][delay_class (1)][coverage_enhancement (1)][length (2 BE)][sequence (2 BE)][payload (N)]. Maximum payload is 1600 bytes per the standard. The parser is zero-allocation, operating on a [u8; 1600] stack buffer and returning Option<NIDDMessage>None on truncation or overlength payload.

Coverage enhancement levels (CE Level 0–4, corresponding to +0, +3, +5, +8 dB) and QoS priority classes are parsed to typed Rust enums, enabling downstream routing decisions without string comparison.

3.3 Inmarsat C and VSAT

The Inmarsat C parser handles the 128-byte maximum payload constraint of the C band Maritime Mobile Satellite Service. The VSAT parser wraps zstd compression for payloads exceeding the threshold, consistent with the bandwidth-optimised usage patterns of geostationary VSAT backhaul links with ~600 ms RTT.

3.4 Sequence Numbering

The ASTS protobuf translator maintains a global sequence counter using AtomicU32 with Ordering::Relaxed fetch-add. A prior defect — each ZeroCopyTranslator instance initialised its own counter to zero — caused all translated messages to carry sequence 0, breaking deduplication and ordering on the upstream side. The global atomic ensures monotonically increasing sequences across translation calls regardless of worker affinity.

— -

  1. Bi-Temporal Store and Spread-Based Routing

4.1 Bi-Temporal Data Model

Each Message in Float carries two independent time dimensions:

  • t_event (Valid Time): the Unix timestamp in milliseconds at which the sensor observed the physical event.

  • t_system (Transaction Time): the Unix timestamp in milliseconds at which the gateway first received the message.

This two-axis model is the standard bitemporal representation formalised in temporal database theory [5], where valid time captures physical-world truth and transaction time captures system knowledge. In the satellite context, t_event and t_system diverge whenever a device transmits from a dead zone: t_event is recorded at the device at the moment of observation, while t_system is recorded at the gateway when the burst is finally delivered after connectivity is restored.

The BiTemporalStore supports independent queries on either axis:


// What actually happened between 14:00 and 15:00 yesterday?

store.query_valid_time(t_start, t_end).await;

// What did the system believe at 15:00 yesterday?

store.query_transaction_time(t_start, t_end).await;

This separation is non-trivial in satellite IoT. Consider a ship that transits a polar dead zone for six hours. When connectivity is restored, a burst of 400 messages arrives in seconds. Each message carries a t_event spanning the past six hours; all carry near-identical t_system values. Without bi-temporal indexing, any downstream query using the system clock would either miss the burst entirely or surface it as a present-moment anomaly. With bi-temporal indexing, both the actual event sequence and the delivery sequence are queryable independently.

4.2 Spread as a Routing Signal

The spread of a message is defined as:


spread_ms = t_system — t_event

Positive spread indicates a delayed message (the canonical reconnect-burst case). Negative spread indicates the device clock is ahead of the gateway clock — a clock drift condition handled by the ClockReconciler.

Float promotes spread from a passive audit metric to an active routing signal. The AsyncBatcher monitors spread on every buffered message and flushes immediately when any message’s spread exceeds DEFAULT_SPREAD_FLUSH_THRESHOLD_MS (30 seconds):


fn should_flush(buffer: &[Message], spread_threshold_ms: i64) -> bool {

buffer.iter().any(|m| m.spread_ms() > spread_threshold_ms)

}

Messages that pass the shard routing stage with spread above the per-protocol adaptive threshold are directed to the dedicated spread_shard — a pre-allocated crossbeam::bounded channel with no backpressure gate and no cadence filtering. The design principle is that reconnect-burst messages are already stale; the correct action is to route and drain them as fast as possible, not to apply the rate-limiting that normal-cadence messages require.

4.3 EWMA Adaptive Threshold

The per-protocol burst threshold is adaptive. Each protocol has a base threshold (Table 1) below which normal operational latency is never classified as a burst. Above the base, the threshold rises with observed spread using a per-protocol EWMA with mean absolute deviation (MAD) envelope:


threshold_ms = max(protocol_base_ms, ewma_spread + 3 × ewma_MAD)

EWMA with α = 0.05 (~20-message half-life) was chosen to adapt slowly to environments with chronic high latency — for example, a ship operating near the Iridium coverage boundary — without misclassifying normal delays as reconnect bursts. The 3-MAD multiplier approximates a 3σ outlier threshold for near-Gaussian spread distributions [6]. A separate EwmaSpreadState instance is maintained per Protocol variant, preventing high-frequency Samsara cellular traffic from inflating the threshold for low-frequency Iridium SBD on the same gateway.

4.4 Clock Reconciliation

IoT device clocks drift meaningfully over dead-zone durations. Empirical measurement on standard IoT hardware shows drift of seconds over short periods and poor rate stability [7]. Float’s ClockReconciler maintains a HashMap<u64, ClockOffset> keyed by device ID, supporting O(1) per-device offset lookup. Each ClockOffset records a confidence score (0.0–1.0) and a staleness timestamp; offsets older than max_age are invalidated. The network time source is configurable: ASTS network time, NTP, GPS, or local system clock.

When a device’s clock is known to be ahead of network time (negative spread), the reconciler applies the stored offset to produce a corrected t_event before the message enters the bi-temporal store.

— -

  1. Reconnect-Burst Recovery

5.1 The Contact Window Problem

A LEO satellite is visible from a ground station for 5–15 minutes per pass, with 6–14 passes per day depending on orbital geometry [3]. Traffic is inherently bursty at pass boundaries: devices that accumulated data during the dead zone transmit simultaneously when the satellite rises above the elevation threshold. At the gateway, this produces a sharp traffic spike — a reconnect burst — where all messages carry the same or similar t_system but t_event values spanning the preceding dead-zone duration.

5.2 Pre-Allocated Shard Architecture

Float’s ShardManager pre-allocates two special shards at construction time:

  • deadzone_shard: a bounded crossbeam channel for messages arriving during confirmed dead-zone transitions.

  • spread_shard: a bounded crossbeam channel for high-spread messages classified as reconnect-burst candidates.

Pre-allocation eliminates the allocation latency that would otherwise occur at the moment of burst onset — exactly when the gateway is under maximum load. Each shard is served by an independent ShardWorker task that owns the crossbeam Receiver, preventing lock contention between protocol workers. Backpressure (80% capacity limit on regular shards, measured via AtomicU64 rather than O(n) stats scan) is not applied to the spread shard.

5.3 Batch Operations

The drain_spread_shard_once method collects all translated message pairs into a local vector, then performs a single set_batch on the cache and a single create_batch_snapshot on the snapshot manager. This replaces N lock acquisitions with 1, amortising Tokio’s async mutex overhead across the entire burst. The BiTemporalStore.store_batch() applies the same pattern: one write-lock acquisition to commit an entire batch.

— -

  1. Reliability

6.1 Circuit Breaker

The upstream ASTS API call in send_to_asts is wrapped in a CircuitBreaker with configurable failure threshold and recovery timeout. State transitions use AtomicU32 for the circuit state (Closed / Open / HalfOpen), avoiding the mutex overhead that would otherwise serialize concurrent upstream calls. The half-open state allows one probe call through after the recovery timeout, closing the circuit on success and re-opening on failure.

The circuit breaker pattern for satellite upstream calls is motivated by the asymmetric failure modes of satellite-connected gateways: a burst of connectivity after a long dead zone may coincide with a transient upstream API failure. Without a circuit breaker, the gateway would generate a cascade of failed API calls proportional to the burst size. With the circuit breaker open, the gateway classifies the situation as a known failure and falls back gracefully [8].

6.2 Snapshot Manager

SnapshotManager maintains an in-memory audit snapshot store using a HashMap<String, Snapshot> for O(1) lookup and a VecDeque<String> for insertion-order eviction. A naive implementation using only HashMap requires an O(n) scan to find the oldest entry on capacity overflow. The VecDeque front-pop gives O(1) amortised eviction: ghost keys (IDs removed by drain or delete before eviction fires) are skipped by continuing to pop until a live key is found.

— -

  1. Performance Evaluation

Float’s latency suite (in benches/latency_bench.rs) measures five critical paths using Criterion [9] with a dedicated Tokio runtime per benchmark:

  1. parse-to-queue: raw bytes to AsyncBatcher send, across payload sizes {16, 64, 256, 340} bytes.

  2. queue-to-translate: message creation to synchronous translation completion.

  3. cache-hit translation: gateway send with pre-warmed cache.

  4. emergency path: emergency-priority message from gateway send to completion.

  5. reconnect-burst drain: spreading {10, 50, 100, 500} messages across the burst drain cycle.

All benchmarks run in CI on ubuntu-latest with Criterion’s statistical regression detection. Benchmark artifacts are uploaded to GitHub Actions via actions/upload-artifact@v4.

The most analytically significant paths are (2) and (5). Path (2) should be sub-millisecond in all configurations; any regression here indicates lock contention in the translation pool. Path (5) is expected to scale sublinearly with burst size due to the single-lock-acquisition batch design; linear scaling would indicate a regression to per-message locking.

For Iridium SBD in production, the dominant latency is bearer physics: 5–20 seconds for short messages [2]. Float’s internal paths are below the measurement floor of satellite scheduling latency. For AST SpaceMobile’s direct-to-cell path, where link latency approaches terrestrial (~40 ms propagation from LEO altitude), internal processing time is meaningful; this is the path where the latency benchmarks are most credible.

— -

  1. Open Challenges

SCHC integration. 3GPP Release 17 mandates Static Context Header Compression and Fragmentation (SCHC, RFC 8724) for NTN NB-IoT. Recent work identifies uncertainty about whether SCHC can function effectively in DtS-IoT environments [3]. Float currently handles raw NIDD payloads; a SCHC compression/decompression adapter would be needed for full 3GPP NTN compliance.

DTN interoperability. Delay-Tolerant Networking (DTN, RFC 9171 Bundle Protocol v7) provides standardised store-and-forward with custody transfer semantics for disruption-tolerant links. A Rust implementation (dtn7-rs) exists but has no protocol translation layer. Float’s spread shard architecture is semantically adjacent to DTN custody transfer; a float-dtn feature crate connecting the two would enable use in multi-hop DTN networks and NASA/ESA adjacent deployments.

no_std gateway. Float’s no-std feature flag is declared but not fully implemented. An embassy-net compatible no_std gateway mode would allow Float to run on the gateway hardware itself (edge processing), consistent with the ~40% device energy reduction reported for gateway-based vs direct-to-satellite architectures [3].

p99 latency characterisation. Criterion reports mean and standard deviation; tail latency under concurrent load is not currently measured. A hdrhistogram integration in the burst drain benchmark would expose p99/p99.9 distributions, which are the operationally meaningful metrics for SLA conversations with satellite operators handling mixed-fleet bursts.

NIDD transport layer. The current send_to_asts implementation uses HTTP/REST via reqwest. AST SpaceMobile’s cellular broadband tier is REST-accessible. NIDD devices, however, use the T7 Diameter interface or the 3GPP SCEF (Service Capability Exposure Function), not HTTP. Full NIDD uplink support requires a separate transport implementation beyond the current HTTP client.

— -

  1. Conclusion

Float provides the first open-source Rust implementation of a multi-protocol satellite IoT gateway with bi-temporal audit semantics. The key contribution is the promotion of bi-temporal spread from passive metadata to an active routing control signal, enabling reconnect-burst recovery without a separate out-of-band signalling mechanism. The pre-allocated shard architecture eliminates allocation latency at burst onset, and the per-protocol EWMA adaptive threshold prevents chronic high-latency environments from generating false burst classifications.

The satellite IoT market is in a structural fragmentation phase: 100+ operators, each with distinct protocol semantics, and a documented open research challenge of protocol interoperability [3]. Float’s Apache-2.0 licence permits embedding in both open and proprietary stacks, positioning it as infrastructure-layer software in the same tradition as smoltcp, embassy-net, and tokio — libraries that gain traction by solving the problem correctly, once, in memory-safe Rust, rather than requiring each operator to solve it independently in C…

## References

[1] IoT Analytics, “Satellite IoT competitive landscape: 5 notable insights,” IoT Analytics Market Report 2025–2030, June 2025. Available: https://iot-analytics.com/satellite-iot-competitive-landscape/

[2] Beam Communications, “Short Burst Data (SBD) Services,” Technical Overview. Available: https://www.beamcommunications.com/services/short-burst-data-sbd. ”Global network latency for the delivery of messages ranges from 5 seconds for short messages to 20 seconds for longer ones.”

[3] S. [Authors], “Direct-to-satellite internet of things (DtS-IoT): a tutorial review on architectures, protocols, and future directions,” Frontiers in Communications and Networks, 2026. DOI: 10.3389/frcmn.2026.1750955

[4] S. Mergendahl, N. Burow, H. Okhravi, “Rust for Embedded Systems: Current State, Challenges and Open Problems,” Proc. ACM SIGSAC CCS, 2024. arXiv:2311.05063

[5] C. S. Jensen and R. T. Snodgrass, “Temporal Data Management,” IEEE Trans. Knowledge and Data Engineering, vol. 11, no. 1, pp. 36–44, 1999. Reprinted in Comprehensive insights into bitemporal databases: a PRISMA-guided systematic review, Journal of Data, Information and Management, 2026. DOI: 10.1007/s42488–026–00162-x

[6] S. Boyd, N. Parikh, E. Chu, “Exponentially Weighted Moving Models,” arXiv:2404.08136, April 2024.

[7] A. Hälinen, H. Tikkanen, M. Laurinen, “A System for Clock Synchronization in an Internet of Things,” arXiv:1806.02474, June 2018. ”Clock drift on the order of seconds over relatively short time periods.”

[8] M. Camilli, A. Bellettini, L. Capra, “Circuit Breakers, Discovery, and API Gateways in Microservices,” arXiv:1609.05830, 2016.

[9] B. Brooks, “Criterion.rs: Statistics-driven Microbenchmarking in Rust,” https://github.com/bheisler/criterion.rs

[10] 3GPP TS 24.582, “Non-IP Data Delivery (NIDD) using Control Plane CIoT EPS optimisation,” 3rd Generation Partnership Project, Rel-16/17.

[11] BeWhere Holdings Inc., “BeWhere Holdings Inc. Successfully Connects IoT Device on AST SpaceMobile’s Direct-to-Device Satellite Network,” Newsfile Corp., October 28, 2025.

[12] T. Lauterbach et al., “dtn7-rs: A Delay-Tolerant Networking Implementation in Rust,” DTN7 Project, https://dtn7.github.io/

[13] O. Kodheli et al., “Satellite Communications in the New Space Era: A Survey and Future Challenges,” IEEE Commun. Surveys Tuts., vol. 23, no. 1, pp. 70–109, 2021.


메타데이터
post_id
a44962c8ac74
slug
float-protocols-a-memory-safe-rust-gateway-for-heterogeneous-satellite-iot-protocol-translation-a44962c8ac74
url
https://medium.com/@theo_56051/float-protocols-a-memory-safe-rust-gateway-for-heterogeneous-satellite-iot-protocol-translation-a44962c8ac74
canonical_url
https://medium.com/@theo_56051/float-protocols-a-memory-safe-rust-gateway-for-heterogeneous-satellite-iot-protocol-translation-a44962c8ac74
author_url
https://medium.com/@theo_56051
status
ok
fetched_at
2026-06-09 15:37:30