Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Public method for creating a Session #128

Merged
merged 3 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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) {
baoyachi marked this conversation as resolved.
Show resolved Hide resolved
// 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> {
baoyachi marked this conversation as resolved.
Show resolved Hide resolved
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
Loading