/* Hurry Curry! - a game about cooking Copyright 2024 metamuffin This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License only. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ use anyhow::{bail, Result}; use get_if_addrs::get_if_addrs; use igd::{ aio::{search_gateway, Gateway}, PortMappingProtocol, SearchOptions, }; use log::{error, info}; use std::{ net::{IpAddr, Ipv4Addr, SocketAddrV4}, time::Duration, }; use tokio::time::interval; pub async fn upnp_loop(port: u16) { // TODO multiple gateways let (gateway, local_addr) = match upnp_setup().await { Ok(g) => g, Err(e) => { error!("UPnP gateway not found: {e}"); return; } }; let mut interval = interval(Duration::from_secs(120)); loop { interval.tick().await; match gateway .add_port( PortMappingProtocol::TCP, 27032, SocketAddrV4::new(local_addr, port), 800, "Hurry Curry! Game Server", ) .await { Ok(()) => info!("port mapped successfully"), Err(e) => error!("upnp failed: {e}"), } } } async fn upnp_setup() -> Result<(Gateway, Ipv4Addr)> { let gateway = search_gateway(SearchOptions::default()).await?; info!("IGD address is {}", gateway.addr); for i in get_if_addrs()? { let a = i.addr.ip(); if !a.is_loopback() { if let IpAddr::V4(a) = a { info!("local v4 address is {a}"); return Ok((gateway, a)); } } } bail!("no good local address found") }