close: implement complete close handshake

pull/7/head
Alexey Galakhov 8 years ago
parent caba37c41e
commit 4714773370
  1. 4
      src/error.rs
  2. 29
      src/protocol/mod.rs

@ -16,6 +16,8 @@ pub type Result<T> = result::Result<T, Error>;
/// Possible WebSocket errors
#[derive(Debug)]
pub enum Error {
/// WebSocket connection closed (normally)
ConnectionClosed,
/// Input-output error
Io(io::Error),
/// Buffer capacity exhausted
@ -33,6 +35,7 @@ pub enum Error {
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::ConnectionClosed => write!(f, "Connection closed"),
Error::Io(ref err) => write!(f, "IO error: {}", err),
Error::Capacity(ref msg) => write!(f, "Space limit exceeded: {}", msg),
Error::Protocol(ref msg) => write!(f, "WebSocket protocol error: {}", msg),
@ -46,6 +49,7 @@ impl fmt::Display for Error {
impl ErrorTrait for Error {
fn description(&self) -> &str {
match *self {
Error::ConnectionClosed => "",
Error::Io(ref err) => err.description(),
Error::Capacity(ref msg) => msg.borrow(),
Error::Protocol(ref msg) => msg.borrow(),

@ -82,7 +82,8 @@ impl<Stream> WebSocket<Stream>
match self.state {
WebSocketState::Active => {
self.state = WebSocketState::ClosedByUs;
// TODO
let frame = Frame::close(None);
self.send_queue.push_back(frame);
}
_ => {
// already closed, nothing to do
@ -220,7 +221,6 @@ impl<Stream> WebSocket<Stream>
} // match opcode
} else {
//Ok(None) // TODO handle EOF?
Err(Error::Protocol("Connection reset without closing handshake".into()))
}
}
@ -240,25 +240,26 @@ impl<Stream> WebSocket<Stream>
Frame::close(None)
};
self.send_queue.push_back(reply);
Ok(())
}
WebSocketState::ClosedByPeer => {
// It is already closed, just ignore.
Ok(())
}
WebSocketState::ClosedByUs => {
// We received a reply.
match self.role {
Role::Client => {
// Client waits for the server to close the connection.
Ok(())
}
Role::Server => {
// Server closes the connection.
// TODO
Err(Error::ConnectionClosed)
}
}
}
}
//unimplemented!()
Ok(())
}
/// Received a ping frame.
@ -294,7 +295,23 @@ impl<Stream> WebSocket<Stream>
while let Some(data) = self.send_queue.pop_front() {
self.send_one_frame(data)?;
}
Ok(())
// If we're closing and there is nothing to send anymore, we should close the connection.
match self.state {
WebSocketState::ClosedByPeer if self.send_queue.is_empty() => {
// 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
// maximum segment lifetimes (2MSL), while there is no corresponding
// server impact as a TIME_WAIT connection is immediately reopened upon
// a new SYN with a higher seq number). (RFC 6455)
match self.role {
Role::Client => Ok(()),
Role::Server => Err(Error::ConnectionClosed),
}
}
_ => Ok(()),
}
}
/// Send a single pending frame.

Loading…
Cancel
Save