windows upnp work
This commit is contained in:
parent
ebd36d82ef
commit
d922bc1f5d
16
Cargo.lock
generated
16
Cargo.lock
generated
@ -499,14 +499,13 @@ checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "attohttpc"
|
name = "attohttpc"
|
||||||
version = "0.16.3"
|
version = "0.24.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fdb8867f378f33f78a811a8eb9bf108ad99430d7aad43315dd9319c827ef6247"
|
checksum = "8d9a9bf8b79a749ee0b911b91b671cc2b6c670bdbc7e3dfd537576ddc94bb2a2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"http",
|
"http",
|
||||||
"log",
|
"log",
|
||||||
"url",
|
"url",
|
||||||
"wildmatch",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -5406,9 +5405,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "veilid-igd"
|
name = "veilid-igd"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28428a3f826ed334f995522e554d7c8c1a5a0e0a0248fc795a31022ddf436c9d"
|
checksum = "ce2b3c073da0025538ff4cf5bea61a7a7a046c1bf060e2d0981c71800747551d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"attohttpc",
|
"attohttpc",
|
||||||
"log",
|
"log",
|
||||||
@ -5517,6 +5516,7 @@ dependencies = [
|
|||||||
"wasm-bindgen-test",
|
"wasm-bindgen-test",
|
||||||
"wasm-logger",
|
"wasm-logger",
|
||||||
"wee_alloc",
|
"wee_alloc",
|
||||||
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -5781,12 +5781,6 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8"
|
checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wildmatch"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7f44b95f62d34113cf558c93511ac93027e03e9c29a60dd0fd70e6e025c7270a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
@ -18,6 +18,7 @@ cursive_core = { git = "https://gitlab.com/veilid/cursive.git" }
|
|||||||
# keyvaluedb-memorydb = { path = "../keyvaluedb/keyvaluedb-memorydb" }
|
# keyvaluedb-memorydb = { path = "../keyvaluedb/keyvaluedb-memorydb" }
|
||||||
# keyvaluedb-sqlite = { path = "../keyvaluedb/keyvaluedb-sqlite" }
|
# keyvaluedb-sqlite = { path = "../keyvaluedb/keyvaluedb-sqlite" }
|
||||||
# keyvaluedb-web = { path = "../keyvaluedb/keyvaluedb-web" }
|
# keyvaluedb-web = { path = "../keyvaluedb/keyvaluedb-web" }
|
||||||
|
# igd = { package = "veilid-igd", path = "../rust-igd" }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = "s"
|
opt-level = "s"
|
||||||
|
@ -170,7 +170,7 @@ keyvaluedb-sqlite = "0.1.1"
|
|||||||
|
|
||||||
# Network
|
# Network
|
||||||
async-tungstenite = { version = "0.23.0", features = ["async-tls"] }
|
async-tungstenite = { version = "0.23.0", features = ["async-tls"] }
|
||||||
igd = { package = "veilid-igd", version = "0.1.0" }
|
igd = { package = "veilid-igd", version = "0.1.1" }
|
||||||
async-tls = "0.12.0"
|
async-tls = "0.12.0"
|
||||||
webpki = "0.22.1"
|
webpki = "0.22.1"
|
||||||
webpki-roots = "0.25.2"
|
webpki-roots = "0.25.2"
|
||||||
|
@ -12,6 +12,5 @@ pub use system::*;
|
|||||||
|
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
pub mod android;
|
pub mod android;
|
||||||
pub mod network_interfaces;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -26,7 +26,7 @@ struct PortMapValue {
|
|||||||
|
|
||||||
struct IGDManagerInner {
|
struct IGDManagerInner {
|
||||||
local_ip_addrs: BTreeMap<AddressType, IpAddr>,
|
local_ip_addrs: BTreeMap<AddressType, IpAddr>,
|
||||||
gateways: BTreeMap<AddressType, Arc<Gateway>>,
|
gateways: BTreeMap<IpAddr, Arc<Gateway>>,
|
||||||
port_maps: BTreeMap<PortMapKey, PortMapValue>,
|
port_maps: BTreeMap<PortMapKey, PortMapValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,17 +121,21 @@ impl IGDManager {
|
|||||||
|
|
||||||
fn find_gateway(
|
fn find_gateway(
|
||||||
inner: &mut IGDManagerInner,
|
inner: &mut IGDManagerInner,
|
||||||
address_type: AddressType,
|
local_ip: IpAddr,
|
||||||
) -> Option<Arc<Gateway>> {
|
) -> Option<Arc<Gateway>> {
|
||||||
if let Some(gw) = inner.gateways.get(&address_type) {
|
|
||||||
|
if let Some(gw) = inner.gateways.get(&local_ip) {
|
||||||
return Some(gw.clone());
|
return Some(gw.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let gateway = match address_type {
|
let gateway = match local_ip {
|
||||||
AddressType::IPV4 => {
|
IpAddr::V4(v4) => {
|
||||||
match igd::search_gateway(SearchOptions::new_v4(
|
let mut opts = SearchOptions::new_v4(
|
||||||
UPNP_GATEWAY_DETECT_TIMEOUT_MS as u64,
|
UPNP_GATEWAY_DETECT_TIMEOUT_MS as u64,
|
||||||
)) {
|
);
|
||||||
|
opts.bind_addr = SocketAddr::V4(SocketAddrV4::new(v4, 0));
|
||||||
|
|
||||||
|
match igd::search_gateway(opts) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log_net!(debug "couldn't find ipv4 igd: {}", e);
|
log_net!(debug "couldn't find ipv4 igd: {}", e);
|
||||||
@ -139,11 +143,14 @@ impl IGDManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AddressType::IPV6 => {
|
IpAddr::V6(v6) => {
|
||||||
match igd::search_gateway(SearchOptions::new_v6(
|
let mut opts = SearchOptions::new_v6(
|
||||||
Ipv6SearchScope::LinkLocal,
|
Ipv6SearchScope::LinkLocal,
|
||||||
UPNP_GATEWAY_DETECT_TIMEOUT_MS as u64,
|
UPNP_GATEWAY_DETECT_TIMEOUT_MS as u64,
|
||||||
)) {
|
);
|
||||||
|
opts.bind_addr = SocketAddr::V6(SocketAddrV6::new(v6, 0, 0, 0));
|
||||||
|
|
||||||
|
match igd::search_gateway(opts) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log_net!(debug "couldn't find ipv6 igd: {}", e);
|
log_net!(debug "couldn't find ipv6 igd: {}", e);
|
||||||
@ -151,17 +158,18 @@ impl IGDManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
let gw = Arc::new(gateway);
|
let gw = Arc::new(gateway);
|
||||||
inner.gateways.insert(address_type, gw.clone());
|
inner.gateways.insert(local_ip, gw.clone());
|
||||||
Some(gw)
|
Some(gw)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_gateway(
|
fn get_gateway(
|
||||||
inner: &mut IGDManagerInner,
|
inner: &mut IGDManagerInner,
|
||||||
address_type: AddressType,
|
local_ip: IpAddr,
|
||||||
) -> Option<Arc<Gateway>> {
|
) -> Option<Arc<Gateway>> {
|
||||||
if let Some(gw) = inner.gateways.get(&address_type) {
|
if let Some(gw) = inner.gateways.get(&local_ip) {
|
||||||
return Some(gw.clone());
|
return Some(gw.clone());
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
@ -191,8 +199,12 @@ impl IGDManager {
|
|||||||
let pmk = found?;
|
let pmk = found?;
|
||||||
let _pmv = inner.port_maps.remove(&pmk).expect("key found but remove failed");
|
let _pmv = inner.port_maps.remove(&pmk).expect("key found but remove failed");
|
||||||
|
|
||||||
|
|
||||||
|
// Get local ip address
|
||||||
|
let local_ip = Self::find_local_ip(&mut inner, at)?;
|
||||||
|
|
||||||
// Find gateway
|
// Find gateway
|
||||||
let gw = Self::find_gateway(&mut inner, at)?;
|
let gw = Self::find_gateway(&mut inner, local_ip)?;
|
||||||
|
|
||||||
// Unmap port
|
// Unmap port
|
||||||
match gw.remove_port(convert_llpt(llpt), mapped_port) {
|
match gw.remove_port(convert_llpt(llpt), mapped_port) {
|
||||||
@ -233,7 +245,7 @@ impl IGDManager {
|
|||||||
let local_ip = Self::find_local_ip(&mut inner, at)?;
|
let local_ip = Self::find_local_ip(&mut inner, at)?;
|
||||||
|
|
||||||
// Find gateway
|
// Find gateway
|
||||||
let gw = Self::find_gateway(&mut inner, at)?;
|
let gw = Self::find_gateway(&mut inner, local_ip)?;
|
||||||
|
|
||||||
// Get external address
|
// Get external address
|
||||||
let ext_ip = match gw.get_external_ip() {
|
let ext_ip = match gw.get_external_ip() {
|
||||||
@ -326,14 +338,6 @@ impl IGDManager {
|
|||||||
// Process full renewals
|
// Process full renewals
|
||||||
for (k, v) in full_renews {
|
for (k, v) in full_renews {
|
||||||
|
|
||||||
// Get gateway for address type
|
|
||||||
let gw = match Self::get_gateway(&mut inner, k.at) {
|
|
||||||
Some(gw) => gw,
|
|
||||||
None => {
|
|
||||||
return Err(eyre!("gateway missing for address type"));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get local ip for address type
|
// Get local ip for address type
|
||||||
let local_ip = match Self::get_local_ip(&mut inner, k.at) {
|
let local_ip = match Self::get_local_ip(&mut inner, k.at) {
|
||||||
Some(ip) => ip,
|
Some(ip) => ip,
|
||||||
@ -342,6 +346,14 @@ impl IGDManager {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Get gateway for interface
|
||||||
|
let gw = match Self::get_gateway(&mut inner, local_ip) {
|
||||||
|
Some(gw) => gw,
|
||||||
|
None => {
|
||||||
|
return Err(eyre!("gateway missing for interface"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Delete the mapping if it exists, ignore any errors here
|
// Delete the mapping if it exists, ignore any errors here
|
||||||
let _ = gw.remove_port(convert_llpt(k.llpt), v.mapped_port);
|
let _ = gw.remove_port(convert_llpt(k.llpt), v.mapped_port);
|
||||||
inner.port_maps.remove(&k);
|
inner.port_maps.remove(&k);
|
||||||
@ -370,14 +382,6 @@ impl IGDManager {
|
|||||||
// Process normal renewals
|
// Process normal renewals
|
||||||
for (k, mut v) in renews {
|
for (k, mut v) in renews {
|
||||||
|
|
||||||
// Get gateway for address type
|
|
||||||
let gw = match Self::get_gateway(&mut inner, k.at) {
|
|
||||||
Some(gw) => gw,
|
|
||||||
None => {
|
|
||||||
return Err(eyre!("gateway missing for address type"));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get local ip for address type
|
// Get local ip for address type
|
||||||
let local_ip = match Self::get_local_ip(&mut inner, k.at) {
|
let local_ip = match Self::get_local_ip(&mut inner, k.at) {
|
||||||
Some(ip) => ip,
|
Some(ip) => ip,
|
||||||
@ -386,6 +390,14 @@ impl IGDManager {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Get gateway for interface
|
||||||
|
let gw = match Self::get_gateway(&mut inner, local_ip) {
|
||||||
|
Some(gw) => gw,
|
||||||
|
None => {
|
||||||
|
return Err(eyre!("gateway missing for address type"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let desc = this.get_description(k.llpt, k.local_port);
|
let desc = this.get_description(k.llpt, k.local_port);
|
||||||
match gw.add_port(convert_llpt(k.llpt), v.mapped_port, SocketAddr::new(local_ip, k.local_port), (UPNP_MAPPING_LIFETIME_MS + 999) / 1000, &desc) {
|
match gw.add_port(convert_llpt(k.llpt), v.mapped_port, SocketAddr::new(local_ip, k.local_port), (UPNP_MAPPING_LIFETIME_MS + 999) / 1000, &desc) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
|
@ -10,7 +10,6 @@ use super::*;
|
|||||||
use crate::routing_table::*;
|
use crate::routing_table::*;
|
||||||
use connection_manager::*;
|
use connection_manager::*;
|
||||||
use discovery_context::*;
|
use discovery_context::*;
|
||||||
use network_interfaces::*;
|
|
||||||
use network_tcp::*;
|
use network_tcp::*;
|
||||||
use protocol::tcp::RawTcpProtocolHandler;
|
use protocol::tcp::RawTcpProtocolHandler;
|
||||||
use protocol::udp::RawUdpProtocolHandler;
|
use protocol::udp::RawUdpProtocolHandler;
|
||||||
@ -316,7 +315,7 @@ impl Network {
|
|||||||
if !from.ip().is_unspecified() {
|
if !from.ip().is_unspecified() {
|
||||||
vec![*from]
|
vec![*from]
|
||||||
} else {
|
} else {
|
||||||
let addrs = self.get_usable_interface_addresses();
|
let addrs = self.get_stable_interface_addresses();
|
||||||
addrs
|
addrs
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|a| {
|
.filter_map(|a| {
|
||||||
@ -358,13 +357,13 @@ impl Network {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_usable_interface_address(&self, addr: IpAddr) -> bool {
|
pub fn is_stable_interface_address(&self, addr: IpAddr) -> bool {
|
||||||
let usable_addrs = self.get_usable_interface_addresses();
|
let stable_addrs = self.get_stable_interface_addresses();
|
||||||
usable_addrs.contains(&addr)
|
stable_addrs.contains(&addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_usable_interface_addresses(&self) -> Vec<IpAddr> {
|
pub fn get_stable_interface_addresses(&self) -> Vec<IpAddr> {
|
||||||
let addrs = self.unlocked_inner.interfaces.best_addresses();
|
let addrs = self.unlocked_inner.interfaces.stable_addresses();
|
||||||
let addrs: Vec<IpAddr> = addrs
|
let addrs: Vec<IpAddr> = addrs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|addr| {
|
.filter(|addr| {
|
||||||
@ -377,7 +376,13 @@ impl Network {
|
|||||||
|
|
||||||
// See if our interface addresses have changed, if so redo public dial info if necessary
|
// See if our interface addresses have changed, if so redo public dial info if necessary
|
||||||
async fn check_interface_addresses(&self) -> EyreResult<bool> {
|
async fn check_interface_addresses(&self) -> EyreResult<bool> {
|
||||||
if !self.unlocked_inner.interfaces.refresh().await? {
|
if !self
|
||||||
|
.unlocked_inner
|
||||||
|
.interfaces
|
||||||
|
.refresh()
|
||||||
|
.await
|
||||||
|
.wrap_err("failed to check network interfaces")?
|
||||||
|
{
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -723,7 +728,7 @@ impl Network {
|
|||||||
{
|
{
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
inner.enable_ipv4 = false;
|
inner.enable_ipv4 = false;
|
||||||
for addr in self.get_usable_interface_addresses() {
|
for addr in self.get_stable_interface_addresses() {
|
||||||
if addr.is_ipv4() {
|
if addr.is_ipv4() {
|
||||||
log_net!(debug "enable address {:?} as ipv4", addr);
|
log_net!(debug "enable address {:?} as ipv4", addr);
|
||||||
inner.enable_ipv4 = true;
|
inner.enable_ipv4 = true;
|
||||||
|
@ -342,7 +342,7 @@ impl Network {
|
|||||||
|
|
||||||
// See if this public address is also a local interface address we haven't registered yet
|
// See if this public address is also a local interface address we haven't registered yet
|
||||||
let is_interface_address = (|| {
|
let is_interface_address = (|| {
|
||||||
for ip_addr in self.get_usable_interface_addresses() {
|
for ip_addr in self.get_stable_interface_addresses() {
|
||||||
if pdi_addr.ip() == ip_addr {
|
if pdi_addr.ip() == ip_addr {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -438,7 +438,7 @@ impl Network {
|
|||||||
|
|
||||||
// See if this public address is also a local interface address
|
// See if this public address is also a local interface address
|
||||||
if !registered_addresses.contains(&gsa.ip())
|
if !registered_addresses.contains(&gsa.ip())
|
||||||
&& self.is_usable_interface_address(gsa.ip())
|
&& self.is_stable_interface_address(gsa.ip())
|
||||||
{
|
{
|
||||||
editor_local_network.register_dial_info(pdi, DialInfoClass::Direct)?;
|
editor_local_network.register_dial_info(pdi, DialInfoClass::Direct)?;
|
||||||
}
|
}
|
||||||
@ -552,7 +552,7 @@ impl Network {
|
|||||||
|
|
||||||
// See if this public address is also a local interface address
|
// See if this public address is also a local interface address
|
||||||
if !registered_addresses.contains(&gsa.ip())
|
if !registered_addresses.contains(&gsa.ip())
|
||||||
&& self.is_usable_interface_address(gsa.ip())
|
&& self.is_stable_interface_address(gsa.ip())
|
||||||
{
|
{
|
||||||
editor_local_network.register_dial_info(pdi, DialInfoClass::Direct)?;
|
editor_local_network.register_dial_info(pdi, DialInfoClass::Direct)?;
|
||||||
}
|
}
|
||||||
@ -653,7 +653,7 @@ impl Network {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// See if this public address is also a local interface address
|
// See if this public address is also a local interface address
|
||||||
if self.is_usable_interface_address(pdi_addr.ip()) {
|
if self.is_stable_interface_address(pdi_addr.ip()) {
|
||||||
editor_local_network.register_dial_info(pdi, DialInfoClass::Direct)?;
|
editor_local_network.register_dial_info(pdi, DialInfoClass::Direct)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,11 +425,11 @@ impl Network {
|
|||||||
trace!("network stopped");
|
trace!("network stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_usable_interface_address(&self, _addr: IpAddr) -> bool {
|
pub fn is_stable_interface_address(&self, _addr: IpAddr) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_usable_interface_addresses(&self) -> Vec<IpAddr> {
|
pub fn get_stable_interface_addresses(&self) -> Vec<IpAddr> {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
pub mod test_host_interface;
|
|
||||||
pub mod test_protected_store;
|
pub mod test_protected_store;
|
||||||
pub mod test_veilid_config;
|
pub mod test_veilid_config;
|
||||||
pub mod test_veilid_core;
|
pub mod test_veilid_core;
|
||||||
|
@ -13,8 +13,6 @@ use crate::*;
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn run_all_tests() {
|
pub async fn run_all_tests() {
|
||||||
// iOS and Android tests also run these.
|
// iOS and Android tests also run these.
|
||||||
info!("TEST: test_host_interface");
|
|
||||||
test_host_interface::test_all().await;
|
|
||||||
info!("TEST: test_types");
|
info!("TEST: test_types");
|
||||||
test_types::test_all().await;
|
test_types::test_all().await;
|
||||||
info!("TEST: test_veilid_core");
|
info!("TEST: test_veilid_core");
|
||||||
@ -114,8 +112,6 @@ cfg_if! {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
run_test!(test_host_interface);
|
|
||||||
|
|
||||||
run_test!(test_types);
|
run_test!(test_types);
|
||||||
|
|
||||||
run_test!(test_veilid_core);
|
run_test!(test_veilid_core);
|
||||||
|
@ -69,7 +69,7 @@ futures-util = { version = "0.3.28", default-features = false, features = [
|
|||||||
chrono = "0.4.31"
|
chrono = "0.4.31"
|
||||||
|
|
||||||
libc = "0.2.148"
|
libc = "0.2.148"
|
||||||
nix = { version = "0.27.1", features = [ "user" ] }
|
nix = { version = "0.27.1", features = ["user"] }
|
||||||
|
|
||||||
# Dependencies for WASM builds only
|
# Dependencies for WASM builds only
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
@ -93,9 +93,8 @@ paranoid-android = { version = "0.2.1", optional = true }
|
|||||||
android_logger = "0.13.3"
|
android_logger = "0.13.3"
|
||||||
|
|
||||||
# Dependencies for Windows
|
# Dependencies for Windows
|
||||||
# [target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
# windows = { version = "^0", features = [ "Win32_NetworkManagement_Dns", "Win32_Foundation", "alloc" ]}
|
winapi = { version = "0.3.9", features = ["iptypes", "iphlpapi"] }
|
||||||
# windows-permissions = "^0"
|
|
||||||
|
|
||||||
# Dependencies for iOS
|
# Dependencies for iOS
|
||||||
[target.'cfg(target_os = "ios")'.dependencies]
|
[target.'cfg(target_os = "ios")'.dependencies]
|
||||||
|
@ -40,6 +40,7 @@ pub mod log_thru;
|
|||||||
pub mod must_join_handle;
|
pub mod must_join_handle;
|
||||||
pub mod must_join_single_future;
|
pub mod must_join_single_future;
|
||||||
pub mod mutable_future;
|
pub mod mutable_future;
|
||||||
|
pub mod network_interfaces;
|
||||||
pub mod network_result;
|
pub mod network_result;
|
||||||
pub mod random;
|
pub mod random;
|
||||||
pub mod single_shot_eventual;
|
pub mod single_shot_eventual;
|
||||||
@ -182,6 +183,8 @@ pub use must_join_single_future::*;
|
|||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use mutable_future::*;
|
pub use mutable_future::*;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
|
pub use network_interfaces::*;
|
||||||
|
#[doc(inline)]
|
||||||
pub use network_result::*;
|
pub use network_result::*;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use random::*;
|
pub use random::*;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#![cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -273,10 +274,10 @@ pub struct PlatformSupportApple {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PlatformSupportApple {
|
impl PlatformSupportApple {
|
||||||
pub fn new() -> EyreResult<Self> {
|
pub fn new() -> Self {
|
||||||
Ok(PlatformSupportApple {
|
PlatformSupportApple {
|
||||||
default_route_interfaces: BTreeSet::new(),
|
default_route_interfaces: BTreeSet::new(),
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn refresh_default_route_interfaces(&mut self) -> EyreResult<()> {
|
async fn refresh_default_route_interfaces(&mut self) -> EyreResult<()> {
|
||||||
@ -433,11 +434,11 @@ impl PlatformSupportApple {
|
|||||||
pub async fn get_interfaces(
|
pub async fn get_interfaces(
|
||||||
&mut self,
|
&mut self,
|
||||||
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
||||||
) -> EyreResult<()> {
|
) -> io::Result<()> {
|
||||||
self.refresh_default_route_interfaces().await?;
|
self.refresh_default_route_interfaces().await?;
|
||||||
|
|
||||||
// Ask for all the addresses we have
|
// Ask for all the addresses we have
|
||||||
let ifaddrs = IfAddrs::new().wrap_err("failed to get interface addresses")?;
|
let ifaddrs = IfAddrs::new()?;
|
||||||
for ifaddr in ifaddrs.iter() {
|
for ifaddr in ifaddrs.iter() {
|
||||||
// Get the interface name
|
// Get the interface name
|
||||||
let ifname = unsafe { CStr::from_ptr(ifaddr.ifa_name) }
|
let ifname = unsafe { CStr::from_ptr(ifaddr.ifa_name) }
|
@ -1,18 +1,17 @@
|
|||||||
|
mod apple;
|
||||||
|
mod netlink;
|
||||||
|
mod sockaddr_tools;
|
||||||
mod tools;
|
mod tools;
|
||||||
|
mod windows;
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(any(target_os = "linux", target_os = "android"))] {
|
if #[cfg(any(target_os = "linux", target_os = "android"))] {
|
||||||
mod netlink;
|
|
||||||
use self::netlink::PlatformSupportNetlink as PlatformSupport;
|
use self::netlink::PlatformSupportNetlink as PlatformSupport;
|
||||||
} else if #[cfg(target_os = "windows")] {
|
} else if #[cfg(target_os = "windows")] {
|
||||||
mod windows;
|
|
||||||
mod sockaddr_tools;
|
|
||||||
use self::windows::PlatformSupportWindows as PlatformSupport;
|
use self::windows::PlatformSupportWindows as PlatformSupport;
|
||||||
} else if #[cfg(any(target_os = "macos", target_os = "ios"))] {
|
} else if #[cfg(any(target_os = "macos", target_os = "ios"))] {
|
||||||
mod apple;
|
|
||||||
mod sockaddr_tools;
|
|
||||||
use self::apple::PlatformSupportApple as PlatformSupport;
|
use self::apple::PlatformSupportApple as PlatformSupport;
|
||||||
} else {
|
} else {
|
||||||
compile_error!("No network interfaces support for this platform!");
|
compile_error!("No network interfaces support for this platform!");
|
||||||
@ -315,13 +314,22 @@ impl fmt::Debug for NetworkInterfaces {
|
|||||||
.finish()?;
|
.finish()?;
|
||||||
if f.alternate() {
|
if f.alternate() {
|
||||||
writeln!(f)?;
|
writeln!(f)?;
|
||||||
writeln!(f, "// best_addresses: {:?}", inner.interface_address_cache)?;
|
writeln!(
|
||||||
|
f,
|
||||||
|
"// stable_addresses: {:?}",
|
||||||
|
inner.interface_address_cache
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
impl Default for NetworkInterfaces {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl NetworkInterfaces {
|
impl NetworkInterfaces {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -344,14 +352,14 @@ impl NetworkInterfaces {
|
|||||||
inner.interface_address_cache.clear();
|
inner.interface_address_cache.clear();
|
||||||
inner.valid = false;
|
inner.valid = false;
|
||||||
}
|
}
|
||||||
// returns Ok(false) if refresh had no changes, Ok(true) if changes were present
|
// returns false if refresh had no changes, true if changes were present
|
||||||
pub async fn refresh(&self) -> EyreResult<bool> {
|
pub async fn refresh(&self) -> std::io::Result<bool> {
|
||||||
let mut last_interfaces = {
|
let mut last_interfaces = {
|
||||||
let mut last_interfaces = BTreeMap::<String, NetworkInterface>::new();
|
let mut last_interfaces = BTreeMap::<String, NetworkInterface>::new();
|
||||||
let mut platform_support = PlatformSupport::new()?;
|
let mut platform_support = PlatformSupport::new();
|
||||||
if let Err(e) = platform_support.get_interfaces(&mut last_interfaces).await {
|
platform_support
|
||||||
debug!("no network interfaces are enabled: {}", e);
|
.get_interfaces(&mut last_interfaces)
|
||||||
}
|
.await?;
|
||||||
last_interfaces
|
last_interfaces
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -361,16 +369,16 @@ impl NetworkInterfaces {
|
|||||||
|
|
||||||
if last_interfaces != inner.interfaces {
|
if last_interfaces != inner.interfaces {
|
||||||
// get last address cache
|
// get last address cache
|
||||||
let old_best_addresses = inner.interface_address_cache.clone();
|
let old_stable_addresses = inner.interface_address_cache.clone();
|
||||||
|
|
||||||
// redo the address cache
|
// redo the address cache
|
||||||
Self::cache_best_addresses(&mut inner);
|
Self::cache_stable_addresses(&mut inner);
|
||||||
|
|
||||||
// See if our best addresses have changed
|
// See if our best addresses have changed
|
||||||
if old_best_addresses != inner.interface_address_cache {
|
if old_stable_addresses != inner.interface_address_cache {
|
||||||
debug!(
|
debug!(
|
||||||
"Network interface addresses changed: \nFrom: {:?}\n To: {:?}\n",
|
"Network interface addresses changed: \nFrom: {:?}\n To: {:?}\n",
|
||||||
old_best_addresses, inner.interface_address_cache
|
old_stable_addresses, inner.interface_address_cache
|
||||||
);
|
);
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
@ -385,14 +393,14 @@ impl NetworkInterfaces {
|
|||||||
f(&inner.interfaces)
|
f(&inner.interfaces)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn best_addresses(&self) -> Vec<IpAddr> {
|
pub fn stable_addresses(&self) -> Vec<IpAddr> {
|
||||||
let inner = self.inner.lock();
|
let inner = self.inner.lock();
|
||||||
inner.interface_address_cache.clone()
|
inner.interface_address_cache.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
|
|
||||||
fn cache_best_addresses(inner: &mut NetworkInterfacesInner) {
|
fn cache_stable_addresses(inner: &mut NetworkInterfacesInner) {
|
||||||
// Reduce interfaces to their best routable ip addresses
|
// Reduce interfaces to their best routable ip addresses
|
||||||
let mut intf_addrs = Vec::new();
|
let mut intf_addrs = Vec::new();
|
||||||
for intf in inner.interfaces.values() {
|
for intf in inner.interfaces.values() {
|
@ -1,3 +1,5 @@
|
|||||||
|
#![cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use alloc::collections::btree_map::Entry;
|
use alloc::collections::btree_map::Entry;
|
||||||
@ -27,7 +29,7 @@ use std::io;
|
|||||||
use std::os::raw::c_int;
|
use std::os::raw::c_int;
|
||||||
use tools::*;
|
use tools::*;
|
||||||
|
|
||||||
fn get_interface_name(index: u32) -> EyreResult<String> {
|
fn get_interface_name(index: u32) -> io::Result<String> {
|
||||||
let mut ifnamebuf = [0u8; (IF_NAMESIZE + 1)];
|
let mut ifnamebuf = [0u8; (IF_NAMESIZE + 1)];
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(all(any(target_os = "android", target_os="linux"), any(target_arch = "arm", target_arch = "aarch64")))] {
|
if #[cfg(all(any(target_os = "android", target_os="linux"), any(target_arch = "arm", target_arch = "aarch64")))] {
|
||||||
@ -69,12 +71,12 @@ pub struct PlatformSupportNetlink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PlatformSupportNetlink {
|
impl PlatformSupportNetlink {
|
||||||
pub fn new() -> EyreResult<Self> {
|
pub fn new() -> Self {
|
||||||
Ok(PlatformSupportNetlink {
|
PlatformSupportNetlink {
|
||||||
connection_jh: None,
|
connection_jh: None,
|
||||||
handle: None,
|
handle: None,
|
||||||
default_route_interfaces: BTreeSet::new(),
|
default_route_interfaces: BTreeSet::new(),
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Figure out which interfaces have default routes
|
// Figure out which interfaces have default routes
|
||||||
@ -245,18 +247,14 @@ impl PlatformSupportNetlink {
|
|||||||
async fn get_interfaces_internal(
|
async fn get_interfaces_internal(
|
||||||
&mut self,
|
&mut self,
|
||||||
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
||||||
) -> EyreResult<()> {
|
) -> io::Result<()> {
|
||||||
// Refresh the routes
|
// Refresh the routes
|
||||||
self.refresh_default_route_interfaces().await?;
|
self.refresh_default_route_interfaces().await?;
|
||||||
|
|
||||||
// Ask for all the addresses we have
|
// Ask for all the addresses we have
|
||||||
let mut names = BTreeMap::<u32, String>::new();
|
let mut names = BTreeMap::<u32, String>::new();
|
||||||
let mut addresses = self.handle.as_ref().unwrap().address().get().execute();
|
let mut addresses = self.handle.as_ref().unwrap().address().get().execute();
|
||||||
while let Some(msg) = addresses
|
while let Some(msg) = addresses.try_next().await? {
|
||||||
.try_next()
|
|
||||||
.await
|
|
||||||
.wrap_err("failed to iterate interface addresses")?
|
|
||||||
{
|
|
||||||
// Have we seen this interface index yet?
|
// Have we seen this interface index yet?
|
||||||
// Get the name from the index, cached, if we can
|
// Get the name from the index, cached, if we can
|
||||||
let ifname = match names.entry(msg.header.index) {
|
let ifname = match names.entry(msg.header.index) {
|
||||||
@ -314,10 +312,9 @@ impl PlatformSupportNetlink {
|
|||||||
pub async fn get_interfaces(
|
pub async fn get_interfaces(
|
||||||
&mut self,
|
&mut self,
|
||||||
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
||||||
) -> EyreResult<()> {
|
) -> io::Result<()> {
|
||||||
// Get the netlink connection
|
// Get the netlink connection
|
||||||
let (connection, handle, _) = new_connection_with_socket::<RTNetLinkSocket>()
|
let (connection, handle, _) = new_connection_with_socket::<RTNetLinkSocket>()?;
|
||||||
.wrap_err("failed to create rtnetlink socket")?;
|
|
||||||
|
|
||||||
// Spawn a connection handler
|
// Spawn a connection handler
|
||||||
let connection_jh = spawn(connection);
|
let connection_jh = spawn(connection);
|
@ -1,3 +1,5 @@
|
|||||||
|
#![cfg(target_os = "windows")]
|
||||||
|
|
||||||
// Copyright 2018 MaidSafe.net limited.
|
// Copyright 2018 MaidSafe.net limited.
|
||||||
//
|
//
|
||||||
// This SAFE Network Software is licensed to you under the MIT license <LICENSE-MIT
|
// This SAFE Network Software is licensed to you under the MIT license <LICENSE-MIT
|
||||||
@ -28,8 +30,8 @@ use winapi::um::iptypes::{
|
|||||||
pub struct PlatformSupportWindows {}
|
pub struct PlatformSupportWindows {}
|
||||||
|
|
||||||
impl PlatformSupportWindows {
|
impl PlatformSupportWindows {
|
||||||
pub fn new() -> EyreResult<Self> {
|
pub fn new() -> Self {
|
||||||
Ok(PlatformSupportWindows {})
|
PlatformSupportWindows {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_interface_flags(intf: &IpAdapterAddresses) -> InterfaceFlags {
|
fn get_interface_flags(intf: &IpAdapterAddresses) -> InterfaceFlags {
|
||||||
@ -55,10 +57,9 @@ impl PlatformSupportWindows {
|
|||||||
pub async fn get_interfaces(
|
pub async fn get_interfaces(
|
||||||
&mut self,
|
&mut self,
|
||||||
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
||||||
) -> EyreResult<()> {
|
) -> io::Result<()> {
|
||||||
// Iterate all the interfaces
|
// Iterate all the interfaces
|
||||||
let windows_interfaces =
|
let windows_interfaces = WindowsInterfaces::new()?;
|
||||||
WindowsInterfaces::new().wrap_err("failed to get windows interfaces")?;
|
|
||||||
for windows_interface in windows_interfaces.iter() {
|
for windows_interface in windows_interfaces.iter() {
|
||||||
// Get name
|
// Get name
|
||||||
let intf_name = windows_interface.name();
|
let intf_name = windows_interface.name();
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
mod test_assembly_buffer;
|
mod test_assembly_buffer;
|
||||||
mod test_async_peek_stream;
|
mod test_async_peek_stream;
|
||||||
|
mod test_network_interfaces;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -13,6 +14,8 @@ use super::*;
|
|||||||
pub async fn run_all_tests() {
|
pub async fn run_all_tests() {
|
||||||
info!("TEST: exec_test_host_interface");
|
info!("TEST: exec_test_host_interface");
|
||||||
test_host_interface::test_all().await;
|
test_host_interface::test_all().await;
|
||||||
|
info!("TEST: exec_test_network_interfaces");
|
||||||
|
test_network_interfaces::test_all().await;
|
||||||
info!("TEST: exec_test_async_peek_stream");
|
info!("TEST: exec_test_async_peek_stream");
|
||||||
test_async_peek_stream::test_all().await;
|
test_async_peek_stream::test_all().await;
|
||||||
info!("TEST: exec_test_async_tag_lock");
|
info!("TEST: exec_test_async_tag_lock");
|
||||||
@ -82,6 +85,15 @@ cfg_if! {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn run_test_network_interfaces() {
|
||||||
|
setup();
|
||||||
|
block_on(async {
|
||||||
|
test_network_interfaces::test_all().await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
#[serial]
|
||||||
fn run_test_async_peek_stream() {
|
fn run_test_async_peek_stream() {
|
||||||
|
@ -2,7 +2,7 @@ use crate::*;
|
|||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(not(target_arch = "wasm32"))] {
|
if #[cfg(not(target_arch = "wasm32"))] {
|
||||||
use intf::network_interfaces::NetworkInterfaces;
|
use network_interfaces::NetworkInterfaces;
|
||||||
|
|
||||||
pub async fn test_network_interfaces() {
|
pub async fn test_network_interfaces() {
|
||||||
info!("testing network interfaces");
|
info!("testing network interfaces");
|
Loading…
Reference in New Issue
Block a user