commit d8893bc93c52e1edd0a76b81f5d65bb10d790474 Merge: 3716611fe 1f8bd93ec Author: Nick Mathewson nickm@torproject.org Date: Mon Mar 19 17:20:37 2018 -0400
Merge remote-tracking branch 'isis/bug23881_r1'
src/common/log.c | 31 ++++ src/common/torlog.h | 14 ++ src/or/main.c | 8 +- src/rust/Cargo.lock | 10 ++ src/rust/Cargo.toml | 3 +- src/rust/protover/Cargo.toml | 6 + src/rust/protover/ffi.rs | 8 +- src/rust/protover/lib.rs | 3 + src/rust/protover/protover.rs | 20 ++- src/rust/tor_allocate/tor_allocate.rs | 19 ++- src/rust/tor_log/Cargo.toml | 18 +++ src/rust/tor_log/lib.rs | 16 ++ src/rust/tor_log/tor_log.rs | 270 ++++++++++++++++++++++++++++++++++ src/rust/tor_util/Cargo.toml | 3 + src/rust/tor_util/ffi.rs | 13 +- src/rust/tor_util/lib.rs | 3 + src/test/test_rust.sh | 2 +- 17 files changed, 423 insertions(+), 24 deletions(-)
diff --cc src/rust/protover/lib.rs index 8e80fcef4,05687c1fb..d1d49d2a5 --- a/src/rust/protover/lib.rs +++ b/src/rust/protover/lib.rs @@@ -26,9 -26,10 +26,12 @@@ extern crate libc extern crate smartlist; extern crate external; extern crate tor_allocate; +#[macro_use] +extern crate tor_util;
+ #[macro_use] + extern crate tor_log; + mod protover; pub mod ffi;
diff --cc src/rust/protover/protover.rs index 03776411c,22a94a164..fd1f41d78 --- a/src/rust/protover/protover.rs +++ b/src/rust/protover/protover.rs @@@ -1,17 -1,14 +1,18 @@@ // Copyright (c) 2016-2017, The Tor Project, Inc. */ // See LICENSE for licensing information */
- use external::c_tor_version_as_new_as; - +use std::str; use std::str::FromStr; +use std::ffi::CStr; use std::fmt; use std::collections::{HashMap, HashSet}; +use std::ops::Range; use std::string::String; +use std::u32;
+ use tor_log::{LogSeverity, LogDomain}; + use external::c_tor_version_as_new_as; + /// The first version of Tor that included "proto" entries in its descriptors. /// Authorities should use this to decide whether to guess proto lines. /// @@@ -105,127 -126,67 +106,126 @@@ pub(crate) fn get_supported_protocols_c /// /// # Returns /// -/// A `Result` whose `Ok` value is a `HashMap<Proto, <u32>>` holding all -/// subprotocols and versions currently supported by tor. -/// -/// The returned `Result`'s `Err` value is an `&'static str` with a description -/// of the error. +/// An `&'a str` whose value is the existing protocols supported by tor. +/// Returned data is in the format as follows: /// -fn tor_supported() -> Result<HashMap<Proto, HashSet<u32>>, &'static str> { - parse_protocols(&SUPPORTED_PROTOCOLS) +/// "HSDir=1-1 LinkAuth=1" +pub fn get_supported_protocols<'a>() -> &'a str { + let supported_cstr: &'static CStr = get_supported_protocols_cstr(); + let supported: &str = match supported_cstr.to_str() { + Ok(x) => x, + Err(_) => "", + }; + + supported }
-/// Get the unique version numbers supported by a subprotocol. -/// -/// # Inputs -/// -/// * `version_string`, a string comprised of "[0-9,-]" -/// -/// # Returns -/// -/// A `Result` whose `Ok` value is a `HashSet<u32>` holding all of the unique -/// version numbers. If there were ranges in the `version_string`, then these -/// are expanded, i.e. `"1-3"` would expand to `HashSet<u32>::new([1, 2, 3])`. -/// The returned HashSet is *unordered*. -/// -/// The returned `Result`'s `Err` value is an `&'static str` with a description -/// of the error. -/// -/// # Errors -/// -/// This function will error if: -/// -/// * the `version_string` is empty or contains an equals (`"="`) sign, -/// * the expansion of a version range produces an error (see -/// `expand_version_range`), -/// * any single version number is not parseable as an `u32` in radix 10, or -/// * there are greater than 2^16 version numbers to expand. -/// -fn get_versions(version_string: &str) -> Result<HashSet<u32>, &'static str> { - if version_string.is_empty() { - return Err("version string is empty"); +pub struct SupportedProtocols(HashMap<Proto, Versions>); + +impl SupportedProtocols { + pub fn from_proto_entries<I, S>(protocol_strs: I) -> Result<Self, &'static str> + where + I: Iterator<Item = S>, + S: AsRef<str>, + { + let mut parsed = HashMap::new(); + for subproto in protocol_strs { + let (name, version) = get_proto_and_vers(subproto.as_ref())?; + parsed.insert(name, version); + } + Ok(SupportedProtocols(parsed)) }
- let mut versions = HashSet::<u32>::new(); + /// Translates a string representation of a protocol list to a + /// SupportedProtocols instance. + /// + /// # Examples + /// + /// ``` + /// use protover::SupportedProtocols; + /// + /// let supported_protocols = SupportedProtocols::from_proto_entries_string( + /// "HSDir=1-2 HSIntro=3-4" + /// ); + /// ``` + pub fn from_proto_entries_string( + proto_entries: &str, + ) -> Result<Self, &'static str> { + Self::from_proto_entries(proto_entries.split(" ")) + }
- for piece in version_string.split(",") { - if piece.contains("-") { - for p in expand_version_range(piece)? { - versions.insert(p); + /// Translate the supported tor versions from a string into a + /// HashMap, which is useful when looking up a specific + /// subprotocol. + /// + fn tor_supported() -> Result<Self, &'static str> { + Self::from_proto_entries_string(get_supported_protocols()) + } +} + +type Version = u32; + +/// Set of versions for a protocol. +#[derive(Debug, PartialEq, Eq)] +pub struct Versions(HashSet<Version>); + +impl Versions { + /// Get the unique version numbers supported by a subprotocol. + /// + /// # Inputs + /// + /// * `version_string`, a string comprised of "[0-9,-]" + /// + /// # Returns + /// + /// A `Result` whose `Ok` value is a `HashSet<u32>` holding all of the unique + /// version numbers. If there were ranges in the `version_string`, then these + /// are expanded, i.e. `"1-3"` would expand to `HashSet<u32>::new([1, 2, 3])`. + /// The returned HashSet is *unordered*. + /// + /// The returned `Result`'s `Err` value is an `&'static str` with a description + /// of the error. + /// + /// # Errors + /// + /// This function will error if: + /// + /// * the `version_string` is empty or contains an equals (`"="`) sign, + /// * the expansion of a version range produces an error (see + /// `expand_version_range`), + /// * any single version number is not parseable as an `u32` in radix 10, or + /// * there are greater than 2^16 version numbers to expand. + /// + fn from_version_string( + version_string: &str, + ) -> Result<Self, &'static str> { + let mut versions = HashSet::<Version>::new(); + + for piece in version_string.split(",") { + if piece.contains("-") { + for p in expand_version_range(piece)? { + versions.insert(p); + } + } else if piece == "" { + continue; + } else { + let v = u32::from_str(piece).or( + Err("invalid protocol entry"), + )?; + if v == u32::MAX { + return Err("invalid protocol entry"); + } + versions.insert(v); } - } else { - versions.insert(u32::from_str(piece).or( - Err("invalid protocol entry"), - )?); - }
- if versions.len() > MAX_PROTOCOLS_TO_EXPAND as usize { - return Err("Too many versions to expand"); + if versions.len() > MAX_PROTOCOLS_TO_EXPAND { + return Err("Too many versions to expand"); + } } + Ok(Versions(versions)) } - Ok(versions) }
- /// Parse the subprotocol type and its version numbers. /// /// # Inputs diff --cc src/rust/tor_util/lib.rs index 12cb3896b,4d5cbb568..94697b606 --- a/src/rust/tor_util/lib.rs +++ b/src/rust/tor_util/lib.rs @@@ -7,5 -8,7 +7,8 @@@ extern crate libc; extern crate tor_allocate;
+ #[macro_use] + extern crate tor_log; + pub mod ffi; +pub mod strings;