Merge remote-tracking branch 'origin/release/v1.1.21' into develop
This commit is contained in:
Generated
+14
@@ -389,6 +389,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"
|
||||
@@ -4049,6 +4058,7 @@ dependencies = [
|
||||
name = "nym-network-requester"
|
||||
version = "1.1.20"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-file-watcher",
|
||||
"async-trait",
|
||||
"bs58",
|
||||
@@ -4225,6 +4235,7 @@ dependencies = [
|
||||
"log",
|
||||
"nym-bin-common",
|
||||
"nym-sdk",
|
||||
"nym-socks5-requests",
|
||||
"nym-sphinx-anonymous-replies",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -4330,10 +4341,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",
|
||||
]
|
||||
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -32,6 +32,18 @@ pub enum Socks5RequestError {
|
||||
|
||||
#[error(transparent)]
|
||||
ProviderInterfaceError(#[from] ServiceProviderMessagingError),
|
||||
|
||||
#[error("received unsupported request protocol version: {protocol_version}")]
|
||||
UnsupportedProtocolVersion {
|
||||
protocol_version: <Socks5Request as interface::ServiceProviderRequest>::ProtocolVersion,
|
||||
},
|
||||
}
|
||||
|
||||
fn make_bincode_serializer() -> impl bincode::Options {
|
||||
use bincode::Options;
|
||||
bincode::DefaultOptions::new()
|
||||
.with_big_endian()
|
||||
.with_varint_encoding()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// 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<u8> for RequestFlag {
|
||||
@@ -24,6 +27,7 @@ impl TryFrom<u8> 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<Recipient>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct SendRequest {
|
||||
pub conn_id: ConnectionId,
|
||||
pub data: Vec<u8>,
|
||||
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<u8> = 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// 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<u8> for ResponseFlag {
|
||||
@@ -22,12 +25,13 @@ impl TryFrom<u8> 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<u8> = 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<u8>,
|
||||
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<u8> = 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+12
@@ -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"
|
||||
@@ -3683,10 +3692,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",
|
||||
]
|
||||
|
||||
|
||||
@@ -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" }
|
||||
|
||||
|
||||
@@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ pub enum ResponseContent<T: ServiceProviderRequest = EmptyMessage> {
|
||||
ProviderData(T::Response),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(u8)]
|
||||
pub enum ResponseTag {
|
||||
/// Value tag representing [`Control`] variant of the [`Response`]
|
||||
|
||||
@@ -54,3 +54,4 @@ nym-client-websocket-requests = { path = "../../clients/native/websocket-request
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.5.0"
|
||||
anyhow = "1.0.68"
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// 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<ReconstructedMessage>) -> Socks5Response {
|
||||
assert_eq!(received.len(), 1);
|
||||
let response: Response<Socks5Request> = 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(())
|
||||
}
|
||||
@@ -25,8 +25,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;
|
||||
@@ -67,7 +68,6 @@ struct NRServiceProvider {
|
||||
|
||||
controller_sender: ControllerSender,
|
||||
mix_input_sender: MixProxySender<MixnetMessage>,
|
||||
//shared_lane_queue_lengths: LaneQueueLengths,
|
||||
stats_collector: Option<ServiceStatisticsCollector>,
|
||||
shutdown: TaskManager,
|
||||
}
|
||||
@@ -149,6 +149,7 @@ impl ServiceProvider<Socks5Request> for NRServiceProvider {
|
||||
}
|
||||
self.handle_proxy_send(req)
|
||||
}
|
||||
Socks5RequestContent::Query(query) => return self.handle_query(query),
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
@@ -255,7 +256,6 @@ impl NRServiceProviderBuilder {
|
||||
mixnet_client,
|
||||
controller_sender,
|
||||
mix_input_sender,
|
||||
//shared_lane_queue_lengths: mixnet_client.shared_lane_queue_lengths(),
|
||||
stats_collector,
|
||||
shutdown,
|
||||
};
|
||||
@@ -477,6 +477,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<Option<Socks5Response>, 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.
|
||||
|
||||
Reference in New Issue
Block a user