Never ending story with lifetime


#1

Hello,

Can someone point me in direction how to achieve following goal:
I want to implement method on struct that will return ssh channel for further command execution.
I came up with following code (ignore unwraps - they will be handled) but I’m getting lifetime error. I don’t know where to put those bloody <'a> markers to make this running:

pub struct MikrotikDevice {
    ip_addr: net::IpAddr,
    username: String,
    password: String,
    private_key: Vec<u8>,
    ssh_port: u16,
    telnet_port: u16,
}

impl MikrotikDevice {
    pub fn connect(&self) -> Result<ssh2::Channel, &'static str> {
        let tcp = TcpStream::connect((self.ip_addr, self.ssh_port)).unwrap();
        let mut sess = ssh2::Session::new().unwrap();
        sess.handshake(&tcp).unwrap();
        sess.userauth_password(&self.username, &self.password).unwrap();
        let mut channel = sess.channel_session().unwrap();
        Ok(channel)

    }
}

Compilation error:

src/mikrotik.rs:31:27: 31:31 error: `sess` does not live long enough
src/mikrotik.rs:31         let mut channel = sess.channel_session().unwrap();
                                             ^~~~
src/mikrotik.rs:26:66: 34:6 note: reference must be valid for the anonymous lifetime #1 defined on the block at 26:65...
src/mikrotik.rs:26     pub fn connect(&self) -> Result<ssh2::Channel, &'static str> {
                                                                                    ^
src/mikrotik.rs:28:54: 34:6 note: ...but borrowed value is only valid for the block suffix following statement 1 at 28:53
src/mikrotik.rs:28         let mut sess = ssh2::Session::new().unwrap();

Thanks for suggestion in advance.


#2

A Channel borrows (and must be outlived by) a Session (that’s what its 'sess lifetime parameter does). Here the session gets destroyed at the end of the function so the borrow checker is preventing a dangling pointer situation. You need to store the session and doing that in a method taking &self is going to be a challenge, while a &mut self method will make the struct unusable until the channel is dropped.


#3

That was my assumption, but I wonder how to implement such functionality.
I was thinking to create session object in a struct so i will live inside struct, but You telling me this will not work (last sentence).


#4

Note how the Session API has separate fn handshake(&mut self) and fn channel_session(&self) -> Channel. So the easy way is to call them in separate methods, connect once and then make many channels. But just connect(&self) -> Channel is going to be quite tricky.