mirror of
https://github.com/chipsenkbeil/distant.git
synced 2024-10-30 21:20:24 +00:00
parent
e4199bb773
commit
4180ae279a
@ -11,6 +11,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Fixed
|
||||
### 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
|
||||
### Added
|
||||
- New `--ssh-backend` option for CLI that accepts `libssh` or `ssh2` for
|
||||
|
667
Cargo.lock
generated
667
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"
|
||||
categories = ["command-line-utilities"]
|
||||
keywords = ["cli"]
|
||||
version = "0.16.3"
|
||||
version = "0.16.4"
|
||||
authors = ["Chip Senkbeil <chip@senkbeil.org>"]
|
||||
edition = "2018"
|
||||
homepage = "https://github.com/chipsenkbeil/distant"
|
||||
@ -26,7 +26,7 @@ ssh2 = ["distant-ssh2/ssh2"]
|
||||
|
||||
[dependencies]
|
||||
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"
|
||||
indoc = "1.0.3"
|
||||
log = "0.4.14"
|
||||
@ -43,7 +43,7 @@ termwiz = "0.15.0"
|
||||
whoami = "1.1.2"
|
||||
|
||||
# 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]
|
||||
fork = "0.1.18"
|
||||
|
@ -6,7 +6,7 @@ RUN apk add --no-cache curl
|
||||
# 1. Specify the distant version
|
||||
# 2. Download the MUSL artifact as alpine uses musl
|
||||
# 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
|
||||
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"
|
||||
categories = ["network-programming"]
|
||||
keywords = ["api", "async"]
|
||||
version = "0.16.3"
|
||||
version = "0.16.4"
|
||||
authors = ["Chip Senkbeil <chip@senkbeil.org>"]
|
||||
edition = "2018"
|
||||
homepage = "https://github.com/chipsenkbeil/distant"
|
||||
|
@ -283,7 +283,7 @@ impl Session {
|
||||
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) {
|
||||
self.request_task.abort();
|
||||
self.response_task.abort();
|
||||
|
@ -2,7 +2,7 @@
|
||||
name = "distant-ssh2"
|
||||
description = "Library to enable native ssh-2 protocol for use with distant sessions"
|
||||
categories = ["network-programming"]
|
||||
version = "0.16.3"
|
||||
version = "0.16.4"
|
||||
authors = ["Chip Senkbeil <chip@senkbeil.org>"]
|
||||
edition = "2018"
|
||||
homepage = "https://github.com/chipsenkbeil/distant"
|
||||
@ -17,7 +17,7 @@ ssh2 = ["wezterm-ssh/ssh2", "wezterm-ssh/vendored-openssl-ssh2"]
|
||||
|
||||
[dependencies]
|
||||
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"
|
||||
log = "0.4.14"
|
||||
rand = { version = "0.8.4", features = ["getrandom"] }
|
||||
|
@ -513,7 +513,7 @@ impl Ssh2Session {
|
||||
let host = self.host().to_string();
|
||||
|
||||
// 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
|
||||
let mut args = vec![
|
||||
@ -560,6 +560,7 @@ impl Ssh2Session {
|
||||
.map_err(|x| io::Error::new(io::ErrorKind::BrokenPipe, x))?;
|
||||
|
||||
// Close out ssh session
|
||||
cleanup_session();
|
||||
session.abort();
|
||||
let _ = session.wait().await;
|
||||
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
|
||||
/// underneath
|
||||
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
|
||||
if !self.authenticated {
|
||||
return Err(io::Error::new(
|
||||
@ -630,7 +635,7 @@ impl Ssh2Session {
|
||||
} = self;
|
||||
|
||||
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()));
|
||||
while let Ok(Some(req)) = t_read.receive::<Request>().await {
|
||||
if let Err(x) =
|
||||
@ -642,7 +647,7 @@ impl Ssh2Session {
|
||||
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 {
|
||||
if let Err(x) = t_write.send(res).await {
|
||||
error!("Ssh session sender failed: {}", x);
|
||||
@ -652,6 +657,12 @@ impl Ssh2Session {
|
||||
debug!("Ssh sender task is now closed");
|
||||
});
|
||||
|
||||
Ok(session)
|
||||
Ok((
|
||||
session,
|
||||
Box::new(move || {
|
||||
send_task.abort();
|
||||
request_task.abort();
|
||||
}),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
44
src/link.rs
44
src/link.rs
@ -11,26 +11,32 @@ use tokio::task::{JoinError, JoinHandle};
|
||||
/// Represents a link between a remote process' stdin/stdout/stderr and this process'
|
||||
/// stdin/stdout/stderr
|
||||
pub struct RemoteProcessLink {
|
||||
_stdin_thread: thread::JoinHandle<()>,
|
||||
stdin_task: JoinHandle<io::Result<()>>,
|
||||
_stdin_thread: Option<thread::JoinHandle<()>>,
|
||||
stdin_task: Option<JoinHandle<io::Result<()>>>,
|
||||
stdout_task: JoinHandle<io::Result<()>>,
|
||||
stderr_task: JoinHandle<io::Result<()>>,
|
||||
}
|
||||
|
||||
macro_rules! from_pipes {
|
||||
($stdin:expr, $stdout:expr, $stderr:expr) => {{
|
||||
let (stdin_thread, mut stdin_rx) = stdin::spawn_channel(MAX_PIPE_CHUNK_SIZE);
|
||||
let stdin_task = tokio::spawn(async move {
|
||||
loop {
|
||||
if let Some(input) = stdin_rx.recv().await {
|
||||
if let Err(x) = $stdin.write(&*input).await {
|
||||
break Err(x);
|
||||
let mut stdin_thread = None;
|
||||
let mut stdin_task = None;
|
||||
if let Some(mut stdin_handle) = $stdin {
|
||||
let (thread, mut rx) = stdin::spawn_channel(MAX_PIPE_CHUNK_SIZE);
|
||||
let task = tokio::spawn(async move {
|
||||
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 handle = io::stdout();
|
||||
loop {
|
||||
@ -70,7 +76,7 @@ macro_rules! from_pipes {
|
||||
impl RemoteProcessLink {
|
||||
/// Creates a new process link from the pipes of a remote process
|
||||
pub fn from_remote_pipes(
|
||||
mut stdin: RemoteStdin,
|
||||
stdin: Option<RemoteStdin>,
|
||||
mut stdout: RemoteStdout,
|
||||
mut stderr: RemoteStderr,
|
||||
) -> Self {
|
||||
@ -79,7 +85,7 @@ impl RemoteProcessLink {
|
||||
|
||||
/// Creates a new process link from the pipes of a remote LSP server process
|
||||
pub fn from_remote_lsp_pipes(
|
||||
mut stdin: RemoteLspStdin,
|
||||
stdin: Option<RemoteLspStdin>,
|
||||
mut stdout: RemoteLspStdout,
|
||||
mut stderr: RemoteLspStderr,
|
||||
) -> Self {
|
||||
@ -94,12 +100,18 @@ impl RemoteProcessLink {
|
||||
|
||||
/// Waits for the stdin, stdout, and stderr tasks to complete
|
||||
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
|
||||
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.stderr_task.abort();
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ async fn start(
|
||||
|
||||
// Now, map the remote process' stdin/stdout/stderr to our own process
|
||||
let link = RemoteProcessLink::from_remote_pipes(
|
||||
proc.stdin.take().unwrap(),
|
||||
proc.stdin.take(),
|
||||
proc.stdout.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
|
||||
let link = RemoteProcessLink::from_remote_lsp_pipes(
|
||||
proc.stdin.take().unwrap(),
|
||||
proc.stdin.take(),
|
||||
proc.stdout.take().unwrap(),
|
||||
proc.stderr.take().unwrap(),
|
||||
);
|
||||
|
@ -6,7 +6,7 @@ use crate::{
|
||||
utils,
|
||||
};
|
||||
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 terminal_size::{terminal_size, Height, Width};
|
||||
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(
|
||||
RemoteStdin::disconnected(),
|
||||
None,
|
||||
proc.stdout.take().unwrap(),
|
||||
proc.stderr.take().unwrap(),
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user