rust-igd
rust-igd copied to clipboard
Use agonistic IP parsing & Manual Tokio selection
Should solve #52 and #47?
I tried to test this with the aio example, but it didn't compile for me (OSX Big Sur). Failed at igd.
Is there something I'm doing wrong?
Partial output of : cargo run --features=aio --example aio 10.1.1.35:4321
Compiling tokio v1.0.1
...
Compiling igd v0.12.0 (/Users/darrin/src/t/rust-igd)
error[E0433]: failed to resolve: use of undeclared crate or module `tokio`
--> src/aio/search.rs:6:5
|
6 | use tokio::net::UdpSocket;
| ^^^^^ use of undeclared crate or module `tokio`
Hey thanks for this. Looks like I misconfigured the CI, it was not running for pull requests. Can you push again to trigger it?
Edit: You should probably merge/rebase on master to get the changes to the github workflows
Tokio 0.2 and especially 0.3 are obsolete at this point, there's little sense in providing support for them.
@vorot93 well I used this project in actix and 3.x is still using tokio 0.2 this point...maybe i misconfigured something?
@stevefan1999-personal Hey, this issue is a blocker for me too, as I need support for dual-stack LAN. If needed, I can take over this PR. I can also just make my own if you'd prefer (still based off yours, yours has good work that doesn't need to be duplicated)
@Silvea12 You still interested
@canewsin I jumped over to use rupnp for what I was doing instead, though I am no longer really touching IGD stuff anymore, and it's been long enough I don't remember what changes I planned to make unfortunately.
It generally looks like this crate isn't maintained anymore (last commit 17 months ago) so if I were you I'd either fork it or look elsewhere like I did.
A bit of sample code for IGD stuff in rupnp:
Code
async fn get_igd() -> Result<(Device, Service)> {
trace!("Discovering root node");
let discovered_devices =
rupnp::discover(&SearchTarget::RootDevice, Duration::from_millis(5000))
.await?
.filter_map(|e| e.ok());
pin!(discovered_devices);
let root_device: Device = discovered_devices
.next()
.await
.ok_or_else(|| eyre!("No root device found, maybe UPnP is disabled?"))?;
trace!(url = %root_device.url());
for service in root_device.services_iter() {
trace!(service_type = %service.service_type(), service_id = service.service_id());
}
trace!(device = root_device.friendly_name(), "Discovering services");
let service = root_device
.services_iter()
.find(|service| {
let urn = service.service_type();
urn.domain_name() == "schemas-upnp-org"
&& urn.typ() == "WANIPConnection"
&& urn.version() <= 2
})
.cloned()
.ok_or_else(|| eyre!("IGD not supported on your router."))?;
Ok((root_device, service))
}
Code
pub async fn forward_port(port: u16) -> Result<()> {
let (root_device, service) = get_igd().await?;
let internal_ip = local_ip()?;
// Lease duration is in seconds
// NewRemoteHost being empty string/blank = wildcard
// language=xml
let arguments = format!(
"<NewRemoteHost/>
<NewExternalPort>{port}</NewExternalPort>
<NewProtocol>UDP</NewProtocol>
<NewInternalPort>{port}</NewInternalPort>
<NewInternalClient>{internal_ip}</NewInternalClient>
<NewEnabled>1</NewEnabled>
<NewPortMappingDescription>NAT Punchthrough Experiment</NewPortMappingDescription>
<NewLeaseDuration>60</NewLeaseDuration>"
);
debug!(%internal_ip, port, "Adding port mapping");
service
.action(root_device.url(), "AddPortMapping", &arguments)
.await?;
Ok(())
}
with some help from the local-ip-address crate to help with the mapping.
So overall, not a bad replacement.