diff options
Diffstat (limited to 'src/igd_actor.rs')
-rw-r--r-- | src/igd_actor.rs | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/src/igd_actor.rs b/src/igd_actor.rs index bb9099e..d32f5dc 100644 --- a/src/igd_actor.rs +++ b/src/igd_actor.rs @@ -22,7 +22,7 @@ pub struct IgdActor { impl IgdActor { pub async fn new( - priv_ip: &str, + priv_ip: Option<&str>, refresh: Duration, expire: Duration, rxp: &watch::Receiver<messages::PublicExposedPorts>, @@ -32,16 +32,44 @@ impl IgdActor { .context("Failed to find IGD gateway")?; info!("IGD gateway: {}", gw); + let private_ip = if let Some(ip) = priv_ip { + info!("Using private IP from config: {}", ip); + ip.to_string() + } else { + info!("Trying to automatically detect private IP"); + let gwa = gw.addr.ip().octets(); + let cmplen = match gwa { + [192, 168, _, _] => 3, + [10, _, _, _] => 2, + _ => panic!( + "Gateway IP does not appear to be in a local network ({})", + gw.addr.ip() + ), + }; + let public_ip = get_if_addrs::get_if_addrs()? + .into_iter() + .map(|i| i.addr.ip()) + .filter(|a| match a { + std::net::IpAddr::V4(a4) => (a4.octets()[..cmplen] == gwa[..cmplen]), + _ => false, + }) + .next() + .expect("No interface has an IP on same subnet as gateway") + .to_string(); + info!("Found private IP: {}", public_ip); + public_ip + }; + let ctx = Self { gateway: gw, rx_ports: rxp.clone(), - private_ip: priv_ip.to_string(), + private_ip, refresh: refresh, expire: expire, last_ports: messages::PublicExposedPorts::new(), }; - return Ok(ctx) + return Ok(ctx); } pub async fn listen(&mut self) -> Result<()> { @@ -49,7 +77,7 @@ impl IgdActor { loop { // 1. Wait for an event let new_ports = select! { - Some(ports) = self.rx_ports.recv() => Some(ports), + _ = self.rx_ports.changed() => Some(self.rx_ports.borrow().clone()), _ = interval.tick() => None, else => return Ok(()) // Sender dropped, terminate loop. }; @@ -93,6 +121,6 @@ impl IgdActor { } } - return Ok(()) + return Ok(()); } } |