From d29a37e213edfeefd037b068651cc8007ad8096a Mon Sep 17 00:00:00 2001 From: baoyachi Date: Mon, 31 Jul 2023 14:59:25 +0800 Subject: [PATCH 1/3] By using the built-in SessionBuilder in openssh, or a custom SessionBuilder, create a TempDir. --- .gitignore | 2 +- src/builder.rs | 31 +++++++++++++++++-- src/session.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 111 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 203223e52..ba9ddd03f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ /target /ci-target Cargo.lock - +.idea/ .DS_Store diff --git a/src/builder.rs b/src/builder.rs index ffb603640..a81988581 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -93,6 +93,16 @@ impl Default for SessionBuilder { } impl SessionBuilder { + /// Return the user set in builder. + pub fn get_user(&self) -> Option<&str> { + self.user.as_deref() + } + + /// Return the port set in builder. + pub fn get_port(&self) -> Option<&str> { + self.port.as_deref() + } + /// Set the ssh user (`ssh -l`). /// /// Defaults to `None`. @@ -286,7 +296,21 @@ impl SessionBuilder { Ok(f(tempdir)) } - fn resolve<'a, 'b>(&'a self, mut destination: &'b str) -> (Cow<'a, Self>, &'b str) { + /// [`SessionBuilder`] support for `destination` parsing. + /// The format of `destination` is the same as the `destination` argument to `ssh`. + /// + /// # Examples + /// + /// ```rust + /// use std::borrow::Cow; + /// use openssh::SessionBuilder; + /// let b = SessionBuilder::default(); + /// let (b, d) = b.resolve("ssh://test-user@127.0.0.1:2222"); + /// assert_eq!(b.get_port().as_deref(), Some("2222")); + /// assert_eq!(b.get_user().as_deref(), Some("test-user")); + /// assert_eq!(d, "127.0.0.1"); + /// ``` + pub fn resolve<'a, 'b>(&'a self, mut destination: &'b str) -> (Cow<'a, Self>, &'b str) { // the "new" ssh://user@host:port form is not supported by all versions of ssh, // so we always translate it into the option form. let mut user = None; @@ -324,7 +348,8 @@ impl SessionBuilder { (Cow::Owned(with_overrides), destination) } - async fn launch_master(&self, destination: &str) -> Result { + /// Create ssh master session and return [`TempDir`] + pub async fn launch_master(&self, destination: &str) -> Result { let socketdir = if let Some(socketdir) = self.control_dir.as_ref() { socketdir } else { @@ -334,7 +359,7 @@ impl SessionBuilder { let prefix = ".ssh-connection"; if self.clean_history_control_dir { - let _ = clean_history_control_dir(&socketdir, prefix); + let _ = clean_history_control_dir(socketdir, prefix); } let dir = Builder::new() diff --git a/src/session.rs b/src/session.rs index be0018d01..d023cc8bc 100644 --- a/src/session.rs +++ b/src/session.rs @@ -53,13 +53,93 @@ pub struct Session(SessionImp); // TODO: UserKnownHostsFile for custom known host fingerprint. impl Session { + /// The method for creating a [`Session`] and externally control the creation of TempDir. + /// + /// By using the built-in [`SessionBuilder`] in openssh, or a custom SessionBuilder, + /// create a TempDir. + /// + /// # Examples + /// + /// ```rust,no_run + /// # use std::error::Error; + /// # #[cfg(feature = "process-mux")] + /// # #[tokio::main] + /// # async fn main() -> Result<(), Box> { + /// + /// use openssh::{Session, Stdio, SessionBuilder}; + /// use openssh_sftp_client::Sftp; + /// + /// let builder = SessionBuilder::default(); + /// let (builder, destination) = builder.resolve("ssh://jon@ssh.thesquareplanet.com:222"); + /// let tempdir = builder.launch_master(destination).await?; + /// + /// let session = Session::new_process_mux(tempdir); + /// + /// let mut child = session + /// .subsystem("sftp") + /// .stdin(Stdio::piped()) + /// .stdout(Stdio::piped()) + /// .spawn() + /// .await?; + /// + /// Sftp::new( + /// child.stdin().take().unwrap(), + /// child.stdout().take().unwrap(), + /// Default::default(), + /// ) + /// .await? + /// .close() + /// .await?; + /// + /// # Ok(()) } + /// ``` #[cfg(feature = "process-mux")] - pub(super) fn new_process_mux(tempdir: TempDir) -> Self { + pub fn new_process_mux(tempdir: TempDir) -> Self { Self(SessionImp::ProcessImpl(process_impl::Session::new(tempdir))) } + /// The method for creating a [`Session`] and externally control the creation of TempDir. + /// + /// By using the built-in [`SessionBuilder`] in openssh, or a custom SessionBuilder, + /// create a TempDir. + /// + /// # Examples + /// + /// ```rust,no_run + /// # use std::error::Error; + /// # #[cfg(feature = "native-mux")] + /// # #[tokio::main] + /// # async fn main() -> Result<(), Box> { + /// + /// use openssh::{Session, Stdio, SessionBuilder}; + /// use openssh_sftp_client::Sftp; + /// + /// let builder = SessionBuilder::default(); + /// let (builder, destination) = builder.resolve("ssh://jon@ssh.thesquareplanet.com:222"); + /// let tempdir = builder.launch_master(destination).await?; + /// + /// let session = Session::new_native_mux(tempdir); + /// + /// let mut child = session + /// .subsystem("sftp") + /// .stdin(Stdio::piped()) + /// .stdout(Stdio::piped()) + /// .spawn() + /// .await?; + /// + /// Sftp::new( + /// child.stdin().take().unwrap(), + /// child.stdout().take().unwrap(), + /// Default::default(), + /// ) + /// .await? + /// .close() + /// .await?; + /// + /// # Ok(()) } + /// ``` #[cfg(feature = "native-mux")] - pub(super) fn new_native_mux(tempdir: TempDir) -> Self { + pub fn new_native_mux(tempdir: TempDir) -> Self { Self(SessionImp::NativeMuxImpl(native_mux_impl::Session::new( tempdir, ))) From 5d4042da827e8dc3c6c50cbebfe64a946b050df0 Mon Sep 17 00:00:00 2001 From: "baoyachi. Aka Rust Hairy crabs" Date: Mon, 31 Jul 2023 22:05:30 +0800 Subject: [PATCH 2/3] Update src/builder.rs Co-authored-by: Jiahao XU --- src/builder.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/builder.rs b/src/builder.rs index a81988581..f912f4c15 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -348,7 +348,8 @@ impl SessionBuilder { (Cow::Owned(with_overrides), destination) } - /// Create ssh master session and return [`TempDir`] + /// Create ssh master session and return [`TempDir`] which + /// contains the ssh control socket. pub async fn launch_master(&self, destination: &str) -> Result { let socketdir = if let Some(socketdir) = self.control_dir.as_ref() { socketdir From 40840c5b0e96ead3be75624c97102b2996379954 Mon Sep 17 00:00:00 2001 From: baoyachi Date: Mon, 31 Jul 2023 22:06:33 +0800 Subject: [PATCH 3/3] remove code --- src/builder.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/builder.rs b/src/builder.rs index f912f4c15..8ff2dda94 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -302,7 +302,6 @@ impl SessionBuilder { /// # Examples /// /// ```rust - /// use std::borrow::Cow; /// use openssh::SessionBuilder; /// let b = SessionBuilder::default(); /// let (b, d) = b.resolve("ssh://test-user@127.0.0.1:2222");