pull/146/head
Chip Senkbeil 2 years ago
parent 5a70d795e0
commit 4c16b1f17d
No known key found for this signature in database
GPG Key ID: 35EF1F8EC72A4131

@ -1,13 +1,38 @@
use distant_net::{AuthChallengeFn, AuthErrorFn, AuthInfoFn, AuthVerifyFn, AuthVerifyKind};
use async_trait::async_trait;
use distant_net::auth::{AuthErrorKind, AuthHandler, AuthQuestion, AuthVerifyKind};
use log::*;
use std::io;
use std::{collections::HashMap, io};
/// Configuration to use when creating a new [`DistantManagerClient`](super::DistantManagerClient)
pub struct DistantManagerClientConfig {
pub on_challenge: Box<AuthChallengeFn>,
pub on_verify: Box<AuthVerifyFn>,
pub on_info: Box<AuthInfoFn>,
pub on_error: Box<AuthErrorFn>,
pub on_challenge:
Box<dyn FnMut(Vec<AuthQuestion>, HashMap<String, String>) -> io::Result<Vec<String>>>,
pub on_verify: Box<dyn FnMut(AuthVerifyKind, String) -> io::Result<bool>>,
pub on_info: Box<dyn FnMut(String) -> io::Result<()>>,
pub on_error: Box<dyn FnMut(AuthErrorKind, &str) -> io::Result<()>>,
}
#[async_trait]
impl AuthHandler for DistantManagerClientConfig {
async fn on_challenge(
&mut self,
questions: Vec<AuthQuestion>,
options: HashMap<String, String>,
) -> io::Result<Vec<String>> {
(self.on_challenge)(questions, options)
}
async fn on_verify(&mut self, kind: AuthVerifyKind, text: String) -> io::Result<bool> {
(self.on_verify)(kind, text)
}
async fn on_info(&mut self, text: String) -> io::Result<()> {
(self.on_info)(text)
}
async fn on_error(&mut self, kind: AuthErrorKind, text: &str) -> io::Result<()> {
(self.on_error)(kind, text)
}
}
impl DistantManagerClientConfig {
@ -47,7 +72,7 @@ impl DistantManagerClientConfig {
answers.push(answer);
}
answers
Ok(answers)
}),
on_verify: Box::new(move |kind, text| {
trace!("[manager client] on_verify({kind}, {text})");
@ -55,30 +80,25 @@ impl DistantManagerClientConfig {
AuthVerifyKind::Host => {
eprintln!("{}", text);
match text_prompt("Enter [y/N]> ") {
Ok(answer) => {
trace!("Verify? Answer = '{answer}'");
matches!(answer.trim(), "y" | "Y" | "yes" | "YES")
}
Err(x) => {
error!("Failed verification: {x}");
false
}
}
let answer = text_prompt("Enter [y/N]> ")?;
trace!("Verify? Answer = '{answer}'");
Ok(matches!(answer.trim(), "y" | "Y" | "yes" | "YES"))
}
x => {
error!("Unsupported verify kind: {x}");
false
Ok(false)
}
}
}),
on_info: Box::new(|text| {
trace!("[manager client] on_info({text})");
println!("{}", text);
Ok(())
}),
on_error: Box::new(|kind, text| {
trace!("[manager client] on_error({kind}, {text})");
eprintln!("{}: {}", kind, text);
Ok(())
}),
}
}

@ -4,8 +4,7 @@ use crate::{
};
use async_trait::async_trait;
use distant_net::{
router, Auth, AuthClient, Client, IntoSplit, Listener, MpscListener, Request, Response, Server,
ServerCtx, ServerExt, UntypedTransportRead, UntypedTransportWrite,
Client, Listener, MpscListener, Request, Response, Server, ServerCtx, ServerExt,
};
use log::*;
use std::{collections::HashMap, io, sync::Arc};
@ -29,11 +28,6 @@ pub use handler::*;
mod r#ref;
pub use r#ref::*;
router!(DistantManagerRouter {
auth_transport: Response<Auth> => Request<Auth>,
manager_transport: Request<ManagerRequest> => Response<ManagerResponse>,
});
/// Represents a manager of multiple distant server connections
pub struct DistantManager {
/// Receives authentication clients to feed into local data of server

@ -1,9 +1,6 @@
use crate::{
data::Map,
manager::{
data::{ChannelId, ConnectionId, Destination},
BoxedDistantReader, BoxedDistantWriter,
},
manager::data::{ChannelId, ConnectionId, Destination},
DistantMsg, DistantRequestData, DistantResponseData, ManagerResponse,
};
use distant_net::{Request, Response, ServerReply};
@ -43,7 +40,7 @@ impl DistantManagerChannel {
.map_err(|x| {
io::Error::new(
io::ErrorKind::BrokenPipe,
format!("channel {} send failed: {}", channel_id, x),
format!("channel {channel_id} send failed: {x}"),
)
})
}
@ -56,7 +53,7 @@ impl DistantManagerChannel {
.map_err(|x| {
io::Error::new(
io::ErrorKind::BrokenPipe,
format!("channel {} close failed: {}", channel_id, x),
format!("channel {channel_id} close failed: {x}"),
)
})
}
@ -103,7 +100,7 @@ impl DistantManagerConnection {
}
Ok(None) => break,
Err(x) => {
error!("[Conn {}] {}", connection_id, x);
error!("[Conn {connection_id}] {x}");
continue;
}
}
@ -141,7 +138,7 @@ impl DistantManagerConnection {
response,
};
if let Err(x) = reply.send(response).await {
error!("[Conn {}] {}", connection_id, x);
error!("[Conn {connection_id}] {x}");
}
}
}
@ -149,11 +146,11 @@ impl DistantManagerConnection {
// Combine channel id with request id so we can properly forward
// the response containing this in the origin id
let request = Request {
id: format!("{}_{}", id, request.id),
id: format!("{id}_{}", request.id),
payload: request.payload,
};
if let Err(x) = writer.write(request).await {
error!("[Conn {}] {}", connection_id, x);
error!("[Conn {connection_id}] {x}");
}
}
}
@ -184,7 +181,7 @@ impl DistantManagerConnection {
.map_err(|x| {
io::Error::new(
io::ErrorKind::BrokenPipe,
format!("open_channel failed: {}", x),
format!("open_channel failed: {x}"),
)
})?;
Ok(DistantManagerChannel {

@ -1,68 +1,79 @@
use crate::{
data::Map, manager::data::Destination, DistantMsg, DistantRequestData, DistantResponseData,
data::Map, manager::data::Destination, DistantClient, DistantMsg, DistantRequestData,
DistantResponseData,
};
use async_trait::async_trait;
use distant_net::{AuthClient, Request, Response, TypedAsyncRead, TypedAsyncWrite};
use distant_net::{auth::Authenticator, Request, Response};
use std::{future::Future, io};
pub type BoxedDistantWriter =
Box<dyn TypedAsyncWrite<Request<DistantMsg<DistantRequestData>>> + Send>;
pub type BoxedDistantReader =
Box<dyn TypedAsyncRead<Response<DistantMsg<DistantResponseData>>> + Send>;
pub type BoxedDistantWriterReader = (BoxedDistantWriter, BoxedDistantReader);
pub type BoxedLaunchHandler = Box<dyn LaunchHandler>;
pub type BoxedConnectHandler = Box<dyn ConnectHandler>;
/// Used to launch a server at the specified destination, returning some result as a vec of bytes
/// Represents an interface to start a server at some remote `destination` and then connect to the
/// started server.
///
/// * `destination` is the location where the server will be started.
/// * `options` is provided to include extra information needed to launch or establish the
/// connection.
/// * `authenticator` is provided to support a challenge-based authentication while launching or
/// connecting.
///
/// Returns a [`Destination`] representing the new origin to use if a connection is desired.
#[async_trait]
pub trait LaunchHandler: Send + Sync {
async fn launch(
&self,
destination: &Destination,
options: &Map,
auth_client: &mut AuthClient,
authenticator: &mut dyn Authenticator,
) -> io::Result<Destination>;
}
#[async_trait]
impl<F, R> LaunchHandler for F
where
F: for<'a> Fn(&'a Destination, &'a Map, &'a mut AuthClient) -> R + Send + Sync + 'static,
F: for<'a> Fn(&'a Destination, &'a Map, &'a mut dyn Authenticator) -> R + Send + Sync + 'static,
R: Future<Output = io::Result<Destination>> + Send + 'static,
{
async fn launch(
&self,
destination: &Destination,
options: &Map,
auth_client: &mut AuthClient,
authenticator: &mut dyn Authenticator,
) -> io::Result<Destination> {
self(destination, options, auth_client).await
self(destination, options, authenticator).await
}
}
/// Used to connect to a destination, returning a connected reader and writer pair
/// Represents an interface to perform a connection to some remote `destination`.
///
/// * `destination` is the location of the server to connect to.
/// * `options` is provided to include extra information needed to establish the connection.
/// * `authenticator` is provided to support a challenge-based authentication while connecting.
///
/// Returns a [`FramedTransport`] representing the connection.
#[async_trait]
pub trait ConnectHandler: Send + Sync {
async fn connect(
&self,
destination: &Destination,
options: &Map,
auth_client: &mut AuthClient,
authenticator: &mut dyn Authenticator,
) -> io::Result<BoxedDistantWriterReader>;
}
#[async_trait]
impl<F, R> ConnectHandler for F
where
F: for<'a> Fn(&'a Destination, &'a Map, &'a mut AuthClient) -> R + Send + Sync + 'static,
F: for<'a> Fn(&'a Destination, &'a Map, &'a mut dyn Authenticator) -> R + Send + Sync + 'static,
R: Future<Output = io::Result<BoxedDistantWriterReader>> + Send + 'static,
{
async fn connect(
&self,
destination: &Destination,
options: &Map,
auth_client: &mut AuthClient,
authenticator: &mut dyn Authenticator,
) -> io::Result<BoxedDistantWriterReader> {
self(destination, options, auth_client).await
self(destination, options, authenticator).await
}
}

Loading…
Cancel
Save