1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
|
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]
#![warn(missing_docs)]
#![warn(noop_method_call)]
#![warn(unreachable_pub)]
#![warn(clippy::all)]
#![deny(clippy::await_holding_lock)]
#![deny(clippy::cargo_common_metadata)]
#![deny(clippy::cast_lossless)]
#![deny(clippy::checked_conversions)]
#![warn(clippy::cognitive_complexity)]
#![deny(clippy::debug_assert_with_mut_call)]
#![deny(clippy::exhaustive_enums)]
#![deny(clippy::exhaustive_structs)]
#![deny(clippy::expl_impl_clone_on_copy)]
#![deny(clippy::fallible_impl_from)]
#![deny(clippy::implicit_clone)]
#![deny(clippy::large_stack_arrays)]
#![warn(clippy::manual_ok_or)]
#![deny(clippy::missing_docs_in_private_items)]
#![warn(clippy::needless_borrow)]
#![warn(clippy::needless_pass_by_value)]
#![warn(clippy::option_option)]
#![deny(clippy::print_stderr)]
#![deny(clippy::print_stdout)]
#![warn(clippy::rc_buffer)]
#![deny(clippy::ref_option_ref)]
#![warn(clippy::semicolon_if_nothing_returned)]
#![warn(clippy::trait_duplication_in_bounds)]
#![deny(clippy::unnecessary_wraps)]
#![warn(clippy::unseparated_literal_suffix)]
#![deny(clippy::unwrap_used)]
#![allow(clippy::let_unit_value)] // This can reasonably be done for explicitness
#![allow(clippy::uninlined_format_args)]
#![allow(clippy::significant_drop_in_scrutinee)] // arti/-/merge_requests/588/#note_2812945
#![allow(clippy::result_large_err)] // temporary workaround for arti#587
#![allow(clippy::needless_raw_string_hashes)] // complained-about code is fine, often best
//! <!-- @@ end lint list maintained by maint/add_warning @@ -->
use std::fmt::{self, Display};
use std::str::FromStr;
use derive_adhoc::Adhoc;
use serde::{Deserialize, Serialize};
use serde::{Deserializer, Serializer};
use thiserror::Error;
use tor_basic_utils::impl_debug_hex;
use tor_keymgr::KeySpecifierComponentViaDisplayFromStr;
#[cfg(test)]
#[macro_use]
mod test_temp_dir;
#[macro_use] // SerdeStringOrTransparent
mod time_store;
mod anon_level;
pub mod config;
mod err;
mod helpers;
mod ipt_mgr;
mod ipt_set;
mod keys;
mod nickname;
mod replay;
mod req;
mod state;
pub mod status;
mod svc;
mod timeout_track;
// rustdoc doctests can't use crate-public APIs, so are broken if provided for private items.
// So we export the whole module again under this name.
// Supports the Example in timeout_track.rs's module-level docs.
//
// Any out-of-crate user needs to write this ludicrous name in their code,
// so we don't need to put any warnings in the docs for the individual items.)
//
// (`#[doc(hidden)] pub mod timeout_track;` would work for the test but it would
// completely suppress the actual documentation, which is not what we want.)
#[doc(hidden)]
pub mod timeout_track_for_doctests_unstable_no_semver_guarantees {
pub use crate::timeout_track::*;
}
#[doc(hidden)]
pub mod time_store_for_doctests_unstable_no_semver_guarantees {
pub use crate::time_store::*;
}
pub use anon_level::Anonymity;
pub use config::OnionServiceConfig;
pub use err::{ClientError, EstablishSessionError, FatalError, IntroRequestError, StartupError};
pub use keys::{
BlindIdKeypairSpecifier, BlindIdPublicKeySpecifier, DescSigningKeypairSpecifier,
HsIdKeypairSpecifier, HsIdPublicKeySpecifier,
};
pub use nickname::{HsNickname, InvalidNickname};
pub use req::{RendRequest, StreamRequest};
pub use state::StateMgr;
pub use svc::netdir::NetdirProviderShutdown;
pub use svc::OnionService;
use err::IptStoreError;
/// Persistent local identifier for an introduction point
///
/// Changes when the IPT relay changes, or the IPT key material changes.
/// (Different for different `.onion` services, obviously)
///
/// Is a randomly-generated byte string, currently 32 long.
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Adhoc)]
#[derive_adhoc(SerdeStringOrTransparent)]
pub(crate) struct IptLocalId([u8; 32]);
impl_debug_hex!(IptLocalId.0);
impl Display for IptLocalId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for v in self.0 {
write!(f, "{v:02x}")?;
}
Ok(())
}
}
/// Invalid [`IptLocalId`] - for example bad string representation
#[derive(Debug, Error, Clone, Eq, PartialEq)]
#[error("invalid IptLocalId")]
#[non_exhaustive]
pub(crate) struct InvalidIptLocalId {}
impl FromStr for IptLocalId {
type Err = InvalidIptLocalId;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut b = [0; 32];
hex::decode_to_slice(s, &mut b).map_err(|_: hex::FromHexError| InvalidIptLocalId {})?;
Ok(IptLocalId(b))
}
}
impl KeySpecifierComponentViaDisplayFromStr for IptLocalId {}
impl IptLocalId {
/// Return a fixed dummy `IptLocalId`, for testing etc.
///
/// The id is made by repeating `which` 32 times.
#[cfg(test)]
pub(crate) fn dummy(which: u8) -> Self {
IptLocalId([which; 32]) // I can't think of a good way not to specify 32 again here
}
}
pub use helpers::handle_rend_requests;
#[cfg(test)]
pub(crate) mod test {
// @@ begin test lint list maintained by maint/add_warning @@
#![allow(clippy::bool_assert_comparison)]
#![allow(clippy::clone_on_copy)]
#![allow(clippy::dbg_macro)]
#![allow(clippy::print_stderr)]
#![allow(clippy::print_stdout)]
#![allow(clippy::single_char_pattern)]
#![allow(clippy::unwrap_used)]
#![allow(clippy::unchecked_duration_subtraction)]
#![allow(clippy::useless_vec)]
#![allow(clippy::needless_pass_by_value)]
//! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
use super::*;
use itertools::{chain, Itertools};
#[derive(Serialize, Deserialize, Eq, PartialEq, Debug)]
struct IptLidTest {
lid: IptLocalId,
}
#[test]
fn lid_serde() {
let t = IptLidTest {
lid: IptLocalId::dummy(7),
};
let json = serde_json::to_string(&t).unwrap();
assert_eq!(
json,
// This also tests <IptLocalId as Display> since that's how we serialise it
r#"{"lid":"0707070707070707070707070707070707070707070707070707070707070707"}"#,
);
let u: IptLidTest = serde_json::from_str(&json).unwrap();
assert_eq!(t, u);
let mpack = rmp_serde::to_vec_named(&t).unwrap();
assert_eq!(
mpack,
chain!(&[129, 163], b"lid", &[220, 0, 32], &[0x07; 32],)
.cloned()
.collect_vec()
);
let u: IptLidTest = rmp_serde::from_slice(&mpack).unwrap();
assert_eq!(t, u);
}
}
|