Use quick_xml in upnp crate instead of serde_xml_rs

This commit is contained in:
Igor Katson 2024-08-28 11:50:27 +01:00
parent 52ca07fe41
commit b22298189c
No known key found for this signature in database
GPG key ID: B4EC22B66D61A3F5
4 changed files with 56 additions and 49 deletions

20
Cargo.lock generated
View file

@ -1616,9 +1616,9 @@ dependencies = [
"futures",
"httparse",
"network-interface",
"quick-xml",
"reqwest",
"serde",
"serde-xml-rs",
"tokio",
"tracing",
"tracing-subscriber",
@ -2649,18 +2649,6 @@ dependencies = [
"serde_derive",
]
[[package]]
name = "serde-xml-rs"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb3aa78ecda1ebc9ec9847d5d3aba7d618823446a049ba2491940506da6e2782"
dependencies = [
"log",
"serde",
"thiserror",
"xml-rs",
]
[[package]]
name = "serde_derive"
version = "1.0.209"
@ -3932,12 +3920,6 @@ dependencies = [
"tap",
]
[[package]]
name = "xml-rs"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "539a77ee7c0de333dcc6da69b177380a0b81e0dacfa4f7344c465a36871ee601"
[[package]]
name = "zerocopy"
version = "0.7.35"

View file

@ -16,13 +16,13 @@ tracing = "0.1"
anyhow = "1"
reqwest = { version = "0.12", default-features = false }
serde = { version = "1", features = ["derive"] }
serde-xml-rs = "0.6.0"
tokio = { version = "1", features = ["macros"] }
futures = "0.3"
url = "2"
network-interface = { version = "2" }
httparse = "1.9.4"
bstr = "1.10.0"
quick-xml = { version = "0.36.1", features = ["serialize"] }
[dev-dependencies]
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }

View file

@ -4,7 +4,6 @@ use futures::{stream::FuturesUnordered, StreamExt, TryFutureExt};
use network_interface::NetworkInterfaceConfig;
use reqwest::Client;
use serde::Deserialize;
use serde_xml_rs::from_str;
use std::{
collections::HashSet,
net::{Ipv4Addr, SocketAddr, SocketAddrV4},
@ -115,19 +114,19 @@ async fn forward_port(
Ok(())
}
#[derive(Clone, Debug, Deserialize)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
struct RootDesc {
#[serde(rename = "device")]
devices: Vec<Device>,
}
#[derive(Default, Clone, Debug, Deserialize)]
#[derive(Default, Clone, Debug, Deserialize, PartialEq, Eq)]
pub struct DeviceList {
#[serde(rename = "device")]
devices: Vec<Device>,
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
pub struct Device {
#[serde(rename = "deviceType")]
pub device_type: String,
@ -169,13 +168,13 @@ impl Device {
}
}
#[derive(Clone, Debug, Deserialize, Default)]
#[derive(Clone, Debug, Deserialize, Default, PartialEq, Eq)]
pub struct ServiceList {
#[serde(rename = "service", default)]
pub services: Vec<Service>,
}
#[derive(Clone, Debug, Deserialize)]
#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
pub struct Service {
#[serde(rename = "serviceType")]
pub service_type: String,
@ -256,7 +255,7 @@ async fn discover_services(location: Url) -> anyhow::Result<RootDesc> {
.await
.context("failed to read response body")?;
trace!("received from {location}: {response}");
let root_desc: RootDesc = from_str(&response)
let root_desc: RootDesc = quick_xml::de::from_str(&response)
.context("failed to parse response body as xml")
.map_err(|e| {
debug!("failed to parse this XML: {response}");
@ -476,12 +475,56 @@ impl UpnpPortForwarder {
#[cfg(test)]
mod tests {
use serde_xml_rs::from_str;
use quick_xml::de::from_str;
use crate::RootDesc;
use crate::{Device, DeviceList, RootDesc, Service, ServiceList};
#[test]
fn test_parse() {
dbg!(from_str::<RootDesc>(include_str!("resources/test/devices-0.xml")).unwrap());
let actual = from_str::<RootDesc>(include_str!("resources/test/devices-0.xml")).unwrap();
let expected = RootDesc {
devices: vec![Device {
device_type: "urn:schemas-upnp-org:device:InternetGatewayDevice:1".into(),
friendly_name: "ARRIS TG3492LG".into(),
service_list: ServiceList {
services: vec![Service {
service_type: "urn:schemas-upnp-org:service:Layer3Forwarding:1".into(),
control_url: "/upnp/control/Layer3Forwarding".into(),
scpd_url: "/Layer3ForwardingSCPD.xml".into(),
}],
},
device_list: DeviceList {
devices: vec![Device {
device_type: "urn:schemas-upnp-org:device:WANDevice:1".into(),
friendly_name: "WANDevice:1".into(),
service_list: ServiceList {
services: vec![Service {
service_type:
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1".into(),
control_url: "/upnp/control/WANCommonInterfaceConfig0".into(),
scpd_url: "/WANCommonInterfaceConfigSCPD.xml".into(),
}],
},
device_list: DeviceList {
devices: vec![Device {
device_type: "urn:schemas-upnp-org:device:WANConnectionDevice:1"
.into(),
friendly_name: "WANConnectionDevice:1".into(),
service_list: ServiceList {
services: vec![Service {
service_type:
"urn:schemas-upnp-org:service:WANIPConnection:1".into(),
control_url: "/upnp/control/WANIPConnection0".into(),
scpd_url: "/WANIPConnectionServiceSCPD.xml".into(),
}],
},
device_list: DeviceList { devices: vec![] },
}],
},
}],
},
}],
};
assert_eq!(actual, expected);
}
}

View file

@ -2012,9 +2012,9 @@ dependencies = [
"futures",
"httparse",
"network-interface",
"quick-xml 0.36.1",
"reqwest",
"serde",
"serde-xml-rs",
"tokio",
"tracing",
"url",
@ -3211,18 +3211,6 @@ dependencies = [
"serde_derive",
]
[[package]]
name = "serde-xml-rs"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb3aa78ecda1ebc9ec9847d5d3aba7d618823446a049ba2491940506da6e2782"
dependencies = [
"log",
"serde",
"thiserror",
"xml-rs",
]
[[package]]
name = "serde_derive"
version = "1.0.209"
@ -5011,12 +4999,6 @@ dependencies = [
"rustix",
]
[[package]]
name = "xml-rs"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "539a77ee7c0de333dcc6da69b177380a0b81e0dacfa4f7344c465a36871ee601"
[[package]]
name = "zerocopy"
version = "0.7.35"