1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-23 15:04:36 +03:00

ssh: remove some boilerplate

This commit is contained in:
Wez Furlong 2021-10-19 19:23:13 -07:00
parent 199fd6f52f
commit 74b763a3f6
2 changed files with 145 additions and 350 deletions

View File

@ -10,13 +10,10 @@ use crate::sftp::file::{
CloseFile, File, FileId, FileRequest, FlushFile, FsyncFile, MetadataFile, ReadFile,
SetMetadataFile, WriteFile,
};
use crate::sftp::{
Canonicalize, CreateDir, GetMetadata, OpenDir, OpenWithMode, ReadDir, ReadLink, RemoveDir,
RemoveFile, Rename, SetMetadata, SftpChannelError, SftpChannelResult, SftpRequest, Symlink,
SymlinkMetadata,
};
use crate::sftp::{OpenWithMode, SftpChannelError, SftpChannelResult, SftpRequest};
use crate::sftpwrap::SftpWrap;
use anyhow::{anyhow, Context};
use camino::Utf8PathBuf;
use filedescriptor::{
poll, pollfd, socketpair, AsRawSocketDescriptor, FileDescriptor, POLLIN, POLLOUT,
};
@ -434,17 +431,11 @@ impl SessionInner {
}
Ok(true)
}
SessionRequest::Sftp(SftpRequest::OpenWithMode(msg)) => {
if let Err(err) = self.open_with_mode(sess, &msg) {
log::error!("{:?} -> error: {:#}", msg, err);
}
Ok(true)
SessionRequest::Sftp(SftpRequest::OpenWithMode(msg, reply)) => {
dispatch(reply, || self.open_with_mode(sess, &msg), "OpenWithMode")
}
SessionRequest::Sftp(SftpRequest::OpenDir(msg)) => {
if let Err(err) = self.open_dir(sess, &msg) {
log::error!("{:?} -> error: {:#}", msg, err);
}
Ok(true)
SessionRequest::Sftp(SftpRequest::OpenDir(path, reply)) => {
dispatch(reply, || self.open_dir(sess, path), "OpenDir")
}
SessionRequest::Sftp(SftpRequest::File(FileRequest::Write(msg))) => {
if let Err(err) = self.write_file(sess, &msg) {
@ -500,71 +491,57 @@ impl SessionInner {
}
Ok(true)
}
SessionRequest::Sftp(SftpRequest::ReadDir(msg)) => {
if let Err(err) = self.read_dir(sess, &msg) {
log::error!("{:?} -> error: {:#}", msg, err);
}
Ok(true)
SessionRequest::Sftp(SftpRequest::ReadDir(path, reply)) => {
dispatch(reply, || self.init_sftp(sess)?.read_dir(&path), "read_dir")
}
SessionRequest::Sftp(SftpRequest::CreateDir(msg)) => {
if let Err(err) = self.create_dir(sess, &msg) {
log::error!("{:?} -> error: {:#}", msg, err);
}
Ok(true)
SessionRequest::Sftp(SftpRequest::CreateDir(msg, reply)) => dispatch(
reply,
|| self.init_sftp(sess)?.create_dir(&msg.filename, msg.mode),
"create_dir",
),
SessionRequest::Sftp(SftpRequest::RemoveDir(path, reply)) => dispatch(
reply,
|| self.init_sftp(sess)?.remove_dir(&path),
"remove_dir",
),
SessionRequest::Sftp(SftpRequest::Metadata(path, reply)) => {
dispatch(reply, || self.init_sftp(sess)?.metadata(&path), "metadata")
}
SessionRequest::Sftp(SftpRequest::RemoveDir(msg)) => {
if let Err(err) = self.remove_dir(sess, &msg) {
log::error!("{:?} -> error: {:#}", msg, err);
}
Ok(true)
}
SessionRequest::Sftp(SftpRequest::Metadata(msg)) => {
if let Err(err) = self.metadata(sess, &msg) {
log::error!("{:?} -> error: {:#}", msg, err);
}
Ok(true)
}
SessionRequest::Sftp(SftpRequest::SymlinkMetadata(msg)) => {
if let Err(err) = self.symlink_metadata(sess, &msg) {
log::error!("{:?} -> error: {:#}", msg, err);
}
Ok(true)
}
SessionRequest::Sftp(SftpRequest::SetMetadata(msg)) => {
if let Err(err) = self.set_metadata(sess, &msg) {
log::error!("{:?} -> error: {:#}", msg, err);
}
Ok(true)
}
SessionRequest::Sftp(SftpRequest::Symlink(msg)) => {
if let Err(err) = self.symlink(sess, &msg) {
log::error!("{:?} -> error: {:#}", msg, err);
}
Ok(true)
}
SessionRequest::Sftp(SftpRequest::ReadLink(msg)) => {
if let Err(err) = self.read_link(sess, &msg) {
log::error!("{:?} -> error: {:#}", msg, err);
}
Ok(true)
}
SessionRequest::Sftp(SftpRequest::Canonicalize(msg)) => {
if let Err(err) = self.canonicalize(sess, &msg) {
log::error!("{:?} -> error: {:#}", msg, err);
}
Ok(true)
}
SessionRequest::Sftp(SftpRequest::Rename(msg)) => {
if let Err(err) = self.rename(sess, &msg) {
log::error!("{:?} -> error: {:#}", msg, err);
}
Ok(true)
}
SessionRequest::Sftp(SftpRequest::RemoveFile(msg)) => {
if let Err(err) = self.remove_file(sess, &msg) {
log::error!("{:?} -> error: {:#}", msg, err);
}
Ok(true)
SessionRequest::Sftp(SftpRequest::SymlinkMetadata(path, reply)) => dispatch(
reply,
|| self.init_sftp(sess)?.symlink_metadata(&path),
"symlink_metadata",
),
SessionRequest::Sftp(SftpRequest::SetMetadata(msg, reply)) => dispatch(
reply,
|| {
self.init_sftp(sess)?
.set_metadata(&msg.filename, msg.metadata)
},
"set_metadata",
),
SessionRequest::Sftp(SftpRequest::Symlink(msg, reply)) => dispatch(
reply,
|| self.init_sftp(sess)?.symlink(&msg.path, &msg.target),
"symlink",
),
SessionRequest::Sftp(SftpRequest::ReadLink(path, reply)) => dispatch(
reply,
|| self.init_sftp(sess)?.read_link(&path),
"read_link",
),
SessionRequest::Sftp(SftpRequest::Canonicalize(path, reply)) => dispatch(
reply,
|| self.init_sftp(sess)?.canonicalize(&path),
"canonicalize",
),
SessionRequest::Sftp(SftpRequest::Rename(msg, reply)) => dispatch(
reply,
|| self.init_sftp(sess)?.rename(&msg.src, &msg.dst, msg.opts),
"rename",
),
SessionRequest::Sftp(SftpRequest::RemoveFile(path, reply)) => {
dispatch(reply, || self.init_sftp(sess)?.unlink(&path), "remove_file")
}
};
sess.set_blocking(false);
@ -662,47 +639,33 @@ impl SessionInner {
&mut self,
sess: &mut SessionWrap,
msg: &OpenWithMode,
) -> anyhow::Result<()> {
let result = self
.init_sftp(sess)
.and_then(|sftp| sftp.open(&msg.filename, msg.opts));
) -> SftpChannelResult<File> {
let ssh_file = self.init_sftp(sess)?.open(&msg.filename, msg.opts)?;
match result {
Ok(ssh_file) => {
let file_id = self.next_file_id;
self.next_file_id += 1;
let file_id = self.next_file_id;
self.next_file_id += 1;
let file = File::new(file_id);
let file = File::new(file_id);
msg.reply.try_send(Ok(file))?;
self.files.insert(file_id, ssh_file);
}
Err(x) => msg.reply.try_send(Err(x))?,
}
Ok(())
self.files.insert(file_id, ssh_file);
Ok(file)
}
/// Helper to open a directory for reading its contents.
pub fn open_dir(&mut self, sess: &mut SessionWrap, msg: &OpenDir) -> anyhow::Result<()> {
let result = self
.init_sftp(sess)
.and_then(|sftp| sftp.open_dir(&msg.filename));
pub fn open_dir(
&mut self,
sess: &mut SessionWrap,
path: Utf8PathBuf,
) -> SftpChannelResult<Dir> {
let ssh_dir = self.init_sftp(sess)?.open_dir(&path)?;
match result {
Ok(ssh_file) => {
let dir_id = self.next_file_id;
self.next_file_id += 1;
let dir_id = self.next_file_id;
self.next_file_id += 1;
let dir = Dir::new(dir_id);
let dir = Dir::new(dir_id);
msg.reply.try_send(Ok(dir))?;
self.dirs.insert(dir_id, ssh_file);
}
Err(x) => msg.reply.try_send(Err(x))?,
}
Ok(())
self.dirs.insert(dir_id, ssh_dir);
Ok(dir)
}
/// Writes to a loaded file.
@ -830,127 +793,6 @@ impl SessionInner {
Ok(())
}
/// Convenience function to read the files in a directory.
pub fn read_dir(&mut self, sess: &mut SessionWrap, msg: &ReadDir) -> anyhow::Result<()> {
let result = self
.init_sftp(sess)
.and_then(|sftp| sftp.read_dir(&msg.filename));
msg.reply.try_send(result)?;
Ok(())
}
/// Create a directory on the remote filesystem.
pub fn create_dir(&mut self, sess: &mut SessionWrap, msg: &CreateDir) -> anyhow::Result<()> {
let result = self
.init_sftp(sess)
.and_then(|sftp| sftp.create_dir(&msg.filename, msg.mode));
msg.reply.try_send(result)?;
Ok(())
}
/// Remove a directory from the remote filesystem.
pub fn remove_dir(&mut self, sess: &mut SessionWrap, msg: &RemoveDir) -> anyhow::Result<()> {
let result = self
.init_sftp(sess)
.and_then(|sftp| sftp.remove_dir(&msg.filename));
msg.reply.try_send(result)?;
Ok(())
}
/// Get the metadata for a file, performed by stat(2).
pub fn metadata(&mut self, sess: &mut SessionWrap, msg: &GetMetadata) -> anyhow::Result<()> {
let result = self
.init_sftp(sess)
.and_then(|sftp| sftp.metadata(&msg.filename));
msg.reply.try_send(result)?;
Ok(())
}
/// Get the metadata for a file, performed by lstat(2).
pub fn symlink_metadata(
&mut self,
sess: &mut SessionWrap,
msg: &SymlinkMetadata,
) -> anyhow::Result<()> {
let result = self
.init_sftp(sess)
.and_then(|sftp| sftp.symlink_metadata(&msg.filename));
msg.reply.try_send(result)?;
Ok(())
}
/// Set the metadata for a file.
pub fn set_metadata(
&mut self,
sess: &mut SessionWrap,
msg: &SetMetadata,
) -> anyhow::Result<()> {
let result = self
.init_sftp(sess)
.and_then(|sftp| sftp.set_metadata(&msg.filename, msg.metadata));
msg.reply.try_send(result)?;
Ok(())
}
/// Create symlink at `target` pointing at `path`.
pub fn symlink(&mut self, sess: &mut SessionWrap, msg: &Symlink) -> anyhow::Result<()> {
let result = self
.init_sftp(sess)
.and_then(|sftp| sftp.symlink(&msg.path, &msg.target));
msg.reply.try_send(result)?;
Ok(())
}
/// Read a symlink at `path`.
pub fn read_link(&mut self, sess: &mut SessionWrap, msg: &ReadLink) -> anyhow::Result<()> {
let result = self
.init_sftp(sess)
.and_then(|sftp| sftp.read_link(&msg.path));
msg.reply.try_send(result)?;
Ok(())
}
/// Resolve the real path for `path`.
pub fn canonicalize(
&mut self,
sess: &mut SessionWrap,
msg: &Canonicalize,
) -> anyhow::Result<()> {
let result = self
.init_sftp(sess)
.and_then(|sftp| sftp.canonicalize(&msg.path));
msg.reply.try_send(result)?;
Ok(())
}
/// Rename the filesystem object on the remote filesystem.
pub fn rename(&mut self, sess: &mut SessionWrap, msg: &Rename) -> anyhow::Result<()> {
let result = self.init_sftp(sess).and_then(|sftp| {
sftp.rename(&msg.src, &msg.dst, msg.opts)
.map_err(SftpChannelError::from)
});
msg.reply.try_send(result)?;
Ok(())
}
/// Remove a file on the remote filesystem.
pub fn remove_file(&mut self, sess: &mut SessionWrap, msg: &RemoveFile) -> anyhow::Result<()> {
let result = self.init_sftp(sess).and_then(|sftp| sftp.unlink(&msg.file));
msg.reply.try_send(result)?;
Ok(())
}
/// Initialize the sftp channel if not already created, returning a mutable reference to it
fn init_sftp<'a>(&mut self, sess: &'a mut SessionWrap) -> SftpChannelResult<&'a mut SftpWrap> {
match sess {
@ -1011,3 +853,16 @@ fn read_into_buf<R: Read>(r: &mut R, buf: &mut VecDeque<u8>) -> std::io::Result<
}
}
}
/// A little helper to ensure that the Result returned by `f()`
/// is routed via a Sender
fn dispatch<T, F>(reply: Sender<T>, f: F, what: &str) -> anyhow::Result<bool>
where
F: FnOnce() -> T,
T: Send + Sync + 'static,
{
if let Err(err) = reply.try_send(f()) {
log::error!("{}: {:#}", what, err);
}
Ok(true)
}

View File

@ -75,8 +75,8 @@ impl Sftp {
OpenWithMode {
filename: filename.try_into().map_err(into_invalid_data)?,
opts,
reply,
},
reply,
)))
.await?;
let mut result = rx.recv().await??;
@ -128,10 +128,10 @@ impl Sftp {
{
let (reply, rx) = bounded(1);
self.tx
.send(SessionRequest::Sftp(SftpRequest::OpenDir(OpenDir {
filename: filename.try_into().map_err(into_invalid_data)?,
.send(SessionRequest::Sftp(SftpRequest::OpenDir(
filename.try_into().map_err(into_invalid_data)?,
reply,
})))
)))
.await?;
let mut result = rx.recv().await??;
result.initialize_sender(self.tx.clone());
@ -152,10 +152,10 @@ impl Sftp {
{
let (reply, rx) = bounded(1);
self.tx
.send(SessionRequest::Sftp(SftpRequest::ReadDir(ReadDir {
filename: filename.try_into().map_err(into_invalid_data)?,
.send(SessionRequest::Sftp(SftpRequest::ReadDir(
filename.try_into().map_err(into_invalid_data)?,
reply,
})))
)))
.await?;
let result = rx.recv().await??;
Ok(result)
@ -169,11 +169,13 @@ impl Sftp {
{
let (reply, rx) = bounded(1);
self.tx
.send(SessionRequest::Sftp(SftpRequest::CreateDir(CreateDir {
filename: filename.try_into().map_err(into_invalid_data)?,
mode,
.send(SessionRequest::Sftp(SftpRequest::CreateDir(
CreateDir {
filename: filename.try_into().map_err(into_invalid_data)?,
mode,
},
reply,
})))
)))
.await?;
let result = rx.recv().await??;
Ok(result)
@ -187,10 +189,10 @@ impl Sftp {
{
let (reply, rx) = bounded(1);
self.tx
.send(SessionRequest::Sftp(SftpRequest::RemoveDir(RemoveDir {
filename: filename.try_into().map_err(into_invalid_data)?,
.send(SessionRequest::Sftp(SftpRequest::RemoveDir(
filename.try_into().map_err(into_invalid_data)?,
reply,
})))
)))
.await?;
let result = rx.recv().await??;
Ok(result)
@ -204,10 +206,10 @@ impl Sftp {
{
let (reply, rx) = bounded(1);
self.tx
.send(SessionRequest::Sftp(SftpRequest::Metadata(GetMetadata {
filename: filename.try_into().map_err(into_invalid_data)?,
.send(SessionRequest::Sftp(SftpRequest::Metadata(
filename.try_into().map_err(into_invalid_data)?,
reply,
})))
)))
.await?;
let result = rx.recv().await??;
Ok(result)
@ -222,10 +224,8 @@ impl Sftp {
let (reply, rx) = bounded(1);
self.tx
.send(SessionRequest::Sftp(SftpRequest::SymlinkMetadata(
SymlinkMetadata {
filename: filename.try_into().map_err(into_invalid_data)?,
reply,
},
filename.try_into().map_err(into_invalid_data)?,
reply,
)))
.await?;
let result = rx.recv().await??;
@ -244,8 +244,8 @@ impl Sftp {
SetMetadata {
filename: filename.try_into().map_err(into_invalid_data)?,
metadata,
reply,
},
reply,
)))
.await?;
let result = rx.recv().await??;
@ -262,11 +262,13 @@ impl Sftp {
{
let (reply, rx) = bounded(1);
self.tx
.send(SessionRequest::Sftp(SftpRequest::Symlink(Symlink {
path: path.try_into().map_err(into_invalid_data)?,
target: target.try_into().map_err(into_invalid_data)?,
.send(SessionRequest::Sftp(SftpRequest::Symlink(
Symlink {
path: path.try_into().map_err(into_invalid_data)?,
target: target.try_into().map_err(into_invalid_data)?,
},
reply,
})))
)))
.await?;
let result = rx.recv().await??;
Ok(result)
@ -280,10 +282,10 @@ impl Sftp {
{
let (reply, rx) = bounded(1);
self.tx
.send(SessionRequest::Sftp(SftpRequest::ReadLink(ReadLink {
path: path.try_into().map_err(into_invalid_data)?,
.send(SessionRequest::Sftp(SftpRequest::ReadLink(
path.try_into().map_err(into_invalid_data)?,
reply,
})))
)))
.await?;
let result = rx.recv().await??;
Ok(result)
@ -298,10 +300,8 @@ impl Sftp {
let (reply, rx) = bounded(1);
self.tx
.send(SessionRequest::Sftp(SftpRequest::Canonicalize(
Canonicalize {
path: path.try_into().map_err(into_invalid_data)?,
reply,
},
path.try_into().map_err(into_invalid_data)?,
reply,
)))
.await?;
let result = rx.recv().await??;
@ -323,12 +323,14 @@ impl Sftp {
{
let (reply, rx) = bounded(1);
self.tx
.send(SessionRequest::Sftp(SftpRequest::Rename(Rename {
src: src.try_into().map_err(into_invalid_data)?,
dst: dst.try_into().map_err(into_invalid_data)?,
opts,
.send(SessionRequest::Sftp(SftpRequest::Rename(
Rename {
src: src.try_into().map_err(into_invalid_data)?,
dst: dst.try_into().map_err(into_invalid_data)?,
opts,
},
reply,
})))
)))
.await?;
let result = rx.recv().await??;
Ok(result)
@ -342,10 +344,10 @@ impl Sftp {
{
let (reply, rx) = bounded(1);
self.tx
.send(SessionRequest::Sftp(SftpRequest::RemoveFile(RemoveFile {
file: file.try_into().map_err(into_invalid_data)?,
.send(SessionRequest::Sftp(SftpRequest::RemoveFile(
file.try_into().map_err(into_invalid_data)?,
reply,
})))
)))
.await?;
let result = rx.recv().await??;
Ok(result)
@ -354,19 +356,22 @@ impl Sftp {
#[derive(Debug)]
pub(crate) enum SftpRequest {
OpenWithMode(OpenWithMode),
OpenDir(OpenDir),
ReadDir(ReadDir),
CreateDir(CreateDir),
RemoveDir(RemoveDir),
Metadata(GetMetadata),
SymlinkMetadata(SymlinkMetadata),
SetMetadata(SetMetadata),
Symlink(Symlink),
ReadLink(ReadLink),
Canonicalize(Canonicalize),
Rename(Rename),
RemoveFile(RemoveFile),
OpenWithMode(OpenWithMode, Sender<SftpChannelResult<File>>),
OpenDir(Utf8PathBuf, Sender<SftpChannelResult<Dir>>),
ReadDir(
Utf8PathBuf,
Sender<SftpChannelResult<Vec<(Utf8PathBuf, Metadata)>>>,
),
CreateDir(CreateDir, Sender<SftpChannelResult<()>>),
RemoveDir(Utf8PathBuf, Sender<SftpChannelResult<()>>),
Metadata(Utf8PathBuf, Sender<SftpChannelResult<Metadata>>),
SymlinkMetadata(Utf8PathBuf, Sender<SftpChannelResult<Metadata>>),
SetMetadata(SetMetadata, Sender<SftpChannelResult<()>>),
Symlink(Symlink, Sender<SftpChannelResult<()>>),
ReadLink(Utf8PathBuf, Sender<SftpChannelResult<Utf8PathBuf>>),
Canonicalize(Utf8PathBuf, Sender<SftpChannelResult<Utf8PathBuf>>),
Rename(Rename, Sender<SftpChannelResult<()>>),
RemoveFile(Utf8PathBuf, Sender<SftpChannelResult<()>>),
/// Specialized type for file-based operations
File(FileRequest),
@ -377,82 +382,24 @@ pub(crate) enum SftpRequest {
pub(crate) struct OpenWithMode {
pub filename: Utf8PathBuf,
pub opts: OpenOptions,
pub reply: Sender<SftpChannelResult<File>>,
}
#[derive(Debug)]
pub(crate) struct Open {
pub filename: Utf8PathBuf,
pub reply: Sender<SftpChannelResult<File>>,
}
#[derive(Debug)]
pub(crate) struct Create {
pub filename: Utf8PathBuf,
pub reply: Sender<SftpChannelResult<File>>,
}
#[derive(Debug)]
pub(crate) struct OpenDir {
pub filename: Utf8PathBuf,
pub reply: Sender<SftpChannelResult<Dir>>,
}
#[derive(Debug)]
pub(crate) struct ReadDir {
pub filename: Utf8PathBuf,
pub reply: Sender<SftpChannelResult<Vec<(Utf8PathBuf, Metadata)>>>,
}
#[derive(Debug)]
pub(crate) struct CreateDir {
pub filename: Utf8PathBuf,
pub mode: i32,
pub reply: Sender<SftpChannelResult<()>>,
}
#[derive(Debug)]
pub(crate) struct RemoveDir {
pub filename: Utf8PathBuf,
pub reply: Sender<SftpChannelResult<()>>,
}
#[derive(Debug)]
pub(crate) struct GetMetadata {
pub filename: Utf8PathBuf,
pub reply: Sender<SftpChannelResult<Metadata>>,
}
#[derive(Debug)]
pub(crate) struct SymlinkMetadata {
pub filename: Utf8PathBuf,
pub reply: Sender<SftpChannelResult<Metadata>>,
}
#[derive(Debug)]
pub(crate) struct SetMetadata {
pub filename: Utf8PathBuf,
pub metadata: Metadata,
pub reply: Sender<SftpChannelResult<()>>,
}
#[derive(Debug)]
pub(crate) struct Symlink {
pub path: Utf8PathBuf,
pub target: Utf8PathBuf,
pub reply: Sender<SftpChannelResult<()>>,
}
#[derive(Debug)]
pub(crate) struct ReadLink {
pub path: Utf8PathBuf,
pub reply: Sender<SftpChannelResult<Utf8PathBuf>>,
}
#[derive(Debug)]
pub(crate) struct Canonicalize {
pub path: Utf8PathBuf,
pub reply: Sender<SftpChannelResult<Utf8PathBuf>>,
}
#[derive(Debug)]
@ -460,13 +407,6 @@ pub(crate) struct Rename {
pub src: Utf8PathBuf,
pub dst: Utf8PathBuf,
pub opts: RenameOptions,
pub reply: Sender<SftpChannelResult<()>>,
}
#[derive(Debug)]
pub(crate) struct RemoveFile {
pub file: Utf8PathBuf,
pub reply: Sender<SftpChannelResult<()>>,
}
impl From<ssh2::Error> for SftpChannelError {