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