Chrono dep made optional
This commit is contained in:
parent
0b807f03a6
commit
2b6317a9e2
9 changed files with 181 additions and 79 deletions
|
@ -16,10 +16,11 @@
|
|||
*/
|
||||
|
||||
use super::{CertConsumer, MAX_DEPTH};
|
||||
use crate::error::Error;
|
||||
use chrono::{Datelike, TimeZone, Utc}; // TODO
|
||||
use core::fmt::Write;
|
||||
use log::warn;
|
||||
use crate::{
|
||||
error::Error,
|
||||
utils::epoch::{UtcCalendar, MATTER_EPOCH_SECS},
|
||||
};
|
||||
use core::{fmt::Write, time::Duration};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ASN1Writer<'a> {
|
||||
|
@ -261,31 +262,34 @@ impl<'a> CertConsumer for ASN1Writer<'a> {
|
|||
self.write_str(0x06, oid)
|
||||
}
|
||||
|
||||
fn utctime(&mut self, _tag: &str, epoch: u32) -> Result<(), Error> {
|
||||
let mut matter_epoch = Utc
|
||||
.with_ymd_and_hms(2000, 1, 1, 0, 0, 0)
|
||||
.unwrap()
|
||||
.timestamp();
|
||||
fn utctime(&mut self, _tag: &str, epoch: u32, utc_calendar: UtcCalendar) -> Result<(), Error> {
|
||||
let matter_epoch = MATTER_EPOCH_SECS + epoch as u64;
|
||||
|
||||
matter_epoch += epoch as i64;
|
||||
let dt = utc_calendar(Duration::from_secs(matter_epoch as _));
|
||||
|
||||
let dt = match Utc.timestamp_opt(matter_epoch, 0) {
|
||||
chrono::LocalResult::None => return Err(Error::InvalidTime),
|
||||
chrono::LocalResult::Single(s) => s,
|
||||
chrono::LocalResult::Ambiguous(_, a) => {
|
||||
warn!("Ambiguous time for epoch {epoch}; returning latest timestamp: {a}");
|
||||
a
|
||||
}
|
||||
};
|
||||
let mut time_str: heapless::String<32> = heapless::String::<32>::new();
|
||||
|
||||
if dt.year() >= 2050 {
|
||||
if dt.year >= 2050 {
|
||||
// If year is >= 2050, ASN.1 requires it to be Generalised Time
|
||||
let mut time_str = heapless::String::<32>::new();
|
||||
write!(&mut time_str, "{}Z", dt.format("%Y%m%d%H%M%S")).unwrap();
|
||||
write!(
|
||||
&mut time_str,
|
||||
"{:04}{:02}{:02}{:02}{:02}{:02}Z",
|
||||
dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second
|
||||
)
|
||||
.unwrap();
|
||||
self.write_str(0x18, time_str.as_bytes())
|
||||
} else {
|
||||
let mut time_str = heapless::String::<32>::new();
|
||||
write!(&mut time_str, "{}Z", dt.format("%y%m%d%H%M%S")).unwrap();
|
||||
write!(
|
||||
&mut time_str,
|
||||
"{:02}{:02}{:02}{:02}{:02}{:02}Z",
|
||||
dt.year % 100,
|
||||
dt.month,
|
||||
dt.day,
|
||||
dt.hour,
|
||||
dt.minute,
|
||||
dt.second
|
||||
)
|
||||
.unwrap();
|
||||
self.write_str(0x17, time_str.as_bytes())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ use crate::{
|
|||
crypto::KeyPair,
|
||||
error::Error,
|
||||
tlv::{self, FromTLV, OctetStr, TLVArray, TLVElement, TLVWriter, TagType, ToTLV},
|
||||
utils::writebuf::WriteBuf,
|
||||
utils::{epoch::UtcCalendar, writebuf::WriteBuf},
|
||||
};
|
||||
use log::error;
|
||||
use num_derive::FromPrimitive;
|
||||
|
@ -617,17 +617,21 @@ impl<'a> Cert<'a> {
|
|||
Ok(wb.as_slice().len())
|
||||
}
|
||||
|
||||
pub fn as_asn1(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
pub fn as_asn1(&self, buf: &mut [u8], utc_calendar: UtcCalendar) -> Result<usize, Error> {
|
||||
let mut w = ASN1Writer::new(buf);
|
||||
self.encode(&mut w)?;
|
||||
self.encode(&mut w, Some(utc_calendar))?;
|
||||
Ok(w.as_slice().len())
|
||||
}
|
||||
|
||||
pub fn verify_chain_start(&self) -> CertVerifier {
|
||||
CertVerifier::new(self)
|
||||
pub fn verify_chain_start(&self, utc_calendar: UtcCalendar) -> CertVerifier {
|
||||
CertVerifier::new(self, utc_calendar)
|
||||
}
|
||||
|
||||
fn encode(&self, w: &mut dyn CertConsumer) -> Result<(), Error> {
|
||||
fn encode(
|
||||
&self,
|
||||
w: &mut dyn CertConsumer,
|
||||
utc_calendar: Option<UtcCalendar>,
|
||||
) -> Result<(), Error> {
|
||||
w.start_seq("")?;
|
||||
|
||||
w.start_ctx("Version:", 0)?;
|
||||
|
@ -646,8 +650,10 @@ impl<'a> Cert<'a> {
|
|||
self.issuer.encode("Issuer:", w)?;
|
||||
|
||||
w.start_seq("Validity:")?;
|
||||
w.utctime("Not Before:", self.not_before)?;
|
||||
w.utctime("Not After:", self.not_after)?;
|
||||
if let Some(utc_calendar) = utc_calendar {
|
||||
w.utctime("Not Before:", self.not_before, utc_calendar)?;
|
||||
w.utctime("Not After:", self.not_after, utc_calendar)?;
|
||||
}
|
||||
w.end_seq()?;
|
||||
|
||||
self.subject.encode("Subject:", w)?;
|
||||
|
@ -679,7 +685,7 @@ impl<'a> fmt::Display for Cert<'a> {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut printer = CertPrinter::new(f);
|
||||
let _ = self
|
||||
.encode(&mut printer)
|
||||
.encode(&mut printer, None)
|
||||
.map_err(|e| error!("Error decoding certificate: {}", e));
|
||||
// Signature is not encoded by the Cert Decoder
|
||||
writeln!(f, "Signature: {:x?}", self.get_signature())
|
||||
|
@ -688,11 +694,12 @@ impl<'a> fmt::Display for Cert<'a> {
|
|||
|
||||
pub struct CertVerifier<'a> {
|
||||
cert: &'a Cert<'a>,
|
||||
utc_calendar: UtcCalendar,
|
||||
}
|
||||
|
||||
impl<'a> CertVerifier<'a> {
|
||||
pub fn new(cert: &'a Cert) -> Self {
|
||||
Self { cert }
|
||||
pub fn new(cert: &'a Cert, utc_calendar: UtcCalendar) -> Self {
|
||||
Self { cert, utc_calendar }
|
||||
}
|
||||
|
||||
pub fn add_cert(self, parent: &'a Cert) -> Result<CertVerifier<'a>, Error> {
|
||||
|
@ -700,7 +707,7 @@ impl<'a> CertVerifier<'a> {
|
|||
return Err(Error::InvalidAuthKey);
|
||||
}
|
||||
let mut asn1 = [0u8; MAX_ASN1_CERT_SIZE];
|
||||
let len = self.cert.as_asn1(&mut asn1)?;
|
||||
let len = self.cert.as_asn1(&mut asn1, self.utc_calendar)?;
|
||||
let asn1 = &asn1[..len];
|
||||
|
||||
let k = KeyPair::new_from_public(parent.get_pubkey())?;
|
||||
|
@ -713,7 +720,7 @@ impl<'a> CertVerifier<'a> {
|
|||
})?;
|
||||
|
||||
// TODO: other validation checks
|
||||
Ok(CertVerifier::new(parent))
|
||||
Ok(CertVerifier::new(parent, self.utc_calendar))
|
||||
}
|
||||
|
||||
pub fn finalise(self) -> Result<(), Error> {
|
||||
|
@ -740,7 +747,7 @@ pub trait CertConsumer {
|
|||
fn start_ctx(&mut self, tag: &str, id: u8) -> Result<(), Error>;
|
||||
fn end_ctx(&mut self) -> Result<(), Error>;
|
||||
fn oid(&mut self, tag: &str, oid: &[u8]) -> Result<(), Error>;
|
||||
fn utctime(&mut self, tag: &str, epoch: u32) -> Result<(), Error>;
|
||||
fn utctime(&mut self, tag: &str, epoch: u32, utc_calendar: UtcCalendar) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
const MAX_DEPTH: usize = 10;
|
||||
|
@ -758,36 +765,44 @@ mod tests {
|
|||
use crate::tlv::{self, FromTLV, TLVWriter, TagType, ToTLV};
|
||||
use crate::utils::writebuf::WriteBuf;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[test]
|
||||
fn test_asn1_encode_success() {
|
||||
{
|
||||
let mut asn1_buf = [0u8; 1000];
|
||||
let c = Cert::new(&test_vectors::CHIP_CERT_INPUT1).unwrap();
|
||||
let len = c.as_asn1(&mut asn1_buf).unwrap();
|
||||
let len = c
|
||||
.as_asn1(&mut asn1_buf, crate::utils::epoch::sys_utc_calendar)
|
||||
.unwrap();
|
||||
assert_eq!(&test_vectors::ASN1_OUTPUT1, &asn1_buf[..len]);
|
||||
}
|
||||
|
||||
{
|
||||
let mut asn1_buf = [0u8; 1000];
|
||||
let c = Cert::new(&test_vectors::CHIP_CERT_INPUT2).unwrap();
|
||||
let len = c.as_asn1(&mut asn1_buf).unwrap();
|
||||
let len = c
|
||||
.as_asn1(&mut asn1_buf, crate::utils::epoch::sys_utc_calendar)
|
||||
.unwrap();
|
||||
assert_eq!(&test_vectors::ASN1_OUTPUT2, &asn1_buf[..len]);
|
||||
}
|
||||
|
||||
{
|
||||
let mut asn1_buf = [0u8; 1000];
|
||||
let c = Cert::new(&test_vectors::CHIP_CERT_TXT_IN_DN).unwrap();
|
||||
let len = c.as_asn1(&mut asn1_buf).unwrap();
|
||||
let len = c
|
||||
.as_asn1(&mut asn1_buf, crate::utils::epoch::sys_utc_calendar)
|
||||
.unwrap();
|
||||
assert_eq!(&test_vectors::ASN1_OUTPUT_TXT_IN_DN, &asn1_buf[..len]);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[test]
|
||||
fn test_verify_chain_success() {
|
||||
let noc = Cert::new(&test_vectors::NOC1_SUCCESS).unwrap();
|
||||
let icac = Cert::new(&test_vectors::ICAC1_SUCCESS).unwrap();
|
||||
let rca = Cert::new(&test_vectors::RCA1_SUCCESS).unwrap();
|
||||
let a = noc.verify_chain_start();
|
||||
let a = noc.verify_chain_start(crate::utils::epoch::sys_utc_calendar);
|
||||
a.add_cert(&icac)
|
||||
.unwrap()
|
||||
.add_cert(&rca)
|
||||
|
@ -796,31 +811,34 @@ mod tests {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[test]
|
||||
fn test_verify_chain_incomplete() {
|
||||
// The chain doesn't lead up to a self-signed certificate
|
||||
let noc = Cert::new(&test_vectors::NOC1_SUCCESS).unwrap();
|
||||
let icac = Cert::new(&test_vectors::ICAC1_SUCCESS).unwrap();
|
||||
let a = noc.verify_chain_start();
|
||||
let a = noc.verify_chain_start(crate::utils::epoch::sys_utc_calendar);
|
||||
assert_eq!(
|
||||
Err(Error::InvalidAuthKey),
|
||||
a.add_cert(&icac).unwrap().finalise()
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[test]
|
||||
fn test_auth_key_chain_incorrect() {
|
||||
let noc = Cert::new(&test_vectors::NOC1_AUTH_KEY_FAIL).unwrap();
|
||||
let icac = Cert::new(&test_vectors::ICAC1_SUCCESS).unwrap();
|
||||
let a = noc.verify_chain_start();
|
||||
let a = noc.verify_chain_start(crate::utils::epoch::sys_utc_calendar);
|
||||
assert_eq!(Err(Error::InvalidAuthKey), a.add_cert(&icac).map(|_| ()));
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[test]
|
||||
fn test_cert_corrupted() {
|
||||
let noc = Cert::new(&test_vectors::NOC1_CORRUPT_CERT).unwrap();
|
||||
let icac = Cert::new(&test_vectors::ICAC1_SUCCESS).unwrap();
|
||||
let a = noc.verify_chain_start();
|
||||
let a = noc.verify_chain_start(crate::utils::epoch::sys_utc_calendar);
|
||||
assert_eq!(Err(Error::InvalidSignature), a.add_cert(&icac).map(|_| ()));
|
||||
}
|
||||
|
||||
|
|
|
@ -16,10 +16,11 @@
|
|||
*/
|
||||
|
||||
use super::{CertConsumer, MAX_DEPTH};
|
||||
use crate::error::Error;
|
||||
use chrono::{TimeZone, Utc};
|
||||
use core::fmt;
|
||||
use log::warn;
|
||||
use crate::{
|
||||
error::Error,
|
||||
utils::epoch::{UtcCalendar, MATTER_EPOCH_SECS},
|
||||
};
|
||||
use core::{fmt, time::Duration};
|
||||
|
||||
pub struct CertPrinter<'a, 'b> {
|
||||
level: usize,
|
||||
|
@ -122,24 +123,12 @@ impl<'a, 'b> CertConsumer for CertPrinter<'a, 'b> {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
fn utctime(&mut self, tag: &str, epoch: u32) -> Result<(), Error> {
|
||||
let mut matter_epoch = Utc
|
||||
.with_ymd_and_hms(2000, 1, 1, 0, 0, 0)
|
||||
.unwrap()
|
||||
.timestamp();
|
||||
fn utctime(&mut self, tag: &str, epoch: u32, utc_calendar: UtcCalendar) -> Result<(), Error> {
|
||||
let matter_epoch = MATTER_EPOCH_SECS + epoch as u64;
|
||||
|
||||
matter_epoch += epoch as i64;
|
||||
let dt = utc_calendar(Duration::from_secs(matter_epoch as _));
|
||||
|
||||
let dt = match Utc.timestamp_opt(matter_epoch, 0) {
|
||||
chrono::LocalResult::None => return Err(Error::InvalidTime),
|
||||
chrono::LocalResult::Single(s) => s,
|
||||
chrono::LocalResult::Ambiguous(_, a) => {
|
||||
warn!("Ambiguous time for epoch {epoch}; returning latest timestamp: {a}");
|
||||
a
|
||||
}
|
||||
};
|
||||
|
||||
let _ = writeln!(self.f, "{} {} {}", SPACE[self.level], tag, dt);
|
||||
let _ = writeln!(self.f, "{} {} {:?}", SPACE[self.level], tag, dt);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,10 @@ use crate::{
|
|||
pairing::{print_pairing_code_and_qr, DiscoveryCapabilities},
|
||||
secure_channel::{pake::PaseMgr, spake2p::VerifierData},
|
||||
transport::udp::MATTER_PORT,
|
||||
utils::{epoch::Epoch, rand::Rand},
|
||||
utils::{
|
||||
epoch::{Epoch, UtcCalendar},
|
||||
rand::Rand,
|
||||
},
|
||||
};
|
||||
|
||||
/// Device Commissioning Data
|
||||
|
@ -46,6 +49,7 @@ pub struct Matter<'a> {
|
|||
pub mdns_mgr: RefCell<MdnsMgr<'a>>,
|
||||
pub epoch: Epoch,
|
||||
pub rand: Rand,
|
||||
pub utc_calendar: UtcCalendar,
|
||||
pub dev_det: &'a BasicInfoConfig<'a>,
|
||||
}
|
||||
|
||||
|
@ -61,6 +65,7 @@ impl<'a> Matter<'a> {
|
|||
mdns: &'a mut dyn Mdns,
|
||||
epoch: Epoch,
|
||||
rand: Rand,
|
||||
utc_calendar: UtcCalendar,
|
||||
) -> Self {
|
||||
Self {
|
||||
fabric_mgr: RefCell::new(FabricMgr::new()),
|
||||
|
@ -76,6 +81,7 @@ impl<'a> Matter<'a> {
|
|||
)),
|
||||
epoch,
|
||||
rand,
|
||||
utc_calendar,
|
||||
dev_det,
|
||||
}
|
||||
}
|
||||
|
@ -150,3 +156,9 @@ impl<'a> Borrow<Rand> for Matter<'a> {
|
|||
&self.rand
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Borrow<UtcCalendar> for Matter<'a> {
|
||||
fn borrow(&self) -> &UtcCalendar {
|
||||
&self.utc_calendar
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ use crate::{
|
|||
queue::{Msg, WorkQ},
|
||||
session::{CaseDetails, CloneData, NocCatIds, SessionMode},
|
||||
},
|
||||
utils::{rand::Rand, writebuf::WriteBuf},
|
||||
utils::{epoch::UtcCalendar, rand::Rand, writebuf::WriteBuf},
|
||||
};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
|
@ -71,11 +71,16 @@ impl CaseSession {
|
|||
pub struct Case<'a> {
|
||||
fabric_mgr: &'a RefCell<FabricMgr>,
|
||||
rand: Rand,
|
||||
utc_calendar: UtcCalendar,
|
||||
}
|
||||
|
||||
impl<'a> Case<'a> {
|
||||
pub fn new(fabric_mgr: &'a RefCell<FabricMgr>, rand: Rand) -> Self {
|
||||
Self { fabric_mgr, rand }
|
||||
pub fn new(fabric_mgr: &'a RefCell<FabricMgr>, rand: Rand, utc_calendar: UtcCalendar) -> Self {
|
||||
Self {
|
||||
fabric_mgr,
|
||||
rand,
|
||||
utc_calendar,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn casesigma3_handler(&mut self, ctx: &mut ProtoCtx) -> Result<bool, Error> {
|
||||
|
@ -126,7 +131,9 @@ impl<'a> Case<'a> {
|
|||
if let Some(icac) = d.initiator_icac {
|
||||
initiator_icac = Some(Cert::new(icac.0)?);
|
||||
}
|
||||
if let Err(e) = Case::validate_certs(fabric, &initiator_noc, &initiator_icac) {
|
||||
if let Err(e) =
|
||||
Case::validate_certs(fabric, &initiator_noc, &initiator_icac, self.utc_calendar)
|
||||
{
|
||||
error!("Certificate Chain doesn't match: {}", e);
|
||||
common::create_sc_status_report(ctx.tx, common::SCStatusCodes::InvalidParameter, None)?;
|
||||
ctx.exch_ctx.exch.close();
|
||||
|
@ -332,8 +339,13 @@ impl<'a> Case<'a> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_certs(fabric: &Fabric, noc: &Cert, icac: &Option<Cert>) -> Result<(), Error> {
|
||||
let mut verifier = noc.verify_chain_start();
|
||||
fn validate_certs(
|
||||
fabric: &Fabric,
|
||||
noc: &Cert,
|
||||
icac: &Option<Cert>,
|
||||
utc_calendar: UtcCalendar,
|
||||
) -> Result<(), Error> {
|
||||
let mut verifier = noc.verify_chain_start(utc_calendar);
|
||||
|
||||
if fabric.get_fabric_id() != noc.get_fabric_id()? {
|
||||
return Err(Error::Invalid);
|
||||
|
|
|
@ -18,8 +18,13 @@
|
|||
use core::cell::RefCell;
|
||||
|
||||
use crate::{
|
||||
error::*, fabric::FabricMgr, mdns::MdnsMgr, secure_channel::common::*, tlv,
|
||||
transport::proto_ctx::ProtoCtx, utils::rand::Rand,
|
||||
error::*,
|
||||
fabric::FabricMgr,
|
||||
mdns::MdnsMgr,
|
||||
secure_channel::common::*,
|
||||
tlv,
|
||||
transport::proto_ctx::ProtoCtx,
|
||||
utils::{epoch::UtcCalendar, rand::Rand},
|
||||
};
|
||||
use log::{error, info};
|
||||
use num;
|
||||
|
@ -41,9 +46,10 @@ impl<'a> SecureChannel<'a> {
|
|||
fabric_mgr: &'a RefCell<FabricMgr>,
|
||||
mdns: &'a RefCell<MdnsMgr<'a>>,
|
||||
rand: Rand,
|
||||
utc_calendar: UtcCalendar,
|
||||
) -> Self {
|
||||
SecureChannel {
|
||||
case: Case::new(fabric_mgr, rand),
|
||||
case: Case::new(fabric_mgr, rand, utc_calendar),
|
||||
pase,
|
||||
mdns,
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ use crate::secure_channel::common::PROTO_ID_SECURE_CHANNEL;
|
|||
use crate::secure_channel::core::SecureChannel;
|
||||
use crate::transport::mrp::ReliableMessage;
|
||||
use crate::transport::{exchange, packet::Packet};
|
||||
use crate::utils::epoch::Epoch;
|
||||
use crate::utils::epoch::{Epoch, UtcCalendar};
|
||||
use crate::utils::rand::Rand;
|
||||
|
||||
use super::proto_ctx::ProtoCtx;
|
||||
|
@ -167,13 +167,23 @@ pub struct TransportMgr<'a> {
|
|||
|
||||
impl<'a> TransportMgr<'a> {
|
||||
pub fn new<
|
||||
T: Borrow<RefCell<FabricMgr>> + Borrow<RefCell<PaseMgr>> + Borrow<Epoch> + Borrow<Rand>,
|
||||
T: Borrow<RefCell<FabricMgr>>
|
||||
+ Borrow<RefCell<PaseMgr>>
|
||||
+ Borrow<Epoch>
|
||||
+ Borrow<Rand>
|
||||
+ Borrow<UtcCalendar>,
|
||||
>(
|
||||
matter: &'a T,
|
||||
mdns_mgr: &'a RefCell<MdnsMgr<'a>>,
|
||||
) -> Self {
|
||||
Self::wrap(
|
||||
SecureChannel::new(matter.borrow(), matter.borrow(), mdns_mgr, *matter.borrow()),
|
||||
SecureChannel::new(
|
||||
matter.borrow(),
|
||||
matter.borrow(),
|
||||
mdns_mgr,
|
||||
*matter.borrow(),
|
||||
*matter.borrow(),
|
||||
),
|
||||
*matter.borrow(),
|
||||
*matter.borrow(),
|
||||
)
|
||||
|
|
|
@ -2,13 +2,60 @@ use core::time::Duration;
|
|||
|
||||
pub type Epoch = fn() -> Duration;
|
||||
|
||||
pub type UtcCalendar = fn(Duration) -> UtcDate;
|
||||
|
||||
pub const MATTER_EPOCH_SECS: u64 = 946684800; // Seconds from 1970/01/01 00:00:00 till 2000/01/01 00:00:00 UTC
|
||||
|
||||
#[derive(Default, Debug, Clone, Eq, PartialEq)]
|
||||
pub struct UtcDate {
|
||||
pub year: u16,
|
||||
pub month: u8, // 1 - 12
|
||||
pub day: u8, // 1 - 31
|
||||
pub hour: u8, // 0 - 23
|
||||
pub minute: u8,
|
||||
pub second: u8,
|
||||
pub millis: u16,
|
||||
}
|
||||
|
||||
pub fn dummy_epoch() -> Duration {
|
||||
Duration::from_secs(0)
|
||||
}
|
||||
|
||||
pub fn dummy_utc_calendar(_duration: Duration) -> UtcDate {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub fn sys_epoch() -> Duration {
|
||||
std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub fn sys_utc_calendar(duration: Duration) -> UtcDate {
|
||||
use chrono::{Datelike, TimeZone, Timelike};
|
||||
use log::warn;
|
||||
|
||||
let dt = match chrono::Utc.timestamp_opt(duration.as_secs() as _, duration.subsec_nanos()) {
|
||||
chrono::LocalResult::None => panic!("Invalid time"),
|
||||
chrono::LocalResult::Single(s) => s,
|
||||
chrono::LocalResult::Ambiguous(_, a) => {
|
||||
warn!(
|
||||
"Ambiguous time for epoch {:?}; returning latest timestamp: {a}",
|
||||
duration
|
||||
);
|
||||
a
|
||||
}
|
||||
};
|
||||
|
||||
UtcDate {
|
||||
year: dt.year() as _,
|
||||
month: dt.month() as _,
|
||||
day: dt.day() as _,
|
||||
hour: dt.hour() as _,
|
||||
minute: dt.minute() as _,
|
||||
second: dt.second() as _,
|
||||
millis: (dt.nanosecond() / 1000) as _,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,11 @@ use matter::{
|
|||
proto_ctx::ProtoCtx,
|
||||
session::{CaseDetails, CloneData, NocCatIds, SessionMgr, SessionMode},
|
||||
},
|
||||
utils::{epoch::sys_epoch, rand::dummy_rand, writebuf::WriteBuf},
|
||||
utils::{
|
||||
epoch::{sys_epoch, sys_utc_calendar},
|
||||
rand::dummy_rand,
|
||||
writebuf::WriteBuf,
|
||||
},
|
||||
Matter,
|
||||
};
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
|
@ -105,7 +109,7 @@ impl<'a> ImInput<'a> {
|
|||
pub type DmHandler<'a> = handler_chain_type!(OnOffCluster, EchoCluster, DescriptorCluster, EchoCluster | RootEndpointHandler<'a>);
|
||||
|
||||
pub fn matter(mdns: &mut dyn Mdns) -> Matter<'_> {
|
||||
Matter::new(&BASIC_INFO, mdns, sys_epoch, dummy_rand)
|
||||
Matter::new(&BASIC_INFO, mdns, sys_epoch, dummy_rand, sys_utc_calendar)
|
||||
}
|
||||
|
||||
/// An Interaction Model Engine to facilitate easy testing
|
||||
|
|
Loading…
Add table
Reference in a new issue