windows upnp work

This commit is contained in:
John Smith
2023-10-13 17:57:38 -04:00
parent ebd36d82ef
commit d922bc1f5d
20 changed files with 138 additions and 111 deletions

View File

@@ -26,7 +26,7 @@ struct PortMapValue {
struct IGDManagerInner {
local_ip_addrs: BTreeMap<AddressType, IpAddr>,
gateways: BTreeMap<AddressType, Arc<Gateway>>,
gateways: BTreeMap<IpAddr, Arc<Gateway>>,
port_maps: BTreeMap<PortMapKey, PortMapValue>,
}
@@ -121,17 +121,21 @@ impl IGDManager {
fn find_gateway(
inner: &mut IGDManagerInner,
address_type: AddressType,
local_ip: IpAddr,
) -> 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());
}
let gateway = match address_type {
AddressType::IPV4 => {
match igd::search_gateway(SearchOptions::new_v4(
let gateway = match local_ip {
IpAddr::V4(v4) => {
let mut opts = SearchOptions::new_v4(
UPNP_GATEWAY_DETECT_TIMEOUT_MS as u64,
)) {
);
opts.bind_addr = SocketAddr::V4(SocketAddrV4::new(v4, 0));
match igd::search_gateway(opts) {
Ok(v) => v,
Err(e) => {
log_net!(debug "couldn't find ipv4 igd: {}", e);
@@ -139,11 +143,14 @@ impl IGDManager {
}
}
}
AddressType::IPV6 => {
match igd::search_gateway(SearchOptions::new_v6(
IpAddr::V6(v6) => {
let mut opts = SearchOptions::new_v6(
Ipv6SearchScope::LinkLocal,
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,
Err(e) => {
log_net!(debug "couldn't find ipv6 igd: {}", e);
@@ -151,17 +158,18 @@ impl IGDManager {
}
}
}
};
let gw = Arc::new(gateway);
inner.gateways.insert(address_type, gw.clone());
inner.gateways.insert(local_ip, gw.clone());
Some(gw)
}
fn get_gateway(
inner: &mut IGDManagerInner,
address_type: AddressType,
local_ip: IpAddr,
) -> 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());
}
None
@@ -191,8 +199,12 @@ impl IGDManager {
let pmk = found?;
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
let gw = Self::find_gateway(&mut inner, at)?;
let gw = Self::find_gateway(&mut inner, local_ip)?;
// Unmap 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)?;
// Find gateway
let gw = Self::find_gateway(&mut inner, at)?;
let gw = Self::find_gateway(&mut inner, local_ip)?;
// Get external address
let ext_ip = match gw.get_external_ip() {
@@ -325,14 +337,6 @@ impl IGDManager {
// Process full renewals
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
let local_ip = match Self::get_local_ip(&mut inner, k.at) {
@@ -341,6 +345,14 @@ impl IGDManager {
return Err(eyre!("local ip missing for address type"));
}
};
// 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
let _ = gw.remove_port(convert_llpt(k.llpt), v.mapped_port);
@@ -370,14 +382,6 @@ impl IGDManager {
// Process normal renewals
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
let local_ip = match Self::get_local_ip(&mut inner, k.at) {
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);
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(()) => {

View File

@@ -10,7 +10,6 @@ use super::*;
use crate::routing_table::*;
use connection_manager::*;
use discovery_context::*;
use network_interfaces::*;
use network_tcp::*;
use protocol::tcp::RawTcpProtocolHandler;
use protocol::udp::RawUdpProtocolHandler;
@@ -316,7 +315,7 @@ impl Network {
if !from.ip().is_unspecified() {
vec![*from]
} else {
let addrs = self.get_usable_interface_addresses();
let addrs = self.get_stable_interface_addresses();
addrs
.iter()
.filter_map(|a| {
@@ -358,13 +357,13 @@ impl Network {
})
}
pub fn is_usable_interface_address(&self, addr: IpAddr) -> bool {
let usable_addrs = self.get_usable_interface_addresses();
usable_addrs.contains(&addr)
pub fn is_stable_interface_address(&self, addr: IpAddr) -> bool {
let stable_addrs = self.get_stable_interface_addresses();
stable_addrs.contains(&addr)
}
pub fn get_usable_interface_addresses(&self) -> Vec<IpAddr> {
let addrs = self.unlocked_inner.interfaces.best_addresses();
pub fn get_stable_interface_addresses(&self) -> Vec<IpAddr> {
let addrs = self.unlocked_inner.interfaces.stable_addresses();
let addrs: Vec<IpAddr> = addrs
.into_iter()
.filter(|addr| {
@@ -377,7 +376,13 @@ impl Network {
// See if our interface addresses have changed, if so redo public dial info if necessary
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);
}
@@ -723,7 +728,7 @@ impl Network {
{
let mut inner = self.inner.lock();
inner.enable_ipv4 = false;
for addr in self.get_usable_interface_addresses() {
for addr in self.get_stable_interface_addresses() {
if addr.is_ipv4() {
log_net!(debug "enable address {:?} as ipv4", addr);
inner.enable_ipv4 = true;

View File

@@ -342,7 +342,7 @@ impl Network {
// See if this public address is also a local interface address we haven't registered yet
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 {
return true;
}
@@ -438,7 +438,7 @@ impl Network {
// See if this public address is also a local interface address
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)?;
}
@@ -552,7 +552,7 @@ impl Network {
// See if this public address is also a local interface address
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)?;
}
@@ -653,7 +653,7 @@ impl Network {
}
// 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)?;
}
}

View File

@@ -425,11 +425,11 @@ impl Network {
trace!("network stopped");
}
pub fn is_usable_interface_address(&self, _addr: IpAddr) -> bool {
pub fn is_stable_interface_address(&self, _addr: IpAddr) -> bool {
false
}
pub fn get_usable_interface_addresses(&self) -> Vec<IpAddr> {
pub fn get_stable_interface_addresses(&self) -> Vec<IpAddr> {
Vec::new()
}