pub async fn into_distant_session_info(
        self,
        opts: IntoDistantSessionOpts,
    ) -> io::Result<SessionInfo> {
        // Exit early if not authenticated as this is a requirement
        if !self.authenticated {
            return Err(io::Error::new(
                io::ErrorKind::PermissionDenied,
                "Not authenticated",
            ));
        }

        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?;

        // Build arguments for distant to execute listen subcommand
        let mut args = vec![
            String::from("listen"),
            String::from("--host"),
            String::from("ssh"),
        ];
        args.extend(
            shell_words::split(&opts.args)
                .map_err(|x| io::Error::new(io::ErrorKind::InvalidInput, x))?,
        );

        // If we are using a login shell, we need to make the binary be sh
        // so we can appropriately pipe into the login shell
        let (bin, args) = if opts.use_login_shell {
            (
                String::from("sh"),
                vec![
                    String::from("-c"),
                    shell_words::quote(&format!(
                        "echo {} {} | $SHELL -l",
                        opts.binary,
                        args.join(" ")
                    ))
                    .to_string(),
                ],
            )
        } else {
            (opts.binary, args)
        };

        // Spawn distant server and detach it so that we don't kill it when the
        // ssh session is closed
        debug!("Executing {} {}", bin, args.join(" "));
        let mut proc = session
            .spawn("<ssh-launch>", bin, args, true)
            .await
            .map_err(|x| io::Error::new(io::ErrorKind::Other, x))?;
        let mut stdout = proc.stdout.take().unwrap();
        let mut stderr = proc.stderr.take().unwrap();
        let (success, code) = proc
            .wait()
            .await
            .map_err(|x| io::Error::new(io::ErrorKind::BrokenPipe, x))?;

        // Close out ssh session
        session.abort();
        let _ = session.wait().await;
        let mut output = String::new();

        // If successful, grab the session information and establish a connection
        // with the distant server
        if success {
            while let Ok(data) = stdout.read().await {
                output.push_str(&data);
            }

            let maybe_info = output
                .lines()
                .find_map(|line| line.parse::<SessionInfo>().ok());
            match maybe_info {
                Some(mut info) => {
                    info.host = host;
                    Ok(info)
                }
                None => Err(io::Error::new(
                    io::ErrorKind::InvalidData,
                    "Missing session data",
                )),
            }
        } else {
            while let Ok(data) = stderr.read().await {
                output.push_str(&data);
            }

            Err(io::Error::new(
                io::ErrorKind::Other,
                format!(
                    "Spawning distant failed [{}]: {}",
                    code.map(|x| x.to_string())
                        .unwrap_or_else(|| String::from("???")),
                    output
                ),
            ))
        }
    }
/// Consume [`Ssh2Session`] and produce a distant [`SessionInfo`] representing a remote
/// distant server that is spawned using the ssh session
Consume [`Ssh2Session`] and produce a distant [`SessionInfo`] representing a remote
distant server that is spawned using the ssh session
Consume [ ` Ssh2Session ` ] and produce a distant [ ` SessionInfo ` ] representing a remote distant server that is spawned using the ssh session
pub async fn into_distant_session_info(
        self,
        opts: IntoDistantSessionOpts,
    ) -> io::Result<SessionInfo> {
        // Exit early if not authenticated as this is a requirement
        if !self.authenticated {
            return Err(io::Error::new(
                io::ErrorKind::PermissionDenied,
                "Not authenticated",
            ));
        }
        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?;
        // Build arguments for distant to execute listen subcommand
        let mut args = vec![
            String::from("listen"),
            String::from("--host"),
            String::from("ssh"),
        ];
        args.extend(
            shell_words::split(&opts.args)
                .map_err(|x| io::Error::new(io::ErrorKind::InvalidInput, x))?,
        );
        // If we are using a login shell, we need to make the binary be sh
        // so we can appropriately pipe into the login shell
        let (bin, args) = if opts.use_login_shell {
            (
                String::from("sh"),
                vec![
                    String::from("-c"),
                    shell_words::quote(&format!(
                        "echo {} {} | $SHELL -l",
                        opts.binary,
                        args.join(" ")
                    ))
                    .to_string(),
                ],
            )
        } else {
            (opts.binary, args)
        };
        // Spawn distant server and detach it so that we don't kill it when the
        // ssh session is closed
        debug!("Executing {} {}", bin, args.join(" "));
        let mut proc = session
            .spawn("<ssh-launch>", bin, args, true)
            .await
            .map_err(|x| io::Error::new(io::ErrorKind::Other, x))?;
        let mut stdout = proc.stdout.take().unwrap();
        let mut stderr = proc.stderr.take().unwrap();
        let (success, code) = proc
            .wait()
            .await
            .map_err(|x| io::Error::new(io::ErrorKind::BrokenPipe, x))?;
        // Close out ssh session
        session.abort();
        let _ = session.wait().await;
        let mut output = String::new();
        // If successful, grab the session information and establish a connection
        // with the distant server
        if success {
            while let Ok(data) = stdout.read().await {
                output.push_str(&data);
            }
            let maybe_info = output
                .lines()
                .find_map(|line| line.parse::<SessionInfo>().ok());
            match maybe_info {
                Some(mut info) => {
                    info.host = host;
                    Ok(info)
                }
                None => Err(io::Error::new(
                    io::ErrorKind::InvalidData,
                    "Missing session data",
                )),
            }
        } else {
            while let Ok(data) = stderr.read().await {
                output.push_str(&data);
            }
            Err(io::Error::new(
                io::ErrorKind::Other,
                format!(
                    "Spawning distant failed [{}]: {}",
                    code.map(|x| x.to_string())
                        .unwrap_or_else(|| String::from("???")),
                    output
                ),
            ))
        }
    }
pub async fn into_distant_session_info ( self , opts : IntoDistantSessionOpts , ) -> io :: Result < SessionInfo > { // Exit early if not authenticated as this is a requirement if ! self . authenticated { return Err ( io :: Error :: new ( io :: ErrorKind :: PermissionDenied , " " , ) ) ; } 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 ? ; // Build arguments for distant to execute listen subcommand let mut args = vec ! [ String from ( " " ) String from ( " " ) String from ( " " ) ] ; args . extend ( shell_words :: split ( & opts . args ) . map_err ( | x | io :: Error :: new ( io :: ErrorKind :: InvalidInput , x ) ) ? , ) ; // If we are using a login shell, we need to make the binary be sh // so we can appropriately pipe into the login shell let ( bin , args ) = if opts . use_login_shell { ( String :: from ( " " ) , vec ! [ String from ( " " ) shell_words quote ( format ( " " opts binary args join ( " " ) ) ) to_string ( ) ] , ) } else { ( opts . binary , args ) } ; // Spawn distant server and detach it so that we don't kill it when the // ssh session is closed debug ! ( " " bin args join ( " " ) ) ; let mut proc = session . spawn ( " " , bin , args , true ) . await . map_err ( | x | io :: Error :: new ( io :: ErrorKind :: Other , x ) ) ? ; let mut stdout = proc . stdout . take ( ) . unwrap ( ) ; let mut stderr = proc . stderr . take ( ) . unwrap ( ) ; let ( success , code ) = proc . wait ( ) . await . map_err ( | x | io :: Error :: new ( io :: ErrorKind :: BrokenPipe , x ) ) ? ; // Close out ssh session session . abort ( ) ; let _ = session . wait ( ) . await ; let mut output = String :: new ( ) ; // If successful, grab the session information and establish a connection // with the distant server if success { while let Ok ( data ) = stdout . read ( ) . await { output . push_str ( & data ) ; } let maybe_info = output . lines ( ) . find_map ( | line | line . parse :: < SessionInfo > ( ) . ok ( ) ) ; match maybe_info { Some ( mut info ) => { info . host = host ; Ok ( info ) } None => Err ( io :: Error :: new ( io :: ErrorKind :: InvalidData , " " , ) ) , } } else { while let Ok ( data ) = stderr . read ( ) . await { output . push_str ( & data ) ; } Err ( io :: Error :: new ( io :: ErrorKind :: Other , format ! ( " " code map ( x x to_string ( ) ) unwrap_or_else ( String from ( " " ) ) output ) , ) ) } }
Consume [`Ssh2Session`] and produce a distant [`SessionInfo`] representing a remote
distant server that is spawned using the ssh session
Consume [ ` Ssh2Session ` ] and produce a distant [ ` SessionInfo ` ] representing a remote distant server that is spawned using the ssh session
self
opts
IntoDistantSessionOpts