tor_netdoc/doc/netstatus/
rs.rs

1//! Routerstatus-specific parts of networkstatus parsing.
2//!
3//! This is a private module; relevant pieces are re-exported by its
4//! parent.
5
6#[cfg(feature = "build_docs")]
7pub(crate) mod build;
8pub(crate) mod md;
9#[cfg(feature = "plain-consensus")]
10pub(crate) mod plain;
11#[cfg(feature = "ns-vote")]
12pub(crate) mod vote;
13
14use super::{ConsensusFlavor, ConsensusMethods};
15use crate::doc;
16use crate::doc::netstatus::NetstatusKwd;
17use crate::doc::netstatus::{IgnoredPublicationTimeSp, Protocols, RelayFlags, RelayWeight};
18use crate::parse::parser::Section;
19use crate::types::misc::*;
20use crate::types::version::TorVersion;
21use crate::util::intern::InternCache;
22use crate::{Error, NetdocErrorKind as EK, Result};
23use itertools::chain;
24use std::sync::Arc;
25use std::{net, time};
26use tor_error::internal;
27use tor_llcrypto::pk::rsa::RsaIdentity;
28
29#[cfg(feature = "parse2")]
30use {
31    super::consensus_methods_comma_separated, //
32    derive_deftly::Deftly,
33};
34
35/// A version as presented in a router status.
36///
37/// This can either be a parsed Tor version, or an unparsed string.
38//
39// TODO: This might want to merge, at some point, with routerdesc::RelayPlatform.
40#[derive(Clone, Debug, Eq, PartialEq, Hash, derive_more::Display)]
41#[non_exhaustive]
42pub enum Version {
43    /// A Tor version
44    Tor(TorVersion),
45    /// A string we couldn't parse.
46    Other(Arc<str>),
47}
48
49/// A cache of unparsable version strings.
50///
51/// We use this because we expect there not to be very many distinct versions of
52/// relay software in existence.
53static OTHER_VERSION_CACHE: InternCache<str> = InternCache::new();
54
55/// `m` item in votes
56///
57/// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:m>
58///
59/// This is different to the `m` line in in microdesc consensuses.
60/// Plain consensuses don't have `m` lines at all.
61///
62/// ### Non-invariants
63///
64///  * There may be overlapping or even contradictory information.
65///  * It might not be sorted.
66///    Users of the structure who need to emit reproducible document encodings.
67///    must sort it.
68///  * These non-invariants apply both within one instance of this struct,
69///    and across multiple instances of it within a `RouterStatus`.
70#[derive(Debug, Clone, Default, Eq, PartialEq)]
71#[cfg(feature = "ns-vote")]
72#[cfg_attr(feature = "parse2", derive(Deftly), derive_deftly(ItemValueParseable))]
73#[non_exhaustive]
74pub struct RouterStatusMdDigestsVote {
75    /// The methods for which this document is applicable.
76    #[cfg_attr(
77        feature = "parse2",
78        deftly(netdoc(with = "consensus_methods_comma_separated"))
79    )]
80    pub consensus_methods: ConsensusMethods,
81
82    /// The various hashes of this document.
83    pub digests: Vec<IdentifiedDigest>,
84}
85
86impl std::str::FromStr for Version {
87    type Err = Error;
88
89    fn from_str(s: &str) -> Result<Self> {
90        let mut elts = s.splitn(3, ' ');
91        if elts.next() == Some("Tor") {
92            if let Some(Ok(v)) = elts.next().map(str::parse) {
93                return Ok(Version::Tor(v));
94            }
95        }
96
97        Ok(Version::Other(OTHER_VERSION_CACHE.intern_ref(s)))
98    }
99}
100
101/// Helper to decode a document digest in the format in which it
102/// appears in a given kind of routerstatus.
103trait FromRsString: Sized {
104    /// Try to decode the given object.
105    fn decode(s: &str) -> Result<Self>;
106}