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