1
//! Implementation for the style of router descriptors used in
2
//! old-style "ns" consensus documents.
3

            
4
use super::{FromRsString, GenericRouterStatus};
5
use crate::doc::netstatus::{
6
    ConsensusFlavor, NetstatusKwd, ParseRouterStatus, RelayFlags, RelayWeight, RouterStatus,
7
};
8
use crate::doc::routerdesc::RdDigest;
9
use crate::types::misc::*;
10
use crate::{parse::parser::Section, util::private::Sealed};
11
use crate::{Error, Result};
12
use std::net;
13

            
14
use tor_error::internal;
15
use tor_llcrypto::pk::rsa::RsaIdentity;
16
use tor_protover::Protocols;
17

            
18
use std::convert::TryInto;
19

            
20
/// A single relay's status, as represented in a "ns" consensus.
21
///
22
/// Only available if `tor-netdoc` is built with the `ns_consensus` feature.
23
#[derive(Debug, Clone)]
24
pub struct NsConsensusRouterStatus {
25
    /// Underlying generic routerstatus object.
26
    ///
27
    /// This is private because we don't want to leak that these two
28
    /// types have the same implementation "under the hood".
29
    rs: GenericRouterStatus<RdDigest>,
30
}
31

            
32
impl From<GenericRouterStatus<RdDigest>> for NsConsensusRouterStatus {
33
    fn from(rs: GenericRouterStatus<RdDigest>) -> Self {
34
        NsConsensusRouterStatus { rs }
35
    }
36
}
37

            
38
super::implement_accessors! {NsConsensusRouterStatus}
39

            
40
impl NsConsensusRouterStatus {
41
    /// Return the expected router descriptor digest for this routerstatus
42
    pub fn rd_digest(&self) -> &RdDigest {
43
        &self.rs.doc_digest
44
    }
45
}
46

            
47
impl Sealed for NsConsensusRouterStatus {}
48

            
49
impl RouterStatus for NsConsensusRouterStatus {
50
    type DocumentDigest = RdDigest;
51

            
52
    /// Return the expected microdescriptor digest for this routerstatus
53
14
    fn rsa_identity(&self) -> &RsaIdentity {
54
14
        &self.rs.identity
55
14
    }
56

            
57
    fn doc_digest(&self) -> &RdDigest {
58
        self.rd_digest()
59
    }
60
}
61

            
62
impl ParseRouterStatus for NsConsensusRouterStatus {
63
10
    fn flavor() -> ConsensusFlavor {
64
10
        ConsensusFlavor::Ns
65
10
    }
66

            
67
8
    fn from_section(sec: &Section<'_, NetstatusKwd>) -> Result<NsConsensusRouterStatus> {
68
8
        let rs = GenericRouterStatus::from_section(sec, false)?;
69
8
        Ok(NsConsensusRouterStatus { rs })
70
8
    }
71
}
72

            
73
impl FromRsString for RdDigest {
74
8
    fn decode(s: &str) -> Result<RdDigest> {
75
8
        s.parse::<B64>()?
76
8
            .check_len(20..=20)?
77
8
            .as_bytes()
78
8
            .try_into()
79
8
            .map_err(|_| Error::from(internal!("correct length on digest, but unable to convert")))
80
8
    }
81
}