9a68702d4d
* revamping mixnode connfig * wip * native client config revamping * wip * building socks5 * using const for mixnnode config template * compiling updated gateway * nym-api * nym-sdk * everything compiling once more but definitely not compatible with CI and older versions (yet) * creating full directory structure on init * renamed paths to storage_paths and fixed mixnode template * mixnode config migration * gateway config migration * nym-api config migration * native client config migration * socks5 client config migration * NR config migration * removed deprecations (that will be resolved in the following PRs) + fixed clippy * nym-connect clippy * nym-connect config updates * outfox fixes * defined socks5 lib config * clippy * fixed wasm client build * removed explicit packet_type argument when starting base client it's known implicitly from the previously passed config struct * Empty commit * fixed re-using gateway information when client configs are re-initialised * fixed borrowing id value in nym-connect * post-rebase fixes * updated 'old_config' versions --------- Co-authored-by: Tommy Verrall <tommy@nymtech.net>
187 lines
7.2 KiB
Rust
187 lines
7.2 KiB
Rust
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
use crate::interface::{
|
|
BinaryInformation, ControlRequest, ControlResponse, EmptyMessage, ProviderInterfaceVersion,
|
|
Request, RequestContent, Response, ResponseContent, ServiceProviderRequest, SupportedVersions,
|
|
};
|
|
use async_trait::async_trait;
|
|
use nym_sphinx_anonymous_replies::requests::AnonymousSenderTag;
|
|
|
|
pub mod interface;
|
|
|
|
pub const DEFAULT_SERVICE_PROVIDERS_DIR: &str = "service-providers";
|
|
|
|
// FUTURE WORK:
|
|
// for next version (v4) of the interface, refactor `reply::MixnetAddress` from the socks5 SP
|
|
// and move it here so that you could optionally attach your sender address with any request for easier responses
|
|
|
|
/// Trait that every ServiceProvider on the Nym network should implement and adhere to.
|
|
#[async_trait]
|
|
pub trait ServiceProvider<T: ServiceProviderRequest = EmptyMessage>
|
|
where
|
|
T: Send + 'static,
|
|
Self: Sync,
|
|
{
|
|
type ServiceProviderError: From<<T as ServiceProviderRequest>::Error>;
|
|
|
|
// TODO: refactor to use some version of `reply::MixnetAddress`
|
|
// in case explicit address was provided
|
|
async fn on_request(
|
|
&mut self,
|
|
sender: Option<AnonymousSenderTag>,
|
|
request: Request<T>,
|
|
) -> Result<(), Self::ServiceProviderError>;
|
|
|
|
async fn handle_request(
|
|
&mut self,
|
|
sender: Option<AnonymousSenderTag>,
|
|
request: Request<T>,
|
|
) -> Result<Option<Response<T>>, Self::ServiceProviderError> {
|
|
match request.content {
|
|
RequestContent::Control(control_request) => self
|
|
.handle_control_request(sender, control_request, request.interface_version)
|
|
.await
|
|
.map(|maybe_res| {
|
|
maybe_res.map(|control_res| Response {
|
|
interface_version: request.interface_version,
|
|
content: ResponseContent::Control(control_res),
|
|
})
|
|
}),
|
|
RequestContent::ProviderData(provider_data_request) => self
|
|
.handle_provider_data_request(
|
|
sender,
|
|
provider_data_request,
|
|
request.interface_version,
|
|
)
|
|
.await
|
|
.map(|maybe_res| {
|
|
maybe_res.map(|provider_data_res| Response {
|
|
interface_version: request.interface_version,
|
|
content: ResponseContent::ProviderData(provider_data_res),
|
|
})
|
|
}),
|
|
}
|
|
}
|
|
|
|
async fn handle_control_request(
|
|
&mut self,
|
|
_sender: Option<AnonymousSenderTag>,
|
|
request: ControlRequest,
|
|
interface_version: ProviderInterfaceVersion,
|
|
) -> Result<Option<ControlResponse>, Self::ServiceProviderError> {
|
|
if interface_version.is_legacy() {
|
|
// control requests didn't exist in the legacy version
|
|
Ok(None)
|
|
} else {
|
|
let response = match request {
|
|
// Version 3 requests:
|
|
ControlRequest::Health => {
|
|
self.handle_health_control_request().await?;
|
|
Some(ControlResponse::Health)
|
|
}
|
|
ControlRequest::BinaryInfo => {
|
|
let info = self.handle_binary_info_control_request().await?;
|
|
Some(ControlResponse::BinaryInfo(Box::new(info)))
|
|
}
|
|
ControlRequest::SupportedRequestVersions => {
|
|
let versions = self.handle_supported_request_versions_request().await?;
|
|
Some(ControlResponse::SupportedRequestVersions(versions))
|
|
} //
|
|
// TODO: if we ever add new request for interface version 4 (or higher),
|
|
// we need to include a check to make sure we return a `None` if passed `interface_version` was 3
|
|
};
|
|
Ok(response)
|
|
}
|
|
}
|
|
|
|
// I don't think you can do anything more simple than that, but allow for custom implementations
|
|
// in case, for example, you wanted to include additional statistics collection here
|
|
async fn handle_health_control_request(&self) -> Result<(), Self::ServiceProviderError> {
|
|
Ok(())
|
|
}
|
|
|
|
// well, this has to be handled manually
|
|
async fn handle_binary_info_control_request(
|
|
&self,
|
|
) -> Result<BinaryInformation, Self::ServiceProviderError>;
|
|
|
|
async fn handle_supported_request_versions_request(
|
|
&self,
|
|
) -> Result<SupportedVersions, Self::ServiceProviderError> {
|
|
Ok(SupportedVersions {
|
|
interface_version: ProviderInterfaceVersion::new_current().to_string(),
|
|
provider_version: T::max_supported_version().to_string(),
|
|
})
|
|
}
|
|
|
|
async fn handle_provider_data_request(
|
|
&mut self,
|
|
sender: Option<AnonymousSenderTag>,
|
|
request: T,
|
|
interface_version: ProviderInterfaceVersion,
|
|
) -> Result<Option<T::Response>, Self::ServiceProviderError>;
|
|
}
|
|
|
|
// #[async_trait]
|
|
// pub trait ServiceProviderClient<T: ServiceProviderRequest = EmptyMessage>
|
|
// where
|
|
// T: Send + 'static,
|
|
// Self: Sync,
|
|
// {
|
|
// type ServiceProviderClientError: From<<T as ServiceProviderRequest>::Error>;
|
|
//
|
|
// fn provider_interface_version(&self) -> ProviderInterfaceVersion;
|
|
//
|
|
// fn get_control_response(
|
|
// maybe_res: Option<Response<T>>,
|
|
// ) -> Result<Option<ControlResponse>, Self::ServiceProviderClientError> {
|
|
// let Some(res) = maybe_res else {
|
|
// return Ok(None)
|
|
// };
|
|
//
|
|
// match res.content {
|
|
// ResponseContent::Control(res) => Ok(Some(res)),
|
|
// ResponseContent::ProviderData(_) => Err(Self::ServiceProviderClientError::from(
|
|
// ServiceProviderMessagingError::UnexpectedProviderDataResponse.into(),
|
|
// )),
|
|
// }
|
|
// }
|
|
//
|
|
// fn get_provider_data_response(
|
|
// maybe_res: Option<Response<T>>,
|
|
// ) -> Result<Option<T::Response>, Self::ServiceProviderClientError> {
|
|
// let Some(res) = maybe_res else {
|
|
// return Ok(None)
|
|
// };
|
|
//
|
|
// match res.content {
|
|
// ResponseContent::ProviderData(res) => Ok(Some(res)),
|
|
// ResponseContent::Control(_) => Err(Self::ServiceProviderClientError::from(
|
|
// ServiceProviderMessagingError::UnexpectedControlResponse.into(),
|
|
// )),
|
|
// }
|
|
// }
|
|
//
|
|
// // async fn send_control_request_anonymously(
|
|
// // &mut self,
|
|
// // request: ControlRequest,
|
|
// // ) -> Result<Option<ControlResponse>, Self::ServiceProviderClientError>;
|
|
// //
|
|
// // async fn send_provider_data_request_anonymously(
|
|
// // &mut self,
|
|
// // request: T,
|
|
// // ) -> Result<Option<T::Response>, Self::ServiceProviderClientError>;
|
|
// //
|
|
// // TODO: extend the traits and messaging to allow for attaching own address
|
|
// // async fn send_control_request_with_address(
|
|
// // &mut self,
|
|
// // request: ControlRequest,
|
|
// // ) -> Result<Option<ControlResponse>, Self::ServiceProviderClientError>;
|
|
// //
|
|
// // async fn send_provider_data_request_with_address(
|
|
// // &mut self,
|
|
// // request: T,
|
|
// // ) -> Result<Option<T::Response>, Self::ServiceProviderClientError>;
|
|
// }
|