sdlan-rs/src/utils/helper.rs
2025-12-25 16:31:36 +08:00

161 lines
3.8 KiB
Rust

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<T>(DashMap<String, Arc<T>>);
impl<T> MyDashMap<T> {
pub fn new() -> Self {
MyDashMap(DashMap::new())
}
pub fn get(&self, key: &str) -> Option<Arc<T>> {
if let Some(t) = self.0.get(key) {
return Some(t.clone());
}
None
}
pub fn insert(&self, key: String, value: Arc<T>) -> Option<Arc<T>> {
self.0.insert(key, value)
}
pub fn remove(&self, key: &str) -> Option<(String, Arc<T>)> {
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<u8>) -> Result<String> {
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<SdlanSock> {
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
}