diff --git a/crates/relay/src/server.rs b/crates/relay/src/server.rs index 2ce8cb466d80aeca68e791d61f6ea4e495bd59c7..388312dc25add7d0260a74253b7eb6ae6444617a 100644 --- a/crates/relay/src/server.rs +++ b/crates/relay/src/server.rs @@ -935,13 +935,13 @@ impl Outbox { } } - /// Everything queued, waiting up to `wait` for something; none once closed. + /// Everything queued, waiting up to `wait` for something; none once closed and empty. fn take(&self, wait: Duration) -> Option> { let mut queue = self.queue.lock().unwrap(); if queue.frames.is_empty() && !queue.closed { queue = self.ready.wait_timeout(queue, wait).unwrap().0; } - if queue.closed { + if queue.closed && queue.frames.is_empty() { return None; } queue.bytes = 0; @@ -956,7 +956,7 @@ impl Outbox { } if queue.bytes + frame.len() > self.most { drop(queue); - self.close(); + self.abort(); return; } queue.bytes += frame.len(); @@ -964,14 +964,19 @@ impl Outbox { self.ready.notify_one(); } + /// Hangs up after writing what is queued, which tells a refused guest its code was wrong. fn close(&self) { - let mut queue = self.queue.lock().unwrap(); - *queue = Queue { + self.queue.lock().unwrap().closed = true; + self.ready.notify_one(); + } + + /// Hangs up now, dropping what is queued. + fn abort(&self) { + *self.queue.lock().unwrap() = Queue { closed: true, ..Queue::default() }; self.ready.notify_one(); - drop(queue); if let Some(stream) = &self.stream { let _ = stream.shutdown(Shutdown::Both); } @@ -983,13 +988,14 @@ impl Outbox { let frame = { let mut queue = self.queue.lock().unwrap(); loop { - if queue.closed { - return; - } if let Some(frame) = queue.frames.pop_front() { queue.bytes -= frame.len(); break frame; } + if queue.closed { + drop(queue); + return self.abort(); + } queue = self.ready.wait(queue).unwrap(); } }; @@ -997,8 +1003,7 @@ impl Outbox { return; }; if stream.write_all(&frame).is_err() { - self.close(); - return; + return self.abort(); } } } diff --git a/crates/relay/tests/relay.rs b/crates/relay/tests/relay.rs index 34d1b1f64e3d43a9de9bd9c158ba129130ae8049..240d765708d243dcb436ca141c674435da6ccbcb 100644 --- a/crates/relay/tests/relay.rs +++ b/crates/relay/tests/relay.rs @@ -275,7 +275,8 @@ fn an_unknown_code_or_room_is_refused() { assert_eq!(status(relay.join("/v1/room/")), "HTTP/1.1 404 Not Found"); } -/// Five wrong codes burn a code: it admits no one new, and its owner hears so. +/// Five wrong codes burn a code: it admits no one new, and its owner hears so. A wrong guess +/// still hears what the owner said before refusing it. #[test] fn wrong_codes_burn_a_code() { let relay = Relay::start(&["--failures-per-minute", "100"]); @@ -285,7 +286,12 @@ fn wrong_codes_burn_a_code() { let mut guess = relay.join(&path).unwrap(); assert_eq!(guess.text(), format!("welcome {slot} 1")); assert_eq!(owner.text(), format!("joined {slot}")); + owner.send_to(slot, b"hello"); owner.say(&format!("failed {slot}")); + assert_eq!( + guess.hear(), + Message::Binary([&1u32.to_be_bytes()[..], b"hello"].concat()) + ); assert!(guess.closed(Duration::from_secs(5))); assert_eq!(owner.text(), format!("left {slot}")); }