Bump to 0.16.4 and fix #80 and fix #102

pull/104/head
Chip Senkbeil 2 years ago
parent e4199bb773
commit 4180ae279a
No known key found for this signature in database
GPG Key ID: 35EF1F8EC72A4131

@ -11,6 +11,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
### Removed ### Removed
## [0.16.4] - 2022-06-01
### Added
- Dockerfile using Alpine linux with a basic install of distant, tagged as
`chipsenkbeil/distant:0.16.3`
### Fixed
- [Issue #90](https://github.com/chipsenkbeil/distant/issues/90)
- [Issue #103](https://github.com/chipsenkbeil/distant/issues/103)
## [0.16.3] - 2022-05-29 ## [0.16.3] - 2022-05-29
### Added ### Added
- New `--ssh-backend` option for CLI that accepts `libssh` or `ssh2` for - New `--ssh-backend` option for CLI that accepts `libssh` or `ssh2` for

659
Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -3,7 +3,7 @@ name = "distant"
description = "Operate on a remote computer through file and process manipulation" description = "Operate on a remote computer through file and process manipulation"
categories = ["command-line-utilities"] categories = ["command-line-utilities"]
keywords = ["cli"] keywords = ["cli"]
version = "0.16.3" version = "0.16.4"
authors = ["Chip Senkbeil <chip@senkbeil.org>"] authors = ["Chip Senkbeil <chip@senkbeil.org>"]
edition = "2018" edition = "2018"
homepage = "https://github.com/chipsenkbeil/distant" homepage = "https://github.com/chipsenkbeil/distant"
@ -26,7 +26,7 @@ ssh2 = ["distant-ssh2/ssh2"]
[dependencies] [dependencies]
derive_more = { version = "0.99.16", default-features = false, features = ["display", "from", "error", "is_variant"] } derive_more = { version = "0.99.16", default-features = false, features = ["display", "from", "error", "is_variant"] }
distant-core = { version = "=0.16.3", path = "distant-core", features = ["structopt"] } distant-core = { version = "=0.16.4", path = "distant-core", features = ["structopt"] }
flexi_logger = "0.18.0" flexi_logger = "0.18.0"
indoc = "1.0.3" indoc = "1.0.3"
log = "0.4.14" log = "0.4.14"
@ -43,7 +43,7 @@ termwiz = "0.15.0"
whoami = "1.1.2" whoami = "1.1.2"
# Optional native SSH functionality # Optional native SSH functionality
distant-ssh2 = { version = "=0.16.3", path = "distant-ssh2", default-features = false, features = ["serde"], optional = true } distant-ssh2 = { version = "=0.16.4", path = "distant-ssh2", default-features = false, features = ["serde"], optional = true }
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]
fork = "0.1.18" fork = "0.1.18"

@ -6,7 +6,7 @@ RUN apk add --no-cache curl
# 1. Specify the distant version # 1. Specify the distant version
# 2. Download the MUSL artifact as alpine uses musl # 2. Download the MUSL artifact as alpine uses musl
# 3. Make the binary executable # 3. Make the binary executable
ARG distant_version=0.16.3 ARG distant_version=0.16.4
ARG distant_url=https://github.com/chipsenkbeil/distant/releases/download/v${distant_version}/distant-linux64-musl ARG distant_url=https://github.com/chipsenkbeil/distant/releases/download/v${distant_version}/distant-linux64-musl
RUN curl -L ${distant_url} > /usr/local/bin/distant && chmod +x /usr/local/bin/distant RUN curl -L ${distant_url} > /usr/local/bin/distant && chmod +x /usr/local/bin/distant

@ -3,7 +3,7 @@ name = "distant-core"
description = "Core library for distant, enabling operation on a remote computer through file and process manipulation" description = "Core library for distant, enabling operation on a remote computer through file and process manipulation"
categories = ["network-programming"] categories = ["network-programming"]
keywords = ["api", "async"] keywords = ["api", "async"]
version = "0.16.3" version = "0.16.4"
authors = ["Chip Senkbeil <chip@senkbeil.org>"] authors = ["Chip Senkbeil <chip@senkbeil.org>"]
edition = "2018" edition = "2018"
homepage = "https://github.com/chipsenkbeil/distant" homepage = "https://github.com/chipsenkbeil/distant"

@ -283,7 +283,7 @@ impl Session {
tokio::try_join!(self.request_task, self.response_task).map(|_| ()) tokio::try_join!(self.request_task, self.response_task).map(|_| ())
} }
/// Abort the session's current connection by forcing its response task to shutdown /// Abort the session's current connection by forcing its tasks to abort
pub fn abort(&self) { pub fn abort(&self) {
self.request_task.abort(); self.request_task.abort();
self.response_task.abort(); self.response_task.abort();

@ -2,7 +2,7 @@
name = "distant-ssh2" name = "distant-ssh2"
description = "Library to enable native ssh-2 protocol for use with distant sessions" description = "Library to enable native ssh-2 protocol for use with distant sessions"
categories = ["network-programming"] categories = ["network-programming"]
version = "0.16.3" version = "0.16.4"
authors = ["Chip Senkbeil <chip@senkbeil.org>"] authors = ["Chip Senkbeil <chip@senkbeil.org>"]
edition = "2018" edition = "2018"
homepage = "https://github.com/chipsenkbeil/distant" homepage = "https://github.com/chipsenkbeil/distant"
@ -17,7 +17,7 @@ ssh2 = ["wezterm-ssh/ssh2", "wezterm-ssh/vendored-openssl-ssh2"]
[dependencies] [dependencies]
async-compat = "0.2.1" async-compat = "0.2.1"
distant-core = { version = "=0.16.3", path = "../distant-core" } distant-core = { version = "=0.16.4", path = "../distant-core" }
futures = "0.3.16" futures = "0.3.16"
log = "0.4.14" log = "0.4.14"
rand = { version = "0.8.4", features = ["getrandom"] } rand = { version = "0.8.4", features = ["getrandom"] }

@ -513,7 +513,7 @@ impl Ssh2Session {
let host = self.host().to_string(); let host = self.host().to_string();
// Turn our ssh connection into a client session so we can use it to spawn our server // Turn our ssh connection into a client session so we can use it to spawn our server
let mut session = self.into_ssh_client_session().await?; let (mut session, cleanup_session) = self.into_ssh_client_session_impl().await?;
// Build arguments for distant to execute listen subcommand // Build arguments for distant to execute listen subcommand
let mut args = vec![ let mut args = vec![
@ -560,6 +560,7 @@ impl Ssh2Session {
.map_err(|x| io::Error::new(io::ErrorKind::BrokenPipe, x))?; .map_err(|x| io::Error::new(io::ErrorKind::BrokenPipe, x))?;
// Close out ssh session // Close out ssh session
cleanup_session();
session.abort(); session.abort();
let _ = session.wait().await; let _ = session.wait().await;
let mut output = Vec::new(); let mut output = Vec::new();
@ -609,6 +610,10 @@ impl Ssh2Session {
/// Consume [`Ssh2Session`] and produce a distant [`Session`] that is powered by an ssh client /// Consume [`Ssh2Session`] and produce a distant [`Session`] that is powered by an ssh client
/// underneath /// underneath
pub async fn into_ssh_client_session(self) -> io::Result<Session> { pub async fn into_ssh_client_session(self) -> io::Result<Session> {
self.into_ssh_client_session_impl().await.map(|x| x.0)
}
async fn into_ssh_client_session_impl(self) -> io::Result<(Session, Box<dyn FnOnce()>)> {
// Exit early if not authenticated as this is a requirement // Exit early if not authenticated as this is a requirement
if !self.authenticated { if !self.authenticated {
return Err(io::Error::new( return Err(io::Error::new(
@ -630,7 +635,7 @@ impl Ssh2Session {
} = self; } = self;
let (tx, mut rx) = mpsc::channel(1); let (tx, mut rx) = mpsc::channel(1);
tokio::spawn(async move { let request_task = tokio::spawn(async move {
let state = Arc::new(Mutex::new(handler::State::default())); let state = Arc::new(Mutex::new(handler::State::default()));
while let Ok(Some(req)) = t_read.receive::<Request>().await { while let Ok(Some(req)) = t_read.receive::<Request>().await {
if let Err(x) = if let Err(x) =
@ -642,7 +647,7 @@ impl Ssh2Session {
debug!("Ssh receiver task is now closed"); debug!("Ssh receiver task is now closed");
}); });
tokio::spawn(async move { let send_task = tokio::spawn(async move {
while let Some(res) = rx.recv().await { while let Some(res) = rx.recv().await {
if let Err(x) = t_write.send(res).await { if let Err(x) = t_write.send(res).await {
error!("Ssh session sender failed: {}", x); error!("Ssh session sender failed: {}", x);
@ -652,6 +657,12 @@ impl Ssh2Session {
debug!("Ssh sender task is now closed"); debug!("Ssh sender task is now closed");
}); });
Ok(session) Ok((
session,
Box::new(move || {
send_task.abort();
request_task.abort();
}),
))
} }
} }

@ -11,26 +11,32 @@ use tokio::task::{JoinError, JoinHandle};
/// Represents a link between a remote process' stdin/stdout/stderr and this process' /// Represents a link between a remote process' stdin/stdout/stderr and this process'
/// stdin/stdout/stderr /// stdin/stdout/stderr
pub struct RemoteProcessLink { pub struct RemoteProcessLink {
_stdin_thread: thread::JoinHandle<()>, _stdin_thread: Option<thread::JoinHandle<()>>,
stdin_task: JoinHandle<io::Result<()>>, stdin_task: Option<JoinHandle<io::Result<()>>>,
stdout_task: JoinHandle<io::Result<()>>, stdout_task: JoinHandle<io::Result<()>>,
stderr_task: JoinHandle<io::Result<()>>, stderr_task: JoinHandle<io::Result<()>>,
} }
macro_rules! from_pipes { macro_rules! from_pipes {
($stdin:expr, $stdout:expr, $stderr:expr) => {{ ($stdin:expr, $stdout:expr, $stderr:expr) => {{
let (stdin_thread, mut stdin_rx) = stdin::spawn_channel(MAX_PIPE_CHUNK_SIZE); let mut stdin_thread = None;
let stdin_task = tokio::spawn(async move { let mut stdin_task = None;
loop { if let Some(mut stdin_handle) = $stdin {
if let Some(input) = stdin_rx.recv().await { let (thread, mut rx) = stdin::spawn_channel(MAX_PIPE_CHUNK_SIZE);
if let Err(x) = $stdin.write(&*input).await { let task = tokio::spawn(async move {
break Err(x); loop {
if let Some(input) = rx.recv().await {
if let Err(x) = stdin_handle.write(&*input).await {
break Err(x);
}
} else {
break Ok(());
} }
} else {
break Ok(());
} }
} });
}); stdin_thread = Some(thread);
stdin_task = Some(task);
}
let stdout_task = tokio::spawn(async move { let stdout_task = tokio::spawn(async move {
let handle = io::stdout(); let handle = io::stdout();
loop { loop {
@ -70,7 +76,7 @@ macro_rules! from_pipes {
impl RemoteProcessLink { impl RemoteProcessLink {
/// Creates a new process link from the pipes of a remote process /// Creates a new process link from the pipes of a remote process
pub fn from_remote_pipes( pub fn from_remote_pipes(
mut stdin: RemoteStdin, stdin: Option<RemoteStdin>,
mut stdout: RemoteStdout, mut stdout: RemoteStdout,
mut stderr: RemoteStderr, mut stderr: RemoteStderr,
) -> Self { ) -> Self {
@ -79,7 +85,7 @@ impl RemoteProcessLink {
/// Creates a new process link from the pipes of a remote LSP server process /// Creates a new process link from the pipes of a remote LSP server process
pub fn from_remote_lsp_pipes( pub fn from_remote_lsp_pipes(
mut stdin: RemoteLspStdin, stdin: Option<RemoteLspStdin>,
mut stdout: RemoteLspStdout, mut stdout: RemoteLspStdout,
mut stderr: RemoteLspStderr, mut stderr: RemoteLspStderr,
) -> Self { ) -> Self {
@ -94,12 +100,18 @@ impl RemoteProcessLink {
/// Waits for the stdin, stdout, and stderr tasks to complete /// Waits for the stdin, stdout, and stderr tasks to complete
pub async fn wait(self) -> Result<(), JoinError> { pub async fn wait(self) -> Result<(), JoinError> {
tokio::try_join!(self.stdin_task, self.stdout_task, self.stderr_task).map(|_| ()) if let Some(stdin_task) = self.stdin_task {
tokio::try_join!(stdin_task, self.stdout_task, self.stderr_task).map(|_| ())
} else {
tokio::try_join!(self.stdout_task, self.stderr_task).map(|_| ())
}
} }
/// Aborts the link by aborting tasks processing stdin, stdout, and stderr /// Aborts the link by aborting tasks processing stdin, stdout, and stderr
pub fn abort(&self) { pub fn abort(&self) {
self.stdin_task.abort(); if let Some(stdin_task) = self.stdin_task.as_ref() {
stdin_task.abort();
}
self.stdout_task.abort(); self.stdout_task.abort();
self.stderr_task.abort(); self.stderr_task.abort();
} }

@ -147,7 +147,7 @@ async fn start(
// Now, map the remote process' stdin/stdout/stderr to our own process // Now, map the remote process' stdin/stdout/stderr to our own process
let link = RemoteProcessLink::from_remote_pipes( let link = RemoteProcessLink::from_remote_pipes(
proc.stdin.take().unwrap(), proc.stdin.take(),
proc.stdout.take().unwrap(), proc.stdout.take().unwrap(),
proc.stderr.take().unwrap(), proc.stderr.take().unwrap(),
); );

@ -96,7 +96,7 @@ async fn start(
// Now, map the remote LSP server's stdin/stdout/stderr to our own process // Now, map the remote LSP server's stdin/stdout/stderr to our own process
let link = RemoteProcessLink::from_remote_lsp_pipes( let link = RemoteProcessLink::from_remote_lsp_pipes(
proc.stdin.take().unwrap(), proc.stdin.take(),
proc.stdout.take().unwrap(), proc.stdout.take().unwrap(),
proc.stderr.take().unwrap(), proc.stderr.take().unwrap(),
); );

@ -6,7 +6,7 @@ use crate::{
utils, utils,
}; };
use derive_more::{Display, Error, From}; use derive_more::{Display, Error, From};
use distant_core::{LspData, PtySize, RemoteProcess, RemoteProcessError, RemoteStdin, Session}; use distant_core::{LspData, PtySize, RemoteProcess, RemoteProcessError, Session};
use log::*; use log::*;
use terminal_size::{terminal_size, Height, Width}; use terminal_size::{terminal_size, Height, Width};
use termwiz::{ use termwiz::{
@ -139,9 +139,10 @@ async fn start(
} }
}); });
// Now, map the remote LSP server's stdin/stdout/stderr to our own process // Now, map the remote shell's stdout/stderr to our own process,
// while stdin is handled by the task above
let link = RemoteProcessLink::from_remote_pipes( let link = RemoteProcessLink::from_remote_pipes(
RemoteStdin::disconnected(), None,
proc.stdout.take().unwrap(), proc.stdout.take().unwrap(),
proc.stderr.take().unwrap(), proc.stderr.take().unwrap(),
); );

Loading…
Cancel
Save