tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

commit fc2a42cc49fdcab9bbc0d90212c3c7bebda238b8
parent 9766d53cf990432f25fb70916fe9b165f1d4a36d
Author: Isis Lovecruft <isis@torproject.org>
Date:   Tue, 27 Mar 2018 02:41:25 +0000

rust: Refactor protover::compute_for_old_tor().

During code review and discussion with Chelsea Komlo, she pointed out
that protover::compute_for_old_tor() was a public function whose
return type was `&'static CStr`.  We both agree that C-like parts of
APIs should:

1. not be exposed publicly (to other Rust crates),
2. only be called in the appropriate FFI code,
3. not expose types which are meant for FFI code (e.g. `*mut char`,
   `CString`, `*const c_int`, etc.) to the pure-Rust code of other
   crates.
4. FFI code (e.g. things in `ffi.rs` modules) should _never_ be called
   from pure-Rust, not even from other modules in its own crate
   (i.e. do not call `protover::ffi::*` from anywhere in
   `protover::protoset::*`, etc).

With that in mind, this commit makes the following changes:

 * CHANGE `protover::compute_for_old_tor()` to be
   visible only at the `pub(crate)` level.
 * RENAME `protover::compute_for_old_tor()` to
   `protover::compute_for_old_tor_cstr()` to reflect the last change.
 * ADD a new `protover::compute_for_old_tor()` function wrapper which
   is public and intended for other Rust code to use, which returns a
   `&str`.

Diffstat:
Msrc/rust/protover/ffi.rs | 2+-
Msrc/rust/protover/protover.rs | 54+++++++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 46 insertions(+), 10 deletions(-)

diff --git a/src/rust/protover/ffi.rs b/src/rust/protover/ffi.rs @@ -231,6 +231,6 @@ pub extern "C" fn protover_compute_for_old_tor(version: *const c_char) -> *const Err(_) => return empty.as_ptr(), }; - supported = compute_for_old_tor(&version); + supported = compute_for_old_tor_cstr(&version); supported.as_ptr() } diff --git a/src/rust/protover/protover.rs b/src/rust/protover/protover.rs @@ -600,8 +600,8 @@ pub fn is_supported_here(proto: &Protocol, vers: &Version) -> bool { supported_versions.contains(vers) } -/// Older versions of Tor cannot infer their own subprotocols -/// Used to determine which subprotocols are supported by older Tor versions. +/// Since older versions of Tor cannot infer their own subprotocols, +/// determine which subprotocols are supported by older Tor versions. /// /// # Inputs /// @@ -615,34 +615,70 @@ pub fn is_supported_here(proto: &Protocol, vers: &Version) -> bool { /// "HSDir=1-1 LinkAuth=1" /// /// This function returns the protocols that are supported by the version input, -/// only for tor versions older than FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS. +/// only for tor versions older than `FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS` +/// (but not older than 0.2.4.19). For newer tors (or older than 0.2.4.19), it +/// returns an empty string. /// -/// C_RUST_COUPLED: src/rust/protover.c `compute_for_old_tor` -pub fn compute_for_old_tor(version: &str) -> &'static CStr { +/// # Note +/// +/// This function is meant to be called for/within FFI code. If you'd +/// like to use this code in Rust, please see `compute_for_old_tor()`. +// +// C_RUST_COUPLED: src/rust/protover.c `compute_for_old_tor` +pub(crate) fn compute_for_old_tor_cstr(version: &str) -> &'static CStr { let empty: &'static CStr = cstr!(""); if c_tor_version_as_new_as(version, FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS) { 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"); } - 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"); } - 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"); } - empty } +/// Since older versions of Tor cannot infer their own subprotocols, +/// determine which subprotocols are supported by older Tor versions. +/// +/// # Inputs +/// +/// * `version`, a string comprised of "[0-9a-z.-]" +/// +/// # Returns +/// +/// A `Result` whose `Ok` value is an `&'static str` encoding a list of protocol +/// names and supported versions. The string takes the following format: +/// +/// "HSDir=1-1 LinkAuth=1" +/// +/// This function returns the protocols that are supported by the version input, +/// only for tor versions older than `FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS`. +/// (but not older than 0.2.4.19). For newer tors (or older than 0.2.4.19), its +/// `Ok` `Result` contains an empty string. +/// +/// Otherwise, its `Err` contains a `ProtoverError::Unparseable` if the +/// `version` string was invalid utf-8. +/// +/// # Note +/// +/// This function is meant to be called for/within non-FFI Rust code. +// +// C_RUST_COUPLED: src/rust/protover.c `compute_for_old_tor` +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)) +} + #[cfg(test)] mod test { use std::str::FromStr;