chiark / gitweb /
client: rate limit when returned data contains only junk
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 8 Aug 2021 01:41:44 +0000 (02:41 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 8 Aug 2021 01:48:47 +0000 (02:48 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/bin/client.rs
src/slip.rs

index 491fec3b9a0818ef54ea31a8941c1d8fca0eac8f..c7965861fadb5d4db4ec10d34f9e9afaac8b11c8 100644 (file)
@@ -273,14 +273,21 @@ async fn run_client<C:HCC>(
           reqs.swap_remove(goti);
 
           if let Some(got) = got {
-            reporter.lock().success();
+            
             //eprintln!("got={:?}", DumpHex(&got));
-            checkn(SlipNoConv,ic.mtu, &got, &mut rx_queue, |header| {
+            match checkn(SlipNoConv,ic.mtu, &got, &mut rx_queue, |header| {
               let addr = ip_packet_addr::<true>(header)?;
               if addr != ic.link.client.0 { throw!(PE::Dst(addr)) }
               Ok(())
-            }, |e| error!("{} #{}: rx discarding: {}", &ic, req_num, e));
-          
+            }, |e| error!("{} #{}: rx discarding: {}", &ic, req_num, e)) {
+              Ok(()) => reporter.lock().success(),
+              Err(ErrorOnlyBad) => {
+                reqs.push(Box::pin(async {
+                  tokio::time::sleep(ic.http_retry).await;
+                  None
+                }));
+              },
+            }
           }
         },
 
index 9baf87546b481a4649ff1b6d93fcfe684213bdc6..397aa548aeda73cd0672cc5bb0fe1b271945ca39 100644 (file)
@@ -24,6 +24,10 @@ impl SlipMime for Slip2Mime { const CONV_TO: Option<bool> = Some(true); }
 impl SlipMime for Mime2Slip { const CONV_TO: Option<bool> = Some(false); }
 impl SlipMime for SlipNoConv { const CONV_TO: Option<bool> = None; }
 
+#[derive(Debug)]
+pub struct ErrorOnlyBad;
+
+#[throws(ErrorOnlyBad)]
 pub fn checkn<AC, EH, OUT, M: SlipMime+Copy>(
   mime: M,
   mtu: u32,
@@ -37,13 +41,17 @@ pub fn checkn<AC, EH, OUT, M: SlipMime+Copy>(
 {
   //  eprintln!("before: {:?}", DumpHex(data));
   if data.is_empty() { return }
+  let mut ok = false;
+  let mut err = false;
   for packet in data.split(|&c| c == SLIP_END) {
     match check1(mime, mtu, packet, addr_chk) {
-      Err(e) => error_handler(e),
-      Ok(packet) => out.extend(iter::once(packet)),
+      Err(PacketError::Empty) => { }
+      Err(e) => { err=true; error_handler(e); },
+      Ok(packet) => { ok=true; out.extend(iter::once(packet)); },
     }
   }
 //  eprintln!(" after: {:?}", DumpHex(data));
+  if err && !ok { throw!(ErrorOnlyBad) }
 }
 
 #[throws(PacketError)]