Skip to content

Commit

Permalink
Update wezterm-ssh dep to 0.2.0, fix ssh -> distant session, refactor…
Browse files Browse the repository at this point in the history
… session to have optional details included
  • Loading branch information
chipsenkbeil committed Oct 11, 2021
1 parent 043ae6c commit c2e5885
Show file tree
Hide file tree
Showing 9 changed files with 196 additions and 70 deletions.
47 changes: 6 additions & 41 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

85 changes: 74 additions & 11 deletions distant-core/src/client/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ use crate::{
net::{Codec, DataStream, Transport, TransportError},
};
use log::*;
use serde::{Deserialize, Serialize};
use std::{
convert,
net::SocketAddr,
ops::{Deref, DerefMut},
path::{Path, PathBuf},
sync::{Arc, Weak},
};
use tokio::{
Expand All @@ -29,13 +31,54 @@ mod mailbox;
pub use mailbox::Mailbox;
use mailbox::PostOffice;

/// Details about the session
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SessionDetails {
/// Indicates session is a TCP type
Tcp { addr: SocketAddr, tag: String },

/// Indicates session is a Unix socket type
Socket { path: PathBuf, tag: String },

/// Indicates session type is inmemory
Inmemory { tag: String },
}

impl SessionDetails {
/// Represents the tag associated with the session
pub fn tag(&self) -> &str {
match self {
Self::Tcp { tag, .. } => tag.as_str(),
Self::Socket { tag, .. } => tag.as_str(),
Self::Inmemory { tag } => tag.as_str(),
}
}

/// Represents the socket address associated with the session, if it has one
pub fn addr(&self) -> Option<SocketAddr> {
match self {
Self::Tcp { addr, .. } => Some(*addr),
_ => None,
}
}

/// Represents the path associated with the session, if it has one
pub fn path(&self) -> Option<&Path> {
match self {
Self::Socket { path, .. } => Some(path.as_path()),
_ => None,
}
}
}

/// Represents a session with a remote server that can be used to send requests & receive responses
pub struct Session {
/// Used to send requests to a server
channel: SessionChannel,

/// Textual description of the underlying connection
connection_tag: String,
/// Details about the session
details: Option<SessionDetails>,

/// Contains the task that is running to send requests to a server
request_task: JoinHandle<()>,
Expand All @@ -54,14 +97,18 @@ impl Session {
U: Codec + Send + 'static,
{
let transport = Transport::<TcpStream, U>::connect(addr, codec).await?;
let details = SessionDetails::Tcp {
addr,
tag: transport.to_connection_tag(),
};
debug!(
"Session has been established with {}",
transport
.peer_addr()
.map(|x| x.to_string())
.unwrap_or_else(|_| String::from("???"))
);
Self::initialize(transport)
Self::initialize_with_details(transport, Some(details))
}

/// Connect to a remote TCP server, timing out after duration has passed
Expand All @@ -86,15 +133,20 @@ impl Session {
where
U: Codec + Send + 'static,
{
let transport = Transport::<tokio::net::UnixStream, U>::connect(path, codec).await?;
let p = path.as_ref();
let transport = Transport::<tokio::net::UnixStream, U>::connect(p, codec).await?;
let details = SessionDetails::Socket {
path: p.to_path_buf(),
tag: transport.to_connection_tag(),
};
debug!(
"Session has been established with {}",
transport
.peer_addr()
.map(|x| format!("{:?}", x))
.unwrap_or_else(|_| String::from("???"))
);
Self::initialize(transport)
Self::initialize_with_details(transport, Some(details))
}

/// Connect to a proxy unix socket, timing out after duration has passed
Expand All @@ -113,13 +165,24 @@ impl Session {
}

impl Session {
/// Initializes a session using the provided transport
/// Initializes a session using the provided transport and no extra details
pub fn initialize<T, U>(transport: Transport<T, U>) -> io::Result<Self>
where
T: DataStream,
U: Codec + Send + 'static,
{
let connection_tag = transport.to_connection_tag();
Self::initialize_with_details(transport, None)
}

/// Initializes a session using the provided transport and extra details
pub fn initialize_with_details<T, U>(
transport: Transport<T, U>,
details: Option<SessionDetails>,
) -> io::Result<Self>
where
T: DataStream,
U: Codec + Send + 'static,
{
let (mut t_read, mut t_write) = transport.into_split();
let post_office = Arc::new(Mutex::new(PostOffice::new()));
let weak_post_office = Arc::downgrade(&post_office);
Expand Down Expand Up @@ -190,7 +253,7 @@ impl Session {

Ok(Self {
channel,
connection_tag,
details,
request_task,
response_task,
prune_task,
Expand All @@ -199,9 +262,9 @@ impl Session {
}

impl Session {
/// Returns a textual description of the underlying connection
pub fn connection_tag(&self) -> &str {
&self.connection_tag
/// Returns details about the session, if it has any
pub fn details(&self) -> Option<&SessionDetails> {
self.details.as_ref()
}

/// Waits for the session to terminate, which results when the receiving end of the network
Expand Down
24 changes: 24 additions & 0 deletions distant-core/src/net/transport/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,30 @@ where
self.0.get_ref().to_connection_tag()
}

/// Returns a reference to the underlying I/O stream
///
/// Note that care should be taken to not tamper with the underlying stream of data coming in
/// as it may corrupt the stream of frames otherwise being worked with
pub fn get_ref(&self) -> &T {
self.0.get_ref()
}

/// Returns a reference to the underlying I/O stream
///
/// Note that care should be taken to not tamper with the underlying stream of data coming in
/// as it may corrupt the stream of frames otherwise being worked with
pub fn get_mut(&mut self) -> &mut T {
self.0.get_mut()
}

/// Consumes the transport, returning its underlying I/O stream
///
/// Note that care should be taken to not tamper with the underlying stream of data coming in
/// as it may corrupt the stream of frames otherwise being worked with.
pub fn into_inner(self) -> T {
self.0.into_inner()
}

/// Splits transport into read and write halves
pub fn into_split(
self,
Expand Down
12 changes: 6 additions & 6 deletions distant-lua/src/session.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{runtime, utils};
use distant_core::{
SecretKey32, Session as DistantSession, SessionChannel, XChaCha20Poly1305Codec,
SecretKey32, Session as DistantSession, SessionChannel, SessionDetails, XChaCha20Poly1305Codec,
};
use distant_ssh2::{IntoDistantSessionOpts, Ssh2Session};
use log::*;
Expand Down Expand Up @@ -118,8 +118,8 @@ fn with_session<T>(id: usize, f: impl FnOnce(&DistantSession) -> T) -> LuaResult
Ok(f(session))
}

fn get_session_connection_tag(id: usize) -> LuaResult<String> {
with_session(id, |session| session.connection_tag().to_string())
fn get_session_details(id: usize) -> LuaResult<Option<SessionDetails>> {
with_session(id, |session| session.details().cloned())
}

fn get_session_channel(id: usize) -> LuaResult<SessionChannel> {
Expand Down Expand Up @@ -181,7 +181,7 @@ impl Session {
})
.await
.to_lua_err()?,
Mode::Ssh => ssh_session.into_ssh_client_session().to_lua_err()?,
Mode::Ssh => ssh_session.into_ssh_client_session().await.to_lua_err()?,
};

// Fourth, store our current session in our global map and then return a reference
Expand Down Expand Up @@ -276,8 +276,8 @@ macro_rules! impl_methods {
impl UserData for Session {
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("id", |_, this| Ok(this.id));
fields.add_field_method_get("connection_tag", |_, this| {
get_session_connection_tag(this.id)
fields.add_field_method_get("details", |lua, this| {
get_session_details(this.id).and_then(|x| to_value!(lua, &x))
});
}

Expand Down
2 changes: 1 addition & 1 deletion distant-ssh2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ rpassword = "5.0.1"
shell-words = "1.0"
smol = "1.2"
tokio = { version = "1.12.0", features = ["full"] }
wezterm-ssh = { version = "0.2.0", features = ["vendored-openssl"], git = "https://github.com/chipsenkbeil/wezterm" }
wezterm-ssh = { version = "0.2.0", features = ["vendored-openssl"] }

# Optional serde support for data structures
serde = { version = "1.0.126", features = ["derive"], optional = true }
Expand Down
11 changes: 8 additions & 3 deletions distant-ssh2/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ use std::{
sync::Arc,
};
use tokio::sync::{mpsc, Mutex};
use wezterm_ssh::{Child, ExecResult, OpenFileType, OpenOptions, Session as WezSession, WriteMode};
use wezterm_ssh::{
Child, ExecResult, FilePermissions, OpenFileType, OpenOptions, Session as WezSession, WriteMode,
};

const MAX_PIPE_CHUNK_SIZE: usize = 8192;
const READ_PAUSE_MILLIS: u64 = 50;
Expand Down Expand Up @@ -588,9 +590,12 @@ async fn metadata(
Ok(Outgoing::from(ResponseData::Metadata(Metadata {
canonicalized_path,
file_type,
len: metadata.len(),
len: metadata.size.unwrap_or(0),
// Check that owner, group, or other has write permission (if not, then readonly)
readonly: metadata.is_readonly(),
readonly: metadata
.permissions
.map(FilePermissions::is_readonly)
.unwrap_or(true),
accessed: metadata.accessed.map(u128::from),
modified: metadata.modified.map(u128::from),
created: None,
Expand Down
Loading

0 comments on commit c2e5885

Please sign in to comment.