aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2019-10-19 23:35:55 -0400
committerJesse Luehrs <doy@tozt.net>2019-10-20 00:52:52 -0400
commit31535dfd1d36d255451fa8dd2785d03032d10ce3 (patch)
tree7e24403b140747c638c84c292bc5f990dc5d48b7
parente9c854d1b0ea566cc96777a2358736137f7d7647 (diff)
downloadteleterm-31535dfd1d36d255451fa8dd2785d03032d10ce3.tar.gz
teleterm-31535dfd1d36d255451fa8dd2785d03032d10ce3.zip
simplify config loading
-rw-r--r--src/cmd/play.rs20
-rw-r--r--src/cmd/record.rs55
-rw-r--r--src/cmd/server.rs94
-rw-r--r--src/cmd/stream.rs127
-rw-r--r--src/cmd/watch.rs83
-rw-r--r--src/config.rs340
6 files changed, 339 insertions, 380 deletions
diff --git a/src/cmd/play.rs b/src/cmd/play.rs
index 22bd220..7eae765 100644
--- a/src/cmd/play.rs
+++ b/src/cmd/play.rs
@@ -1,10 +1,9 @@
use crate::prelude::*;
use std::io::Write as _;
-#[derive(serde::Deserialize, Debug)]
+#[derive(serde::Deserialize, Debug, Default)]
pub struct Config {
- #[serde(default = "crate::config::default_ttyrec_filename")]
- filename: String,
+ ttyrec: crate::config::Ttyrec,
}
impl crate::config::Config for Config {
@@ -12,14 +11,11 @@ impl crate::config::Config for Config {
&mut self,
matches: &clap::ArgMatches<'a>,
) -> Result<()> {
- if matches.is_present("filename") {
- self.filename = matches.value_of("filename").unwrap().to_string();
- }
- Ok(())
+ self.ttyrec.merge_args(matches)
}
fn run(&self) -> Result<()> {
- let fut = PlaySession::new(&self.filename);
+ let fut = PlaySession::new(&self.ttyrec.filename);
tokio::run(fut.map_err(|e| {
eprintln!("{}", e);
}));
@@ -27,14 +23,6 @@ impl crate::config::Config for Config {
}
}
-impl Default for Config {
- fn default() -> Self {
- Self {
- filename: crate::config::default_ttyrec_filename(),
- }
- }
-}
-
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")
diff --git a/src/cmd/record.rs b/src/cmd/record.rs
index cf291b9..3e19ed8 100644
--- a/src/cmd/record.rs
+++ b/src/cmd/record.rs
@@ -1,19 +1,10 @@
use crate::prelude::*;
use tokio::io::AsyncWrite as _;
-#[derive(serde::Deserialize, Debug)]
+#[derive(serde::Deserialize, Debug, Default)]
pub struct Config {
- #[serde(default = "crate::config::default_ttyrec_filename")]
- filename: String,
-
- #[serde(default = "crate::config::default_connection_buffer_size")]
- buffer_size: usize,
-
- #[serde(skip, default = "crate::config::default_command")]
- command: String,
-
- #[serde(skip, default = "crate::config::default_args")]
- args: Vec<String>,
+ command: crate::config::Command,
+ ttyrec: crate::config::Ttyrec,
}
impl crate::config::Config for Config {
@@ -21,34 +12,17 @@ impl crate::config::Config for Config {
&mut self,
matches: &clap::ArgMatches<'a>,
) -> Result<()> {
- if matches.is_present("filename") {
- self.filename = matches.value_of("filename").unwrap().to_string();
- }
- if matches.is_present("buffer-size") {
- let buffer_size = matches.value_of("buffer-size").unwrap();
- self.buffer_size = buffer_size.parse().context(
- crate::error::ParseBufferSize { input: buffer_size },
- )?;
- }
- if matches.is_present("command") {
- self.command = matches.value_of("command").unwrap().to_string();
- }
- if matches.is_present("args") {
- self.args = matches
- .values_of("args")
- .unwrap()
- .map(std::string::ToString::to_string)
- .collect();
- }
+ self.command.merge_args(matches)?;
+ self.ttyrec.merge_args(matches)?;
Ok(())
}
fn run(&self) -> Result<()> {
let fut = RecordSession::new(
- &self.filename,
- self.buffer_size,
- &self.command,
- &self.args,
+ &self.ttyrec.filename,
+ self.command.buffer_size,
+ &self.command.command,
+ &self.command.args,
);
tokio::run(fut.map_err(|e| {
eprintln!("{}", e);
@@ -57,17 +31,6 @@ impl crate::config::Config for Config {
}
}
-impl Default for Config {
- fn default() -> Self {
- Self {
- filename: crate::config::default_ttyrec_filename(),
- buffer_size: crate::config::default_connection_buffer_size(),
- command: crate::config::default_command(),
- args: crate::config::default_args(),
- }
- }
-}
-
pub fn cmd<'a, 'b>(app: clap::App<'a, 'b>) -> clap::App<'a, 'b> {
app.about("Record a terminal session to a file")
.arg(
diff --git a/src/cmd/server.rs b/src/cmd/server.rs
index 858c6b8..ea238ba 100644
--- a/src/cmd/server.rs
+++ b/src/cmd/server.rs
@@ -1,32 +1,9 @@
use crate::prelude::*;
-use std::convert::TryFrom as _;
use std::io::Read as _;
-#[derive(serde::Deserialize, Debug)]
+#[derive(serde::Deserialize, Debug, Default)]
pub struct Config {
- #[serde(
- deserialize_with = "crate::config::listen_address",
- default = "crate::config::default_listen_address"
- )]
- listen_address: std::net::SocketAddr,
-
- #[serde(default = "crate::config::default_connection_buffer_size")]
- buffer_size: usize,
-
- #[serde(
- deserialize_with = "crate::config::read_timeout",
- default = "crate::config::default_read_timeout"
- )]
- read_timeout: std::time::Duration,
-
- tls_identity_file: Option<String>,
-
- #[serde(
- deserialize_with = "crate::config::allowed_login_methods",
- default = "crate::config::default_allowed_login_methods"
- )]
- allowed_login_methods:
- std::collections::HashSet<crate::protocol::AuthType>,
+ server: crate::config::Server,
}
impl crate::config::Config for Config {
@@ -34,59 +11,25 @@ impl crate::config::Config for Config {
&mut self,
matches: &clap::ArgMatches<'a>,
) -> Result<()> {
- if matches.is_present("address") {
- self.listen_address = matches
- .value_of("address")
- .unwrap()
- .parse()
- .context(crate::error::ParseAddr)?;
- }
- if matches.is_present("buffer-size") {
- let s = matches.value_of("buffer-size").unwrap();
- self.buffer_size = s
- .parse()
- .context(crate::error::ParseBufferSize { input: s })?;
- }
- if matches.is_present("read-timeout") {
- let s = matches.value_of("read-timeout").unwrap();
- self.read_timeout = s
- .parse()
- .map(std::time::Duration::from_secs)
- .context(crate::error::ParseReadTimeout { input: s })?;
- }
- if matches.is_present("tls-identity-file") {
- self.tls_identity_file = Some(
- matches.value_of("tls-identity-file").unwrap().to_string(),
- );
- }
- if matches.is_present("allowed-login-methods") {
- self.allowed_login_methods = matches
- .values_of("allowed-login-methods")
- .unwrap()
- .map(crate::protocol::AuthType::try_from)
- .collect::<Result<
- std::collections::HashSet<crate::protocol::AuthType>,
- >>()?;
- }
- Ok(())
+ self.server.merge_args(matches)
}
fn run(&self) -> Result<()> {
let (acceptor, server) =
- if let Some(tls_identity_file) = &self.tls_identity_file {
+ if let Some(tls_identity_file) = &self.server.tls_identity_file {
create_server_tls(
- self.listen_address,
- self.buffer_size,
- self.read_timeout,
+ self.server.listen_address,
+ self.server.buffer_size,
+ self.server.read_timeout,
tls_identity_file,
- self.allowed_login_methods.clone(),
+ self.server.allowed_login_methods.clone(),
)?
} else {
create_server(
- self.listen_address,
- self.buffer_size,
- self.read_timeout,
- self.allowed_login_methods.clone(),
+ self.server.listen_address,
+ self.server.buffer_size,
+ self.server.read_timeout,
+ self.server.allowed_login_methods.clone(),
)?
};
tokio::run(futures::future::lazy(move || {
@@ -102,19 +45,6 @@ impl crate::config::Config for Config {
}
}
-impl Default for Config {
- fn default() -> Self {
- Self {
- listen_address: crate::config::default_listen_address(),
- buffer_size: crate::config::default_connection_buffer_size(),
- read_timeout: crate::config::default_read_timeout(),
- tls_identity_file: None,
- allowed_login_methods:
- crate::config::default_allowed_login_methods(),
- }
- }
-}
-
pub fn cmd<'a, 'b>(app: clap::App<'a, 'b>) -> clap::App<'a, 'b> {
app.about("Run a teleterm server")
.arg(
diff --git a/src/cmd/stream.rs b/src/cmd/stream.rs
index 809e480..14f4fac 100644
--- a/src/cmd/stream.rs
+++ b/src/cmd/stream.rs
@@ -1,41 +1,10 @@
use crate::prelude::*;
use tokio::io::AsyncWrite as _;
-#[derive(serde::Deserialize, Debug)]
+#[derive(serde::Deserialize, Debug, Default)]
pub struct Config {
- #[serde(
- deserialize_with = "crate::config::auth",
- default = "crate::config::default_auth"
- )]
- auth: crate::protocol::Auth,
-
- #[serde(
- deserialize_with = "crate::config::connect_address",
- default = "crate::config::default_connect_address"
- )]
- connect_address: (String, std::net::SocketAddr),
-
- #[serde(default = "crate::config::default_tls")]
- tls: bool,
-
- #[serde(default = "crate::config::default_connection_buffer_size")]
- buffer_size: usize,
-
- #[serde(skip, default = "crate::config::default_command")]
- command: String,
-
- #[serde(skip, default = "crate::config::default_args")]
- args: Vec<String>,
-}
-
-impl Config {
- fn host(&self) -> &str {
- &self.connect_address.0
- }
-
- fn addr(&self) -> &std::net::SocketAddr {
- &self.connect_address.1
- }
+ client: crate::config::Client,
+ command: crate::config::Command,
}
impl crate::config::Config for Config {
@@ -43,52 +12,33 @@ impl crate::config::Config for Config {
&mut self,
matches: &clap::ArgMatches<'a>,
) -> Result<()> {
- if matches.is_present("login-recurse-center") {
- let id = crate::oauth::load_client_auth_id(
- crate::protocol::AuthType::RecurseCenter,
- );
- self.auth = crate::protocol::Auth::recurse_center(
- id.as_ref().map(std::string::String::as_str),
- );
- }
- if matches.is_present("login-plain") {
- let username =
- matches.value_of("login-plain").unwrap().to_string();
- self.auth = crate::protocol::Auth::plain(&username);
- }
- if matches.is_present("address") {
- let address = matches.value_of("address").unwrap();
- self.connect_address =
- crate::config::to_connect_address(address)?;
- }
- if matches.is_present("tls") {
- self.tls = true;
- }
- if matches.is_present("buffer-size") {
- let buffer_size = matches.value_of("buffer-size").unwrap();
- self.buffer_size = buffer_size.parse().context(
- crate::error::ParseBufferSize { input: buffer_size },
- )?;
- }
- if matches.is_present("command") {
- self.command = matches.value_of("command").unwrap().to_string();
- }
- if matches.is_present("args") {
- self.args = matches
- .values_of("args")
- .unwrap()
- .map(std::string::ToString::to_string)
- .collect();
- }
+ self.client.merge_args(matches)?;
+ self.command.merge_args(matches)?;
Ok(())
}
fn run(&self) -> Result<()> {
- let host = self.host().to_string();
- let address = *self.addr();
+ let host = self.client.host().to_string();
+ let address = *self.client.addr();
+ let auth = match self.client.auth {
+ crate::protocol::AuthType::Plain => {
+ let username = self
+ .client
+ .username
+ .clone()
+ .context(crate::error::CouldntFindUsername)?;
+ crate::protocol::Auth::plain(&username)
+ }
+ crate::protocol::AuthType::RecurseCenter => {
+ let id = crate::oauth::load_client_auth_id(self.client.auth);
+ crate::protocol::Auth::recurse_center(
+ id.as_ref().map(std::string::String::as_str),
+ )
+ }
+ };
let fut: Box<
dyn futures::future::Future<Item = (), Error = Error> + Send,
- > = if self.tls {
+ > = if self.client.tls {
let connector = native_tls::TlsConnector::new()
.context(crate::error::CreateConnector)?;
let connect: crate::client::Connector<_> = Box::new(move || {
@@ -107,11 +57,11 @@ impl crate::config::Config for Config {
)
});
Box::new(StreamSession::new(
- &self.command,
- &self.args,
+ &self.command.command,
+ &self.command.args,
connect,
- self.buffer_size,
- &self.auth,
+ self.command.buffer_size,
+ &auth,
))
} else {
let connect: crate::client::Connector<_> = Box::new(move || {
@@ -121,11 +71,11 @@ impl crate::config::Config for Config {
)
});
Box::new(StreamSession::new(
- &self.command,
- &self.args,
+ &self.command.command,
+ &self.command.args,
connect,
- self.buffer_size,
- &self.auth,
+ self.command.buffer_size,
+ &auth,
))
};
tokio::run(fut.map_err(|e| {
@@ -135,19 +85,6 @@ impl crate::config::Config for Config {
}
}
-impl Default for Config {
- fn default() -> Self {
- Self {
- auth: crate::config::default_auth(),
- connect_address: crate::config::default_connect_address(),
- tls: crate::config::default_tls(),
- buffer_size: crate::config::default_connection_buffer_size(),
- command: crate::config::default_command(),
- args: crate::config::default_args(),
- }
- }
-}
-
pub fn cmd<'a, 'b>(app: clap::App<'a, 'b>) -> clap::App<'a, 'b> {
app.about("Stream your terminal")
.arg(
diff --git a/src/cmd/watch.rs b/src/cmd/watch.rs
index 66a6881..62ef2e0 100644
--- a/src/cmd/watch.rs
+++ b/src/cmd/watch.rs
@@ -1,32 +1,9 @@
use crate::prelude::*;
use std::io::Write as _;
-#[derive(serde::Deserialize, Debug)]
+#[derive(serde::Deserialize, Debug, Default)]
pub struct Config {
- #[serde(
- deserialize_with = "crate::config::auth",
- default = "crate::config::default_auth"
- )]
- auth: crate::protocol::Auth,
-
- #[serde(
- deserialize_with = "crate::config::connect_address",
- default = "crate::config::default_connect_address"
- )]
- connect_address: (String, std::net::SocketAddr),
-
- #[serde(default = "crate::config::default_tls")]
- tls: bool,
-}
-
-impl Config {
- fn host(&self) -> &str {
- &self.connect_address.0
- }
-
- fn addr(&self) -> &std::net::SocketAddr {
- &self.connect_address.1
- }
+ client: crate::config::Client,
}
impl crate::config::Config for Config {
@@ -34,37 +11,31 @@ impl crate::config::Config for Config {
&mut self,
matches: &clap::ArgMatches<'a>,
) -> Result<()> {
- if matches.is_present("login-recurse-center") {
- let id = crate::oauth::load_client_auth_id(
- crate::protocol::AuthType::RecurseCenter,
- );
- self.auth = crate::protocol::Auth::recurse_center(
- id.as_ref().map(std::string::String::as_str),
- );
- }
- if matches.is_present("login-plain") {
- let username =
- matches.value_of("login-plain").unwrap().to_string();
- self.auth = crate::protocol::Auth::plain(&username);
- }
- if matches.is_present("address") {
- let address = matches.value_of("address").unwrap();
- self.connect_address =
- crate::config::to_connect_address(address)?;
- }
- if matches.is_present("tls") {
- self.tls = true;
- }
- Ok(())
+ self.client.merge_args(matches)
}
fn run(&self) -> Result<()> {
- let host = self.host().to_string();
- let address = *self.addr();
- let auth = self.auth.clone();
+ let host = self.client.host().to_string();
+ let address = *self.client.addr();
+ let auth = match self.client.auth {
+ crate::protocol::AuthType::Plain => {
+ let username = self
+ .client
+ .username
+ .clone()
+ .context(crate::error::CouldntFindUsername)?;
+ crate::protocol::Auth::plain(&username)
+ }
+ crate::protocol::AuthType::RecurseCenter => {
+ let id = crate::oauth::load_client_auth_id(self.client.auth);
+ crate::protocol::Auth::recurse_center(
+ id.as_ref().map(std::string::String::as_str),
+ )
+ }
+ };
let fut: Box<
dyn futures::future::Future<Item = (), Error = Error> + Send,
- > = if self.tls {
+ > = if self.client.tls {
let connector = native_tls::TlsConnector::new()
.context(crate::error::CreateConnector)?;
let make_connector: Box<
@@ -110,16 +81,6 @@ impl crate::config::Config for Config {
}
}
-impl Default for Config {
- fn default() -> Self {
- Self {
- auth: crate::config::default_auth(),
- connect_address: crate::config::default_connect_address(),
- tls: crate::config::default_tls(),
- }
- }
-}
-
pub fn cmd<'a, 'b>(app: clap::App<'a, 'b>) -> clap::App<'a, 'b> {
app.about("Watch teleterm streams")
.arg(
diff --git a/src/config.rs b/src/config.rs
index 5fed3d5..b59bbcf 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -5,7 +5,7 @@ use std::net::ToSocketAddrs as _;
const DEFAULT_LISTEN_ADDRESS: &str = "127.0.0.1:4144";
const DEFAULT_CONNECT_ADDRESS: &str = "127.0.0.1:4144";
-const DEFAULT_CONNECTION_BUFFER_SIZE: usize = 4 * 1024 * 1024;
+const DEFAULT_BUFFER_SIZE: usize = 4 * 1024 * 1024;
const DEFAULT_READ_TIMEOUT: std::time::Duration =
std::time::Duration::from_secs(120);
const DEFAULT_AUTH_TYPE: crate::protocol::AuthType =
@@ -21,25 +21,90 @@ pub trait Config: std::fmt::Debug {
fn run(&self) -> Result<()>;
}
-pub fn listen_address<'a, D>(
+#[derive(serde::Deserialize, Debug)]
+pub struct Client {
+ #[serde(deserialize_with = "auth_type", default = "default_auth_type")]
+ pub auth: crate::protocol::AuthType,
+
+ #[serde(default = "default_username")]
+ pub username: Option<String>,
+
+ #[serde(
+ deserialize_with = "connect_address",
+ default = "default_connect_address"
+ )]
+ pub connect_address: (String, std::net::SocketAddr),
+
+ #[serde(default = "default_tls")]
+ pub tls: bool,
+}
+
+impl Client {
+ pub fn host(&self) -> &str {
+ &self.connect_address.0
+ }
+
+ pub fn addr(&self) -> &std::net::SocketAddr {
+ &self.connect_address.1
+ }
+
+ pub fn merge_args<'a>(
+ &mut self,
+ matches: &clap::ArgMatches<'a>,
+ ) -> Result<()> {
+ if matches.is_present("login-recurse-center") {
+ self.auth = crate::protocol::AuthType::RecurseCenter;
+ }
+ if matches.is_present("login-plain") {
+ let username = matches
+ .value_of("login-plain")
+ .map(std::string::ToString::to_string);
+ self.auth = crate::protocol::AuthType::Plain;
+ self.username = username;
+ }
+ if matches.is_present("address") {
+ let address = matches.value_of("address").unwrap();
+ self.connect_address = to_connect_address(address)?;
+ }
+ if matches.is_present("tls") {
+ self.tls = true;
+ }
+ Ok(())
+ }
+}
+
+impl Default for Client {
+ fn default() -> Self {
+ Self {
+ auth: default_auth_type(),
+ username: default_username(),
+ connect_address: default_connect_address(),
+ tls: default_tls(),
+ }
+ }
+}
+
+fn auth_type<'a, D>(
deserializer: D,
-) -> std::result::Result<std::net::SocketAddr, D::Error>
+) -> std::result::Result<crate::protocol::AuthType, D::Error>
where
D: serde::de::Deserializer<'a>,
{
- to_listen_address(&<String>::deserialize(deserializer)?)
- .map_err(serde::de::Error::custom)
+ crate::protocol::AuthType::try_from(
+ <String>::deserialize(deserializer)?.as_ref(),
+ )
+ .map_err(serde::de::Error::custom)
}
-pub fn default_listen_address() -> std::net::SocketAddr {
- to_listen_address(DEFAULT_LISTEN_ADDRESS).unwrap()
+fn default_auth_type() -> crate::protocol::AuthType {
+ DEFAULT_AUTH_TYPE
}
-pub fn to_listen_address(address: &str) -> Result<std::net::SocketAddr> {
- address.parse().context(crate::error::ParseAddr)
+fn default_username() -> Option<String> {
+ std::env::var("USER").ok()
}
-pub fn connect_address<'a, D>(
+fn connect_address<'a, D>(
deserializer: D,
) -> std::result::Result<(String, std::net::SocketAddr), D::Error>
where
@@ -49,12 +114,12 @@ where
.map_err(serde::de::Error::custom)
}
-pub fn default_connect_address() -> (String, std::net::SocketAddr) {
+fn default_connect_address() -> (String, std::net::SocketAddr) {
to_connect_address(DEFAULT_CONNECT_ADDRESS).unwrap()
}
// XXX this does a blocking dns lookup - should try to find an async version
-pub fn to_connect_address(
+fn to_connect_address(
address: &str,
) -> Result<(String, std::net::SocketAddr)> {
let mut address_parts = address.split(':');
@@ -72,47 +137,131 @@ pub fn to_connect_address(
Ok((host.to_string(), socket_addr))
}
-pub fn default_connection_buffer_size() -> usize {
- DEFAULT_CONNECTION_BUFFER_SIZE
+fn default_tls() -> bool {
+ DEFAULT_TLS
}
-pub fn read_timeout<'a, D>(
+#[derive(serde::Deserialize, Debug)]
+pub struct Server {
+ #[serde(
+ deserialize_with = "listen_address",
+ default = "default_listen_address"
+ )]
+ pub listen_address: std::net::SocketAddr,
+
+ #[serde(default = "default_buffer_size")]
+ pub buffer_size: usize,
+
+ #[serde(
+ rename = "read_timeout_secs",
+ deserialize_with = "read_timeout",
+ default = "default_read_timeout"
+ )]
+ pub read_timeout: std::time::Duration,
+
+ pub tls_identity_file: Option<String>,
+
+ #[serde(
+ deserialize_with = "allowed_login_methods",
+ default = "default_allowed_login_methods"
+ )]
+ pub allowed_login_methods:
+ std::collections::HashSet<crate::protocol::AuthType>,
+}
+
+impl Server {
+ pub fn merge_args<'a>(
+ &mut self,
+ matches: &clap::ArgMatches<'a>,
+ ) -> Result<()> {
+ if matches.is_present("address") {
+ self.listen_address = matches
+ .value_of("address")
+ .unwrap()
+ .parse()
+ .context(crate::error::ParseAddr)?;
+ }
+ if matches.is_present("buffer-size") {
+ let s = matches.value_of("buffer-size").unwrap();
+ self.buffer_size = s
+ .parse()
+ .context(crate::error::ParseBufferSize { input: s })?;
+ }
+ if matches.is_present("read-timeout") {
+ let s = matches.value_of("read-timeout").unwrap();
+ self.read_timeout = s
+ .parse()
+ .map(std::time::Duration::from_secs)
+ .context(crate::error::ParseReadTimeout { input: s })?;
+ }
+ if matches.is_present("tls-identity-file") {
+ self.tls_identity_file = Some(
+ matches.value_of("tls-identity-file").unwrap().to_string(),
+ );
+ }
+ if matches.is_present("allowed-login-methods") {
+ self.allowed_login_methods = matches
+ .values_of("allowed-login-methods")
+ .unwrap()
+ .map(crate::protocol::AuthType::try_from)
+ .collect::<Result<
+ std::collections::HashSet<crate::protocol::AuthType>,
+ >>()?;
+ }
+ Ok(())
+ }
+}
+
+impl Default for Server {
+ fn default() -> Self {
+ Self {
+ listen_address: default_listen_address(),
+ buffer_size: default_buffer_size(),
+ read_timeout: default_read_timeout(),
+ tls_identity_file: None,
+ allowed_login_methods: default_allowed_login_methods(),
+ }
+ }
+}
+
+fn listen_address<'a, D>(
deserializer: D,
-) -> std::result::Result<std::time::Duration, D::Error>
+) -> std::result::Result<std::net::SocketAddr, D::Error>
where
D: serde::de::Deserializer<'a>,
{
- Ok(std::time::Duration::from_secs(u64::deserialize(
- deserializer,
- )?))
-}
-
-pub fn default_read_timeout() -> std::time::Duration {
- DEFAULT_READ_TIMEOUT
+ to_listen_address(&<String>::deserialize(deserializer)?)
+ .map_err(serde::de::Error::custom)
}
-pub fn default_tls() -> bool {
- DEFAULT_TLS
+fn default_listen_address() -> std::net::SocketAddr {
+ to_listen_address(DEFAULT_LISTEN_ADDRESS).unwrap()
}
-pub fn default_command() -> String {
- std::env::var("SHELL").unwrap_or_else(|_| "/bin/bash".to_string())
+fn to_listen_address(address: &str) -> Result<std::net::SocketAddr> {
+ address.parse().context(crate::error::ParseAddr)
}
-pub fn default_args() -> Vec<String> {
- vec![]
+fn default_buffer_size() -> usize {
+ DEFAULT_BUFFER_SIZE
}
-pub fn default_ttyrec_filename() -> String {
- DEFAULT_TTYREC_FILENAME.to_string()
+fn read_timeout<'a, D>(
+ deserializer: D,
+) -> std::result::Result<std::time::Duration, D::Error>
+where
+ D: serde::de::Deserializer<'a>,
+{
+ Ok(std::time::Duration::from_secs(u64::deserialize(
+ deserializer,
+ )?))
}
-pub fn default_allowed_login_methods(
-) -> std::collections::HashSet<crate::protocol::AuthType> {
- crate::protocol::AuthType::iter().collect()
+fn default_read_timeout() -> std::time::Duration {
+ DEFAULT_READ_TIMEOUT
}
-pub fn allowed_login_methods<'a, D>(
+fn allowed_login_methods<'a, D>(
deserializer: D,
) -> std::result::Result<
std::collections::HashSet<crate::protocol::AuthType>,
@@ -169,61 +318,92 @@ where
.collect()
}
-pub fn auth<'a, D>(
- deserializer: D,
-) -> std::result::Result<crate::protocol::Auth, D::Error>
-where
- D: serde::de::Deserializer<'a>,
-{
- LoginType::deserialize(deserializer).and_then(|login_type| {
- match login_type.login_type {
- crate::protocol::AuthType::Plain => login_type
- .username
+fn default_allowed_login_methods(
+) -> std::collections::HashSet<crate::protocol::AuthType> {
+ crate::protocol::AuthType::iter().collect()
+}
+
+#[derive(serde::Deserialize, Debug)]
+pub struct Command {
+ #[serde(default = "default_buffer_size")]
+ pub buffer_size: usize,
+
+ #[serde(skip, default = "default_command")]
+ pub command: String,
+
+ #[serde(skip, default = "default_args")]
+ pub args: Vec<String>,
+}
+
+impl Command {
+ pub fn merge_args<'a>(
+ &mut self,
+ matches: &clap::ArgMatches<'a>,
+ ) -> Result<()> {
+ if matches.is_present("buffer-size") {
+ let buffer_size = matches.value_of("buffer-size").unwrap();
+ self.buffer_size = buffer_size.parse().context(
+ crate::error::ParseBufferSize { input: buffer_size },
+ )?;
+ }
+ if matches.is_present("command") {
+ self.command = matches.value_of("command").unwrap().to_string();
+ }
+ if matches.is_present("args") {
+ self.args = matches
+ .values_of("args")
+ .unwrap()
.map(std::string::ToString::to_string)
- .or_else(default_username)
- .ok_or_else(|| Error::CouldntFindUsername)
- .map(|username| crate::protocol::Auth::Plain { username })
- .map_err(serde::de::Error::custom),
- crate::protocol::AuthType::RecurseCenter => {
- Ok(crate::protocol::Auth::RecurseCenter {
- id: login_type.id.map(std::string::ToString::to_string),
- })
- }
+ .collect();
}
- })
+ Ok(())
+ }
}
-pub fn default_auth() -> crate::protocol::Auth {
- let username = default_username()
- .ok_or_else(|| Error::CouldntFindUsername)
- .unwrap();
- crate::protocol::Auth::Plain { username }
+impl Default for Command {
+ fn default() -> Self {
+ Self {
+ buffer_size: default_buffer_size(),
+ command: default_command(),
+ args: default_args(),
+ }
+ }
}
-#[derive(serde::Deserialize)]
-struct LoginType<'a> {
- #[serde(deserialize_with = "auth_type", default = "default_auth_type")]
- login_type: crate::protocol::AuthType,
- username: Option<&'a str>,
- id: Option<&'a str>,
+fn default_command() -> String {
+ std::env::var("SHELL").unwrap_or_else(|_| "/bin/bash".to_string())
}
-fn auth_type<'a, D>(
- deserializer: D,
-) -> std::result::Result<crate::protocol::AuthType, D::Error>
-where
- D: serde::de::Deserializer<'a>,
-{
- crate::protocol::AuthType::try_from(
- <String>::deserialize(deserializer)?.as_ref(),
- )
- .map_err(serde::de::Error::custom)
+fn default_args() -> Vec<String> {
+ vec![]
}
-fn default_auth_type() -> crate::protocol::AuthType {
- DEFAULT_AUTH_TYPE
+#[derive(serde::Deserialize, Debug)]
+pub struct Ttyrec {
+ #[serde(default = "default_ttyrec_filename")]
+ pub filename: String,
}
-fn default_username() -> Option<String> {
- std::env::var("USER").ok()
+impl Ttyrec {
+ pub fn merge_args<'a>(
+ &mut self,
+ matches: &clap::ArgMatches<'a>,
+ ) -> Result<()> {
+ if matches.is_present("filename") {
+ self.filename = matches.value_of("filename").unwrap().to_string();
+ }
+ Ok(())
+ }
+}
+
+impl Default for Ttyrec {
+ fn default() -> Self {
+ Self {
+ filename: default_ttyrec_filename(),
+ }
+ }
+}
+
+fn default_ttyrec_filename() -> String {
+ DEFAULT_TTYREC_FILENAME.to_string()
}