From c0bab849eff889f8e976272bf0c996a6e7ccff94 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 17 Mar 2021 17:53:24 -0400 Subject: [PATCH] Build fixes, add some standard derives. --- rust-zerotier-core/src/buffer.rs | 12 ++++--- rust-zerotier-core/src/certificate.rs | 18 +++++----- service/src/fastudpsocket.rs | 4 --- service/src/main.rs | 50 ++++++++++++++++----------- service/src/service.rs | 2 +- service/src/weblistener.rs | 40 +++++++++------------ 6 files changed, 63 insertions(+), 63 deletions(-) diff --git a/rust-zerotier-core/src/buffer.rs b/rust-zerotier-core/src/buffer.rs index 7dcde6b63..e9cb883be 100644 --- a/rust-zerotier-core/src/buffer.rs +++ b/rust-zerotier-core/src/buffer.rs @@ -59,12 +59,14 @@ impl Buffer { self.zt_core_buf } - /// Set the size of the data held by this buffer. This is unsafe because - /// setting it to a value larger than CAPACITY will place the buffer into - /// an invalid state. + /// Set the size of the data held by this buffer. + /// This is usually called after writing data into the buffer. #[inline(always)] - pub unsafe fn set_len(&mut self, s: usize) { - self.data_size = s; + pub fn set_len(&mut self, s: usize) { + // CAPACITY will always be a power of two, so we can just mask this + // to make this safe. This is a sanity check to make it impossible to + // set this to an invalid size. + self.data_size = s & (Buffer::CAPACITY - 1); } } diff --git a/rust-zerotier-core/src/certificate.rs b/rust-zerotier-core/src/certificate.rs index 4b87a4bd2..3ca0e5c65 100644 --- a/rust-zerotier-core/src/certificate.rs +++ b/rust-zerotier-core/src/certificate.rs @@ -41,7 +41,7 @@ pub const CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE: u32 = ztcore::ZT_C ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#[derive(PartialEq, Eq, PartialOrd, Ord)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)] pub struct CertificateSerialNo(pub [u8; 48]); impl CertificateSerialNo { @@ -87,7 +87,7 @@ impl<'de> serde::Deserialize<'de> for CertificateSerialNo { ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// Type of certificate subject unique ID -#[derive(FromPrimitive, ToPrimitive, PartialEq, Eq)] +#[derive(FromPrimitive, ToPrimitive, PartialEq, Eq, Clone, Copy)] pub enum CertificateUniqueIdType { NistP384 = ztcore::ZT_CertificateUniqueIdType_ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384 as isize } @@ -124,7 +124,7 @@ impl<'de> serde::Deserialize<'de> for CertificateUniqueIdType { ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#[derive(Serialize, Deserialize, PartialEq, Eq)] +#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct CertificateSubjectUniqueIdSecret { #[serde(with = "Base64Standard")] pub public: Vec, @@ -160,7 +160,7 @@ implement_to_from_json!(CertificateSubjectUniqueIdSecret); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#[derive(FromPrimitive, ToPrimitive, PartialEq, Eq)] +#[derive(FromPrimitive, ToPrimitive, PartialEq, Eq, Clone, Copy)] pub enum CertificateError { None = ztcore::ZT_CertificateError_ZT_CERTIFICATE_ERROR_NONE as isize, HaveNewerCert = ztcore::ZT_CertificateError_ZT_CERTIFICATE_ERROR_HAVE_NEWER_CERT as isize, @@ -225,7 +225,7 @@ impl<'de> serde::Deserialize<'de> for CertificateError { ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#[derive(Serialize, Deserialize, PartialEq, Eq)] +#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct CertificateName { #[serde(rename = "serialNo")] pub serial_no: String, @@ -317,7 +317,7 @@ implement_to_from_json!(CertificateName); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#[derive(Serialize, Deserialize, PartialEq, Eq)] +#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct CertificateNetwork { pub id: NetworkId, pub controller: Option, @@ -366,7 +366,7 @@ implement_to_from_json!(CertificateNetwork); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#[derive(Serialize, Deserialize, PartialEq, Eq)] +#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct CertificateIdentity { pub identity: Identity, pub locator: Option, @@ -395,7 +395,7 @@ implement_to_from_json!(CertificateIdentity); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#[derive(Serialize, Deserialize, PartialEq, Eq)] +#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct CertificateSubject { pub timestamp: i64, pub identities: Vec, @@ -578,7 +578,7 @@ implement_to_from_json!(CertificateSubject); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#[derive(Serialize, Deserialize, PartialEq, Eq)] +#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct Certificate { #[serde(rename = "serialNo")] pub serial_no: CertificateSerialNo, diff --git a/service/src/fastudpsocket.rs b/service/src/fastudpsocket.rs index 04ea19067..e261144e4 100644 --- a/service/src/fastudpsocket.rs +++ b/service/src/fastudpsocket.rs @@ -80,9 +80,6 @@ fn bind_udp_socket(_device_name: &str, address: &InetAddress) -> Result Result may be specified as a 10-digit short ZeroTier address, a fingerprint containing both an address and a SHA384 hash, or an identity. Identities and locators can be specified as either paths to files on the -filesystem or verbatim objects in string format. This is auto-detected."###, ver.0, ver.1, ver.2) +filesystem or verbatim objects in string format. This is auto-detected. +"###, ver.0, ver.1, ver.2) } pub(crate) fn print_help() { - println!("{}", make_help()); + let h = make_help(); + std::io::stdout().write_all(h.as_bytes()); } -fn is_bool(v: String) -> Result<(), String> { +pub(crate) fn parse_bool(v: &str) -> Result { if !v.is_empty() { match v.chars().next().unwrap() { - 'y' | 'Y' | '1' | 't' | 'T' | 'n' | 'N' | '0' | 'f' | 'F' => { return Ok(()); } + 'y' | 'Y' | '1' | 't' | 'T' => { return Ok(true); } + 'n' | 'N' | '0' | 'f' | 'F' => { return Ok(false); } _ => {} } } Err(format!("invalid boolean value: '{}'", v)) } +fn is_valid_bool(v: String) -> Result<(), String> { + parse_bool(v.as_str()).map(|_| ()) +} + fn is_valid_port(v: String) -> Result<(), String> { let i = u16::from_str(v.as_str()).unwrap_or(0); if i >= 1 { @@ -158,6 +166,17 @@ fn is_valid_port(v: String) -> Result<(), String> { Err(format!("invalid TCP/IP port number: {}", v)) } +fn make_store(cli_args: &ArgMatches) -> Arc { + //let json_output = cli_args.is_present("json"); // TODO + let zerotier_path = cli_args.value_of("path").map_or_else(|| unsafe { zerotier_core::cstr_to_string(osdep::platformDefaultHomePath(), -1) }, |ztp| ztp.to_string()); + let store = Store::new(zerotier_path.as_str(), cli_args.value_of("token_path").map_or(None, |tp| Some(tp.to_string())), cli_args.value_of("token").map_or(None, |tok| Some(tok.trim().to_string()))); + if store.is_err() { + eprintln!("FATAL: error accessing directory '{}': {}", zerotier_path, store.err().unwrap().to_string()); + std::process::exit(1); + } + Arc::new(store.unwrap()) +} + fn main() { let cli_args = { let help = make_help(); @@ -177,12 +196,12 @@ fn main() { .subcommand(App::new("blacklist") .subcommand(App::new("cidr") .arg(Arg::with_name("ip_bits").index(1)) - .arg(Arg::with_name("boolean").index(2).validator(is_bool))) + .arg(Arg::with_name("boolean").index(2).validator(is_valid_bool))) .subcommand(App::new("if") .arg(Arg::with_name("prefix").index(1)) - .arg(Arg::with_name("boolean").index(2).validator(is_bool)))) + .arg(Arg::with_name("boolean").index(2).validator(is_valid_bool)))) .subcommand(App::new("portmap") - .arg(Arg::with_name("boolean").index(1).validator(is_bool)))) + .arg(Arg::with_name("boolean").index(1).validator(is_valid_bool)))) .subcommand(App::new("peer") .subcommand(App::new("show") .arg(Arg::with_name("address").index(1).required(true))) @@ -286,17 +305,6 @@ fn main() { args }; - let store = || { - //let json_output = cli_args.is_present("json"); // TODO - let zerotier_path = cli_args.value_of("path").map_or_else(|| unsafe { zerotier_core::cstr_to_string(osdep::platformDefaultHomePath(), -1) }, |ztp| ztp.to_string()); - let store = Store::new(zerotier_path.as_str(), cli_args.value_of("token_path").map_or(None, |tp| Some(tp.to_string())), cli_args.value_of("token").map_or(None, |tok| Some(tok.trim().to_string()))); - if store.is_err() { - eprintln!("FATAL: error accessing directory '{}': {}", zerotier_path, store.err().unwrap().to_string()); - std::process::exit(1); - } - Arc::new(store.unwrap()) - }; - std::process::exit(match cli_args.subcommand() { ("help", None) => { print_help(); @@ -314,14 +322,14 @@ fn main() { ("join", Some(sub_cli_args)) => { 0 } ("leave", Some(sub_cli_args)) => { 0 } ("service", None) => { - let store = store(); - drop(cli_args); // try to let go of unnecessary heap before running service + let store = make_store(&cli_args); + drop(cli_args); // free memory service::run(store) }, ("controller", Some(sub_cli_args)) => { 0 } ("identity", Some(sub_cli_args)) => crate::commands::identity::run(sub_cli_args), ("locator", Some(sub_cli_args)) => crate::commands::locator::run(sub_cli_args), - ("cert", Some(sub_cli_args)) => crate::commands::cert::run(store(), sub_cli_args), + ("cert", Some(sub_cli_args)) => crate::commands::cert::run(make_store(&cli_args), sub_cli_args), _ => { print_help(); 1 diff --git a/service/src/service.rs b/service/src/service.rs index 03e1eae2a..ab86248e0 100644 --- a/service/src/service.rs +++ b/service/src/service.rs @@ -95,7 +95,7 @@ impl NodeEventHandler for Service { TraceEventLayer::VL2 => local_config.settings.log.vl2, TraceEventLayer::VL2Filter => local_config.settings.log.vl2_trace_rules, TraceEventLayer::VL2Multicast => local_config.settings.log.vl2_trace_multicast, - TraceEventLayer::Other => true, + _ => true, } { self.log.log(tm.to_string()); } diff --git a/service/src/weblistener.rs b/service/src/weblistener.rs index 79181677a..b802661b9 100644 --- a/service/src/weblistener.rs +++ b/service/src/weblistener.rs @@ -28,7 +28,6 @@ use crate::service::Service; use std::os::unix::io::AsRawFd; /// Handles API dispatch and other HTTP handler stuff. -#[inline(always)] async fn web_handler(service: Service, req: Request) -> Result, Infallible> { Ok(Response::new("Hello, World".into())) } @@ -45,23 +44,26 @@ impl WebListener { /// Create a new "background" TCP WebListener using the current tokio reactor async runtime. pub fn new(_device_name: &str, addr: SocketAddr, service: &Service) -> Result> { let listener = if addr.is_ipv4() { - let l = socket2::Socket::new(socket2::Domain::ipv4(), socket2::Type::stream(), Some(socket2::Protocol::tcp())); - if l.is_err() { - return Err(Box::new(l.err().unwrap())); + let listener = socket2::Socket::new(socket2::Domain::ipv4(), socket2::Type::stream(), Some(socket2::Protocol::tcp())); + if listener.is_err() { + return Err(Box::new(listener.err().unwrap())); } - let l = l.unwrap(); + let listener = listener.unwrap(); #[cfg(unix)] { - let _ = l.set_reuse_port(true); + let _ = listener.set_reuse_port(true); } - l + listener } else { - let l = socket2::Socket::new(socket2::Domain::ipv6(), socket2::Type::stream(), Some(socket2::Protocol::tcp())); - if l.is_err() { - return Err(Box::new(l.err().unwrap())); + let listener = socket2::Socket::new(socket2::Domain::ipv6(), socket2::Type::stream(), Some(socket2::Protocol::tcp())); + if listener.is_err() { + return Err(Box::new(listener.err().unwrap())); } - let l = l.unwrap(); - let _ = l.set_only_v6(true); - l + let listener = listener.unwrap(); + #[cfg(unix)] { + let _ = listener.set_reuse_port(true); + } + let _ = listener.set_only_v6(true); + listener }; #[cfg(target_os = "linux")] { @@ -70,12 +72,7 @@ impl WebListener { unsafe { let _ = std::ffi::CString::new(_device_name).map(|dn| { let dnb = dn.as_bytes_with_nul(); - let _ = crate::osdep::setsockopt( - sock as std::os::raw::c_int, - crate::osdep::SOL_SOCKET as std::os::raw::c_int, - crate::osdep::SO_BINDTODEVICE as std::os::raw::c_int, - dnb.as_ptr().cast(), - (dnb.len() - 1) as crate::osdep::socklen_t); + let _ = crate::osdep::setsockopt(sock as std::os::raw::c_int, crate::osdep::SOL_SOCKET as std::os::raw::c_int, crate::osdep::SO_BINDTODEVICE as std::os::raw::c_int, dnb.as_ptr().cast(), (dnb.len() - 1) as crate::osdep::socklen_t); }); } } @@ -94,10 +91,7 @@ impl WebListener { if builder.is_err() { return Err(Box::new(builder.err().unwrap())); } - let builder = builder.unwrap() - .http1_half_close(false) - .http1_keepalive(true) - .http1_max_buf_size(131072); + let builder = builder.unwrap().http1_half_close(false).http1_keepalive(true).http1_max_buf_size(131072); let (shutdown_tx, shutdown_rx) = tokio::sync::oneshot::channel::<()>(); let service = service.clone();