From 5aa582132909a9159b810ec175b039900862fb39 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Sun, 20 Oct 2019 09:17:56 +0100 Subject: Make Session be `Send` again Refs: https://github.com/alexcrichton/ssh2-rs/issues/137 --- src/agent.rs | 8 ++++---- src/channel.rs | 8 ++++---- src/knownhosts.rs | 8 ++++---- src/listener.rs | 8 ++++---- src/session.rs | 14 +++++++++++--- src/sftp.rs | 8 ++++---- tests/all/session.rs | 10 ++++++++++ 7 files changed, 41 insertions(+), 23 deletions(-) diff --git a/src/agent.rs b/src/agent.rs index 88c84f5..5eb5bc4 100644 --- a/src/agent.rs +++ b/src/agent.rs @@ -1,8 +1,8 @@ use std::ffi::CString; use std::marker; -use std::rc::Rc; use std::slice; use std::str; +use std::sync::Arc; use util::Binding; use {raw, Error, SessionInner}; @@ -12,7 +12,7 @@ use {raw, Error, SessionInner}; /// Agents can be used to authenticate a session. pub struct Agent { raw: *mut raw::LIBSSH2_AGENT, - sess: Rc, + sess: Arc, } /// An iterator over the identities found in an SSH agent. @@ -30,14 +30,14 @@ pub struct PublicKey<'agent> { impl Agent { pub(crate) fn from_raw_opt( raw: *mut raw::LIBSSH2_AGENT, - sess: &Rc, + sess: &Arc, ) -> Result { if raw.is_null() { Err(Error::last_error_raw(sess.raw).unwrap_or_else(Error::unknown)) } else { Ok(Self { raw, - sess: Rc::clone(sess), + sess: Arc::clone(sess), }) } } diff --git a/src/channel.rs b/src/channel.rs index 3beece6..679a6c1 100644 --- a/src/channel.rs +++ b/src/channel.rs @@ -2,8 +2,8 @@ use libc::{c_char, c_int, c_uchar, c_uint, c_ulong, c_void, size_t}; use std::cmp; use std::io; use std::io::prelude::*; -use std::rc::Rc; use std::slice; +use std::sync::Arc; use {raw, Error, ExtendedData, SessionInner}; @@ -17,21 +17,21 @@ use {raw, Error, ExtendedData, SessionInner}; /// flag on a channel's corresponding `Session`. pub struct Channel { raw: *mut raw::LIBSSH2_CHANNEL, - sess: Rc, + sess: Arc, read_limit: Option, } impl Channel { pub(crate) fn from_raw_opt( raw: *mut raw::LIBSSH2_CHANNEL, - sess: &Rc, + sess: &Arc, ) -> Result { if raw.is_null() { Err(Error::last_error_raw(sess.raw).unwrap_or_else(Error::unknown)) } else { Ok(Self { raw, - sess: Rc::clone(sess), + sess: Arc::clone(sess), read_limit: None, }) } diff --git a/src/knownhosts.rs b/src/knownhosts.rs index fcf5b5e..8ebd6bf 100644 --- a/src/knownhosts.rs +++ b/src/knownhosts.rs @@ -2,8 +2,8 @@ use libc::{c_int, size_t}; use std::ffi::CString; use std::marker; use std::path::Path; -use std::rc::Rc; use std::str; +use std::sync::Arc; use util::{self, Binding}; use {raw, CheckResult, Error, KnownHostFileKind, SessionInner}; @@ -46,7 +46,7 @@ use {raw, CheckResult, Error, KnownHostFileKind, SessionInner}; /// ``` pub struct KnownHosts { raw: *mut raw::LIBSSH2_KNOWNHOSTS, - sess: Rc, + sess: Arc, } /// Iterator over the hosts in a `KnownHosts` structure. @@ -64,14 +64,14 @@ pub struct Host<'kh> { impl KnownHosts { pub(crate) fn from_raw_opt( raw: *mut raw::LIBSSH2_KNOWNHOSTS, - sess: &Rc, + sess: &Arc, ) -> Result { if raw.is_null() { Err(Error::last_error_raw(sess.raw).unwrap_or_else(Error::unknown)) } else { Ok(Self { raw, - sess: Rc::clone(sess), + sess: Arc::clone(sess), }) } } diff --git a/src/listener.rs b/src/listener.rs index 229bb78..afd29fd 100644 --- a/src/listener.rs +++ b/src/listener.rs @@ -1,4 +1,4 @@ -use std::rc::Rc; +use std::sync::Arc; use {raw, Channel, Error, SessionInner}; /// A listener represents a forwarding port from the remote server. @@ -7,7 +7,7 @@ use {raw, Channel, Error, SessionInner}; /// the remote server's port. pub struct Listener { raw: *mut raw::LIBSSH2_LISTENER, - sess: Rc, + sess: Arc, } impl Listener { @@ -21,14 +21,14 @@ impl Listener { pub(crate) fn from_raw_opt( raw: *mut raw::LIBSSH2_LISTENER, - sess: &Rc, + sess: &Arc, ) -> Result { if raw.is_null() { Err(Error::last_error_raw(sess.raw).unwrap_or_else(Error::unknown)) } else { Ok(Self { raw, - sess: Rc::clone(sess), + sess: Arc::clone(sess), }) } } diff --git a/src/session.rs b/src/session.rs index 1009b2c..d1b3da2 100644 --- a/src/session.rs +++ b/src/session.rs @@ -7,9 +7,9 @@ use std::ffi::CString; use std::mem; use std::net::TcpStream; use std::path::Path; -use std::rc::Rc; use std::slice; use std::str; +use std::sync::Arc; use util; use {raw, ByApplication, DisconnectCode, Error, HostKeyType}; @@ -68,6 +68,9 @@ pub(crate) struct SessionInner { tcp: RefCell>, } +// The compiler doesn't know that it is Send safe because of the raw +// pointer inside. We know that the way that it is used by libssh2 +// and this crate is Send safe. unsafe impl Send for SessionInner {} /// An SSH session, typically representing one TCP connection. @@ -76,9 +79,14 @@ unsafe impl Send for SessionInner {} /// session. Sessions are created and then have the TCP socket handed to them /// (via the `set_tcp_stream` method). pub struct Session { - inner: Rc, + inner: Arc, } +// The compiler doesn't know that it is Send safe because of the raw +// pointer inside. We know that the way that it is used by libssh2 +// and this crate is Send safe. +unsafe impl Send for Session {} + /// Metadata returned about a remote file when received via `scp`. pub struct ScpFileStat { stat: libc::stat, @@ -101,7 +109,7 @@ impl Session { Err(Error::unknown()) } else { Ok(Session { - inner: Rc::new(SessionInner { + inner: Arc::new(SessionInner { raw: ret, tcp: RefCell::new(None), }), diff --git a/src/sftp.rs b/src/sftp.rs index 396359b..f840a0f 100644 --- a/src/sftp.rs +++ b/src/sftp.rs @@ -3,7 +3,7 @@ use std::io::prelude::*; use std::io::{self, ErrorKind, SeekFrom}; use std::mem; use std::path::{Path, PathBuf}; -use std::rc::Rc; +use std::sync::Arc; use util; use {raw, Error, SessionInner}; @@ -13,7 +13,7 @@ use {raw, Error, SessionInner}; /// Instances are created through the `sftp` method on a `Session`. pub struct Sftp { raw: *mut raw::LIBSSH2_SFTP, - _sess: Rc, + _sess: Arc, } /// A file handle to an SFTP connection. @@ -105,14 +105,14 @@ pub enum OpenType { impl Sftp { pub(crate) fn from_raw_opt( raw: *mut raw::LIBSSH2_SFTP, - sess: &Rc, + sess: &Arc, ) -> Result { if raw.is_null() { Err(Error::last_error_raw(sess.raw).unwrap_or_else(Error::unknown)) } else { Ok(Self { raw, - _sess: Rc::clone(sess), + _sess: Arc::clone(sess), }) } } diff --git a/tests/all/session.rs b/tests/all/session.rs index 93b0a2e..484610f 100644 --- a/tests/all/session.rs +++ b/tests/all/session.rs @@ -6,6 +6,16 @@ use tempdir::TempDir; use ssh2::{HashType, KeyboardInteractivePrompt, MethodType, Prompt, Session}; +#[test] +fn session_is_send() { + fn must_be_send(_: &T) -> bool { + true + } + + let sess = Session::new().unwrap(); + assert!(must_be_send(&sess)); +} + #[test] fn smoke() { let sess = Session::new().unwrap(); -- cgit v1.2.3