tor_netdoc/doc/netstatus/rs/
build.rs1use super::{GenericRouterStatus, MdConsensusRouterStatus};
4use crate::doc;
5use crate::doc::microdesc::MdDigest;
6use crate::doc::netstatus::{ConsensusBuilder, RelayFlags, RelayWeight};
7use crate::{BuildError as Error, BuildResult as Result};
8use tor_llcrypto::pk::rsa::RsaIdentity;
9use tor_protover::Protocols;
10
11use std::net::SocketAddr;
12
13#[cfg(feature = "ns_consensus")]
14use super::NsConsensusRouterStatus;
15#[cfg(feature = "ns_consensus")]
16use crate::doc::routerdesc::RdDigest;
17
18#[cfg_attr(docsrs, doc(cfg(feature = "build_docs")))]
21#[derive(Debug, Clone)]
22pub struct RouterStatusBuilder<D> {
23 nickname: Option<String>,
25 identity: Option<RsaIdentity>,
27 addrs: Vec<SocketAddr>,
29 doc_digest: Option<D>,
31 flags: RelayFlags,
33 version: Option<String>,
35 protos: Option<Protocols>,
37 weight: Option<RelayWeight>,
39}
40
41impl<D: Clone> RouterStatusBuilder<D> {
42 pub(crate) fn new() -> Self {
44 RouterStatusBuilder {
45 nickname: None,
46 identity: None,
47 addrs: Vec::new(),
48 doc_digest: None,
49 flags: RelayFlags::empty(),
50 version: None,
51 protos: None,
52 weight: None,
53 }
54 }
55
56 pub fn nickname(&mut self, nickname: String) -> &mut Self {
60 self.nickname = Some(nickname);
61 self
62 }
63
64 pub fn identity(&mut self, identity: RsaIdentity) -> &mut Self {
70 self.identity = Some(identity);
71 self
72 }
73 pub fn add_or_port(&mut self, addr: SocketAddr) -> &mut Self {
77 self.addrs.push(addr);
78 self
79 }
80 pub fn doc_digest(&mut self, doc_digest: D) -> &mut Self {
84 self.doc_digest = Some(doc_digest);
85 self
86 }
87 pub fn set_flags(&mut self, flags: RelayFlags) -> &mut Self {
89 self.flags = flags;
90 self
91 }
92 pub fn add_flags(&mut self, flags: RelayFlags) -> &mut Self {
95 self.flags |= flags;
96 self
97 }
98 #[cfg(feature = "testing")]
100 pub fn clear_flags(&mut self, flags: RelayFlags) -> &mut Self {
101 self.flags &= !flags;
102 self
103 }
104 pub fn version(&mut self, version: String) -> &mut Self {
108 self.version = Some(version);
109 self
110 }
111 pub fn protos(&mut self, protos: Protocols) -> &mut Self {
116 self.protos = Some(protos);
117 self
118 }
119 pub fn weight(&mut self, weight: RelayWeight) -> &mut Self {
123 self.weight = Some(weight);
124 self
125 }
126 fn finish(&self) -> Result<GenericRouterStatus<D>> {
128 let nickname = self.nickname.as_deref().unwrap_or("Unnamed").parse()?;
129 let identity = self
130 .identity
131 .ok_or(Error::CannotBuild("Missing RSA identity"))?;
132 if self.addrs.is_empty() {
133 return Err(Error::CannotBuild("No addresses"));
134 }
135 let doc_digest = self
136 .doc_digest
137 .as_ref()
138 .ok_or(Error::CannotBuild("Missing document digest"))?
139 .clone();
140 let protos = self
141 .protos
142 .as_ref()
143 .ok_or(Error::CannotBuild("Missing protocols"))?
144 .clone();
145 let weight = self.weight.unwrap_or(RelayWeight::Unmeasured(0));
146 let version = self.version.as_deref().map(str::parse).transpose()?;
147
148 Ok(GenericRouterStatus {
149 nickname,
150 identity,
151 addrs: self.addrs.clone(),
152 doc_digest,
153 version,
154 protos: doc::PROTOVERS_CACHE.intern(protos),
155 flags: self.flags,
156 weight,
157 })
158 }
159}
160
161#[cfg(feature = "ns_consensus")]
162impl RouterStatusBuilder<RdDigest> {
163 pub fn build_into(
166 &self,
167 builder: &mut ConsensusBuilder<NsConsensusRouterStatus>,
168 ) -> Result<()> {
169 builder.add_rs(self.build()?);
170 Ok(())
171 }
172 pub fn build(&self) -> Result<NsConsensusRouterStatus> {
174 Ok(self.finish()?.into())
175 }
176}
177
178impl RouterStatusBuilder<MdDigest> {
179 pub fn build_into(
182 &self,
183 builder: &mut ConsensusBuilder<MdConsensusRouterStatus>,
184 ) -> Result<()> {
185 builder.add_rs(self.build()?);
186 Ok(())
187 }
188
189 pub fn build(&self) -> Result<MdConsensusRouterStatus> {
191 Ok(self.finish()?.into())
192 }
193}