use crate::config; use crate::utils::SDLanError; use dashmap::DashMap; use std::net::{IpAddr, SocketAddr}; use std::path::Path; use std::sync::Arc; pub struct MyDashMap(DashMap>); impl MyDashMap { pub fn new() -> Self { MyDashMap(DashMap::new()) } pub fn get(&self, key: &str) -> Option> { if let Some(t) = self.0.get(key) { return Some(t.clone()); } None } pub fn insert(&self, key: String, value: Arc) -> Option> { self.0.insert(key, value) } pub fn remove(&self, key: &str) -> Option<(String, Arc)> { self.0.remove(key) } pub fn clear(&self) { self.0.clear() } } use std::time::{Duration, SystemTime, UNIX_EPOCH}; pub fn get_timestamp_after_duration(d: Duration) -> u64 { if let Some(t) = SystemTime::now().checked_add(d) { t.duration_since(UNIX_EPOCH).unwrap().as_secs() } else { 0 } } pub fn get_current_timestamp() -> u64 { SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap() .as_secs() } use crate::peer::SdlanSock; use super::{gen_uuid, Mac, Result, BROADCAST_MAC, IPV6_MULTICAST_MAC, MULTICAST_MAC}; use std::fs::{File, OpenOptions}; use std::io::{Read, Write}; pub fn save_to_file(idfile: &str, content: &str) -> Result<()> { if idfile.len() == 0 { return Err(SDLanError::IOError("file is empty".to_owned())); } let filepath = Path::new(idfile); OpenOptions::new() .create(true) .write(true) .open(filepath)? .write_all(content.as_bytes())?; Ok(()) } pub fn create_or_load_uuid(mut idfile: &str, size: Option) -> Result { if idfile.len() == 0 { idfile = "./.id"; } let filepath = Path::new(idfile); if filepath.exists() { let mut result = String::new(); File::open(filepath)?.read_to_string(&mut result)?; let result = result.trim().to_string(); return Ok(result); } else { let mut uuid = gen_uuid(); if let Some(size) = size { uuid.truncate(size as usize); } OpenOptions::new() .create(true) .write(true) .open(filepath)? .write_all(uuid.as_bytes())?; return Ok(uuid); } } // get sdlansock info from socketaddr pub fn get_sdlan_sock_from_socketaddr(addr: SocketAddr) -> Result { let port = addr.port(); let ip = addr.ip(); match ip { IpAddr::V4(ipv4) => { let v4: u32 = ipv4.into(); let res = SdlanSock { family: config::AF_INET, port: port, // has_v6: false, // v6_port: 0, v4: v4.to_be_bytes(), v6: [0; 16], }; Ok(res) } IpAddr::V6(ipv6) => { let res = SdlanSock { family: config::AF_INET6, port: port, v4: [0; 4], v6: ipv6.octets(), }; Ok(res) } } } #[inline] pub fn is_broadcast(mac: &Mac) -> bool { *mac == BROADCAST_MAC } #[inline] pub fn is_multicast(mac: &Mac) -> bool { (mac[..3] == MULTICAST_MAC[..3]) && ((mac[3] >> 7) != 0x01) } #[inline] pub fn is_ipv6_multicast(mac: &Mac) -> bool { mac[..2] == IPV6_MULTICAST_MAC[..2] } #[inline] pub fn is_multi_broadcast(mac: &Mac) -> bool { is_broadcast(mac) || is_multicast(mac) || is_ipv6_multicast(mac) } pub fn ip_to_string(ip: &u32) -> String { format!( "{}.{}.{}.{}", ((ip >> 24) & 0xff) as u8, ((ip >> 16) & 0xff) as u8, ((ip >> 8) & 0xff) as u8, (ip & 0xff) as u8, ) } pub fn net_bit_len_to_mask(len: u8) -> u32 { let mut res = 0u32; for i in 1..=len { res |= 1 << (32 - i); } res }