Skip to content
This repository has been archived by the owner on Dec 8, 2023. It is now read-only.

Commit

Permalink
Merge pull request #49 from FloGa/feature/use-control-schema-for-mess…
Browse files Browse the repository at this point in the history
…ages

Use control schema for messages
  • Loading branch information
sbstp committed May 10, 2020
2 parents 7557bfb + 63417d9 commit b96f590
Show file tree
Hide file tree
Showing 9 changed files with 475 additions and 342 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Expand Up @@ -19,9 +19,9 @@ xmltree = "0.10"
rand = "0.7"
attohttpc = { version = "0.10", default-features = false }
url = "2"
log = "0.4"
futures = { version = "0.3", optional = true }
tokio = { version = "0.2", optional = true , features = [ "udp", "macros" ]}
log = { version = "0.4", optional = true }
bytes = { version = "0.5", optional = true }
http = {version = "0.2", optional = true }

Expand All @@ -36,7 +36,7 @@ simplelog = "0.7"

[features]
default = []
aio = ["futures", "tokio", "hyper", "bytes", "log", "http"]
aio = ["futures", "tokio", "hyper", "bytes", "http"]

[[example]]
name = "add_any_port"
Expand Down
81 changes: 45 additions & 36 deletions src/aio/gateway.rs
@@ -1,3 +1,4 @@
use std::collections::HashMap;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::net::{Ipv4Addr, SocketAddrV4};
Expand All @@ -13,19 +14,17 @@ use crate::PortMappingProtocol;
pub struct Gateway {
/// Socket address of the gateway
pub addr: SocketAddrV4,
/// Root url of the device
pub root_url: String,
/// Control url of the device
pub control_url: String,
/// Url to get schema data from
pub control_schema_url: String,
/// Control schema for all actions
pub control_schema: HashMap<String, Vec<String>>,
}

impl Gateway {
/// Create a new Gateway
pub fn new(addr: SocketAddrV4, control_url: String) -> Gateway {
Gateway {
addr: addr,
control_url: control_url,
}
}

async fn perform_request(&self, header: &str, body: &str, ok: &str) -> Result<RequestReponse, RequestError> {
let url = format!("{}", self);
let text = soap::send_async(&url, soap::Action::new(header), body).await?;
Expand Down Expand Up @@ -93,35 +92,34 @@ impl Gateway {
return Err(AddAnyPortError::InternalPortZeroInvalid);
}

let external_port = common::random_port();
let schema = self.control_schema.get("AddAnyPortMapping");
if let Some(schema) = schema {
let external_port = common::random_port();

let gateway = self.clone();
let description = description.to_owned();
let description = description.to_owned();

// First, attempt to call the AddAnyPortMapping method.
let resp = self
.perform_request(
messages::ADD_ANY_PORT_MAPPING_HEADER,
&messages::format_add_any_port_mapping_message(
protocol,
external_port,
local_addr,
lease_duration,
&description,
),
"AddAnyPortMappingResponse",
)
.await;
match parsing::parse_add_any_port_mapping_response(resp) {
Ok(port) => Ok(port),
Err(None) => {
// The router does not have the AddAnyPortMapping method.
// Fall back to using AddPortMapping with a random port.
gateway
.retry_add_random_port_mapping(protocol, local_addr, lease_duration, &description)
.await
}
Err(Some(err)) => Err(err),
let resp = self
.perform_request(
messages::ADD_ANY_PORT_MAPPING_HEADER,
&messages::format_add_any_port_mapping_message(
schema,
protocol,
external_port,
local_addr,
lease_duration,
&description,
),
"AddAnyPortMappingResponse",
)
.await;
parsing::parse_add_any_port_mapping_response(resp)
} else {
// The router does not have the AddAnyPortMapping method.
// Fall back to using AddPortMapping with a random port.
let gateway = self.clone();
gateway
.retry_add_random_port_mapping(protocol, local_addr, lease_duration, &description)
.await
}
}

Expand Down Expand Up @@ -200,6 +198,9 @@ impl Gateway {
self.perform_request(
messages::ADD_PORT_MAPPING_HEADER,
&messages::format_add_port_mapping_message(
self.control_schema
.get("AddPortMapping")
.ok_or(RequestError::UnsupportedAction("AddPortMapping".to_string()))?,
protocol,
external_port,
local_addr,
Expand Down Expand Up @@ -245,7 +246,15 @@ impl Gateway {
let res = self
.perform_request(
messages::DELETE_PORT_MAPPING_HEADER,
&messages::format_delete_port_message(protocol, external_port),
&messages::format_delete_port_message(
self.control_schema
.get("DeletePortMapping")
.ok_or(RemovePortError::RequestError(RequestError::UnsupportedAction(
"DeletePortMapping".to_string(),
)))?,
protocol,
external_port,
),
"DeletePortMappingResponse",
)
.await;
Expand Down

0 comments on commit b96f590

Please sign in to comment.