tor_netdoc/doc/netstatus/rs/
ns.rs

1//! Implementation for the style of router descriptors used in
2//! old-style "ns" consensus documents.
3
4use super::{FromRsString, GenericRouterStatus};
5use crate::doc::netstatus::{
6    ConsensusFlavor, NetstatusKwd, ParseRouterStatus, RelayFlags, RelayWeight, RouterStatus,
7};
8use crate::doc::routerdesc::RdDigest;
9use crate::types::misc::*;
10use crate::{parse::parser::Section, util::private::Sealed};
11use crate::{Error, Result};
12use std::net;
13
14use tor_error::internal;
15use tor_llcrypto::pk::rsa::RsaIdentity;
16use tor_protover::Protocols;
17
18/// A single relay's status, as represented in a "ns" consensus.
19///
20/// Only available if `tor-netdoc` is built with the `ns_consensus` feature.
21#[cfg_attr(
22    feature = "dangerous-expose-struct-fields",
23    visible::StructFields(pub),
24    non_exhaustive
25)]
26#[cfg_attr(docsrs, doc(cfg(feature = "ns_consensus")))]
27#[derive(Debug, Clone)]
28pub struct NsConsensusRouterStatus {
29    /// Underlying generic routerstatus object.
30    ///
31    /// This is private because we don't want to leak that these two
32    /// types have the same implementation "under the hood".
33    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
34    rs: GenericRouterStatus<RdDigest>,
35}
36
37impl From<GenericRouterStatus<RdDigest>> for NsConsensusRouterStatus {
38    fn from(rs: GenericRouterStatus<RdDigest>) -> Self {
39        NsConsensusRouterStatus { rs }
40    }
41}
42
43super::implement_accessors! {NsConsensusRouterStatus}
44
45impl NsConsensusRouterStatus {
46    /// Return the expected router descriptor digest for this routerstatus
47    pub fn rd_digest(&self) -> &RdDigest {
48        &self.rs.doc_digest
49    }
50}
51
52impl Sealed for NsConsensusRouterStatus {}
53
54impl RouterStatus for NsConsensusRouterStatus {
55    type DocumentDigest = RdDigest;
56
57    /// Return the expected microdescriptor digest for this routerstatus
58    fn rsa_identity(&self) -> &RsaIdentity {
59        &self.rs.identity
60    }
61
62    fn doc_digest(&self) -> &RdDigest {
63        self.rd_digest()
64    }
65}
66
67impl ParseRouterStatus for NsConsensusRouterStatus {
68    fn flavor() -> ConsensusFlavor {
69        ConsensusFlavor::Ns
70    }
71
72    fn from_section(sec: &Section<'_, NetstatusKwd>) -> Result<NsConsensusRouterStatus> {
73        let rs = GenericRouterStatus::from_section(sec, ConsensusFlavor::Ns)?;
74        Ok(NsConsensusRouterStatus { rs })
75    }
76}
77
78impl FromRsString for RdDigest {
79    fn decode(s: &str) -> Result<RdDigest> {
80        s.parse::<B64>()?
81            .check_len(20..=20)?
82            .as_bytes()
83            .try_into()
84            .map_err(|_| Error::from(internal!("correct length on digest, but unable to convert")))
85    }
86}