fix: 优化net

This commit is contained in:
shiro.lee
2024-07-03 23:00:32 +08:00
parent b33a788c20
commit f9462162a5
2 changed files with 79 additions and 173 deletions
+40 -43
View File
@@ -1,12 +1,17 @@
use std::{
collections::HashMap,
net::{IpAddr, ToSocketAddrs},
collections::HashSet,
net::{IpAddr, SocketAddr, ToSocketAddrs},
};
use anyhow::{Error, Result};
use netif;
use url::Host;
// helper for validating if the provided arg is an ip address.
pub fn is_socket_addr(host: &str) -> bool {
host.parse::<SocketAddr>().is_ok() || host.parse::<IpAddr>().is_ok()
}
pub fn split_host_port(s: &str) -> Result<(String, u16)> {
let parts: Vec<&str> = s.split(':').collect();
if parts.len() == 2 {
@@ -17,38 +22,23 @@ pub fn split_host_port(s: &str) -> Result<(String, u16)> {
Err(Error::msg("Invalid address format or port number"))
}
// is_local_host 判断是否是本地ip
/// checks if the given parameter correspond to one of
/// the local IP of the current machine
pub fn is_local_host(host: Host<&str>, port: u16, local_port: u16) -> bool {
let local_ips = must_get_local_ips();
let local_map =
local_ips
.iter()
.map(|ip| ip.to_string())
.fold(HashMap::new(), |mut acc, item| {
*acc.entry(item).or_insert(true) = true;
acc
});
let local_set: HashSet<IpAddr> = local_ips.into_iter().collect();
let is_local_host = match host {
Host::Domain(domain) => {
let ips: Vec<String> = (domain, 0)
.to_socket_addrs()
.unwrap_or(Vec::new().into_iter())
.map(|addr| addr.ip().to_string())
.collect();
let ips = match (domain, 0).to_socket_addrs().map(|v| v.map(|v| v.ip()).collect::<Vec<_>>()) {
Ok(ips) => ips,
Err(_) => return false,
};
let mut isok = false;
for ip in ips.iter() {
if local_map.contains_key(ip) {
isok = true;
break;
}
}
isok
ips.iter().any(|ip| local_set.contains(ip))
}
Host::Ipv4(ip) => local_map.contains_key(&ip.to_string()),
Host::Ipv6(ip) => local_map.contains_key(&ip.to_string()),
Host::Ipv4(ip) => local_set.contains(&IpAddr::V4(ip)),
Host::Ipv6(ip) => local_set.contains(&IpAddr::V6(ip)),
};
if port > 0 {
@@ -58,37 +48,44 @@ pub fn is_local_host(host: Host<&str>, port: u16, local_port: u16) -> bool {
is_local_host
}
/// returns IPs of local interface
pub fn must_get_local_ips() -> Vec<IpAddr> {
let mut v: Vec<IpAddr> = Vec::new();
if let Some(up) = netif::up().ok() {
v = up.map(|x| x.address().to_owned()).collect();
match netif::up() {
Ok(up) => up.map(|x| x.address().to_owned()).collect(),
Err(_) => vec![],
}
v
}
#[cfg(test)]
mod test {
use std::net::Ipv4Addr;
use std::net::{Ipv4Addr, Ipv6Addr};
use super::*;
#[test]
fn test_must_get_local_ips() {
let ips = must_get_local_ips();
for ip in ips.iter() {
println!("{:?}", ip)
}
let local_ips = must_get_local_ips();
let local_set: HashSet<IpAddr> = local_ips.into_iter().collect();
assert!(local_set.contains(&IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))));
}
#[test]
fn test_is_local_host() {
// let host = Host::Ipv4(Ipv4Addr::new(192, 168, 0, 233));
let host = Host::Domain("localhost");
let is = is_local_host(host, 0, 9000);
assert!(is);
let host = Host::Ipv6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
let is = is_local_host(host, 0, 9000);
assert!(is);
let host = Host::Ipv4(Ipv4Addr::new(8, 8, 8, 8));
let is = is_local_host(host, 0, 9000);
assert!(!is);
let host = Host::Ipv4(Ipv4Addr::new(127, 0, 0, 1));
// let host = Host::Domain("localhost");
let port = 0;
let local_port = 9000;
let is = is_local_host(host, port, local_port);
assert!(is)
let is = is_local_host(host, 8000, 9000);
assert!(!is);
}
}