ove/
net_sntp.rs

1// Copyright (C) 2026 Kamil Lulko <kamil.lulko@gmail.com>
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4//
5// This file is part of oveRTOS.
6
7//! SNTP time synchronization client.
8//!
9//! Provides a safe Rust API for the oveRTOS SNTP subsystem.  A single NTP
10//! query is sent to a time server and the resulting UTC offset is stored
11//! internally.  Useful for wall-clock timestamps, TLS certificate
12//! validation, and log correlation.
13//!
14//! # Example
15//!
16//! ```ignore
17//! use ove::net_sntp;
18//!
19//! let cfg = net_sntp::Config {
20//!     server: b"pool.ntp.org\0",
21//!     timeout_ms: 5000,
22//! };
23//! net_sntp::sync(&cfg).unwrap();
24//! let utc = net_sntp::get_utc().unwrap();
25//! ```
26
27use crate::bindings;
28use crate::error::{Error, Result};
29
30// ---------------------------------------------------------------------------
31// Config
32// ---------------------------------------------------------------------------
33
34/// SNTP client configuration.
35///
36/// `server` must be a null-terminated byte string (e.g. `b"pool.ntp.org\0"`).
37/// A `timeout_ms` of 0 uses the default (5000 ms).
38pub struct Config<'a> {
39    /// NTP server hostname (null-terminated).
40    pub server: &'a [u8],
41    /// Query timeout in milliseconds (0 = default 5000).
42    pub timeout_ms: u32,
43}
44
45impl Default for Config<'_> {
46    fn default() -> Self {
47        Self {
48            server: b"pool.ntp.org\0",
49            timeout_ms: 5000,
50        }
51    }
52}
53
54// ---------------------------------------------------------------------------
55// API
56// ---------------------------------------------------------------------------
57
58/// Synchronize with an NTP server.
59///
60/// Sends a single NTP request and stores the computed UTC offset.
61/// Subsequent calls update the stored offset.
62///
63/// # Errors
64/// Returns an error if the NTP query fails.
65pub fn sync(cfg: &Config) -> Result<()> {
66    let c_cfg = bindings::ove_sntp_config_t {
67        server: cfg.server.as_ptr() as *const _,
68        timeout_ms: cfg.timeout_ms,
69    };
70    let rc = unsafe { bindings::ove_sntp_sync(&c_cfg) };
71    Error::from_code(rc)
72}
73
74/// Get the UTC offset computed by the last successful sync.
75///
76/// The offset can be added to `ove_time_get_us()` to approximate
77/// wall-clock time (microseconds since Unix epoch).
78///
79/// # Errors
80/// Returns `Error::NotSupported` if no sync has been performed.
81pub fn get_offset_us() -> Result<i64> {
82    let mut offset: i64 = 0;
83    let rc = unsafe { bindings::ove_sntp_get_offset_us(&mut offset) };
84    Error::from_code(rc)?;
85    Ok(offset)
86}
87
88/// Get the current UTC time in seconds since Unix epoch.
89///
90/// Convenience function: returns monotonic time + NTP offset.
91///
92/// # Errors
93/// Returns `Error::NotSupported` if no sync has been performed.
94pub fn get_utc() -> Result<u32> {
95    let mut utc: u32 = 0;
96    let rc = unsafe { bindings::ove_sntp_get_utc(&mut utc) };
97    Error::from_code(rc)?;
98    Ok(utc)
99}