From 032c38be9229cfd35f0f6fc8eac5cccc960480d3 Mon Sep 17 00:00:00 2001 From: Marc-Andre Lureau Date: Wed, 2 Apr 2025 22:59:02 +0400 Subject: [PATCH] feat(tokio): add reqwest feature (#734) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the client ReqwestNetworkClient to ironrdp-tokio, so other clients can optionally use the implementation. Signed-off-by: Marc-André Lureau --- Cargo.lock | 6 +++--- crates/ironrdp-async/src/lib.rs | 1 + crates/ironrdp-client/Cargo.toml | 13 ++++++------ crates/ironrdp-client/src/lib.rs | 1 - crates/ironrdp-client/src/rdp.rs | 3 ++- crates/ironrdp-tokio/Cargo.toml | 11 +++++++++- crates/ironrdp-tokio/src/lib.rs | 3 +++ .../src/reqwest.rs} | 21 +++++++++++++------ 8 files changed, 41 insertions(+), 18 deletions(-) rename crates/{ironrdp-client/src/network_client.rs => ironrdp-tokio/src/reqwest.rs} (89%) diff --git a/Cargo.lock b/Cargo.lock index 23134168..374cc231 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2432,16 +2432,13 @@ dependencies = [ "ironrdp-tokio", "proc-exit", "raw-window-handle", - "reqwest", "semver", "smallvec", "softbuffer", - "sspi", "tap", "tokio", "tracing", "tracing-subscriber", - "url", "uuid", "whoami", "windows 0.58.0", @@ -2783,7 +2780,10 @@ version = "0.3.0" dependencies = [ "bytes", "ironrdp-async", + "reqwest", + "sspi", "tokio", + "url", ] [[package]] diff --git a/crates/ironrdp-async/src/lib.rs b/crates/ironrdp-async/src/lib.rs index e2ed55cd..fb126fb0 100644 --- a/crates/ironrdp-async/src/lib.rs +++ b/crates/ironrdp-async/src/lib.rs @@ -13,6 +13,7 @@ mod session; use core::future::Future; use core::pin::Pin; +pub use ironrdp_connector; use ironrdp_connector::sspi::generator::NetworkRequest; use ironrdp_connector::ConnectorResult; diff --git a/crates/ironrdp-client/Cargo.toml b/crates/ironrdp-client/Cargo.toml index b1fbdc17..0bb015f7 100644 --- a/crates/ironrdp-client/Cargo.toml +++ b/crates/ironrdp-client/Cargo.toml @@ -40,14 +40,17 @@ ironrdp = { path = "../ironrdp", version = "0.9", features = [ "rdpsnd", "cliprdr", "displaycontrol", - "connector" + "connector", +] } +ironrdp-core = { path = "../ironrdp-core", version = "0.1", features = [ + "alloc", ] } -ironrdp-core = { path = "../ironrdp-core", version = "0.1", features = ["alloc"] } ironrdp-cliprdr-native = { path = "../ironrdp-cliprdr-native", version = "0.2" } ironrdp-rdpsnd-native = { path = "../ironrdp-rdpsnd-native", version = "0.2" } ironrdp-tls = { path = "../ironrdp-tls", version = "0.1" } -ironrdp-tokio = { path = "../ironrdp-tokio", version = "0.3" } -sspi = { version = "0.15", features = ["network_client", "dns_resolver"] } # TODO: enable additional features +ironrdp-tokio = { path = "../ironrdp-tokio", version = "0.3", features = [ + "reqwest", +] } # Windowing and rendering winit = { version = "0.30", features = ["rwh_06"] } @@ -71,8 +74,6 @@ anyhow = "1" smallvec = "1.13" tap = "1" semver = "1" -reqwest = "0.12" -url = "2.5" raw-window-handle = "0.6" uuid = { version = "1.16" } diff --git a/crates/ironrdp-client/src/lib.rs b/crates/ironrdp-client/src/lib.rs index ba7c9897..0ae2115a 100644 --- a/crates/ironrdp-client/src/lib.rs +++ b/crates/ironrdp-client/src/lib.rs @@ -15,5 +15,4 @@ extern crate tracing; pub mod app; pub mod clipboard; pub mod config; -pub mod network_client; pub mod rdp; diff --git a/crates/ironrdp-client/src/rdp.rs b/crates/ironrdp-client/src/rdp.rs index fedd012e..5469e2aa 100644 --- a/crates/ironrdp-client/src/rdp.rs +++ b/crates/ironrdp-client/src/rdp.rs @@ -10,6 +10,7 @@ use ironrdp::session::{fast_path, ActiveStage, ActiveStageOutput, GracefulDiscon use ironrdp::{cliprdr, connector, rdpdr, rdpsnd, session}; use ironrdp_core::WriteBuf; use ironrdp_rdpsnd_native::cpal; +use ironrdp_tokio::reqwest::ReqwestNetworkClient; use ironrdp_tokio::{single_sequence_step_read, split_tokio_framed, FramedWrite}; use rdpdr::NoopRdpdrBackend; use smallvec::SmallVec; @@ -146,7 +147,7 @@ async fn connect( let mut upgraded_framed = ironrdp_tokio::TokioFramed::new(upgraded_stream); - let mut network_client = crate::network_client::ReqwestNetworkClient::new(); + let mut network_client = ReqwestNetworkClient::new(); let connection_result = ironrdp_tokio::connect_finalize( upgraded, &mut upgraded_framed, diff --git a/crates/ironrdp-tokio/Cargo.toml b/crates/ironrdp-tokio/Cargo.toml index 3991117a..afbf772a 100644 --- a/crates/ironrdp-tokio/Cargo.toml +++ b/crates/ironrdp-tokio/Cargo.toml @@ -15,11 +15,20 @@ categories.workspace = true doctest = false test = false +[features] +default = ["reqwest"] +reqwest = ["dep:reqwest", "dep:sspi", "dep:url"] + [dependencies] bytes = "1" ironrdp-async = { path = "../ironrdp-async", version = "0.4" } # public tokio = { version = "1", features = ["io-util"] } +reqwest = { version = "0.12", optional = true } +sspi = { version = "0.15", features = [ + "network_client", + "dns_resolver", +], optional = true } # TODO: enable additional features +url = { version = "2.5", optional = true } [lints] workspace = true - diff --git a/crates/ironrdp-tokio/src/lib.rs b/crates/ironrdp-tokio/src/lib.rs index ac55c679..bb52b31e 100644 --- a/crates/ironrdp-tokio/src/lib.rs +++ b/crates/ironrdp-tokio/src/lib.rs @@ -4,6 +4,9 @@ #[rustfmt::skip] // do not re-order this pub use pub use ironrdp_async::*; +#[cfg(feature = "reqwest")] +pub mod reqwest; + use core::pin::Pin; use std::io; diff --git a/crates/ironrdp-client/src/network_client.rs b/crates/ironrdp-tokio/src/reqwest.rs similarity index 89% rename from crates/ironrdp-client/src/network_client.rs rename to crates/ironrdp-tokio/src/reqwest.rs index be0815fa..5d2f2b74 100644 --- a/crates/ironrdp-client/src/network_client.rs +++ b/crates/ironrdp-tokio/src/reqwest.rs @@ -2,15 +2,16 @@ use core::future::Future; use core::pin::Pin; use std::net::{IpAddr, Ipv4Addr}; -use ironrdp::connector::{custom_err, ConnectorResult}; -use ironrdp_tokio::AsyncNetworkClient; +use ironrdp_async::ironrdp_connector::{custom_err, ConnectorResult}; use reqwest::Client; use sspi::{Error, ErrorKind}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::{TcpStream, UdpSocket}; use url::Url; -pub(crate) struct ReqwestNetworkClient { +use crate::AsyncNetworkClient; + +pub struct ReqwestNetworkClient { client: Option, } @@ -32,11 +33,17 @@ impl AsyncNetworkClient for ReqwestNetworkClient { } impl ReqwestNetworkClient { - pub(crate) fn new() -> Self { + pub fn new() -> Self { Self { client: None } } } +impl Default for ReqwestNetworkClient { + fn default() -> Self { + Self::new() + } +} + impl ReqwestNetworkClient { async fn send_tcp(&self, url: &Url, data: &[u8]) -> ConnectorResult> { let addr = format!("{}:{}", url.host_str().unwrap_or_default(), url.port().unwrap_or(88)); @@ -89,10 +96,12 @@ impl ReqwestNetworkClient { .recv(&mut buf) .await .map_err(|e| custom_err!("failed to receive UDP request", e))?; + let buf = &buf[0..n]; let mut reply_buf = Vec::with_capacity(n + 4); - reply_buf.extend_from_slice(&(n as u32).to_be_bytes()); - reply_buf.extend_from_slice(&buf[0..n]); + let n = u32::try_from(n).map_err(|e| custom_err!("invalid length", e))?; + reply_buf.extend_from_slice(&n.to_be_bytes()); + reply_buf.extend_from_slice(buf); Ok(reply_buf) }