Skip to main content

tor_netdoc/doc/netstatus/rs/
each_variety.rs

1//! router status entries - items for all varieties, that vary
2//!
3//! **This file is reincluded multiple times**,
4//! by the macros in [`crate::doc::ns_variety_definition_macros`],
5//! once for votes, and once for each consensus flavour.
6//! It is *not* a module `crate::doc::netstatus::rs::each_variety`.
7//!
8//! Each time this file is included by one of the macros mentioned above,
9//! the `ns_***` macros (such as `ns_const_name!`) may expand to different values.
10//!
11//! See [`crate::doc::ns_variety_definition_macros`].
12
13use super::*;
14
15// Explicit parsing arrangements for document digest field in `m` items.
16//
17// https://spec.torproject.org/dir-spec/consensus-formats.html#item:r
18// https://spec.torproject.org/dir-spec/consensus-formats.html#item:m
19// https://spec.torproject.org/dir-spec/computing-consensus.html#flavor:microdesc
20//
21// The document digest moves about, and vote `m` items are even more exciting.
22// This is for the benefit of the `with` annotations for RouterStatus.m.
23//
24// We need to make this an import that can be used with `deftly(netdoc(with = ))`.
25// `with` expects a path, not a type, so we can't use ns_type!.
26//
27// (Normally when trying to parse an item whose single field implements ItemArgumentParseable
28// but not ItemValueParseable, we would use #[deftly(netdoc(single_arg))]
29// but here we can't do that because we can't have variety-dependent attributes.)
30ns_choose! { (
31    use NotPresentEachValue as doc_digest_item_m;
32) (
33    // doc_digest_item_m implemented in rs/md.rs
34) (
35    use RouterStatusMdDigestsVote as doc_digest_item_m;
36) }
37
38/// Type of the referenced document digest in form suitable for parsing and encoding
39type DocDigestB64 = FixedB64<DOC_DIGEST_LEN>;
40
41/// Intro item for a router status entry
42///
43/// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:r>
44///
45/// <https://spec.torproject.org/dir-spec/computing-consensus.html#flavor:microdesc>
46/// `r` item.
47#[derive(Debug, Clone, Deftly)]
48#[derive_deftly(ItemValueParseable)]
49#[non_exhaustive]
50pub struct RouterStatusIntroItem {
51    /// The nickname for this relay.
52    ///
53    /// Nicknames can be used for convenience purpose, but no more:
54    /// there is no mechanism to enforce their uniqueness.
55    pub nickname: Nickname,
56    /// Fingerprint of the old-style RSA identity for this relay.
57    pub identity: Base64Fingerprint,
58    /// Digest of the document for this relay (except md consensuses)
59    // TODO SPEC rename in the spec from `digest` to "doc_digest"
60    // TODO SPEC in md consensuses the referenced document digest is in a separate `m` item
61    pub doc_digest: ns_type!(DocDigestB64, NotPresent, DocDigestB64),
62    /// Publication time.
63    pub publication: ns_type!(
64        IgnoredPublicationTimeSp,
65        IgnoredPublicationTimeSp,
66        Iso8601TimeSp
67    ),
68    /// IPv4 address
69    pub ip: std::net::Ipv4Addr,
70    /// Relay port
71    pub or_port: u16,
72}
73
74/// A single relay's status, in a network status document.
75///
76/// <https://spec.torproject.org/dir-spec/consensus-formats.html#section:router-status>
77///
78/// <https://spec.torproject.org/dir-spec/computing-consensus.html#flavor:microdesc>
79/// under "Changes to router status entries".
80//
81// In most netdocs we would use the item keywords as the field names.  But routerstatus
82// entry keywords are chosen to be very short to minimise the consensus size, so we
83// use longer names in the struct and specify the keyword separately.
84#[derive(Debug, Clone, Deftly)]
85#[derive_deftly(NetdocParseable)]
86#[non_exhaustive]
87pub struct RouterStatus {
88    /// `r` --- Introduce a routerstatus entry
89    ///
90    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:r>
91    /// (and, the md version, which is different).
92    pub r: RouterStatusIntroItem,
93
94    /// `m` --- Microdescriptor or document digest
95    ///
96    /// In an md consensus, the hash of the document for this relay.
97    /// In a vote, microdescriptor hashes for the various consensus methods.
98    ///
99    /// <https://spec.torproject.org/dir-spec/computing-consensus.html#flavor:microdesc>
100    /// `r` item.
101    // We call this field `m` rather than `doc_digest` because it's not always the doc digest.
102    // TODO SPEC in all but md consensuses the referenced document digest is in the `r` intro item
103    #[deftly(netdoc(with = doc_digest_item_m))]
104    pub m: ns_type!(NotPresent, DocDigestB64, Vec<RouterStatusMdDigestsVote>),
105
106    /// `a` --- Further router address(es) (IPv6)
107    ///
108    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:a>
109    /// (and, the md version, which is different).
110    #[deftly(netdoc(single_arg))]
111    pub a: Vec<net::SocketAddr>,
112
113    /// `s` --- Router status flags
114    ///
115    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:s>
116    #[deftly(netdoc(
117        keyword = "s",
118        with = {
119            relay_flags::ParserEncoder::<ns_type!(
120                relay_flags::ConsensusRepr,
121                relay_flags::ConsensusRepr,
122                relay_flags::NoImplicitRepr,
123            )>
124        },
125    ))]
126    pub flags: DocRelayFlags,
127
128    /// `v` --- Relay's Tor software version
129    ///
130    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:v>
131    #[deftly(netdoc(keyword = "v"))]
132    pub version: Option<SoftwareVersion>,
133
134    /// `pr` --- Subprotocol capabilities supported
135    ///
136    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:v>
137    #[deftly(netdoc(keyword = "pr"))]
138    pub protos: Protocols,
139
140    /// `w` --- Bandwidth estimates
141    ///
142    /// <https://spec.torproject.org/dir-spec/consensus-formats.html#item:w>
143    #[deftly(netdoc(flatten))]
144    pub weight: RelayWeightsItem,
145}
146
147impl RouterStatus {
148    /// Return the digest of the document identified by this
149    /// routerstatus.
150    ///
151    /// The `doc_digest` method is provided on all varieties of routerstatus entry
152    /// to help paper over the protocol anomaly, that the digest is in a different place
153    /// in md routerstatus entries.
154    pub fn doc_digest(&self) -> &DocDigest {
155        ns_expr!(&self.r.doc_digest, &self.m, &self.r.doc_digest,)
156    }
157}