Skip to content

Commit

Permalink
Public method for creating a Session (#128)
Browse files Browse the repository at this point in the history
* By using the built-in SessionBuilder in openssh, or a custom SessionBuilder, create a TempDir.

* Update src/builder.rs

Co-authored-by: Jiahao XU <[email protected]>

* remove code

---------

Co-authored-by: Jiahao XU <[email protected]>
  • Loading branch information
baoyachi and NobodyXu authored Aug 1, 2023
1 parent 2e2bfb2 commit c7bb427
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/target
/ci-target
Cargo.lock

.idea/
.DS_Store
31 changes: 28 additions & 3 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down Expand Up @@ -286,7 +296,20 @@ 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 openssh::SessionBuilder;
/// let b = SessionBuilder::default();
/// let (b, d) = b.resolve("ssh://[email protected]: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;
Expand Down Expand Up @@ -324,7 +347,9 @@ impl SessionBuilder {
(Cow::Owned(with_overrides), destination)
}

async fn launch_master(&self, destination: &str) -> Result<TempDir, Error> {
/// Create ssh master session and return [`TempDir`] which
/// contains the ssh control socket.
pub async fn launch_master(&self, destination: &str) -> Result<TempDir, Error> {
let socketdir = if let Some(socketdir) = self.control_dir.as_ref() {
socketdir
} else {
Expand All @@ -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()
Expand Down
84 changes: 82 additions & 2 deletions src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<dyn Error>> {
///
/// use openssh::{Session, Stdio, SessionBuilder};
/// use openssh_sftp_client::Sftp;
///
/// let builder = SessionBuilder::default();
/// let (builder, destination) = builder.resolve("ssh://[email protected]: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<dyn Error>> {
///
/// use openssh::{Session, Stdio, SessionBuilder};
/// use openssh_sftp_client::Sftp;
///
/// let builder = SessionBuilder::default();
/// let (builder, destination) = builder.resolve("ssh://[email protected]: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,
)))
Expand Down

0 comments on commit c7bb427

Please sign in to comment.