1
//! List of directories that ships with Tor, for initial directory
2
//! operations.
3
//!
4
//! When a client doesn't have directory information yet, it uses a
5
//! "Fallback Directory" to retrieve its initial information about the
6
//! network.
7
//!
8
//! # Semver note
9
//!
10
//! The types in this module are re-exported from `arti-client` and
11
//! `tor-dirmgr`: any changes here must be reflected there.
12

            
13
use derive_builder::Builder;
14
use tor_config::ConfigBuildError;
15
use tor_llcrypto::pk::ed25519::Ed25519Identity;
16
use tor_llcrypto::pk::rsa::RsaIdentity;
17

            
18
use serde::Deserialize;
19
use std::net::SocketAddr;
20

            
21
/// A directory whose location ships with Tor (or arti), and which we
22
/// can use for bootstrapping when we don't know anything else about
23
/// the network.
24
//
25
// Note that we do *not* set serde(deny_unknown_fields) on this
26
// structure: we want our fallback directory configuration format to
27
// be future-proof against adding new info about each fallback.
28
65370
#[derive(Debug, Clone, Deserialize, Builder, Eq, PartialEq)]
29
#[builder(build_fn(validate = "FallbackDirBuilder::validate", error = "ConfigBuildError"))]
30
#[builder(derive(Deserialize))]
31
pub struct FallbackDir {
32
    /// RSA identity for the directory relay
33
    rsa_identity: RsaIdentity,
34
    /// Ed25519 identity for the directory relay
35
    ed_identity: Ed25519Identity,
36
    /// List of ORPorts for the directory relay
37
    orports: Vec<SocketAddr>,
38
}
39

            
40
impl FallbackDir {
41
    /// Return a builder that can be used to make a `FallbackDir`.
42
62895
    pub fn builder() -> FallbackDirBuilder {
43
62895
        FallbackDirBuilder::default()
44
62895
    }
45
}
46

            
47
impl FallbackDirBuilder {
48
    /// Make a new FallbackDirBuilder.
49
    ///
50
    /// You only need to use this if you're using a non-default set of
51
    /// fallback directories.
52
    pub fn new() -> Self {
53
        Self::default()
54
    }
55
    /// Add a single OR port for this fallback directory.
56
    ///
57
    /// This field is required, and may be called more than once.
58
94005
    pub fn orport(&mut self, orport: SocketAddr) -> &mut Self {
59
94005
        self.orports.get_or_insert_with(Vec::new).push(orport);
60
94005
        self
61
94005
    }
62
    /// Check whether this builder is ready to make a FallbackDir.
63
    fn validate(&self) -> std::result::Result<(), ConfigBuildError> {
64
65100
        if let Some(orports) = &self.orports {
65
65100
            if orports.is_empty() {
66
                return Err(ConfigBuildError::Invalid {
67
                    field: "orport".to_string(),
68
                    problem: "list was empty".to_string(),
69
                });
70
65055
            }
71
        }
72
65055
        Ok(())
73
65055
    }
74
}
75

            
76
impl tor_linkspec::ChanTarget for FallbackDir {
77
150
    fn addrs(&self) -> &[SocketAddr] {
78
150
        &self.orports[..]
79
150
    }
80
300
    fn ed_identity(&self) -> &Ed25519Identity {
81
300
        &self.ed_identity
82
300
    }
83
150
    fn rsa_identity(&self) -> &RsaIdentity {
84
150
        &self.rsa_identity
85
150
    }
86
}