chiark / gitweb /
cmdlistener: Apply an idle timeout and an upload timeout
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 16 May 2021 19:44:32 +0000 (20:44 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Mon, 17 May 2021 13:58:58 +0000 (14:58 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
daemon/cmdlistener.rs
src/bundles.rs
src/commands.rs

index 1fcd812e60f4dcd0e8b248a22e732fba7b51b304..34bc09ccabafc6b01d7ef48995e72075e599d1b2 100644 (file)
@@ -13,6 +13,9 @@ use authproofs::*;
 
 // ---------- 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;
@@ -262,6 +265,7 @@ fn execute_and_respond<W>(cs: &mut CommandStreamData, cmd: MgmtCommand,
           }
         )?
       };
+      bulk_upload.inner_mut().set_timeout(Some(UPLOAD_TIMEOUT));
       let uploaded = upload.bulk(bulk_upload, size,
                                  &hash, &mut for_response)?;
       {
@@ -1350,12 +1354,21 @@ impl CommandStream<'_> {
   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))?,
       }
index ea61053fc904c9fe5531cf5b8e17b991c28db5d6..f05b9f89e5c1978bae7654aa111caf930497ec3d 100644 (file)
@@ -868,7 +868,10 @@ impl Uploading {
     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)?;
 
index e5095eb55daf90b0ca57f1ebee01d0bebb8d4d23..ceec49be55484cb7e9db01129b75ac9239d11c99 100644 (file)
@@ -242,6 +242,8 @@ pub enum MgmtError {
   #[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 {