// ---------- newtypes, type aliases, basic definitions ----------
+pub const IDLE_TIMEOUT: Duration = Duration::from_secs(60);
+pub const UPLOAD_TIMEOUT: Duration = Duration::from_secs(60);
+
use pwd::Passwd;
use std::os::unix::io::AsRawFd;
use std::os::unix::net::UnixListener;
}
)?
};
+ bulk_upload.inner_mut().set_timeout(Some(UPLOAD_TIMEOUT));
let uploaded = upload.bulk(bulk_upload, size,
&hash, &mut for_response)?;
{
pub fn mainloop(mut self) {
loop {
use MgmtChannelReadError::*;
- match self.chan.read.read_withbulk::<MgmtCommand>() {
+ match {
+ self.chan.read.inner_mut().set_timeout(Some(IDLE_TIMEOUT));
+ let r = self.chan.read.read_withbulk::<MgmtCommand>();
+ r
+ } {
Ok((cmd, mut rbulk)) => {
execute_and_respond(&mut self.d, cmd, &mut rbulk,
&mut self.chan.write)?;
},
Err(EOF) => break,
+ Err(IO(e)) if e.kind() == ErrorKind::TimedOut => {
+ info!("{}: idle timeout reading command stream", &self.d.desc);
+ self.write_error(ME::IdleTimeout)?;
+ break;
+ }
Err(IO(e)) => Err(e).context("read command stream")?,
Err(Parse(s)) => self.write_error(ME::CommandParseFailed(s))?,
}
let mut data_reporter = progress::ReadOriginator::new(
for_progress, Phase::Upload, size, data);
- let copied_size = io::copy(&mut data_reporter, &mut file)
+ let copied_size = match io::copy(&mut data_reporter, &mut file) {
+ Err(e) if e.kind() == ErrorKind::TimedOut => throw!(ME::UploadTimeout),
+ x => x,
+ }
.with_context(|| tmp.clone())
.context("copy").map_err(IE::from)?;
#[error("bad bundle: {0}")] BadBundle(String),
#[error("bundle not found")] BundleNotFound,
#[error("bundle(s) in use, cannot clear ({0})")] BundlesInUse(String),
+ #[error("idle timeout waiting for mgmt command")] IdleTimeout,
+ #[error("upload took too long (timed out)")] UploadTimeout,
}
impl From<InternalError> for MgmtError {