|
@@ -1,8 +1,8 @@
|
|
|
// Copyright (c) 2016-2018, The Tor Project, Inc. */
|
|
|
// See LICENSE for licensing information */
|
|
|
|
|
|
-use std::collections::HashMap;
|
|
|
use std::collections::hash_map;
|
|
|
+use std::collections::HashMap;
|
|
|
use std::ffi::CStr;
|
|
|
use std::fmt;
|
|
|
use std::str;
|
|
@@ -12,8 +12,8 @@ use std::string::String;
|
|
|
use external::c_tor_version_as_new_as;
|
|
|
|
|
|
use errors::ProtoverError;
|
|
|
-use protoset::Version;
|
|
|
use protoset::ProtoSet;
|
|
|
+use protoset::Version;
|
|
|
|
|
|
/// The first version of Tor that included "proto" entries in its descriptors.
|
|
|
/// Authorities should use this to decide whether to guess proto lines.
|
|
@@ -26,7 +26,7 @@ const FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS: &'static str = "0.2.9.3-alpha";
|
|
|
/// before concluding that someone is trying to DoS us
|
|
|
///
|
|
|
/// C_RUST_COUPLED: protover.c `MAX_PROTOCOLS_TO_EXPAND`
|
|
|
-const MAX_PROTOCOLS_TO_EXPAND: usize = (1<<16);
|
|
|
+const MAX_PROTOCOLS_TO_EXPAND: usize = (1 << 16);
|
|
|
|
|
|
/// The maximum size an `UnknownProtocol`'s name may be.
|
|
|
pub(crate) const MAX_PROTOCOL_NAME_LENGTH: usize = 100;
|
|
@@ -132,16 +132,18 @@ impl From<Protocol> for UnknownProtocol {
|
|
|
///
|
|
|
// C_RUST_COUPLED: protover.c `protover_get_supported_protocols`
|
|
|
pub(crate) fn get_supported_protocols_cstr() -> &'static CStr {
|
|
|
- cstr!("Cons=1-2 \
|
|
|
- Desc=1-2 \
|
|
|
- DirCache=1-2 \
|
|
|
- HSDir=1-2 \
|
|
|
- HSIntro=3-4 \
|
|
|
- HSRend=1-2 \
|
|
|
- Link=1-5 \
|
|
|
- LinkAuth=1,3 \
|
|
|
- Microdesc=1-2 \
|
|
|
- Relay=1-2")
|
|
|
+ cstr!(
|
|
|
+ "Cons=1-2 \
|
|
|
+ Desc=1-2 \
|
|
|
+ DirCache=1-2 \
|
|
|
+ HSDir=1-2 \
|
|
|
+ HSIntro=3-4 \
|
|
|
+ HSRend=1-2 \
|
|
|
+ Link=1-5 \
|
|
|
+ LinkAuth=1,3 \
|
|
|
+ Microdesc=1-2 \
|
|
|
+ Relay=1-2"
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
/// A map of protocol names to the versions of them which are supported.
|
|
@@ -150,7 +152,7 @@ pub struct ProtoEntry(HashMap<Protocol, ProtoSet>);
|
|
|
|
|
|
impl Default for ProtoEntry {
|
|
|
fn default() -> ProtoEntry {
|
|
|
- ProtoEntry( HashMap::new() )
|
|
|
+ ProtoEntry(HashMap::new())
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -240,7 +242,7 @@ impl FromStr for ProtoEntry {
|
|
|
/// Generate an implementation of `ToString` for either a `ProtoEntry` or an
|
|
|
/// `UnvalidatedProtoEntry`.
|
|
|
macro_rules! impl_to_string_for_proto_entry {
|
|
|
- ($t:ty) => (
|
|
|
+ ($t:ty) => {
|
|
|
impl ToString for $t {
|
|
|
fn to_string(&self) -> String {
|
|
|
let mut parts: Vec<String> = Vec::new();
|
|
@@ -252,7 +254,7 @@ macro_rules! impl_to_string_for_proto_entry {
|
|
|
parts.join(" ")
|
|
|
}
|
|
|
}
|
|
|
- )
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
impl_to_string_for_proto_entry!(ProtoEntry);
|
|
@@ -266,7 +268,7 @@ pub struct UnvalidatedProtoEntry(HashMap<UnknownProtocol, ProtoSet>);
|
|
|
|
|
|
impl Default for UnvalidatedProtoEntry {
|
|
|
fn default() -> UnvalidatedProtoEntry {
|
|
|
- UnvalidatedProtoEntry( HashMap::new() )
|
|
|
+ UnvalidatedProtoEntry(HashMap::new())
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -324,7 +326,7 @@ impl UnvalidatedProtoEntry {
|
|
|
pub fn all_supported(&self) -> Option<UnvalidatedProtoEntry> {
|
|
|
let mut unsupported: UnvalidatedProtoEntry = UnvalidatedProtoEntry::default();
|
|
|
let supported: ProtoEntry = match ProtoEntry::supported() {
|
|
|
- Ok(x) => x,
|
|
|
+ Ok(x) => x,
|
|
|
Err(_) => return None,
|
|
|
};
|
|
|
|
|
@@ -454,9 +456,9 @@ impl UnvalidatedProtoEntry {
|
|
|
/// * If a protocol name is an empty string, e.g. `"Cons=1,3 =3-5"`.
|
|
|
/// * If a protocol name cannot be parsed as utf-8.
|
|
|
/// * If the version numbers are an empty string, e.g. `"Cons="`.
|
|
|
- fn parse_protocol_and_version_str<'a>(protocol_string: &'a str)
|
|
|
- -> Result<Vec<(&'a str, &'a str)>, ProtoverError>
|
|
|
- {
|
|
|
+ fn parse_protocol_and_version_str<'a>(
|
|
|
+ protocol_string: &'a str,
|
|
|
+ ) -> Result<Vec<(&'a str, &'a str)>, ProtoverError> {
|
|
|
let mut protovers: Vec<(&str, &str)> = Vec::new();
|
|
|
|
|
|
for subproto in protocol_string.split(' ') {
|
|
@@ -523,9 +525,9 @@ impl FromStr for UnvalidatedProtoEntry {
|
|
|
impl UnvalidatedProtoEntry {
|
|
|
/// Create an `UnknownProtocol`, ignoring whether or not it
|
|
|
/// exceeds MAX_PROTOCOL_NAME_LENGTH.
|
|
|
- pub(crate) fn from_str_any_len(protocol_string: &str)
|
|
|
- -> Result<UnvalidatedProtoEntry, ProtoverError>
|
|
|
- {
|
|
|
+ pub(crate) fn from_str_any_len(
|
|
|
+ protocol_string: &str,
|
|
|
+ ) -> Result<UnvalidatedProtoEntry, ProtoverError> {
|
|
|
let mut parsed: UnvalidatedProtoEntry = UnvalidatedProtoEntry::default();
|
|
|
let parts: Vec<(&str, &str)> =
|
|
|
UnvalidatedProtoEntry::parse_protocol_and_version_str(protocol_string)?;
|
|
@@ -560,11 +562,11 @@ impl From<ProtoEntry> for UnvalidatedProtoEntry {
|
|
|
/// The "protocols" are *not* guaranteed to be known/supported `Protocol`s, in
|
|
|
/// order to allow new subprotocols to be introduced even if Directory
|
|
|
/// Authorities don't yet know of them.
|
|
|
-pub struct ProtoverVote( HashMap<UnknownProtocol, HashMap<Version, usize>> );
|
|
|
+pub struct ProtoverVote(HashMap<UnknownProtocol, HashMap<Version, usize>>);
|
|
|
|
|
|
impl Default for ProtoverVote {
|
|
|
fn default() -> ProtoverVote {
|
|
|
- ProtoverVote( HashMap::new() )
|
|
|
+ ProtoverVote(HashMap::new())
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -578,9 +580,10 @@ impl IntoIterator for ProtoverVote {
|
|
|
}
|
|
|
|
|
|
impl ProtoverVote {
|
|
|
- pub fn entry(&mut self, key: UnknownProtocol)
|
|
|
- -> hash_map::Entry<UnknownProtocol, HashMap<Version, usize>>
|
|
|
- {
|
|
|
+ pub fn entry(
|
|
|
+ &mut self,
|
|
|
+ key: UnknownProtocol,
|
|
|
+ ) -> hash_map::Entry<UnknownProtocol, HashMap<Version, usize>> {
|
|
|
self.0.entry(key)
|
|
|
}
|
|
|
|
|
@@ -602,7 +605,10 @@ impl ProtoverVote {
|
|
|
/// assert_eq!("Link=3", vote.to_string());
|
|
|
/// ```
|
|
|
// C_RUST_COUPLED: protover.c protover_compute_vote
|
|
|
- pub fn compute(proto_entries: &[UnvalidatedProtoEntry], threshold: &usize) -> UnvalidatedProtoEntry {
|
|
|
+ pub fn compute(
|
|
|
+ proto_entries: &[UnvalidatedProtoEntry],
|
|
|
+ threshold: &usize,
|
|
|
+ ) -> UnvalidatedProtoEntry {
|
|
|
let mut all_count: ProtoverVote = ProtoverVote::default();
|
|
|
let mut final_output: UnvalidatedProtoEntry = UnvalidatedProtoEntry::default();
|
|
|
|
|
@@ -628,8 +634,7 @@ impl ProtoverVote {
|
|
|
all_count.entry(protocol.clone()).or_insert(HashMap::new());
|
|
|
|
|
|
for version in versions.clone().expand() {
|
|
|
- let counter: &mut usize =
|
|
|
- supported_vers.entry(version).or_insert(0);
|
|
|
+ let counter: &mut usize = supported_vers.entry(version).or_insert(0);
|
|
|
*counter += 1;
|
|
|
}
|
|
|
}
|
|
@@ -708,16 +713,22 @@ pub(crate) fn compute_for_old_tor_cstr(version: &str) -> &'static CStr {
|
|
|
return empty;
|
|
|
}
|
|
|
if c_tor_version_as_new_as(version, "0.2.9.1-alpha") {
|
|
|
- return cstr!("Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1-2 \
|
|
|
- Link=1-4 LinkAuth=1 Microdesc=1-2 Relay=1-2");
|
|
|
+ return cstr!(
|
|
|
+ "Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1-2 \
|
|
|
+ Link=1-4 LinkAuth=1 Microdesc=1-2 Relay=1-2"
|
|
|
+ );
|
|
|
}
|
|
|
if c_tor_version_as_new_as(version, "0.2.7.5") {
|
|
|
- return cstr!("Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 \
|
|
|
- Link=1-4 LinkAuth=1 Microdesc=1-2 Relay=1-2");
|
|
|
+ return cstr!(
|
|
|
+ "Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 \
|
|
|
+ Link=1-4 LinkAuth=1 Microdesc=1-2 Relay=1-2"
|
|
|
+ );
|
|
|
}
|
|
|
if c_tor_version_as_new_as(version, "0.2.4.19") {
|
|
|
- return cstr!("Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 \
|
|
|
- Link=1-4 LinkAuth=1 Microdesc=1 Relay=1-2");
|
|
|
+ return cstr!(
|
|
|
+ "Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 \
|
|
|
+ Link=1-4 LinkAuth=1 Microdesc=1 Relay=1-2"
|
|
|
+ );
|
|
|
}
|
|
|
empty
|
|
|
}
|
|
@@ -752,7 +763,9 @@ pub(crate) fn compute_for_old_tor_cstr(version: &str) -> &'static CStr {
|
|
|
pub fn compute_for_old_tor(version: &str) -> Result<&'static str, ProtoverError> {
|
|
|
// .to_str() fails with a Utf8Error if it couldn't validate the
|
|
|
// utf-8, so convert that here into an Unparseable ProtoverError.
|
|
|
- compute_for_old_tor_cstr(version).to_str().or(Err(ProtoverError::Unparseable))
|
|
|
+ compute_for_old_tor_cstr(version)
|
|
|
+ .to_str()
|
|
|
+ .or(Err(ProtoverError::Unparseable))
|
|
|
}
|
|
|
|
|
|
#[cfg(test)]
|
|
@@ -763,19 +776,19 @@ mod test {
|
|
|
use super::*;
|
|
|
|
|
|
macro_rules! assert_protoentry_is_parseable {
|
|
|
- ($e:expr) => (
|
|
|
+ ($e:expr) => {
|
|
|
let protoentry: Result<ProtoEntry, ProtoverError> = $e.parse();
|
|
|
|
|
|
assert!(protoentry.is_ok(), format!("{:?}", protoentry.err()));
|
|
|
- )
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
macro_rules! assert_protoentry_is_unparseable {
|
|
|
- ($e:expr) => (
|
|
|
+ ($e:expr) => {
|
|
|
let protoentry: Result<ProtoEntry, ProtoverError> = $e.parse();
|
|
|
|
|
|
assert!(protoentry.is_err());
|
|
|
- )
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
@@ -861,24 +874,45 @@ mod test {
|
|
|
#[test]
|
|
|
fn test_contract_protocol_list() {
|
|
|
let mut versions = "";
|
|
|
- assert_eq!(String::from(versions), ProtoSet::from_str(&versions).unwrap().to_string());
|
|
|
+ assert_eq!(
|
|
|
+ String::from(versions),
|
|
|
+ ProtoSet::from_str(&versions).unwrap().to_string()
|
|
|
+ );
|
|
|
|
|
|
versions = "1";
|
|
|
- assert_eq!(String::from(versions), ProtoSet::from_str(&versions).unwrap().to_string());
|
|
|
+ assert_eq!(
|
|
|
+ String::from(versions),
|
|
|
+ ProtoSet::from_str(&versions).unwrap().to_string()
|
|
|
+ );
|
|
|
|
|
|
versions = "1-2";
|
|
|
- assert_eq!(String::from(versions), ProtoSet::from_str(&versions).unwrap().to_string());
|
|
|
+ assert_eq!(
|
|
|
+ String::from(versions),
|
|
|
+ ProtoSet::from_str(&versions).unwrap().to_string()
|
|
|
+ );
|
|
|
|
|
|
versions = "1,3";
|
|
|
- assert_eq!(String::from(versions), ProtoSet::from_str(&versions).unwrap().to_string());
|
|
|
+ assert_eq!(
|
|
|
+ String::from(versions),
|
|
|
+ ProtoSet::from_str(&versions).unwrap().to_string()
|
|
|
+ );
|
|
|
|
|
|
versions = "1-4";
|
|
|
- assert_eq!(String::from(versions), ProtoSet::from_str(&versions).unwrap().to_string());
|
|
|
+ assert_eq!(
|
|
|
+ String::from(versions),
|
|
|
+ ProtoSet::from_str(&versions).unwrap().to_string()
|
|
|
+ );
|
|
|
|
|
|
versions = "1,3,5-7";
|
|
|
- assert_eq!(String::from(versions), ProtoSet::from_str(&versions).unwrap().to_string());
|
|
|
+ assert_eq!(
|
|
|
+ String::from(versions),
|
|
|
+ ProtoSet::from_str(&versions).unwrap().to_string()
|
|
|
+ );
|
|
|
|
|
|
versions = "1-3,500";
|
|
|
- assert_eq!(String::from(versions), ProtoSet::from_str(&versions).unwrap().to_string());
|
|
|
+ assert_eq!(
|
|
|
+ String::from(versions),
|
|
|
+ ProtoSet::from_str(&versions).unwrap().to_string()
|
|
|
+ );
|
|
|
}
|
|
|
}
|