From 542fd92a460566f4f74554e0263d45039a87000f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 9 Jun 2023 09:54:21 +0200 Subject: [PATCH] Allow query network-requestor for open_proxy (#3531) * wip: playing around * WIP * wip * Add query request * Create new example * Restore control_requests example * Remove ControlRequest::OpenProxy * Remove Socks5RequestContent::OpenProxy * Remove bunch of debug logging * Remove more old leftovers * Another few lines of leftovers to remove * Disable logging in example * Return error if incoming request if future version * Serialization unit tests * Network requester in example * Cargo.lock --- Cargo.lock | 14 +++ .../src/socks/mixnet_responses.rs | 8 ++ common/socks5/requests/Cargo.toml | 10 +- common/socks5/requests/src/lib.rs | 12 +++ common/socks5/requests/src/request.rs | 97 +++++++++++++++++-- common/socks5/requests/src/response.rs | 97 ++++++++++++++++--- nym-connect/desktop/Cargo.lock | 12 +++ service-providers/common/Cargo.toml | 2 +- .../common/examples/control_requests.rs | 2 +- .../common/src/interface/control.rs | 2 +- .../common/src/interface/response.rs | 1 + .../network-requester/Cargo.toml | 1 + .../network-requester/examples/query.rs | 73 ++++++++++++++ .../network-requester/src/core.rs | 26 ++++- 14 files changed, 324 insertions(+), 33 deletions(-) create mode 100644 service-providers/network-requester/examples/query.rs diff --git a/Cargo.lock b/Cargo.lock index a5de81f633..47aa3895a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -378,6 +378,15 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bip32" version = "0.3.0" @@ -3922,6 +3931,7 @@ dependencies = [ name = "nym-network-requester" version = "1.1.20" dependencies = [ + "anyhow", "async-file-watcher", "async-trait", "bs58", @@ -4098,6 +4108,7 @@ dependencies = [ "log", "nym-bin-common", "nym-sdk", + "nym-socks5-requests", "nym-sphinx-anonymous-replies", "serde", "serde_json", @@ -4202,10 +4213,13 @@ dependencies = [ name = "nym-socks5-requests" version = "0.1.0" dependencies = [ + "bincode", + "log", "nym-service-providers-common", "nym-sphinx-addressing", "serde", "serde_json", + "tap", "thiserror", ] diff --git a/common/socks5-client-core/src/socks/mixnet_responses.rs b/common/socks5-client-core/src/socks/mixnet_responses.rs index 52086d5aaa..d8ef425ddb 100644 --- a/common/socks5-client-core/src/socks/mixnet_responses.rs +++ b/common/socks5-client-core/src/socks/mixnet_responses.rs @@ -85,6 +85,14 @@ impl MixnetResponseListener { .unwrap(); Ok(()) } + Socks5ResponseContent::Query(response) => { + error!("received a query response which we don't know how to handle yet!"); + error!("got: {:?}", response); + + // I guess we'd need another channel here to forward those to where they need to go + + Ok(()) + } } } diff --git a/common/socks5/requests/Cargo.toml b/common/socks5/requests/Cargo.toml index d100503c6a..acb08b31a6 100644 --- a/common/socks5/requests/Cargo.toml +++ b/common/socks5/requests/Cargo.toml @@ -7,9 +7,11 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -thiserror = { workspace = true } +bincode = "1.3.3" +log = { workspace = true } +nym-service-providers-common = { path = "../../../service-providers/common" } +nym-sphinx-addressing = { path = "../../../common/nymsphinx/addressing" } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } - -nym-sphinx-addressing = { path = "../../../common/nymsphinx/addressing" } -nym-service-providers-common = { path = "../../../service-providers/common" } +tap = { workspace = true } +thiserror = { workspace = true } diff --git a/common/socks5/requests/src/lib.rs b/common/socks5/requests/src/lib.rs index ba81b231a4..d6cff2a5e3 100644 --- a/common/socks5/requests/src/lib.rs +++ b/common/socks5/requests/src/lib.rs @@ -32,6 +32,18 @@ pub enum Socks5RequestError { #[error(transparent)] ProviderInterfaceError(#[from] ServiceProviderMessagingError), + + #[error("received unsupported request protocol version: {protocol_version}")] + UnsupportedProtocolVersion { + protocol_version: ::ProtocolVersion, + }, +} + +fn make_bincode_serializer() -> impl bincode::Options { + use bincode::Options; + bincode::DefaultOptions::new() + .with_big_endian() + .with_varint_encoding() } #[cfg(test)] diff --git a/common/socks5/requests/src/request.rs b/common/socks5/requests/src/request.rs index f296407c0b..78e07e4f02 100644 --- a/common/socks5/requests/src/request.rs +++ b/common/socks5/requests/src/request.rs @@ -1,10 +1,12 @@ // Copyright 2020-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::{Socks5ProtocolVersion, Socks5RequestError, Socks5Response}; +use crate::{make_bincode_serializer, Socks5ProtocolVersion, Socks5RequestError, Socks5Response}; use nym_service_providers_common::interface::{Serializable, ServiceProviderRequest}; use nym_sphinx_addressing::clients::{Recipient, RecipientFormattingError}; +use serde::{Deserialize, Serialize}; use std::convert::TryFrom; +use tap::TapFallible; use thiserror::Error; pub type ConnectionId = u64; @@ -15,6 +17,7 @@ pub type RemoteAddress = String; pub enum RequestFlag { Connect = 0, Send = 1, + Query = 2, } impl TryFrom for RequestFlag { @@ -24,6 +27,7 @@ impl TryFrom for RequestFlag { match value { _ if value == (RequestFlag::Connect as u8) => Ok(Self::Connect), _ if value == (RequestFlag::Send as u8) => Ok(Self::Send), + _ if value == (RequestFlag::Query as u8) => Ok(Self::Query), value => Err(RequestDeserializationError::UnknownRequestFlag { value }), } } @@ -51,6 +55,12 @@ pub enum RequestDeserializationError { #[error("malformed return address - {0}")] MalformedReturnAddress(RecipientFormattingError), + + #[error("failed to deserialize query request: {source}")] + QueryDeserializationError { + #[from] + source: bincode::Error, + }, } impl RequestDeserializationError { @@ -59,7 +69,7 @@ impl RequestDeserializationError { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct ConnectRequest { // TODO: is connection_id redundant now? pub conn_id: ConnectionId, @@ -67,13 +77,19 @@ pub struct ConnectRequest { pub return_address: Option, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct SendRequest { pub conn_id: ConnectionId, pub data: Vec, pub local_closed: bool, } +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub enum QueryRequest { + OpenProxy, + Description, +} + #[derive(Debug, Clone)] pub struct Socks5Request { pub protocol_version: Socks5ProtocolVersion, @@ -108,6 +124,13 @@ impl Serializable for Socks5Request { } let protocol_version = Socks5ProtocolVersion::from(b[0]); + if protocol_version > Self::max_supported_version() { + return Err(Socks5RequestError::UnsupportedProtocolVersion { protocol_version }); + } + + // TODO: handle the case then protocol version if less then the current one. Then we should + // make sure to only respond with the same version + Ok(Socks5Request { protocol_version, content: Socks5RequestContent::try_from_bytes(&b[1..])?, @@ -166,11 +189,21 @@ impl Socks5Request { content: Socks5RequestContent::new_send(conn_id, data, local_closed), } } + + pub fn new_query( + protocol_version: Socks5ProtocolVersion, + query: QueryRequest, + ) -> Socks5Request { + Socks5Request { + protocol_version, + content: Socks5RequestContent::Query(query), + } + } } /// A request from a SOCKS5 client that a Nym Socks5 service provider should /// take an action for an application using a (probably local) Nym Socks5 proxy. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum Socks5RequestContent { /// Start a new TCP connection to the specified `RemoteAddress` and send /// the request data up the connection. @@ -179,6 +212,8 @@ pub enum Socks5RequestContent { /// Re-use an existing TCP connection, sending more request data up it. Send(SendRequest), + + Query(QueryRequest), } impl Socks5RequestContent { @@ -228,12 +263,13 @@ impl Socks5RequestContent { return Err(RequestDeserializationError::NoData); } - if b.len() < 9 { - return Err(RequestDeserializationError::ConnectionIdTooShort); - } - let conn_id = u64::from_be_bytes([b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8]]); match RequestFlag::try_from(b[0])? { RequestFlag::Connect => { + if b.len() < 9 { + return Err(RequestDeserializationError::ConnectionIdTooShort); + } + let conn_id = u64::from_be_bytes([b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8]]); + let connect_request_bytes = &b[9..]; // we need to be able to read at least 2 bytes that specify address length @@ -279,6 +315,11 @@ impl Socks5RequestContent { )) } RequestFlag::Send => { + if b.len() < 9 { + return Err(RequestDeserializationError::ConnectionIdTooShort); + } + let conn_id = u64::from_be_bytes([b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8]]); + let local_closed = b[9] != 0; let data = b[10..].to_vec(); @@ -288,6 +329,11 @@ impl Socks5RequestContent { local_closed, })) } + RequestFlag::Query => { + use bincode::Options; + let query = make_bincode_serializer().deserialize(&b[1..])?; + Ok(Socks5RequestContent::Query(query)) + } } } @@ -317,6 +363,19 @@ impl Socks5RequestContent { .chain(std::iter::once(req.local_closed as u8)) .chain(req.data.into_iter()) .collect(), + + Socks5RequestContent::Query(query) => { + use bincode::Options; + let query_bytes: Vec = make_bincode_serializer() + .serialize(&query) + .tap_err(|err| { + log::error!("Failed to serialize query request: {:?}: {err}", query); + }) + .unwrap_or_default(); + std::iter::once(RequestFlag::Query as u8) + .chain(query_bytes.into_iter()) + .collect() + } } } } @@ -611,4 +670,26 @@ mod request_deserialization_tests { } } } + + #[cfg(test)] + mod serialize_query_request { + use super::*; + + #[test] + fn serialize_there_and_back() { + let open_proxy = Socks5RequestContent::Query(QueryRequest::OpenProxy); + let bytes_open_proxy = open_proxy.clone().into_bytes(); + assert_eq!(bytes_open_proxy, vec![2, 0]); + + let description = Socks5RequestContent::Query(QueryRequest::Description); + let bytes_description = description.clone().into_bytes(); + assert_eq!(bytes_description, vec![2, 1]); + + let open_proxy2 = Socks5RequestContent::try_from_bytes(&bytes_open_proxy).unwrap(); + let description2 = Socks5RequestContent::try_from_bytes(&bytes_description).unwrap(); + + assert_eq!(open_proxy, open_proxy2); + assert_eq!(description, description2); + } + } } diff --git a/common/socks5/requests/src/response.rs b/common/socks5/requests/src/response.rs index 6e698a2b37..d0a34e074b 100644 --- a/common/socks5/requests/src/response.rs +++ b/common/socks5/requests/src/response.rs @@ -1,8 +1,10 @@ // Copyright 2020-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::{ConnectionId, Socks5ProtocolVersion, Socks5RequestError}; +use crate::{make_bincode_serializer, ConnectionId, Socks5ProtocolVersion, Socks5RequestError}; use nym_service_providers_common::interface::{Serializable, ServiceProviderResponse}; +use serde::{Deserialize, Serialize}; +use tap::TapFallible; use thiserror::Error; // don't start tags from 0 for easier backwards compatibility since `NetworkData` @@ -13,6 +15,7 @@ use thiserror::Error; pub enum ResponseFlag { NetworkData = 1, ConnectionError = 2, + Query = 3, } impl TryFrom for ResponseFlag { @@ -22,12 +25,13 @@ impl TryFrom for ResponseFlag { match value { _ if value == (ResponseFlag::NetworkData as u8) => Ok(Self::NetworkData), _ if value == (ResponseFlag::ConnectionError as u8) => Ok(Self::ConnectionError), + _ if value == (ResponseFlag::Query as u8) => Ok(Self::Query), value => Err(ResponseDeserializationError::UnknownResponseFlag { value }), } } } -#[derive(Debug, Error, PartialEq, Eq)] +#[derive(Debug, Error)] pub enum ResponseDeserializationError { #[error("not enough bytes to recover the connection id")] ConnectionIdTooShort, @@ -43,6 +47,12 @@ pub enum ResponseDeserializationError { #[from] source: std::string::FromUtf8Error, }, + + #[error("failed to deserialize query response: {source}")] + QueryDeserializationError { + #[from] + source: bincode::Error, + }, } #[derive(Debug)] @@ -135,12 +145,23 @@ impl Socks5Response { content: Socks5ResponseContent::new_connection_error(connection_id, error_message), } } + + pub fn new_query( + protocol_version: Socks5ProtocolVersion, + query_response: QueryResponse, + ) -> Socks5Response { + Socks5Response { + protocol_version, + content: Socks5ResponseContent::Query(query_response), + } + } } -#[derive(Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum Socks5ResponseContent { NetworkData(NetworkData), ConnectionError(ConnectionError), + Query(QueryResponse), } impl Socks5ResponseContent { @@ -175,6 +196,18 @@ impl Socks5ResponseContent { .chain(res.into_bytes().into_iter()) .collect() } + Socks5ResponseContent::Query(query) => { + use bincode::Options; + let query_bytes: Vec = make_bincode_serializer() + .serialize(&query) + .tap_err(|err| { + log::error!("Failed to serialize query response: {:?}: {err}", query); + }) + .unwrap_or_default(); + std::iter::once(ResponseFlag::Query as u8) + .chain(query_bytes.into_iter()) + .collect() + } } } @@ -193,6 +226,11 @@ impl Socks5ResponseContent { ResponseFlag::ConnectionError => Ok(Socks5ResponseContent::ConnectionError( ConnectionError::try_from_bytes(&b[1..])?, )), + ResponseFlag::Query => { + use bincode::Options; + let query = make_bincode_serializer().deserialize(&b[1..])?; + Ok(Socks5ResponseContent::Query(query)) + } } } } @@ -200,7 +238,7 @@ impl Socks5ResponseContent { /// A remote network network data response retrieved by the Socks5 service provider. This /// can be serialized and sent back through the mixnet to the requesting /// application. -#[derive(Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct NetworkData { pub data: Vec, pub connection_id: ConnectionId, @@ -264,7 +302,7 @@ impl NetworkData { } } -#[derive(Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct ConnectionError { pub connection_id: ConnectionId, pub network_requester_error: String, @@ -318,6 +356,12 @@ impl ConnectionError { } } +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +pub enum QueryResponse { + OpenProxy(bool), + Description(String), +} + #[cfg(test)] mod tests { use super::*; @@ -330,19 +374,18 @@ mod tests { fn fails_when_zero_bytes_are_supplied() { let response_bytes = Vec::new(); - assert_eq!( - ResponseDeserializationError::NoData, - NetworkData::try_from_bytes(&response_bytes).unwrap_err() - ); + let err = NetworkData::try_from_bytes(&response_bytes).unwrap_err(); + assert!(matches!(err, ResponseDeserializationError::NoData)); } #[test] fn fails_when_connection_id_bytes_are_too_short() { let response_bytes = vec![0, 1, 2, 3, 4, 5, 6]; - assert_eq!( + let err = NetworkData::try_from_bytes(&response_bytes).unwrap_err(); + assert!(matches!( + err, ResponseDeserializationError::ConnectionIdTooShort, - NetworkData::try_from_bytes(&response_bytes).unwrap_err() - ); + )); } #[test] @@ -396,11 +439,14 @@ mod tests { #[test] fn deserialization_errors() { let err = ConnectionError::try_from_bytes(&[]).err().unwrap(); - assert_eq!(err, ResponseDeserializationError::NoData); + assert!(matches!(err, ResponseDeserializationError::NoData)); let bytes: [u8; 5] = [1, 2, 3, 4, 5]; let err = ConnectionError::try_from_bytes(&bytes).err().unwrap(); - assert_eq!(err, ResponseDeserializationError::ConnectionIdTooShort); + assert!(matches!( + err, + ResponseDeserializationError::ConnectionIdTooShort + )); let bytes: Vec = 42u64 .to_be_bytes() @@ -414,4 +460,27 @@ mod tests { )); } } + + #[cfg(test)] + mod serialize_query_response { + use super::*; + + #[test] + fn serialize_there_and_back() { + let open_proxy = Socks5ResponseContent::Query(QueryResponse::OpenProxy(true)); + let bytes_open_proxy = open_proxy.clone().into_bytes(); + assert_eq!(bytes_open_proxy, vec![3, 0, 1]); + + let description = + Socks5ResponseContent::Query(QueryResponse::Description("foo".to_string())); + let bytes_description = description.clone().into_bytes(); + assert_eq!(bytes_description, vec![3, 1, 3, 102, 111, 111]); + + let open_proxy2 = Socks5ResponseContent::try_from_bytes(&bytes_open_proxy).unwrap(); + let description2 = Socks5ResponseContent::try_from_bytes(&bytes_description).unwrap(); + + assert_eq!(open_proxy, open_proxy2); + assert_eq!(description, description2); + } + } } diff --git a/nym-connect/desktop/Cargo.lock b/nym-connect/desktop/Cargo.lock index 4021204663..4471a1425e 100644 --- a/nym-connect/desktop/Cargo.lock +++ b/nym-connect/desktop/Cargo.lock @@ -217,6 +217,15 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bip32" version = "0.3.0" @@ -3662,10 +3671,13 @@ dependencies = [ name = "nym-socks5-requests" version = "0.1.0" dependencies = [ + "bincode", + "log", "nym-service-providers-common", "nym-sphinx-addressing", "serde", "serde_json", + "tap", "thiserror", ] diff --git a/service-providers/common/Cargo.toml b/service-providers/common/Cargo.toml index 887526563a..75fac57536 100644 --- a/service-providers/common/Cargo.toml +++ b/service-providers/common/Cargo.toml @@ -21,5 +21,5 @@ anyhow = "1.0.68" tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } nym-sdk = { path = "../../sdk/rust/nym-sdk" } - +nym-socks5-requests = { path = "../../common/socks5/requests" } diff --git a/service-providers/common/examples/control_requests.rs b/service-providers/common/examples/control_requests.rs index 37f472d9f0..eaff26b375 100644 --- a/service-providers/common/examples/control_requests.rs +++ b/service-providers/common/examples/control_requests.rs @@ -1,7 +1,7 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -// use nym_client::client::config::{BaseConfig, Config, GatewayEndpointConfig}; +// use nym_client::client::config::{BaseClientConfig, Config, GatewayEndpointConfig}; // use nym_client::client::{DirectClient, KeyManager, Recipient, ReconstructedMessage, SocketClient}; use nym_sdk::mixnet::{IncludedSurbs, MixnetClient, Recipient, ReconstructedMessage}; use nym_service_providers_common::interface::{ diff --git a/service-providers/common/src/interface/control.rs b/service-providers/common/src/interface/control.rs index 3d7f151f1c..3c172fce80 100644 --- a/service-providers/common/src/interface/control.rs +++ b/service-providers/common/src/interface/control.rs @@ -195,10 +195,10 @@ impl ControlResponse { // (unless the serde's macro is bugged but at this point we're already out of luck) serde_json::to_vec(&info).unwrap() } - ControlResponse::Error(error_response) => serde_json::to_vec(&error_response).unwrap(), ControlResponse::SupportedRequestVersions(supported_versions) => { serde_json::to_vec(&supported_versions).unwrap() } + ControlResponse::Error(error_response) => serde_json::to_vec(&error_response).unwrap(), } } } diff --git a/service-providers/common/src/interface/response.rs b/service-providers/common/src/interface/response.rs index 3114e1d66e..5aff60c5ad 100644 --- a/service-providers/common/src/interface/response.rs +++ b/service-providers/common/src/interface/response.rs @@ -22,6 +22,7 @@ pub enum ResponseContent { ProviderData(T::Response), } +#[derive(Debug)] #[repr(u8)] pub enum ResponseTag { /// Value tag representing [`Control`] variant of the [`Response`] diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index ff19187f9d..0333d90523 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -54,3 +54,4 @@ nym-client-websocket-requests = { path = "../../clients/native/websocket-request [dev-dependencies] tempfile = "3.5.0" +anyhow = "1.0.68" diff --git a/service-providers/network-requester/examples/query.rs b/service-providers/network-requester/examples/query.rs new file mode 100644 index 0000000000..42be5de55b --- /dev/null +++ b/service-providers/network-requester/examples/query.rs @@ -0,0 +1,73 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use nym_sdk::mixnet::{IncludedSurbs, MixnetClient, Recipient, ReconstructedMessage}; +use nym_service_providers_common::interface::{ + ProviderInterfaceVersion, Request, Response, ResponseContent, +}; +use nym_socks5_requests::{QueryRequest, Socks5Request, Socks5Response}; + +fn parse_response(received: Vec) -> Socks5Response { + assert_eq!(received.len(), 1); + let response: Response = Response::try_from_bytes(&received[0].message).unwrap(); + match response.content { + ResponseContent::Control(control) => panic!("unexpected control response: {:?}", control), + ResponseContent::ProviderData(data) => data, + } +} + +async fn wait_for_response(client: &mut MixnetClient) -> Socks5Response { + loop { + let next = client.wait_for_messages().await.unwrap(); + if !next.is_empty() { + return parse_response(next); + } + } +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + //nym_bin_common::logging::setup_logging(); + let mut client = MixnetClient::connect_new().await.unwrap(); + let provider: Recipient = "AN8eLxYWFitCkMn92zim3PrPszxJZDYyFFKP7qnnAAew.8UAxL3LwQBis6WpM3GGXaqKGaVdnLCpGJWumHT6KNdTH@77TSuVU8d1oXKbPzjec2xh4i3Wj5WwUyy9Lr36sm8gZm".parse().unwrap(); + + use nym_socks5_requests::Socks5ProtocolVersion; + + let open_proxy_request = Request::new_provider_data( + ProviderInterfaceVersion::new_current(), + Socks5Request::new_query( + Socks5ProtocolVersion::new_current(), + QueryRequest::OpenProxy, + ), + ); + let description_request = Request::new_provider_data( + ProviderInterfaceVersion::new_current(), + Socks5Request::new_query( + Socks5ProtocolVersion::new_current(), + QueryRequest::Description, + ), + ); + println!("Sending 'OpenProxy' query..."); + client + .send_bytes( + provider, + open_proxy_request.into_bytes(), + IncludedSurbs::new(10), //crashes?? + ) + .await; + let response = wait_for_response(&mut client).await; + println!("response to 'OpenProxy' query: {response:#?}"); + + println!("Sending 'Description' query..."); + client + .send_bytes( + provider, + description_request.into_bytes(), + IncludedSurbs::none(), + ) + .await; + let response = wait_for_response(&mut client).await; + println!("response to 'Description' query: {response:#?}"); + + Ok(()) +} diff --git a/service-providers/network-requester/src/core.rs b/service-providers/network-requester/src/core.rs index c4d4ac8efd..d948c79c6d 100644 --- a/service-providers/network-requester/src/core.rs +++ b/service-providers/network-requester/src/core.rs @@ -24,8 +24,9 @@ use nym_socks5_proxy_helpers::connection_controller::{ }; use nym_socks5_proxy_helpers::proxy_runner::{MixProxyReader, MixProxySender}; use nym_socks5_requests::{ - ConnectRequest, ConnectionId, NetworkData, SendRequest, Socks5ProtocolVersion, - Socks5ProviderRequest, Socks5Request, Socks5RequestContent, Socks5Response, + ConnectRequest, ConnectionId, NetworkData, QueryRequest, QueryResponse, SendRequest, + Socks5ProtocolVersion, Socks5ProviderRequest, Socks5Request, Socks5RequestContent, + Socks5Response, }; use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag; @@ -66,7 +67,6 @@ struct NRServiceProvider { controller_sender: ControllerSender, mix_input_sender: MixProxySender, - //shared_lane_queue_lengths: LaneQueueLengths, stats_collector: Option, shutdown: TaskManager, } @@ -148,6 +148,7 @@ impl ServiceProvider for NRServiceProvider { } self.handle_proxy_send(req) } + Socks5RequestContent::Query(query) => return self.handle_query(query), } Ok(None) @@ -251,7 +252,6 @@ impl NRServiceProviderBuilder { mixnet_client, controller_sender, mix_input_sender, - //shared_lane_queue_lengths: mixnet_client.shared_lane_queue_lengths(), stats_collector, shutdown, }; @@ -473,6 +473,24 @@ impl NRServiceProvider { fn handle_proxy_send(&mut self, req: SendRequest) { self.controller_sender.unbounded_send(req.into()).unwrap() } + + fn handle_query( + &self, + query: QueryRequest, + ) -> Result, NetworkRequesterError> { + let protocol_version = Socks5ProtocolVersion::default(); + let response = match query { + QueryRequest::OpenProxy => Socks5Response::new_query( + protocol_version, + QueryResponse::OpenProxy(self.open_proxy), + ), + QueryRequest::Description => Socks5Response::new_query( + protocol_version, + QueryResponse::Description("Description (placeholder)".to_string()), + ), + }; + Ok(Some(response)) + } } // Helper function to create the mixnet client.