From e2bec4b81f94ae4bb888ec3f6fc1c1084812d954 Mon Sep 17 00:00:00 2001 From: Daniel Abramov Date: Wed, 7 Aug 2019 20:03:52 +0200 Subject: [PATCH] Change the way we return `Err::ConnectionClosed` This way will ensure that we only return this error once. The previous solution fixed the problem, but it did not guarantee that ""connection closed" is returned only once. --- src/protocol/mod.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 1406e84..0d1e5f7 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -18,7 +18,7 @@ use self::frame::coding::{OpCode, Data as OpData, Control as OpCtl, CloseCode}; use util::NonBlockingResult; /// Indicates a Client or Server role of the websocket -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Role { /// This socket is a server Server, @@ -295,8 +295,13 @@ impl WebSocketContext { // If we get to this point, the send queue is empty and the underlying socket is still // willing to take more data. + let closing_state = match self.state { + WebSocketState::ClosedByPeer | WebSocketState::CloseAcknowledged => true, + _ => false, + }; + // If we're closing and there is nothing to send anymore, we should close the connection. - if let (Role::Server, WebSocketState::ClosedByPeer) = (&self.role, &self.state) { + if self.role == Role::Server && closing_state { // The underlying TCP connection, in most normal cases, SHOULD be closed // first by the server, so that it holds the TIME_WAIT state and not the // client (as this would prevent it from re-opening the connection for 2 @@ -567,7 +572,6 @@ impl WebSocketState { /// Check if the state is active, return error if not. fn check_active(&self) -> Result<()> { match self { - WebSocketState::CloseAcknowledged => Err(Error::ConnectionClosed), WebSocketState::Terminated => Err(Error::AlreadyClosed), _ => Ok(()), }