From 80e2740a898bd1003c0d14d16e6f91ebdcdc811d Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 22 Feb 2021 16:00:56 -0500 Subject: [PATCH] Slim down a little, test getifaddrs. --- rust-zerotier-service/Cargo.lock | 69 ++----------------------- rust-zerotier-service/Cargo.toml | 2 +- rust-zerotier-service/src/getifaddrs.rs | 35 +++++++++++-- rust-zerotier-service/src/service.rs | 64 ++++++++++++++--------- 4 files changed, 75 insertions(+), 95 deletions(-) diff --git a/rust-zerotier-service/Cargo.lock b/rust-zerotier-service/Cargo.lock index 47acb0a1d..4b2bed581 100644 --- a/rust-zerotier-service/Cargo.lock +++ b/rust-zerotier-service/Cargo.lock @@ -472,15 +472,6 @@ dependencies = [ "bytes", ] -[[package]] -name = "instant" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" -dependencies = [ - "cfg-if 1.0.0", -] - [[package]] name = "itoa" version = "0.4.7" @@ -499,15 +490,6 @@ version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929" -[[package]] -name = "lock_api" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" -dependencies = [ - "scopeguard", -] - [[package]] name = "log" version = "0.4.13" @@ -653,31 +635,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" -[[package]] -name = "parking_lot" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272" -dependencies = [ - "cfg-if 1.0.0", - "instant", - "libc", - "redox_syscall 0.1.57", - "smallvec", - "winapi", -] - [[package]] name = "percent-encoding" version = "2.1.0" @@ -859,12 +816,6 @@ dependencies = [ "rand_core 0.6.1", ] -[[package]] -name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - [[package]] name = "redox_syscall" version = "0.2.4" @@ -901,12 +852,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - [[package]] name = "serde" version = "1.0.119" @@ -990,12 +935,6 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -[[package]] -name = "smallvec" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" - [[package]] name = "socket2" version = "0.3.19" @@ -1033,7 +972,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "rand 0.8.2", - "redox_syscall 0.2.4", + "redox_syscall", "remove_dir_all", "winapi", ] @@ -1094,9 +1033,7 @@ dependencies = [ "libc", "memchr", "mio", - "num_cpus", "once_cell", - "parking_lot", "pin-project-lite", "signal-hook-registry", "tokio-macros", @@ -1105,9 +1042,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42517d2975ca3114b22a16192634e8241dc5cc1f130be194645970cc1c371494" +checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57" dependencies = [ "proc-macro2", "quote", diff --git a/rust-zerotier-service/Cargo.toml b/rust-zerotier-service/Cargo.toml index 1b4d02af9..fda519f6c 100644 --- a/rust-zerotier-service/Cargo.toml +++ b/rust-zerotier-service/Cargo.toml @@ -10,7 +10,7 @@ build = "build.rs" [dependencies] zerotier-core = { path = "../rust-zerotier-core" } num_cpus = "1" -tokio = { version = "1", features = ["full"] } +tokio = { version = "1", features = ["rt", "net", "time", "signal", "macros"] } warp = "0" serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/rust-zerotier-service/src/getifaddrs.rs b/rust-zerotier-service/src/getifaddrs.rs index 05b8f9ff5..f311d9d56 100644 --- a/rust-zerotier-service/src/getifaddrs.rs +++ b/rust-zerotier-service/src/getifaddrs.rs @@ -11,7 +11,6 @@ */ /****/ -use std::ffi::CStr; use std::mem::size_of; use std::ptr::{copy_nonoverlapping, null_mut}; @@ -30,6 +29,7 @@ fn s6_addr_as_ptr(a: &A) -> *const A { #[cfg(unix)] pub(crate) fn for_each_address(mut f: F) { unsafe { + let mut ifa_name = [0_u8; osdep::IFNAMSIZ as usize]; let mut ifap: *mut osdep::ifaddrs = null_mut(); if osdep::getifaddrs((&mut ifap as *mut *mut osdep::ifaddrs).cast()) == 0 { let mut i = ifap; @@ -43,6 +43,7 @@ pub(crate) fn for_each_address(mut f: F) { } else if sa_family == osdep::AF_INET6 as u8 { copy_nonoverlapping((*i).ifa_addr.cast::(), (&mut a as *mut InetAddress).cast::(), size_of::()); } else { + i = (*i).ifa_next; continue; } @@ -66,9 +67,21 @@ pub(crate) fn for_each_address(mut f: F) { } a.set_port(netmask_bits); - let dev = CStr::from_ptr((*i).ifa_name).to_str(); - if dev.is_ok() { - f(&a, dev.unwrap()); + let mut namlen: usize = 0; + while namlen < (osdep::IFNAMSIZ as usize) { + let c = *(*i).ifa_name.offset(namlen as isize); + if c != 0 { + ifa_name[namlen] = c as u8; + namlen += 1; + } else { + break; + } + } + if namlen > 0 { + let dev = String::from_utf8_lossy(&ifa_name[0..namlen]); + if dev.len() > 0 { + f(&a, dev.as_ref()); + } } } i = (*i).ifa_next; @@ -77,3 +90,17 @@ pub(crate) fn for_each_address(mut f: F) { } } } + +#[cfg(test)] +mod tests { + use zerotier_core::InetAddress; + + #[test] + fn test_getifaddrs() { + println!("starting getifaddrs..."); + crate::getifaddrs::for_each_address(|a: &InetAddress, dev: &str| { + println!(" device: {} ip: {}", dev, a.to_string()) + }); + println!("done.") + } +} diff --git a/rust-zerotier-service/src/service.rs b/rust-zerotier-service/src/service.rs index 41d020437..aef2a0853 100644 --- a/rust-zerotier-service/src/service.rs +++ b/rust-zerotier-service/src/service.rs @@ -12,7 +12,7 @@ /****/ use std::collections::BTreeMap; -use std::net::IpAddr; +use std::net::{IpAddr, SocketAddr}; use std::str::FromStr; use std::sync::{Arc, Mutex, Weak}; use std::sync::atomic::{AtomicBool, Ordering}; @@ -66,6 +66,10 @@ impl NodeEventHandler for Service { Event::Trace => { if !event_data.is_empty() { let _ = Dictionary::new_from_bytes(event_data).map(|tm| { + let tm = zerotier_core::trace::TraceEvent::parse_message(&tm); + let _ = tm.map(|tm| { + self.log.log(tm.to_string()); + }); }); } } @@ -110,17 +114,17 @@ impl NodeEventHandler for Service { impl Service { #[inline(always)] - fn web_api_status(&self, method: Method, headers: HeaderMap, post_data: Bytes) -> Box { + fn web_api_status(&self, remote: Option, method: Method, headers: HeaderMap, post_data: Bytes) -> Box { Box::new(StatusCode::BAD_REQUEST) } #[inline(always)] - fn web_api_network(&self, network_str: String, method: Method, headers: HeaderMap, post_data: Bytes) -> Box { + fn web_api_network(&self, network_str: String, remote: Option, method: Method, headers: HeaderMap, post_data: Bytes) -> Box { Box::new(StatusCode::BAD_REQUEST) } #[inline(always)] - fn web_api_peer(&self, peer_str: String, method: Method, headers: HeaderMap, post_data: Bytes) -> Box { + fn web_api_peer(&self, peer_str: String, remote: Option, method: Method, headers: HeaderMap, post_data: Bytes) -> Box { Box::new(StatusCode::BAD_REQUEST) } @@ -204,6 +208,9 @@ pub(crate) fn run(store: &Arc, auth_token: Option) -> i32 { service.node = Arc::downgrade(&node); let service = service; // make immutable after setting node + // The outer loop runs for as long as the service runs. It repeatedly restarts + // the inner loop, which can exit if it needs to be restarted. This is the case + // if a major configuration change occurs. let mut loop_delay = zerotier_core::NODE_BACKGROUND_TASKS_MAX_INTERVAL; loop { let mut local_config = service.local_config(); @@ -214,26 +221,31 @@ pub(crate) fn run(store: &Arc, auth_token: Option) -> i32 { let s0 = service.clone(); let s1 = service.clone(); let s2 = service.clone(); - warp_server = warp::serve( - warp::any().and(warp::path::end().map(|| { - warp::reply::with_status("404", StatusCode::NOT_FOUND) - }) - .or(warp::path("status").and(warp::method()).and(warp::header::headers_cloned()).and(warp::body::bytes()) - .map(move |method: Method, headers: HeaderMap, post_data: Bytes| { - s0.web_api_status(method, headers, post_data) - })) - .or(warp::path!("network" / String).and(warp::method()).and(warp::header::headers_cloned()).and(warp::body::bytes()) - .map(move |network_str: String, method: Method, headers: HeaderMap, post_data: Bytes| { - s1.web_api_network(network_str, method, headers, post_data) - })) - .or(warp::path!("peer" / String).and(warp::method()).and(warp::header::headers_cloned()).and(warp::body::bytes()) - .map(move |peer_str: String, method: Method, headers: HeaderMap, post_data: Bytes| { - s2.web_api_peer(peer_str, method, headers, post_data) - })) - )).try_bind_with_graceful_shutdown( - (IpAddr::from([127_u8, 0_u8, 0_u8, 1_u8]), local_config.settings.primary_port), - async { let _ = shutdown_rx.await; }, - ); + warp_server = warp::serve(warp::any() + .and(warp::path::end().map(|| { warp::reply::with_status("404", StatusCode::NOT_FOUND) }) + .or(warp::path("status") + .and(warp::addr::remote()) + .and(warp::method()) + .and(warp::header::headers_cloned()) + .and(warp::body::content_length_limit(1048576)) + .and(warp::body::bytes()) + .map(move |remote: Option, method: Method, headers: HeaderMap, post_data: Bytes| { s0.web_api_status(remote, method, headers, post_data) })) + .or(warp::path!("network" / String) + .and(warp::addr::remote()) + .and(warp::method()) + .and(warp::header::headers_cloned()) + .and(warp::body::content_length_limit(1048576)) + .and(warp::body::bytes()) + .map(move |network_str: String, remote: Option, method: Method, headers: HeaderMap, post_data: Bytes| { s1.web_api_network(network_str, remote, method, headers, post_data) })) + .or(warp::path!("peer" / String) + .and(warp::addr::remote()) + .and(warp::method()) + .and(warp::header::headers_cloned()) + .and(warp::body::content_length_limit(1048576)) + .and(warp::body::bytes()) + .map(move |peer_str: String, remote: Option, method: Method, headers: HeaderMap, post_data: Bytes| { s2.web_api_peer(peer_str, remote, method, headers, post_data) })) + ) + ).try_bind_with_graceful_shutdown((IpAddr::from([127_u8, 0_u8, 0_u8, 1_u8]), local_config.settings.primary_port), async { let _ = shutdown_rx.await; }); } if warp_server.is_err() { l!(log, "ERROR: local API http server failed to bind to port {} or failed to start: {}", local_config.settings.primary_port, warp_server.err().unwrap().to_string()); @@ -244,6 +256,9 @@ pub(crate) fn run(store: &Arc, auth_token: Option) -> i32 { // Write zerotier.port which is used by the CLI to know how to reach the HTTP API. store.write_port(local_config.settings.primary_port); + // The inner loop runs the web server in the "background" (async) while periodically + // scanning for significant configuration changes. Some major changes may require + // the inner loop to exit and be restarted. let mut last_checked_config: i64 = 0; loop { let loop_start = ms_since_epoch(); @@ -256,6 +271,7 @@ pub(crate) fn run(store: &Arc, auth_token: Option) -> i32 { now = ms_since_epoch(); let actual_delay = now - loop_start; if actual_delay > ((loop_delay as i64) * 4_i64) { + l!(log, "likely sleep/wake detected, reestablishing links..."); // TODO: handle likely sleep/wake or other system interruption } },