Skip to main content

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