aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2019-10-14 15:10:37 -0400
committerJesse Luehrs <doy@tozt.net>2019-10-14 15:10:37 -0400
commit05a26723ee1329cf8e809961d5d7bc4fda6e1db6 (patch)
tree8ee83acee78c82731b12e23563f97e13f37c1f0a
parent9f530b0022b670c7480b26b4c6614df2d04b4700 (diff)
downloadteleterm-05a26723ee1329cf8e809961d5d7bc4fda6e1db6.tar.gz
teleterm-05a26723ee1329cf8e809961d5d7bc4fda6e1db6.zip
consolidate errors
-rw-r--r--src/client.rs45
-rw-r--r--src/cmd.rs37
-rw-r--r--src/cmd/play.rs37
-rw-r--r--src/cmd/record.rs51
-rw-r--r--src/cmd/server.rs110
-rw-r--r--src/cmd/stream.rs58
-rw-r--r--src/cmd/watch.rs92
-rw-r--r--src/error.rs253
-rw-r--r--src/key_reader.rs25
-rw-r--r--src/prelude.rs2
-rw-r--r--src/process.rs53
-rw-r--r--src/protocol.rs73
-rw-r--r--src/server.rs93
-rw-r--r--src/server/tls.rs32
-rw-r--r--src/term.rs19
-rw-r--r--src/ttyrec.rs38
-rw-r--r--src/util.rs39
17 files changed, 441 insertions, 616 deletions
diff --git a/src/client.rs b/src/client.rs
index 9ef1ae2..75edfbf 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -1,29 +1,6 @@
use crate::prelude::*;
use rand::Rng as _;
-#[derive(Debug, snafu::Snafu)]
-pub enum Error {
- #[snafu(display("{}", source))]
- Common { source: crate::error::Error },
-
- #[snafu(display("{}", source))]
- Resize { source: crate::term::Error },
-
- #[snafu(display("heartbeat timer failed: {}", source))]
- Timer { source: tokio::timer::Error },
-
- #[snafu(display("failed to read message from server: {}", source))]
- ReadServer { source: crate::protocol::Error },
-
- #[snafu(display("failed to write message to server: {}", source))]
- WriteServer { source: crate::protocol::Error },
-
- #[snafu(display("SIGWINCH handler failed: {}", source))]
- SigWinchHandler { source: std::io::Error },
-}
-
-pub type Result<T> = std::result::Result<T, Error>;
-
const HEARTBEAT_DURATION: std::time::Duration =
std::time::Duration::from_secs(30);
const RECONNECT_BACKOFF_BASE: std::time::Duration =
@@ -170,7 +147,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
)
.flatten_stream()
.map(|_| ())
- .context(SigWinchHandler);
+ .context(crate::error::SigWinchHandler);
Some(Box::new(winches))
} else {
None
@@ -261,7 +238,10 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
match &mut self.wsock {
WriteSocket::NotConnected => {
if let Some(timer) = &mut self.reconnect_timer {
- match timer.poll().context(Timer)? {
+ match timer
+ .poll()
+ .context(crate::error::TimerReconnect)?
+ {
futures::Async::Ready(..) => {
self.reconnect_timer = None;
}
@@ -299,7 +279,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
let term = std::env::var("TERM")
.unwrap_or_else(|_| "".to_string());
- let size = crate::term::Size::get().context(Resize)?;
+ let size = crate::term::Size::get()?;
let msg = crate::protocol::Message::login_plain(
&self.username,
&term,
@@ -342,8 +322,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
let mut tmp = ReadSocket::NotConnected;
std::mem::swap(&mut self.rsock, &mut tmp);
if let ReadSocket::Connected(s) = tmp {
- let fut = crate::protocol::Message::read_async(s)
- .context(ReadServer);
+ let fut = crate::protocol::Message::read_async(s);
self.rsock = ReadSocket::ReadingMessage(Box::new(fut));
} else {
unreachable!()
@@ -392,7 +371,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
std::mem::swap(&mut self.wsock, &mut tmp);
if let WriteSocket::Connected(s) = tmp {
if let Some(msg) = self.to_send.pop_front() {
- let fut = msg.write_async(s).context(WriteServer);
+ let fut = msg.write_async(s);
self.wsock =
WriteSocket::WritingMessage(Box::new(fut));
} else {
@@ -424,7 +403,11 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
fn poll_heartbeat(
&mut self,
) -> Result<crate::component_future::Poll<Event>> {
- match self.heartbeat_timer.poll().context(Timer)? {
+ match self
+ .heartbeat_timer
+ .poll()
+ .context(crate::error::TimerHeartbeat)?
+ {
futures::Async::Ready(..) => {
self.send_message(crate::protocol::Message::heartbeat());
Ok(crate::component_future::Poll::DidWork)
@@ -441,7 +424,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
if let Some(winches) = &mut self.winches {
match winches.poll()? {
futures::Async::Ready(Some(_)) => {
- let size = crate::term::Size::get().context(Resize)?;
+ let size = crate::term::Size::get()?;
self.send_message(crate::protocol::Message::resize(
&size,
));
diff --git a/src/cmd.rs b/src/cmd.rs
index 93f1ed8..6566e18 100644
--- a/src/cmd.rs
+++ b/src/cmd.rs
@@ -6,32 +6,6 @@ mod server;
mod stream;
mod watch;
-#[derive(Debug, snafu::Snafu)]
-pub enum Error {
- #[snafu(display("failed to determine program name: {}", source))]
- FindProgramName { source: crate::util::Error },
-
- #[snafu(display("{}", source))]
- Parse { source: clap::Error },
-
- #[snafu(display("{}", source))]
- Play { source: crate::cmd::play::Error },
-
- #[snafu(display("{}", source))]
- Record { source: crate::cmd::record::Error },
-
- #[snafu(display("{}", source))]
- Stream { source: crate::cmd::stream::Error },
-
- #[snafu(display("{}", source))]
- Server { source: crate::cmd::server::Error },
-
- #[snafu(display("{}", source))]
- Watch { source: crate::cmd::watch::Error },
-}
-
-pub type Result<T> = std::result::Result<T, Error>;
-
struct Command {
name: &'static str,
cmd: &'static dyn for<'a, 'b> Fn(clap::App<'a, 'b>) -> clap::App<'a, 'b>,
@@ -67,18 +41,17 @@ const COMMANDS: &[Command] = &[
];
pub fn parse<'a>() -> Result<clap::ArgMatches<'a>> {
- let mut app =
- clap::App::new(crate::util::program_name().context(FindProgramName)?)
- .about("Stream your terminal for other people to watch")
- .author(clap::crate_authors!())
- .version(clap::crate_version!());
+ let mut app = clap::App::new(crate::util::program_name()?)
+ .about("Stream your terminal for other people to watch")
+ .author(clap::crate_authors!())
+ .version(clap::crate_version!());
for cmd in COMMANDS {
let subcommand = clap::SubCommand::with_name(cmd.name);
app = app.subcommand((cmd.cmd)(subcommand));
}
- app.get_matches_safe().context(Parse)
+ app.get_matches_safe().context(crate::error::ParseArgs)
}
pub fn run(matches: &clap::ArgMatches<'_>) -> Result<()> {
diff --git a/src/cmd/play.rs b/src/cmd/play.rs
index 1a337fa..996fd90 100644
--- a/src/cmd/play.rs
+++ b/src/cmd/play.rs
@@ -1,29 +1,6 @@
use crate::prelude::*;
use std::io::Write as _;
-#[derive(Debug, snafu::Snafu)]
-pub enum Error {
- #[snafu(display("{}", source))]
- Common { source: crate::error::Error },
-
- #[snafu(display("failed to open file: {}", source))]
- OpenFile { source: tokio::io::Error },
-
- #[snafu(display("failed to sleep until next frame: {}", source))]
- Sleep { source: tokio::timer::Error },
-
- #[snafu(display("failed to write to stdout: {}", source))]
- WriteTerminal { source: tokio::io::Error },
-
- #[snafu(display("failed to write to stdout: {}", source))]
- FlushTerminal { source: tokio::io::Error },
-
- #[snafu(display("failed to read from file: {}", source))]
- ReadFile { source: crate::ttyrec::Error },
-}
-
-pub type Result<T> = std::result::Result<T, Error>;
-
pub fn cmd<'a, 'b>(app: clap::App<'a, 'b>) -> clap::App<'a, 'b> {
app.about("Play recorded terminal sessions").arg(
clap::Arg::with_name("filename")
@@ -33,9 +10,9 @@ pub fn cmd<'a, 'b>(app: clap::App<'a, 'b>) -> clap::App<'a, 'b> {
)
}
-pub fn run<'a>(matches: &clap::ArgMatches<'a>) -> super::Result<()> {
+pub fn run<'a>(matches: &clap::ArgMatches<'a>) -> Result<()> {
let filename = matches.value_of("filename").unwrap();
- run_impl(filename).context(super::Play)
+ run_impl(filename)
}
fn run_impl(filename: &str) -> Result<()> {
@@ -100,7 +77,7 @@ impl PlaySession {
Ok(crate::component_future::Poll::DidWork)
}
FileState::Opening { fut } => {
- match fut.poll().context(OpenFile)? {
+ match fut.poll().context(crate::error::OpenFile)? {
futures::Async::Ready(file) => {
let file = crate::ttyrec::File::new(file);
self.file = FileState::Open { file };
@@ -119,7 +96,7 @@ impl PlaySession {
&mut self,
) -> Result<crate::component_future::Poll<()>> {
if let FileState::Open { file } = &mut self.file {
- match file.poll_read().context(ReadFile)? {
+ match file.poll_read()? {
futures::Async::Ready(Some(frame)) => {
self.to_write.insert_at(frame.data, frame.time);
Ok(crate::component_future::Poll::DidWork)
@@ -140,13 +117,13 @@ impl PlaySession {
fn poll_write_terminal(
&mut self,
) -> Result<crate::component_future::Poll<()>> {
- match self.to_write.poll().context(Sleep)? {
+ match self.to_write.poll().context(crate::error::Sleep)? {
futures::Async::Ready(Some(data)) => {
// TODO async
let stdout = std::io::stdout();
let mut stdout = stdout.lock();
- stdout.write(&data).context(WriteTerminal)?;
- stdout.flush().context(FlushTerminal)?;
+ stdout.write(&data).context(crate::error::WriteTerminal)?;
+ stdout.flush().context(crate::error::FlushTerminal)?;
Ok(crate::component_future::Poll::DidWork)
}
futures::Async::Ready(None) => {
diff --git a/src/cmd/record.rs b/src/cmd/record.rs
index 5f9e8c4..4577687 100644
--- a/src/cmd/record.rs
+++ b/src/cmd/record.rs
@@ -1,29 +1,6 @@
use crate::prelude::*;
use tokio::io::AsyncWrite as _;
-#[derive(Debug, snafu::Snafu)]
-pub enum Error {
- #[snafu(display("{}", source))]
- Common { source: crate::error::Error },
-
- #[snafu(display("process failed: {}", source))]
- Process { source: crate::process::Error },
-
- #[snafu(display("failed to write to stdout: {}", source))]
- WriteTerminal { source: tokio::io::Error },
-
- #[snafu(display("failed to write to stdout: {}", source))]
- FlushTerminal { source: tokio::io::Error },
-
- #[snafu(display("failed to open file: {}", source))]
- OpenFile { source: tokio::io::Error },
-
- #[snafu(display("failed to write to file: {}", source))]
- WriteFile { source: crate::ttyrec::Error },
-}
-
-pub type Result<T> = std::result::Result<T, Error>;
-
pub fn cmd<'a, 'b>(app: clap::App<'a, 'b>) -> clap::App<'a, 'b> {
app.about("Record a terminal session to a file")
.arg(
@@ -41,7 +18,7 @@ pub fn cmd<'a, 'b>(app: clap::App<'a, 'b>) -> clap::App<'a, 'b> {
.arg(clap::Arg::with_name("args").index(2).multiple(true))
}
-pub fn run<'a>(matches: &clap::ArgMatches<'a>) -> super::Result<()> {
+pub fn run<'a>(matches: &clap::ArgMatches<'a>) -> Result<()> {
let filename = matches.value_of("filename").unwrap();
let buffer_size =
matches
@@ -49,8 +26,6 @@ pub fn run<'a>(matches: &clap::ArgMatches<'a>) -> super::Result<()> {
.map_or(Ok(4 * 1024 * 1024), |s| {
s.parse()
.context(crate::error::ParseBufferSize { input: s })
- .context(Common)
- .context(super::Record)
})?;
let command = matches.value_of("command").map_or_else(
|| std::env::var("SHELL").unwrap_or_else(|_| "/bin/bash".to_string()),
@@ -61,7 +36,7 @@ pub fn run<'a>(matches: &clap::ArgMatches<'a>) -> super::Result<()> {
} else {
vec![]
};
- run_impl(filename, buffer_size, &command, &args).context(super::Record)
+ run_impl(filename, buffer_size, &command, &args)
}
fn run_impl(
@@ -159,11 +134,10 @@ impl RecordSession {
Ok(crate::component_future::Poll::DidWork)
}
FileState::Opening { fut } => {
- match fut.poll().context(OpenFile)? {
+ match fut.poll().context(crate::error::OpenFile)? {
futures::Async::Ready(file) => {
let mut file = crate::ttyrec::File::new(file);
- file.write_frame(self.buffer.contents())
- .context(WriteFile)?;
+ file.write_frame(self.buffer.contents())?;
self.file = FileState::Open { file };
Ok(crate::component_future::Poll::DidWork)
}
@@ -181,7 +155,7 @@ impl RecordSession {
fn poll_read_process(
&mut self,
) -> Result<crate::component_future::Poll<()>> {
- match self.process.poll().context(Process)? {
+ match self.process.poll()? {
futures::Async::Ready(Some(e)) => {
match e {
crate::process::Event::CommandStart(..) => {}
@@ -191,7 +165,7 @@ impl RecordSession {
crate::process::Event::Output(output) => {
self.record_bytes(&output);
if let FileState::Open { file } = &mut self.file {
- file.write_frame(&output).context(WriteFile)?;
+ file.write_frame(&output)?;
}
}
}
@@ -221,7 +195,7 @@ impl RecordSession {
match self
.stdout
.poll_write(&self.buffer.contents()[self.sent_local..])
- .context(WriteTerminal)?
+ .context(crate::error::WriteTerminal)?
{
futures::Async::Ready(n) => {
self.sent_local += n;
@@ -241,7 +215,11 @@ impl RecordSession {
return Ok(crate::component_future::Poll::NothingToDo);
}
- match self.stdout.poll_flush().context(FlushTerminal)? {
+ match self
+ .stdout
+ .poll_flush()
+ .context(crate::error::FlushTerminal)?
+ {
futures::Async::Ready(()) => {
self.needs_flush = false;
Ok(crate::component_future::Poll::DidWork)
@@ -262,7 +240,7 @@ impl RecordSession {
}
};
- match file.poll_write().context(WriteFile)? {
+ match file.poll_write()? {
futures::Async::Ready(()) => {
Ok(crate::component_future::Poll::DidWork)
}
@@ -287,8 +265,7 @@ impl futures::future::Future for RecordSession {
if self.raw_screen.is_none() {
self.raw_screen = Some(
crossterm::RawScreen::into_raw_mode()
- .context(crate::error::IntoRawMode)
- .context(Common)?,
+ .context(crate::error::ToRawMode)?,
);
}
crate::component_future::poll_future(self, Self::POLL_FNS)
diff --git a/src/cmd/server.rs b/src/cmd/server.rs
index a4ccc8f..07d9321 100644
--- a/src/cmd/server.rs
+++ b/src/cmd/server.rs
@@ -1,62 +1,6 @@
use crate::prelude::*;
use std::io::Read as _;
-#[derive(Debug, snafu::Snafu)]
-pub enum Error {
- #[snafu(display("{}", source))]
- Common { source: crate::error::Error },
-
- #[snafu(display("failed to bind: {}", source))]
- Bind { source: tokio::io::Error },
-
- #[snafu(display(
- "failed to parse read timeout '{}': {}",
- input,
- source
- ))]
- ParseReadTimeout {
- input: String,
- source: std::num::ParseIntError,
- },
-
- #[snafu(display("failed to accept: {}", source))]
- Acceptor { source: tokio::io::Error },
-
- #[snafu(display(
- "failed to send accepted socket to server thread: {}",
- source
- ))]
- SocketChannel {
- source: tokio::sync::mpsc::error::TrySendError<tokio::net::TcpStream>,
- },
-
- #[snafu(display("failed to send accepted socket to server thread"))]
- TlsSocketChannel {
- // XXX tokio_tls::Accept doesn't implement Debug or Display
- // source: tokio::sync::mpsc::error::TrySendError<tokio_tls::Accept<tokio::net::TcpStream>>,
- },
-
- #[snafu(display("failed to run server: {}", source))]
- Server { source: crate::server::Error },
-
- #[snafu(display("failed to run server: {}", source))]
- TlsServer { source: crate::server::tls::Error },
-
- #[snafu(display("failed to open identity file: {}", source))]
- OpenIdentityFile { source: std::io::Error },
-
- #[snafu(display("failed to read identity file: {}", source))]
- ReadIdentityFile { source: std::io::Error },
-
- #[snafu(display("failed to parse identity file: {}", source))]
- ParseIdentity { source: native_tls::Error },
-
- #[snafu(display("failed to create tls acceptor: {}", source))]
- CreateAcceptor { source: native_tls::Error },
-}
-
-pub type Result<T> = std::result::Result<T, Error>;
-
pub fn cmd<'a, 'b>(app: clap::App<'a, 'b>) -> clap::App<'a, 'b> {
app.about("Run a teleterm server")
.arg(
@@ -84,12 +28,7 @@ pub fn cmd<'a, 'b>(app: clap::App<'a, 'b>) -> clap::App<'a, 'b> {
pub fn run<'a>(matches: &clap::ArgMatches<'a>) -> super::Result<()> {
let address = matches.value_of("address").map_or_else(
|| Ok("0.0.0.0:4144".parse().unwrap()),
- |s| {
- s.parse()
- .context(crate::error::ParseAddr)
- .context(Common)
- .context(super::Server)
- },
+ |s| s.parse().context(crate::error::ParseAddr),
)?;
let buffer_size =
matches
@@ -97,21 +36,17 @@ pub fn run<'a>(matches: &clap::ArgMatches<'a>) -> super::Result<()> {
.map_or(Ok(4 * 1024 * 1024), |s| {
s.parse()
.context(crate::error::ParseBufferSize { input: s })
- .context(Common)
- .context(super::Server)
})?;
let read_timeout = matches.value_of("read-timeout").map_or(
Ok(std::time::Duration::from_secs(120)),
|s| {
s.parse()
.map(std::time::Duration::from_secs)
- .context(ParseReadTimeout { input: s })
- .context(super::Server)
+ .context(crate::error::ParseReadTimeout { input: s })
},
)?;
let tls_identity_file = matches.value_of("tls-identity-file");
run_impl(address, buffer_size, read_timeout, tls_identity_file)
- .context(super::Server)
}
fn run_impl(
@@ -152,14 +87,18 @@ fn create_server(
Box<dyn futures::future::Future<Item = (), Error = Error> + Send>,
)> {
let (mut sock_w, sock_r) = tokio::sync::mpsc::channel(100);
- let listener = tokio::net::TcpListener::bind(&address).context(Bind)?;
+ let listener = tokio::net::TcpListener::bind(&address)
+ .context(crate::error::Bind)?;
let acceptor = listener
.incoming()
- .context(Acceptor)
- .for_each(move |sock| sock_w.try_send(sock).context(SocketChannel));
+ .context(crate::error::Acceptor)
+ .for_each(move |sock| {
+ sock_w
+ .try_send(sock)
+ .context(crate::error::SendSocketChannel)
+ });
let server =
- crate::server::Server::new(buffer_size, read_timeout, sock_r)
- .context(Server);
+ crate::server::Server::new(buffer_size, read_timeout, sock_r);
Ok((Box::new(acceptor), Box::new(server)))
}
@@ -173,27 +112,30 @@ fn create_server_tls(
Box<dyn futures::future::Future<Item = (), Error = Error> + Send>,
)> {
let (mut sock_w, sock_r) = tokio::sync::mpsc::channel(100);
- let listener = tokio::net::TcpListener::bind(&address).context(Bind)?;
+ let listener = tokio::net::TcpListener::bind(&address)
+ .context(crate::error::Bind)?;
- let mut file =
- std::fs::File::open(tls_identity_file).context(OpenIdentityFile)?;
+ let mut file = std::fs::File::open(tls_identity_file)
+ .context(crate::error::OpenIdentityFile)?;
let mut identity = vec![];
- file.read_to_end(&mut identity).context(ReadIdentityFile)?;
+ file.read_to_end(&mut identity)
+ .context(crate::error::ReadIdentityFile)?;
let identity = native_tls::Identity::from_pkcs12(&identity, "")
- .context(ParseIdentity)?;
- let acceptor =
- native_tls::TlsAcceptor::new(identity).context(CreateAcceptor)?;
+ .context(crate::error::ParseIdentity)?;
+ let acceptor = native_tls::TlsAcceptor::new(identity)
+ .context(crate::error::CreateAcceptor)?;
let acceptor = tokio_tls::TlsAcceptor::from(acceptor);
- let acceptor =
- listener.incoming().context(Acceptor).for_each(move |sock| {
+ let acceptor = listener
+ .incoming()
+ .context(crate::error::Acceptor)
+ .for_each(move |sock| {
let sock = acceptor.accept(sock);
sock_w
.try_send(sock)
- .map_err(|_| Error::TlsSocketChannel {})
+ .map_err(|_| Error::SendSocketChannelTls {})
});
let server =
- crate::server::tls::Server::new(buffer_size, read_timeout, sock_r)
- .context(TlsServer);
+ crate::server::tls::Server::new(buffer_size, read_timeout, sock_r);
Ok((Box::new(acceptor), Box::new(server)))
}
diff --git a/src/cmd/stream.rs b/src/cmd/stream.rs
index b14c063..dac3d2c 100644
--- a/src/cmd/stream.rs
+++ b/src/cmd/stream.rs
@@ -1,32 +1,6 @@
use crate::prelude::*;
use tokio::io::AsyncWrite as _;
-#[derive(Debug, snafu::Snafu)]
-pub enum Error {
- #[snafu(display("{}", source))]
- Common { source: crate::error::Error },
-
- #[snafu(display("{}", source))]
- Util { source: crate::util::Error },
-
- #[snafu(display("failed to write to stdout: {}", source))]
- WriteTerminal { source: tokio::io::Error },
-
- #[snafu(display("failed to write to stdout: {}", source))]
- FlushTerminal { source: tokio::io::Error },
-
- #[snafu(display("process failed: {}", source))]
- Process { source: crate::process::Error },
-
- #[snafu(display("communication with server failed: {}", source))]
- Client { source: crate::client::Error },
-
- #[snafu(display("failed to create tls connector: {}", source))]
- CreateConnector { source: native_tls::Error },
-}
-
-pub type Result<T> = std::result::Result<T, Error>;
-
pub fn cmd<'a, 'b>(app: clap::App<'a, 'b>) -> clap::App<'a, 'b> {
app.about("Stream your terminal")
.arg(
@@ -54,13 +28,9 @@ pub fn run<'a>(matches: &clap::ArgMatches<'a>) -> super::Result<()> {
.value_of("username")
.map(std::string::ToString::to_string)
.or_else(|| std::env::var("USER").ok())
- .context(crate::error::CouldntFindUsername)
- .context(Common)
- .context(super::Stream)?;
+ .context(crate::error::CouldntFindUsername)?;
let (host, address) =
- crate::util::resolve_address(matches.value_of("address"))
- .context(Util)
- .context(super::Stream)?;
+ crate::util::resolve_address(matches.value_of("address"))?;
let tls = matches.is_present("tls");
let buffer_size =
matches
@@ -68,8 +38,6 @@ pub fn run<'a>(matches: &clap::ArgMatches<'a>) -> super::Result<()> {
.map_or(Ok(4 * 1024 * 1024), |s| {
s.parse()
.context(crate::error::ParseBufferSize { input: s })
- .context(Common)
- .context(super::Stream)
})?;
let command = matches.value_of("command").map_or_else(
|| std::env::var("SHELL").unwrap_or_else(|_| "/bin/bash".to_string()),
@@ -81,7 +49,6 @@ pub fn run<'a>(matches: &clap::ArgMatches<'a>) -> super::Result<()> {
vec![]
};
run_impl(&username, &host, address, tls, buffer_size, &command, &args)
- .context(super::Stream)
}
fn run_impl(
@@ -97,8 +64,8 @@ fn run_impl(
let fut: Box<
dyn futures::future::Future<Item = (), Error = Error> + Send,
> = if tls {
- let connector =
- native_tls::TlsConnector::new().context(CreateConnector)?;
+ let connector = native_tls::TlsConnector::new()
+ .context(crate::error::CreateConnector)?;
let connect: crate::client::Connector<_> = Box::new(move || {
let host = host.clone();
let connector = connector.clone();
@@ -108,7 +75,7 @@ fn run_impl(
move |stream| {
connector
.connect(&host, stream)
- .context(crate::error::TlsConnect)
+ .context(crate::error::ConnectTls)
},
))
});
@@ -223,7 +190,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
fn poll_read_client(
&mut self,
) -> Result<crate::component_future::Poll<()>> {
- match self.client.poll().context(Client) {
+ match self.client.poll() {
Ok(futures::Async::Ready(Some(e))) => match e {
crate::client::Event::Disconnect => {
Ok(crate::component_future::Poll::DidWork)
@@ -262,7 +229,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
fn poll_read_process(
&mut self,
) -> Result<crate::component_future::Poll<()>> {
- match self.process.poll().context(Process)? {
+ match self.process.poll()? {
futures::Async::Ready(Some(e)) => {
match e {
crate::process::Event::CommandStart(..) => {}
@@ -299,7 +266,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
match self
.stdout
.poll_write(&self.buffer.contents()[self.sent_local..])
- .context(WriteTerminal)?
+ .context(crate::error::WriteTerminal)?
{
futures::Async::Ready(n) => {
self.sent_local += n;
@@ -319,7 +286,11 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
return Ok(crate::component_future::Poll::NothingToDo);
}
- match self.stdout.poll_flush().context(FlushTerminal)? {
+ match self
+ .stdout
+ .poll_flush()
+ .context(crate::error::FlushTerminal)?
+ {
futures::Async::Ready(()) => {
self.needs_flush = false;
Ok(crate::component_future::Poll::DidWork)
@@ -362,8 +333,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
if self.raw_screen.is_none() {
self.raw_screen = Some(
crossterm::RawScreen::into_raw_mode()
- .context(crate::error::IntoRawMode)
- .context(Common)?,
+ .context(crate::error::ToRawMode)?,
);
}
crate::component_future::poll_future(self, Self::POLL_FNS)
diff --git a/src/cmd/watch.rs b/src/cmd/watch.rs
index 6b395e2..3129bba 100644
--- a/src/cmd/watch.rs
+++ b/src/cmd/watch.rs
@@ -1,44 +1,6 @@
use crate::prelude::*;
use std::io::Write as _;
-#[derive(Debug, snafu::Snafu)]
-pub enum Error {
- #[snafu(display("{}", source))]
- Common { source: crate::error::Error },
-
- #[snafu(display("{}", source))]
- Util { source: crate::util::Error },
-
- #[snafu(display("{}", source))]
- Resize { source: crate::term::Error },
-
- #[snafu(display("failed to read key from terminal: {}", source))]
- ReadKey { source: crate::key_reader::Error },
-
- #[snafu(display("failed to write to terminal: {}", source))]
- WriteTerminal { source: std::io::Error },
-
- #[snafu(display("failed to write to terminal: {}", source))]
- WriteTerminalCrossterm { source: crossterm::ErrorKind },
-
- #[snafu(display("failed to flush writes to terminal: {}", source))]
- FlushTerminal { source: std::io::Error },
-
- #[snafu(display("communication with server failed: {}", source))]
- Client { source: crate::client::Error },
-
- #[snafu(display("received error from server: {}", message))]
- Server { message: String },
-
- #[snafu(display("failed to switch to alternate screen: {}", source))]
- ToAlternateScreen { source: crossterm::ErrorKind },
-
- #[snafu(display("failed to create tls connector: {}", source))]
- CreateConnector { source: native_tls::Error },
-}
-
-pub type Result<T> = std::result::Result<T, Error>;
-
pub fn cmd<'a, 'b>(app: clap::App<'a, 'b>) -> clap::App<'a, 'b> {
app.about("Watch teleterm streams")
.arg(
@@ -59,15 +21,11 @@ pub fn run<'a>(matches: &clap::ArgMatches<'a>) -> super::Result<()> {
.value_of("username")
.map(std::string::ToString::to_string)
.or_else(|| std::env::var("USER").ok())
- .context(crate::error::CouldntFindUsername)
- .context(Common)
- .context(super::Watch)?;
+ .context(crate::error::CouldntFindUsername)?;
let (host, address) =
- crate::util::resolve_address(matches.value_of("address"))
- .context(Util)
- .context(super::Watch)?;
+ crate::util::resolve_address(matches.value_of("address"))?;
let tls = matches.is_present("tls");
- run_impl(&username, &host, address, tls).context(super::Watch)
+ run_impl(&username, &host, address, tls)
}
fn run_impl(
@@ -81,8 +39,8 @@ fn run_impl(
let fut: Box<
dyn futures::future::Future<Item = (), Error = Error> + Send,
> = if tls {
- let connector =
- native_tls::TlsConnector::new().context(CreateConnector)?;
+ let connector = native_tls::TlsConnector::new()
+ .context(crate::error::CreateConnector)?;
let make_connector: Box<
dyn Fn() -> crate::client::Connector<_> + Send,
> = Box::new(move || {
@@ -97,7 +55,7 @@ fn run_impl(
move |stream| {
connector
.connect(&host, stream)
- .context(crate::error::TlsConnect)
+ .context(crate::error::ConnectTls)
},
))
})
@@ -273,7 +231,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
self.state.choosing(
crate::session_list::SessionList::new(
sessions,
- crate::term::Size::get().context(Resize)?,
+ crate::term::Size::get()?,
),
)?;
self.needs_redraw = true;
@@ -287,8 +245,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
msg => {
return Err(crate::error::Error::UnexpectedMessage {
message: msg,
- })
- .context(Common);
+ });
}
}
Ok(())
@@ -337,7 +294,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
self.state.watching(client);
crossterm::terminal()
.clear(crossterm::ClearType::All)
- .context(WriteTerminalCrossterm)?;
+ .context(crate::error::WriteTerminalCrossterm)?;
}
}
_ => {}
@@ -367,8 +324,8 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
// TODO async
let stdout = std::io::stdout();
let mut stdout = stdout.lock();
- stdout.write(&data).context(WriteTerminal)?;
- stdout.flush().context(FlushTerminal)?;
+ stdout.write(&data).context(crate::error::WriteTerminal)?;
+ stdout.flush().context(crate::error::FlushTerminal)?;
}
crate::protocol::Message::Disconnected => {
self.reconnect(true)?;
@@ -379,8 +336,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
msg => {
return Err(crate::error::Error::UnexpectedMessage {
message: msg,
- })
- .context(Common);
+ });
}
}
Ok(())
@@ -424,12 +380,12 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
fn display_loading_screen(&self) -> Result<()> {
crossterm::terminal()
.clear(crossterm::ClearType::All)
- .context(WriteTerminalCrossterm)?;
+ .context(crate::error::WriteTerminalCrossterm)?;
let data = b"loading...\r\nq: quit --> ";
let stdout = std::io::stdout();
let mut stdout = stdout.lock();
- stdout.write(data).context(WriteTerminal)?;
- stdout.flush().context(FlushTerminal)?;
+ stdout.write(data).context(crate::error::WriteTerminal)?;
+ stdout.flush().context(crate::error::FlushTerminal)?;
Ok(())
}
@@ -482,7 +438,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
crossterm::terminal()
.clear(crossterm::ClearType::All)
- .context(WriteTerminalCrossterm)?;
+ .context(crate::error::WriteTerminalCrossterm)?;
println!("welcome to teleterm\r");
println!("available sessions:\r");
println!("\r");
@@ -549,7 +505,9 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
sessions.current_page(),
sessions.total_pages(),
);
- std::io::stdout().flush().context(FlushTerminal)?;
+ std::io::stdout()
+ .flush()
+ .context(crate::error::FlushTerminal)?;
Ok(())
}
@@ -569,7 +527,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
];
fn poll_input(&mut self) -> Result<crate::component_future::Poll<()>> {
- match self.key_reader.poll().context(ReadKey)? {
+ match self.key_reader.poll()? {
futures::Async::Ready(Some(e)) => {
let quit = match &mut self.state {
State::Temporary => unreachable!(),
@@ -593,7 +551,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
fn poll_list_client(
&mut self,
) -> Result<crate::component_future::Poll<()>> {
- match self.list_client.poll().context(Client)? {
+ match self.list_client.poll()? {
futures::Async::Ready(Some(e)) => {
match e {
crate::client::Event::Disconnect => {
@@ -632,7 +590,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
return Ok(crate::component_future::Poll::NothingToDo);
};
- match client.poll().context(Client)? {
+ match client.poll()? {
futures::Async::Ready(Some(e)) => {
match e {
crate::client::Event::Disconnect => {
@@ -676,8 +634,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
if self.raw_screen.is_none() {
self.raw_screen = Some(
crossterm::RawScreen::into_raw_mode()
- .context(crate::error::IntoRawMode)
- .context(Common)?,
+ .context(crate::error::ToRawMode)?,
);
}
let res = crate::component_future::poll_future(self, Self::POLL_FNS);
@@ -693,7 +650,8 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
}
fn new_alternate_screen() -> Result<crossterm::AlternateScreen> {
- crossterm::AlternateScreen::to_alternate(false).context(ToAlternateScreen)
+ crossterm::AlternateScreen::to_alternate(false)
+ .context(crate::error::ToAlternateScreen)
}
fn format_time(dur: u32) -> String {
diff --git a/src/error.rs b/src/error.rs
index 4b7a526..42135d8 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,30 +1,275 @@
#[derive(Debug, snafu::Snafu)]
#[snafu(visibility = "pub")]
pub enum Error {
+ #[snafu(display("failed to accept: {}", source))]
+ Acceptor { source: tokio::io::Error },
+
+ #[snafu(display("failed to bind: {}", source))]
+ Bind { source: tokio::io::Error },
+
#[snafu(display("failed to connect: {}", source))]
Connect { source: std::io::Error },
#[snafu(display("failed to connect: {}", source))]
- TlsConnect { source: native_tls::Error },
+ ConnectTls { source: native_tls::Error },
#[snafu(display("couldn't find username"))]
CouldntFindUsername,
+ #[snafu(display("failed to create tls acceptor: {}", source))]
+ CreateAcceptor { source: native_tls::Error },
+
+ #[snafu(display("failed to create tls connector: {}", source))]
+ CreateConnector { source: native_tls::Error },
+
+ #[snafu(display("eof"))]
+ EOF,
+
+ #[snafu(display("failed to parse string: {:?}", data))]
+ ExtraMessageData { data: Vec<u8> },
+
+ #[snafu(display("failed to write to stdout: {}", source))]
+ FlushTerminal { source: tokio::io::Error },
+
+ #[snafu(display("failed to flush writes to terminal: {}", source))]
+ FlushTerminalSync { source: std::io::Error },
+
+ #[snafu(display("failed to get terminal size: {}", source))]
+ GetTerminalSize { source: crossterm::ErrorKind },
+
+ #[snafu(display("failed to find any resolved addresses"))]
+ HasResolvedAddr,
+
+ #[snafu(display("invalid auth type: {}", ty))]
+ InvalidAuthType { ty: u32 },
+
+ #[snafu(display("invalid message type: {}", ty))]
+ InvalidMessageType { ty: u32 },
+
+ #[snafu(display("invalid watch id: {}", id))]
+ InvalidWatchId { id: String },
+
#[snafu(display(
- "failed to put the terminal into raw mode: {}",
- source
+ "packet length must be at least {} bytes (got {})",
+ expected,
+ len
))]
- IntoRawMode { source: crossterm::ErrorKind },
+ LenTooSmall { len: u32, expected: usize },
+
+ #[snafu(display(
+ "packet length must be at most {} bytes (got {})",
+ expected,
+ len
+ ))]
+ LenTooBig { len: u32, expected: usize },
+
+ #[snafu(display("couldn't find name in argv"))]
+ MissingArgv,
+
+ #[snafu(display(
+ "detected argv path was not a valid filename: {}",
+ path
+ ))]
+ NotAFileName { path: String },
+
+ #[snafu(display("failed to open file: {}", source))]
+ OpenFile { source: tokio::io::Error },
+
+ #[snafu(display("failed to open identity file: {}", source))]
+ OpenIdentityFile { source: std::io::Error },
+
+ #[snafu(display("failed to open a pty: {}", source))]
+ OpenPty { source: std::io::Error },
+
+ #[snafu(display("failed to parse address"))]
+ ParseAddress,
#[snafu(display("failed to parse address: {}", source))]
ParseAddr { source: std::net::AddrParseError },
+ #[snafu(display("{}", source))]
+ ParseArgs { source: clap::Error },
+
#[snafu(display("failed to parse buffer size '{}': {}", input, source))]
ParseBufferSize {
input: String,
source: std::num::ParseIntError,
},
+ #[snafu(display("failed to parse identity file: {}", source))]
+ ParseIdentity { source: native_tls::Error },
+
+ #[snafu(display("failed to parse int: {}", source))]
+ ParseInt {
+ source: std::array::TryFromSliceError,
+ },
+
+ #[snafu(display("failed to parse address: {}", source))]
+ ParsePort { source: std::num::ParseIntError },
+
+ #[snafu(display(
+ "failed to parse read timeout '{}': {}",
+ input,
+ source
+ ))]
+ ParseReadTimeout {
+ input: String,
+ source: std::num::ParseIntError,
+ },
+
+ #[snafu(display("failed to parse string: {}", source))]
+ ParseString { source: std::string::FromUtf8Error },
+
+ #[snafu(display("failed to poll for process exit: {}", source))]
+ ProcessExitPoll { source: std::io::Error },
+
+ #[snafu(display("rate limit exceeded"))]
+ RateLimited,
+
+ #[snafu(display("failed to read from event channel: {}", source))]
+ ReadChannel {
+ source: tokio::sync::mpsc::error::UnboundedRecvError,
+ },
+
+ #[snafu(display("failed to read from file: {}", source))]
+ ReadFile { source: tokio::io::Error },
+
+ #[snafu(display("failed to read identity file: {}", source))]
+ ReadIdentityFile { source: std::io::Error },
+
+ #[snafu(display("{}", source))]
+ ReadMessageWithTimeout {
+ #[snafu(source(from(tokio::timer::timeout::Error<Error>, Box::new)))]
+ source: Box<tokio::timer::timeout::Error<Error>>,
+ },
+
+ #[snafu(display("failed to read packet: {}", source))]
+ ReadPacket { source: std::io::Error },
+
+ #[snafu(display("failed to read packet: {}", source))]
+ ReadPacketAsync { source: tokio::io::Error },
+
+ #[snafu(display("failed to read from pty: {}", source))]
+ ReadPty { source: std::io::Error },
+
+ #[snafu(display("failed to read from terminal: {}", source))]
+ ReadTerminal { source: std::io::Error },
+
+ #[snafu(display("failed to resize pty: {}", source))]
+ ResizePty { source: std::io::Error },
+
+ #[snafu(display("failed to resolve address: {}", source))]
+ ResolveAddress { source: std::io::Error },
+
+ #[snafu(display(
+ "failed to send accepted socket to server thread: {}",
+ source
+ ))]
+ SendSocketChannel {
+ source: tokio::sync::mpsc::error::TrySendError<tokio::net::TcpStream>,
+ },
+
+ #[snafu(display("failed to send accepted socket to server thread"))]
+ SendSocketChannelTls {
+ // XXX tokio_tls::Accept doesn't implement Debug or Display
+ // source: tokio::sync::mpsc::error::TrySendError<tokio_tls::Accept<tokio::net::TcpStream>>,
+ },
+
+ #[snafu(display("received error from server: {}", message))]
+ Server { message: String },
+
+ #[snafu(display("SIGWINCH handler failed: {}", source))]
+ SigWinchHandler { source: std::io::Error },
+
+ #[snafu(display("failed to sleep until next frame: {}", source))]
+ Sleep { source: tokio::timer::Error },
+
+ #[snafu(display(
+ "failed to receive new socket over channel: channel closed"
+ ))]
+ SocketChannelClosed,
+
+ #[snafu(display(
+ "failed to receive new socket over channel: {}",
+ source
+ ))]
+ SocketChannelReceive {
+ source: tokio::sync::mpsc::error::RecvError,
+ },
+
+ #[snafu(display("failed to spawn process for `{}`: {}", cmd, source))]
+ SpawnProcess { cmd: String, source: std::io::Error },
+
+ #[snafu(display(
+ "failed to spawn a background thread to read terminal input: {}",
+ source
+ ))]
+ TerminalInputReadingThread { source: std::io::Error },
+
+ #[snafu(display(
+ "terminal must be smaller than 1000 rows or columns (got {})",
+ size
+ ))]
+ TermTooBig { size: crate::term::Size },
+
+ #[snafu(display("timeout"))]
+ Timeout,
+
+ #[snafu(display("heartbeat timer failed: {}", source))]
+ TimerHeartbeat { source: tokio::timer::Error },
+
+ #[snafu(display("read timeout timer failed: {}", source))]
+ TimerReadTimeout { source: tokio::timer::Error },
+
+ #[snafu(display("reconnect timer failed: {}", source))]
+ TimerReconnect { source: tokio::timer::Error },
+
+ #[snafu(display("failed to switch to alternate screen: {}", source))]
+ ToAlternateScreen { source: crossterm::ErrorKind },
+
+ #[snafu(display(
+ "failed to put the terminal into raw mode: {}",
+ source
+ ))]
+ ToRawMode { source: crossterm::ErrorKind },
+
+ #[snafu(display("unauthenticated message: {:?}", message))]
+ UnauthenticatedMessage { message: crate::protocol::Message },
+
#[snafu(display("unexpected message: {:?}", message))]
UnexpectedMessage { message: crate::protocol::Message },
+
+ #[snafu(display("failed to write to event channel: {}", source))]
+ WriteChannel {
+ source: tokio::sync::mpsc::error::UnboundedSendError,
+ },
+
+ #[snafu(display("failed to write to file: {}", source))]
+ WriteFile { source: tokio::io::Error },
+
+ #[snafu(display("{}", source))]
+ WriteMessageWithTimeout {
+ #[snafu(source(from(tokio::timer::timeout::Error<Error>, Box::new)))]
+ source: Box<tokio::timer::timeout::Error<Error>>,
+ },
+
+ #[snafu(display("failed to write packet: {}", source))]
+ WritePacket { source: std::io::Error },
+
+ #[snafu(display("failed to write packet: {}", source))]
+ WritePacketAsync { source: tokio::io::Error },
+
+ #[snafu(display("failed to write to pty: {}", source))]
+ WritePty { source: std::io::Error },
+
+ #[snafu(display("failed to write to stdout: {}", source))]
+ WriteTerminal { source: tokio::io::Error },
+
+ #[snafu(display("failed to write to terminal: {}", source))]
+ WriteTerminalCrossterm { source: crossterm::ErrorKind },
+
+ #[snafu(display("failed to write to terminal: {}", source))]
+ WriteTerminalSync { source: std::io::Error },
}
+
+pub type Result<T> = std::result::Result<T, Error>;
diff --git a/src/key_reader.rs b/src/key_reader.rs
index 8933667..1e1251a 100644
--- a/src/key_reader.rs
+++ b/src/key_reader.rs
@@ -1,22 +1,5 @@
use crate::prelude::*;
-#[derive(Debug, snafu::Snafu)]
-pub enum Error {
- #[snafu(display(
- "failed to spawn a background thread to read terminal input: {}",
- source
- ))]
- TerminalInputReadingThread { source: std::io::Error },
-
- #[snafu(display("failed to read from event channel: {}", source))]
- ReadChannel {
- source: tokio::sync::mpsc::error::UnboundedRecvError,
- },
-}
-
-#[allow(dead_code)]
-pub type Result<T> = std::result::Result<T, Error>;
-
pub struct KeyReader {
events:
Option<tokio::sync::mpsc::UnboundedReceiver<crossterm::InputEvent>>,
@@ -58,13 +41,17 @@ impl futures::stream::Stream for KeyReader {
}
}
})
- .context(TerminalInputReadingThread)?;
+ .context(crate::error::TerminalInputReadingThread)?;
self.events = Some(events_rx);
self.quit = Some(quit_tx);
}
- self.events.as_mut().unwrap().poll().context(ReadChannel)
+ self.events
+ .as_mut()
+ .unwrap()
+ .poll()
+ .context(crate::error::ReadChannel)
}
}
diff --git a/src/prelude.rs b/src/prelude.rs
index 762632d..05ebbe3 100644
--- a/src/prelude.rs
+++ b/src/prelude.rs
@@ -4,3 +4,5 @@ pub use futures::stream::Stream as _;
pub use snafu::futures01::stream::StreamExt as _;
pub use snafu::futures01::FutureExt as _;
pub use snafu::{OptionExt as _, ResultExt as _};
+
+pub use crate::error::{Error, Result};
diff --git a/src/process.rs b/src/process.rs
index 7f19df6..3756837 100644
--- a/src/process.rs
+++ b/src/process.rs
@@ -3,32 +3,6 @@ use std::os::unix::io::AsRawFd as _;
use tokio::io::{AsyncRead as _, AsyncWrite as _};
use tokio_pty_process::CommandExt as _;
-#[derive(Debug, snafu::Snafu)]
-pub enum Error {
- #[snafu(display("{}", source))]
- Resize { source: crate::term::Error },
-
- #[snafu(display("failed to open a pty: {}", source))]
- OpenPty { source: std::io::Error },
-
- #[snafu(display("failed to spawn process for `{}`: {}", cmd, source))]
- SpawnProcess { cmd: String, source: std::io::Error },
-
- #[snafu(display("failed to read from pty: {}", source))]
- ReadFromPty { source: std::io::Error },
-
- #[snafu(display("failed to write to pty: {}", source))]
- WriteToPty { source: std::io::Error },
-
- #[snafu(display("failed to read from terminal: {}", source))]
- ReadFromTerminal { source: std::io::Error },
-
- #[snafu(display("failed to poll for process exit: {}", source))]
- ProcessExitPoll { source: std::io::Error },
-}
-
-pub type Result<T> = std::result::Result<T, Error>;
-
const READ_BUFFER_SIZE: usize = 4 * 1024;
#[derive(Debug, PartialEq, Eq)]
@@ -121,7 +95,7 @@ impl<R: tokio::io::AsyncRead + 'static> Process<R> {
&mut self,
) -> Result<crate::component_future::Poll<Event>> {
if let Some(size) = &self.needs_resize {
- match size.resize_pty(self.state.pty()).context(Resize)? {
+ match size.resize_pty(self.state.pty())? {
futures::Async::Ready(()) => {
log::debug!("resize({:?})", size);
self.needs_resize = None;
@@ -160,7 +134,7 @@ impl<R: tokio::io::AsyncRead + 'static> Process<R> {
match self
.input
.poll_read(&mut self.buf)
- .context(ReadFromTerminal)?
+ .context(crate::error::ReadTerminal)?
{
futures::Async::Ready(n) => {
log::debug!("read_stdin({})", n);
@@ -187,7 +161,12 @@ impl<R: tokio::io::AsyncRead + 'static> Process<R> {
let (a, b) = self.input_buf.as_slices();
let buf = if a.is_empty() { b } else { a };
- match self.state.pty_mut().poll_write(buf).context(WriteToPty)? {
+ match self
+ .state
+ .pty_mut()
+ .poll_write(buf)
+ .context(crate::error::WritePty)?
+ {
futures::Async::Ready(n) => {
log::debug!("write_stdin({})", n);
for _ in 0..n {
@@ -208,7 +187,7 @@ impl<R: tokio::io::AsyncRead + 'static> Process<R> {
.state
.pty_mut()
.poll_read(&mut self.buf)
- .context(ReadFromPty)
+ .context(crate::error::ReadPty)
{
Ok(futures::Async::Ready(n)) => {
log::debug!("read_stdout({})", n);
@@ -221,7 +200,7 @@ impl<R: tokio::io::AsyncRead + 'static> Process<R> {
Err(e) => {
// XXX this seems to be how eof is returned, but this seems...
// wrong? i feel like there has to be a better way to do this
- if let Error::ReadFromPty { source } = &e {
+ if let Error::ReadPty { source } = &e {
if source.kind() == std::io::ErrorKind::Other {
log::debug!("read_stdout(eof)");
self.stdout_closed = true;
@@ -243,7 +222,12 @@ impl<R: tokio::io::AsyncRead + 'static> Process<R> {
return Ok(crate::component_future::Poll::NothingToDo);
}
- match self.state.process().poll().context(ProcessExitPoll)? {
+ match self
+ .state
+ .process()
+ .poll()
+ .context(crate::error::ProcessExitPoll)?
+ {
futures::Async::Ready(status) => {
log::debug!("exit({})", status);
self.exited = true;
@@ -268,7 +252,8 @@ impl<R: tokio::io::AsyncRead + 'static> futures::stream::Stream
fn poll(&mut self) -> futures::Poll<Option<Self::Item>, Self::Error> {
if self.state.pty.is_none() {
self.state.pty = Some(
- tokio_pty_process::AsyncPtyMaster::open().context(OpenPty)?,
+ tokio_pty_process::AsyncPtyMaster::open()
+ .context(crate::error::OpenPty)?,
);
log::debug!(
"openpty({})",
@@ -280,7 +265,7 @@ impl<R: tokio::io::AsyncRead + 'static> futures::stream::Stream
std::process::Command::new(&self.cmd)
.args(&self.args)
.spawn_pty_async(self.state.pty())
- .context(SpawnProcess {
+ .context(crate::error::SpawnProcess {
cmd: self.cmd.clone(),
})?,
);
diff --git a/src/protocol.rs b/src/protocol.rs
index fb1b91f..ee9eb04 100644
--- a/src/protocol.rs
+++ b/src/protocol.rs
@@ -1,57 +1,6 @@
use crate::prelude::*;
use std::convert::{TryFrom as _, TryInto as _};
-#[derive(Debug, snafu::Snafu)]
-pub enum Error {
- #[snafu(display("failed to read packet: {}", source))]
- Read { source: std::io::Error },
-
- #[snafu(display("failed to read packet: {}", source))]
- ReadAsync { source: tokio::io::Error },
-
- #[snafu(display("failed to write packet: {}", source))]
- Write { source: std::io::Error },
-
- #[snafu(display("failed to write packet: {}", source))]
- WriteAsync { source: tokio::io::Error },
-
- #[snafu(display("failed to parse string: {}", source))]
- ParseString { source: std::string::FromUtf8Error },
-
- #[snafu(display("failed to parse int: {}", source))]
- ParseInt {
- source: std::array::TryFromSliceError,
- },
-
- #[snafu(display(
- "packet length must be at least {} bytes (got {})",
- expected,
- len
- ))]
- LenTooSmall { len: u32, expected: usize },
-
- #[snafu(display(
- "packet length must be at most {} bytes (got {})",
- expected,
- len
- ))]
- LenTooBig { len: u32, expected: usize },
-
- #[snafu(display("failed to parse string: {:?}", data))]
- ExtraMessageData { data: Vec<u8> },
-
- #[snafu(display("invalid message type: {}", ty))]
- InvalidMessageType { ty: u32 },
-
- #[snafu(display("invalid auth type: {}", ty))]
- InvalidAuthType { ty: u32 },
-
- #[snafu(display("eof"))]
- EOF,
-}
-
-pub type Result<T> = std::result::Result<T, Error>;
-
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Session {
pub id: String,
@@ -261,7 +210,8 @@ struct Packet {
impl Packet {
fn read<R: std::io::Read>(mut r: R) -> Result<Self> {
let mut len_buf = [0_u8; std::mem::size_of::<u32>()];
- r.read_exact(&mut len_buf).context(Read)?;
+ r.read_exact(&mut len_buf)
+ .context(crate::error::ReadPacket)?;
let len = u32::from_be_bytes(len_buf.try_into().unwrap());
if (len as usize) < std::mem::size_of::<u32>() {
return Err(Error::LenTooSmall {
@@ -271,7 +221,7 @@ impl Packet {
}
let mut data = vec![0_u8; len as usize];
- r.read_exact(&mut data).context(Read)?;
+ r.read_exact(&mut data).context(crate::error::ReadPacket)?;
let (ty_buf, rest) = data.split_at(std::mem::size_of::<u32>());
let ty = u32::from_be_bytes(ty_buf.try_into().unwrap());
@@ -286,7 +236,7 @@ impl Packet {
) -> impl futures::future::Future<Item = (Self, FramedReader<T>), Error = Error>
{
r.0.into_future()
- .map_err(|(e, _)| Error::ReadAsync { source: e })
+ .map_err(|(e, _)| Error::ReadPacketAsync { source: e })
.and_then(|(data, r)| match data {
Some(data) => Ok((data, r)),
None => Err(Error::EOF),
@@ -312,7 +262,7 @@ impl Packet {
let len_buf = len.to_be_bytes();
let buf: Vec<u8> =
len_buf.iter().chain(bytes.iter()).copied().collect();
- Ok(w.write_all(&buf).context(Write)?)
+ Ok(w.write_all(&buf).context(crate::error::WritePacket)?)
}
fn write_async<T: tokio::io::AsyncWrite>(
@@ -322,7 +272,7 @@ impl Packet {
{
w.0.send(bytes::Bytes::from(self.as_bytes()))
.map(FramedWriter)
- .context(WriteAsync)
+ .context(crate::error::WritePacketAsync)
}
fn as_bytes(&self) -> Vec<u8> {
@@ -481,7 +431,9 @@ impl std::convert::TryFrom<Packet> for Message {
});
}
let (buf, rest) = data.split_at(std::mem::size_of::<u32>());
- let val = u32::from_be_bytes(buf.try_into().context(ParseInt)?);
+ let val = u32::from_be_bytes(
+ buf.try_into().context(crate::error::ParseInt)?,
+ );
Ok((val, rest))
}
fn read_u16(data: &[u8]) -> Result<(u16, &[u8])> {
@@ -492,7 +444,9 @@ impl std::convert::TryFrom<Packet> for Message {
});
}
let (buf, rest) = data.split_at(std::mem::size_of::<u16>());
- let val = u16::from_be_bytes(buf.try_into().context(ParseInt)?);
+ let val = u16::from_be_bytes(
+ buf.try_into().context(crate::error::ParseInt)?,
+ );
Ok((val, rest))
}
fn read_bytes(data: &[u8]) -> Result<(Vec<u8>, &[u8])> {
@@ -509,7 +463,8 @@ impl std::convert::TryFrom<Packet> for Message {
}
fn read_str(data: &[u8]) -> Result<(String, &[u8])> {
let (bytes, rest) = read_bytes(data)?;
- let val = String::from_utf8(bytes).context(ParseString)?;
+ let val = String::from_utf8(bytes)
+ .context(crate::error::ParseString)?;
Ok((val, rest))
}
fn read_size(data: &[u8]) -> Result<(crate::term::Size, &[u8])> {
diff --git a/src/server.rs b/src/server.rs
index aac968a..8f7ea1c 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -3,64 +3,6 @@ use tokio::util::FutureExt as _;
pub mod tls;
-#[derive(Debug, snafu::Snafu)]
-pub enum Error {
- #[snafu(display("{}", source))]
- Common { source: crate::error::Error },
-
- #[snafu(display(
- "failed to receive new socket over channel: {}",
- source
- ))]
- SocketChannelReceive {
- source: tokio::sync::mpsc::error::RecvError,
- },
-
- #[snafu(display(
- "failed to receive new socket over channel: channel closed"
- ))]
- SocketChannelClosed,
-
- #[snafu(display("failed to read message: {}", source))]
- ReadMessageWithTimeout {
- source: tokio::timer::timeout::Error<crate::protocol::Error>,
- },
-
- #[snafu(display("failed to read message: {}", source))]
- ReadMessage { source: crate::protocol::Error },
-
- #[snafu(display("failed to write message: {}", source))]
- WriteMessageWithTimeout {
- source: tokio::timer::timeout::Error<crate::protocol::Error>,
- },
-
- #[snafu(display("failed to write message: {}", source))]
- WriteMessage { source: crate::protocol::Error },
-
- #[snafu(display("unauthenticated message: {:?}", message))]
- UnauthenticatedMessage { message: crate::protocol::Message },
-
- #[snafu(display(
- "terminal must be smaller than 1000 rows or columns (got {})",
- size
- ))]
- TermTooBig { size: crate::term::Size },
-
- #[snafu(display("invalid watch id: {}", id))]
- InvalidWatchId { id: String },
-
- #[snafu(display("rate limit exceeded"))]
- RateLimited,
-
- #[snafu(display("timeout"))]
- Timeout,
-
- #[snafu(display("read timeout timer failed: {}", source))]
- Timer { source: tokio::timer::Error },
-}
-
-pub type Result<T> = std::result::Result<T, Error>;
-
enum ReadSocket<
S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static,
> {
@@ -290,7 +232,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
) -> Self {
let sock_stream = sock_r
.map(move |s| Connection::new(s, buffer_size))
- .context(SocketChannelReceive);
+ .context(crate::error::SocketChannelReceive);
Self {
buffer_size,
read_timeout,
@@ -390,8 +332,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
Err(Error::InvalidWatchId { id })
}
}
- m => Err(crate::error::Error::UnexpectedMessage { message: m })
- .context(Common),
+ m => Err(crate::error::Error::UnexpectedMessage { message: m }),
}
}
@@ -440,8 +381,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
conn.last_activity = std::time::Instant::now();
Ok(())
}
- m => Err(crate::error::Error::UnexpectedMessage { message: m })
- .context(Common),
+ m => Err(crate::error::Error::UnexpectedMessage { message: m }),
}
}
@@ -469,8 +409,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
term_info.size = size;
Ok(())
}
- m => Err(crate::error::Error::UnexpectedMessage { message: m })
- .context(Common),
+ m => Err(crate::error::Error::UnexpectedMessage { message: m }),
}
}
@@ -540,7 +479,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
let fut = Box::new(
crate::protocol::Message::read_async(s)
.timeout(self.read_timeout)
- .context(ReadMessageWithTimeout),
+ .context(crate::error::ReadMessageWithTimeout),
);
conn.rsock = Some(ReadSocket::Reading(fut));
} else {
@@ -565,7 +504,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
if source.is_inner() {
let source = source.into_inner().unwrap();
match source {
- crate::protocol::Error::ReadAsync {
+ Error::ReadPacketAsync {
source: ref tokio_err,
} => {
if tokio_err.kind()
@@ -573,19 +512,19 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
{
Ok(crate::component_future::Poll::Event(()))
} else {
- Err(Error::ReadMessage { source })
+ Err(source)
}
}
- crate::protocol::Error::EOF => Ok(
+ Error::EOF => Ok(
crate::component_future::Poll::Event(()),
),
- _ => Err(Error::ReadMessage { source }),
+ _ => Err(source),
}
} else if source.is_elapsed() {
Err(Error::Timeout)
} else {
let source = source.into_timer().unwrap();
- Err(Error::Timer { source })
+ Err(Error::TimerReadTimeout { source })
}
} else {
Err(e)
@@ -608,7 +547,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
let fut = msg
.write_async(s)
.timeout(self.read_timeout)
- .context(WriteMessageWithTimeout);
+ .context(crate::error::WriteMessageWithTimeout);
conn.wsock =
Some(WriteSocket::Writing(Box::new(fut)));
} else {
@@ -634,7 +573,7 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
if source.is_inner() {
let source = source.into_inner().unwrap();
match source {
- crate::protocol::Error::WriteAsync {
+ Error::WritePacketAsync {
source: ref tokio_err,
} => {
if tokio_err.kind()
@@ -644,19 +583,19 @@ impl<S: tokio::io::AsyncRead + tokio::io::AsyncWrite + Send + 'static>
(),
))
} else {
- Err(Error::WriteMessage { source })
+ Err(source)
}
}
- crate::protocol::Error::EOF => Ok(
+ Error::EOF => Ok(
crate::component_future::Poll::Event(()),
),
- _ => Err(Error::WriteMessage { source }),
+ _ => Err(source),
}
} else if source.is_elapsed() {
Err(Error::Timeout)
} else {
let source = source.into_timer().unwrap();
- Err(Error::Timer { source })
+ Err(Error::TimerReadTimeout { source })
}
} else {
Err(e)
diff --git a/src/server/tls.rs b/src/server/tls.rs
index 3ee2c8a..1edec77 100644
--- a/src/server/tls.rs
+++ b/src/server/tls.rs
@@ -1,29 +1,5 @@
use crate::prelude::*;
-#[derive(Debug, snafu::Snafu)]
-pub enum Error {
- #[snafu(display("{}", source))]
- Common { source: crate::error::Error },
-
- #[snafu(display("{}", source))]
- InnerServer { source: super::Error },
-
- #[snafu(display(
- "failed to receive new socket over channel: {}",
- source
- ))]
- SocketChannelReceive {
- source: tokio::sync::mpsc::error::RecvError,
- },
-
- #[snafu(display(
- "failed to receive new socket over channel: channel closed"
- ))]
- SocketChannelClosed,
-}
-
-pub type Result<T> = std::result::Result<T, Error>;
-
pub struct Server {
server: super::Server<tokio_tls::TlsStream<tokio::net::TcpStream>>,
sock_r:
@@ -66,7 +42,11 @@ impl Server {
fn poll_new_connections(
&mut self,
) -> Result<crate::component_future::Poll<()>> {
- match self.sock_r.poll().context(SocketChannelReceive)? {
+ match self
+ .sock_r
+ .poll()
+ .context(crate::error::SocketChannelReceive)?
+ {
futures::Async::Ready(Some(sock)) => {
self.accepting_sockets.push(sock);
Ok(crate::component_future::Poll::DidWork)
@@ -121,7 +101,7 @@ impl Server {
}
fn poll_server(&mut self) -> Result<crate::component_future::Poll<()>> {
- match self.server.poll().context(InnerServer)? {
+ match self.server.poll()? {
futures::Async::Ready(()) => {
Ok(crate::component_future::Poll::DidWork)
}
diff --git a/src/term.rs b/src/term.rs
index a804fff..1d3fec0 100644
--- a/src/term.rs
+++ b/src/term.rs
@@ -1,16 +1,5 @@
use crate::prelude::*;
-#[derive(Debug, snafu::Snafu)]
-pub enum Error {
- #[snafu(display("failed to get terminal size: {}", source))]
- GetTerminalSize { source: crossterm::ErrorKind },
-
- #[snafu(display("failed to resize pty: {}", source))]
- ResizePty { source: std::io::Error },
-}
-
-pub type Result<T> = std::result::Result<T, Error>;
-
const RESET: &[&[u8]] = &[
b"\x1b[3J\x1b[H\x1b[2J",
b"\x1b[H\x1b[J",
@@ -28,8 +17,9 @@ pub struct Size {
impl Size {
pub fn get() -> Result<Self> {
- let (cols, rows) =
- crossterm::terminal().size().context(GetTerminalSize)?;
+ let (cols, rows) = crossterm::terminal()
+ .size()
+ .context(crate::error::GetTerminalSize)?;
Ok(Self { rows, cols })
}
@@ -37,7 +27,8 @@ impl Size {
&self,
pty: &T,
) -> futures::Poll<(), Error> {
- pty.resize(self.rows, self.cols).context(ResizePty)
+ pty.resize(self.rows, self.cols)
+ .context(crate::error::ResizePty)
}
pub fn fits_in(&self, other: &Self) -> bool {
diff --git a/src/ttyrec.rs b/src/ttyrec.rs
index f9cde91..77b95bc 100644
--- a/src/ttyrec.rs
+++ b/src/ttyrec.rs
@@ -2,28 +2,6 @@ use crate::prelude::*;
use std::convert::TryFrom as _;
use tokio::io::{AsyncRead as _, AsyncWrite as _};
-#[derive(Debug, snafu::Snafu)]
-pub enum Error {
- #[snafu(display("failed to read from event channel: {}", source))]
- ReadChannel {
- source: tokio::sync::mpsc::error::UnboundedRecvError,
- },
-
- #[snafu(display("failed to write to event channel: {}", source))]
- WriteChannel {
- source: tokio::sync::mpsc::error::UnboundedSendError,
- },
-
- #[snafu(display("failed to write to file: {}", source))]
- WriteFile { source: tokio::io::Error },
-
- #[snafu(display("failed to read from file: {}", source))]
- ReadFile { source: tokio::io::Error },
-}
-
-#[allow(dead_code)]
-pub type Result<T> = std::result::Result<T, Error>;
-
pub struct Frame {
pub time: std::time::Instant,
pub data: Vec<u8>,
@@ -86,7 +64,7 @@ impl File {
time: now,
data: data.to_vec(),
})
- .context(WriteChannel)
+ .context(crate::error::WriteChannel)
}
pub fn poll_write(
@@ -94,7 +72,7 @@ impl File {
) -> std::result::Result<futures::Async<()>, Error> {
loop {
if self.writing.is_empty() {
- match self.rframe.poll().context(ReadChannel)? {
+ match self.rframe.poll().context(crate::error::ReadChannel)? {
futures::Async::Ready(Some(frame)) => {
self.writing.extend(
frame.as_bytes(self.base_time.unwrap()).iter(),
@@ -110,7 +88,11 @@ impl File {
let (a, b) = self.writing.as_slices();
let buf = if a.is_empty() { b } else { a };
- match self.file.poll_write(buf).context(WriteFile)? {
+ match self
+ .file
+ .poll_write(buf)
+ .context(crate::error::WriteFile)?
+ {
futures::Async::Ready(n) => {
for _ in 0..n {
self.writing.pop_front();
@@ -131,7 +113,11 @@ impl File {
return Ok(futures::Async::Ready(Some(frame)));
}
- match self.file.poll_read(&mut self.read_buf).context(ReadFile)? {
+ match self
+ .file
+ .poll_read(&mut self.read_buf)
+ .context(crate::error::ReadFile)?
+ {
futures::Async::Ready(n) => {
if n > 0 {
self.reading.extend(self.read_buf[..n].iter());
diff --git a/src/util.rs b/src/util.rs
index 23534c5..82bfb11 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -1,34 +1,9 @@
use crate::prelude::*;
use std::net::ToSocketAddrs as _;
-#[derive(Debug, snafu::Snafu)]
-pub enum Error {
- #[snafu(display("couldn't find name in argv"))]
- MissingArgv,
-
- #[snafu(display(
- "detected argv path was not a valid filename: {}",
- path
- ))]
- NotAFileName { path: String },
-
- #[snafu(display("failed to parse address"))]
- ParseAddress,
-
- #[snafu(display("failed to parse address: {}", source))]
- ParsePort { source: std::num::ParseIntError },
-
- #[snafu(display("failed to resolve address: {}", source))]
- ResolveAddress { source: std::io::Error },
-
- #[snafu(display("failed to find any resolved addresses"))]
- HasResolvedAddr,
-}
-
-pub type Result<T> = std::result::Result<T, Error>;
-
pub fn program_name() -> Result<String> {
- let program = std::env::args().next().context(MissingArgv)?;
+ let program =
+ std::env::args().next().context(crate::error::MissingArgv)?;
let path = std::path::Path::new(&program);
let filename = path.file_name();
Ok(filename
@@ -44,13 +19,13 @@ pub fn resolve_address(
) -> Result<(String, std::net::SocketAddr)> {
let address = address.unwrap_or("0.0.0.0:4144");
let mut address_parts = address.split(':');
- let host = address_parts.next().context(ParseAddress)?;
- let port = address_parts.next().context(ParseAddress)?;
- let port: u16 = port.parse().context(ParsePort)?;
+ let host = address_parts.next().context(crate::error::ParseAddress)?;
+ let port = address_parts.next().context(crate::error::ParseAddress)?;
+ let port: u16 = port.parse().context(crate::error::ParsePort)?;
let socket_addr = (host, port)
.to_socket_addrs()
- .context(ResolveAddress)?
+ .context(crate::error::ResolveAddress)?
.next()
- .context(HasResolvedAddr)?;
+ .context(crate::error::HasResolvedAddr)?;
Ok((host.to_string(), socket_addr))
}