From 6f8d18f283b0cbfcc64eed91be0bdc55cf233c51 Mon Sep 17 00:00:00 2001 From: Titouan Rigoudy Date: Sat, 24 Jul 2021 16:55:20 -0400 Subject: [PATCH] Apply same rustfmt.toml to proto/. --- proto/src/core/channel.rs | 425 ++--- proto/src/core/frame.rs | 684 +++---- proto/src/core/prefix.rs | 176 +- proto/src/core/u32.rs | 4 +- proto/src/core/user.rs | 150 +- proto/src/core/value.rs | 1389 ++++++++------- proto/src/handler.rs | 553 +++--- proto/src/packet.rs | 502 +++--- proto/src/peer/message.rs | 301 ++-- proto/src/server/client.rs | 343 ++-- proto/src/server/credentials.rs | 211 +-- proto/src/server/request.rs | 1232 ++++++------- proto/src/server/response.rs | 2575 ++++++++++++++------------- proto/src/server/testing.rs | 582 +++--- proto/src/server/version.rs | 18 +- proto/src/stream.rs | 329 ++-- proto/tests/connect.rs | 90 +- client/rustfmt.toml => rustfmt.toml | 0 18 files changed, 4898 insertions(+), 4666 deletions(-) rename client/rustfmt.toml => rustfmt.toml (100%) diff --git a/proto/src/core/channel.rs b/proto/src/core/channel.rs index 77e7894..acbb654 100644 --- a/proto/src/core/channel.rs +++ b/proto/src/core/channel.rs @@ -6,8 +6,8 @@ use futures::stream::{Stream, StreamExt}; use log::debug; use thiserror::Error; use tokio::net::{ - tcp::{OwnedReadHalf, OwnedWriteHalf}, - TcpStream, + tcp::{OwnedReadHalf, OwnedWriteHalf}, + TcpStream, }; use crate::core::frame::{FrameReader, FrameWriter}; @@ -16,21 +16,21 @@ use crate::core::value::{ValueDecode, ValueEncode}; /// An error that arose while exchanging messages over a `Channel`. #[derive(Debug, Error)] pub enum ChannelError { - #[error("unexpected end of file")] - UnexpectedEof, + #[error("unexpected end of file")] + UnexpectedEof, - #[error("i/o error: {0}")] - IOError(#[from] io::Error), + #[error("i/o error: {0}")] + IOError(#[from] io::Error), } impl ChannelError { - #[cfg(test)] - pub fn is_unexpected_eof(&self) -> bool { - match self { - ChannelError::UnexpectedEof => true, - _ => false, - } + #[cfg(test)] + pub fn is_unexpected_eof(&self) -> bool { + match self { + ChannelError::UnexpectedEof => true, + _ => false, } + } } /// A wrapper around a frame reader. Logically a part of `Channel`. @@ -40,270 +40,271 @@ impl ChannelError { /// at the same time in `Channel` without resorting to static methods. #[derive(Debug)] struct ChannelReader { - inner: FrameReader, + inner: FrameReader, } impl ChannelReader where - ReadFrame: ValueDecode + Debug, + ReadFrame: ValueDecode + Debug, { - async fn read(&mut self) -> io::Result> { - self.inner.read().await.map(|frame| { - debug!("Channel: received frame: {:?}", frame); - frame - }) - } - - async fn read_strict(&mut self) -> Result { - match self.read().await? { - None => Err(ChannelError::UnexpectedEof), - Some(frame) => Ok(frame), - } + async fn read(&mut self) -> io::Result> { + self.inner.read().await.map(|frame| { + debug!("Channel: received frame: {:?}", frame); + frame + }) + } + + async fn read_strict(&mut self) -> Result { + match self.read().await? { + None => Err(ChannelError::UnexpectedEof), + Some(frame) => Ok(frame), } + } } /// An asynchronous bidirectional message channel over TCP. #[derive(Debug)] pub struct Channel { - reader: ChannelReader, - writer: FrameWriter, + reader: ChannelReader, + writer: FrameWriter, } impl Channel where - ReadFrame: ValueDecode + Debug, - WriteFrame: ValueEncode + Debug, + ReadFrame: ValueDecode + Debug, + WriteFrame: ValueEncode + Debug, { - /// Wraps the given `stream` to yield a message channel. - pub fn new(stream: TcpStream) -> Self { - let (read_half, write_half) = stream.into_split(); - Self { - reader: ChannelReader { - inner: FrameReader::new(read_half), - }, - writer: FrameWriter::new(write_half), - } - } - - // This future sends all the requests from `request_stream` through `writer` - // until the stream is finished, then resolves. - async fn send>( - writer: &mut FrameWriter, - send_stream: S, - ) -> io::Result<()> { - tokio::pin!(send_stream); - while let Some(frame) = send_stream.next().await { - debug!("Channel: sending frame: {:?}", frame); - writer.write(&frame).await?; - } - Ok(()) + /// Wraps the given `stream` to yield a message channel. + pub fn new(stream: TcpStream) -> Self { + let (read_half, write_half) = stream.into_split(); + Self { + reader: ChannelReader { + inner: FrameReader::new(read_half), + }, + writer: FrameWriter::new(write_half), } - - // It would be easier to inline this `select!` call inside `run()`, but that - // fails due to some weird, undiagnosed error due to the interaction of - // `async_stream::try_stream!`, `select!` and the `?` operator. - async fn run_once>>( - send_task: S, - reader: &mut ChannelReader, - ) -> Result, ChannelError> { - tokio::select! { - send_result = send_task => { - send_result?; - Ok(None) - }, - read_result = reader.read_strict() => read_result.map(Some), - } - } - - /// Attempts to read a single frame from the underlying stream. - pub async fn read(&mut self) -> Result { - self.reader.read_strict().await + } + + // This future sends all the requests from `request_stream` through `writer` + // until the stream is finished, then resolves. + async fn send>( + writer: &mut FrameWriter, + send_stream: S, + ) -> io::Result<()> { + tokio::pin!(send_stream); + while let Some(frame) = send_stream.next().await { + debug!("Channel: sending frame: {:?}", frame); + writer.write(&frame).await?; } - - /// Attempts to write a single frame to the underlying stream. - pub async fn write(&mut self, frame: &WriteFrame) -> io::Result<()> { - self.writer.write(frame).await + Ok(()) + } + + // It would be easier to inline this `select!` call inside `run()`, but that + // fails due to some weird, undiagnosed error due to the interaction of + // `async_stream::try_stream!`, `select!` and the `?` operator. + async fn run_once>>( + send_task: S, + reader: &mut ChannelReader, + ) -> Result, ChannelError> { + tokio::select! { + send_result = send_task => { + send_result?; + Ok(None) + }, + read_result = reader.read_strict() => read_result.map(Some), } - - /// Sends the given stream of frames while receiving frames in return. - /// Once `send_stream` is exhausted, shuts down the underlying TCP stream, - /// drains incoming frames, then terminates. - pub fn run>( - mut self, - send_stream: S, - ) -> impl Stream> { - async_stream::try_stream! { - // Drive the main loop: send requests and receive responses. - // - // We make a big future out of the operation of waiting for requests - // to send and from `request_stream` and sending them out through - // `self.writer`, that we can then poll repeatedly and concurrently - // with polling for responses. This allows us to concurrently write - // and read from the underlying `TcpStream` in full duplex mode. - { - let send_task = Self::send(&mut self.writer, send_stream); - tokio::pin!(send_task); - - while let Some(frame) = - Self::run_once(&mut send_task, &mut self.reader).await? { - yield frame; - } + } + + /// Attempts to read a single frame from the underlying stream. + pub async fn read(&mut self) -> Result { + self.reader.read_strict().await + } + + /// Attempts to write a single frame to the underlying stream. + pub async fn write(&mut self, frame: &WriteFrame) -> io::Result<()> { + self.writer.write(frame).await + } + + /// Sends the given stream of frames while receiving frames in return. + /// Once `send_stream` is exhausted, shuts down the underlying TCP stream, + /// drains incoming frames, then terminates. + pub fn run>( + mut self, + send_stream: S, + ) -> impl Stream> { + async_stream::try_stream! { + // Drive the main loop: send requests and receive responses. + // + // We make a big future out of the operation of waiting for requests + // to send and from `request_stream` and sending them out through + // `self.writer`, that we can then poll repeatedly and concurrently + // with polling for responses. This allows us to concurrently write + // and read from the underlying `TcpStream` in full duplex mode. + { + let send_task = Self::send(&mut self.writer, send_stream); + tokio::pin!(send_task); + + while let Some(frame) = + Self::run_once(&mut send_task, &mut self.reader).await? { + yield frame; } + } - debug!("Channel: shutting down writer"); - self.writer.shutdown().await?; + debug!("Channel: shutting down writer"); + self.writer.shutdown().await?; - // Drain the receiving end of the connection. - while let Some(frame) = self.reader.read().await? { - yield frame; - } - } + // Drain the receiving end of the connection. + while let Some(frame) = self.reader.read().await? { + yield frame; + } } + } } #[cfg(test)] mod tests { - use futures::stream::{self, StreamExt}; - use tokio::net::{TcpListener, TcpStream}; - use tokio::sync::oneshot; + use futures::stream::{self, StreamExt}; + use tokio::net::{TcpListener, TcpStream}; + use tokio::sync::oneshot; - use super::Channel; + use super::Channel; - // Enable capturing logs in tests. - fn init() { - let _ = env_logger::builder().is_test(true).try_init(); - } + // Enable capturing logs in tests. + fn init() { + let _ = env_logger::builder().is_test(true).try_init(); + } - #[tokio::test] - async fn read_write() { - init(); + #[tokio::test] + async fn read_write() { + init(); - let listener = TcpListener::bind("localhost:0").await.unwrap(); - let address = listener.local_addr().unwrap(); + let listener = TcpListener::bind("localhost:0").await.unwrap(); + let address = listener.local_addr().unwrap(); - let listener_task = tokio::spawn(async move { - let (stream, _) = listener.accept().await.unwrap(); - let mut channel = Channel::::new(stream); + let listener_task = tokio::spawn(async move { + let (stream, _) = listener.accept().await.unwrap(); + let mut channel = Channel::::new(stream); - assert_eq!(channel.read().await.unwrap(), 1); - channel.write(&2).await.unwrap(); - }); + assert_eq!(channel.read().await.unwrap(), 1); + channel.write(&2).await.unwrap(); + }); - let stream = TcpStream::connect(address).await.unwrap(); - let mut channel = Channel::::new(stream); + let stream = TcpStream::connect(address).await.unwrap(); + let mut channel = Channel::::new(stream); - channel.write(&1).await.unwrap(); - assert_eq!(channel.read().await.unwrap(), 2); + channel.write(&1).await.unwrap(); + assert_eq!(channel.read().await.unwrap(), 2); - listener_task.await.unwrap(); - } + listener_task.await.unwrap(); + } - #[tokio::test] - async fn read_eof() { - init(); + #[tokio::test] + async fn read_eof() { + init(); - let listener = TcpListener::bind("localhost:0").await.unwrap(); - let address = listener.local_addr().unwrap(); + let listener = TcpListener::bind("localhost:0").await.unwrap(); + let address = listener.local_addr().unwrap(); - let listener_task = tokio::spawn(async move { - // Accept the stream and immediately drop/close it. - listener.accept().await.unwrap(); - }); + let listener_task = tokio::spawn(async move { + // Accept the stream and immediately drop/close it. + listener.accept().await.unwrap(); + }); - let stream = TcpStream::connect(address).await.unwrap(); - let mut channel = Channel::::new(stream); + let stream = TcpStream::connect(address).await.unwrap(); + let mut channel = Channel::::new(stream); - assert!(channel.read().await.unwrap_err().is_unexpected_eof()); + assert!(channel.read().await.unwrap_err().is_unexpected_eof()); - listener_task.await.unwrap(); - } + listener_task.await.unwrap(); + } - #[tokio::test] - async fn open_close() { - init(); + #[tokio::test] + async fn open_close() { + init(); - let listener = TcpListener::bind("localhost:0").await.unwrap(); - let address = listener.local_addr().unwrap(); + let listener = TcpListener::bind("localhost:0").await.unwrap(); + let address = listener.local_addr().unwrap(); - let listener_task = tokio::spawn(async move { - let (stream, _) = listener.accept().await.unwrap(); - let channel = Channel::::new(stream); + let listener_task = tokio::spawn(async move { + let (stream, _) = listener.accept().await.unwrap(); + let channel = Channel::::new(stream); - // Wait forever, receive no messages. - let inbound = channel.run(stream::pending()); - tokio::pin!(inbound); + // Wait forever, receive no messages. + let inbound = channel.run(stream::pending()); + tokio::pin!(inbound); - // The server observes an unexpected EOF error when the client - // decides to close the channel. - let error = inbound.next().await.unwrap().unwrap_err(); - assert!(error.is_unexpected_eof()); - }); + // The server observes an unexpected EOF error when the client + // decides to close the channel. + let error = inbound.next().await.unwrap().unwrap_err(); + assert!(error.is_unexpected_eof()); + }); - let stream = TcpStream::connect(address).await.unwrap(); - let channel = Channel::::new(stream); + let stream = TcpStream::connect(address).await.unwrap(); + let channel = Channel::::new(stream); - // Stop immediately, receive no messages. - let inbound = channel.run(stream::empty()); - tokio::pin!(inbound); + // Stop immediately, receive no messages. + let inbound = channel.run(stream::empty()); + tokio::pin!(inbound); - // The channel is closed cleanly from the client's point of view. - assert!(inbound.next().await.is_none()); + // The channel is closed cleanly from the client's point of view. + assert!(inbound.next().await.is_none()); - listener_task.await.unwrap(); - } + listener_task.await.unwrap(); + } - #[tokio::test] - async fn simple_exchange() { - init(); + #[tokio::test] + async fn simple_exchange() { + init(); - let listener = TcpListener::bind("localhost:0").await.unwrap(); - let address = listener.local_addr().unwrap(); + let listener = TcpListener::bind("localhost:0").await.unwrap(); + let address = listener.local_addr().unwrap(); - let listener_task = tokio::spawn(async move { - let (stream, _) = listener.accept().await.unwrap(); - let channel = Channel::::new(stream); + let listener_task = tokio::spawn(async move { + let (stream, _) = listener.accept().await.unwrap(); + let channel = Channel::::new(stream); - let (tx, rx) = oneshot::channel::(); + let (tx, rx) = oneshot::channel::(); - // Send one message, then wait forever. - let outbound = stream::once(async move { rx.await.unwrap() }).chain(stream::pending()); - let inbound = channel.run(outbound); - tokio::pin!(inbound); + // Send one message, then wait forever. + let outbound = + stream::once(async move { rx.await.unwrap() }).chain(stream::pending()); + let inbound = channel.run(outbound); + tokio::pin!(inbound); - // The server receives the client's message. - assert_eq!(inbound.next().await.unwrap().unwrap(), 1); + // The server receives the client's message. + assert_eq!(inbound.next().await.unwrap().unwrap(), 1); - // Server responds. - tx.send(1001).unwrap(); + // Server responds. + tx.send(1001).unwrap(); - // The server observes an unexpected EOF error when the client - // decides to close the channel. - let error = inbound.next().await.unwrap().unwrap_err(); - assert!(error.is_unexpected_eof()); - }); + // The server observes an unexpected EOF error when the client + // decides to close the channel. + let error = inbound.next().await.unwrap().unwrap_err(); + assert!(error.is_unexpected_eof()); + }); - let stream = TcpStream::connect(address).await.unwrap(); - let channel = Channel::::new(stream); + let stream = TcpStream::connect(address).await.unwrap(); + let channel = Channel::::new(stream); - let (tx, rx) = oneshot::channel::<()>(); + let (tx, rx) = oneshot::channel::<()>(); - // Send one message then wait for a reply. If we did not wait, we might - // shut down the channel before the server has a chance to respond. - let outbound = async_stream::stream! { - yield 1; - rx.await.unwrap(); - }; - let inbound = channel.run(outbound); - tokio::pin!(inbound); + // Send one message then wait for a reply. If we did not wait, we might + // shut down the channel before the server has a chance to respond. + let outbound = async_stream::stream! { + yield 1; + rx.await.unwrap(); + }; + let inbound = channel.run(outbound); + tokio::pin!(inbound); - // The client receives the server's message. - assert_eq!(inbound.next().await.unwrap().unwrap(), 1001); + // The client receives the server's message. + assert_eq!(inbound.next().await.unwrap().unwrap(), 1001); - // Signal to the client that we should shut down. - tx.send(()).unwrap(); + // Signal to the client that we should shut down. + tx.send(()).unwrap(); - assert!(inbound.next().await.is_none()); + assert!(inbound.next().await.is_none()); - listener_task.await.unwrap(); - } + listener_task.await.unwrap(); + } } diff --git a/proto/src/core/frame.rs b/proto/src/core/frame.rs index 850d946..cd130c3 100644 --- a/proto/src/core/frame.rs +++ b/proto/src/core/frame.rs @@ -13,401 +13,411 @@ use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; use super::prefix::Prefixer; use super::u32::{decode_u32, U32_BYTE_LEN}; use super::value::{ - ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncodeError, ValueEncoder, + ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncodeError, + ValueEncoder, }; #[derive(Debug, Error, PartialEq)] pub enum FrameEncodeError { - #[error("encoded value length {length} is too large")] - ValueTooLarge { - /// The length of the encoded value. - length: usize, - }, - - #[error("failed to encode value: {0}")] - ValueEncodeError(#[from] ValueEncodeError), + #[error("encoded value length {length} is too large")] + ValueTooLarge { + /// The length of the encoded value. + length: usize, + }, + + #[error("failed to encode value: {0}")] + ValueEncodeError(#[from] ValueEncodeError), } impl From for io::Error { - fn from(error: FrameEncodeError) -> Self { - io::Error::new(io::ErrorKind::InvalidData, format!("{}", error)) - } + fn from(error: FrameEncodeError) -> Self { + io::Error::new(io::ErrorKind::InvalidData, format!("{}", error)) + } } /// Encodes entire protocol frames containing values of type `T`. #[derive(Debug)] pub struct FrameEncoder { - phantom: PhantomData, + phantom: PhantomData, } impl FrameEncoder { - pub fn new() -> Self { - Self { - phantom: PhantomData, - } + pub fn new() -> Self { + Self { + phantom: PhantomData, } + } - pub fn encode_to(&mut self, value: &T, buffer: &mut BytesMut) -> Result<(), FrameEncodeError> { - let mut prefixer = Prefixer::new(buffer); - - ValueEncoder::new(prefixer.suffix_mut()).encode(value)?; + pub fn encode_to( + &mut self, + value: &T, + buffer: &mut BytesMut, + ) -> Result<(), FrameEncodeError> { + let mut prefixer = Prefixer::new(buffer); - if let Err(prefixer) = prefixer.finalize() { - return Err(FrameEncodeError::ValueTooLarge { - length: prefixer.suffix().len(), - }); - } + ValueEncoder::new(prefixer.suffix_mut()).encode(value)?; - Ok(()) + if let Err(prefixer) = prefixer.finalize() { + return Err(FrameEncodeError::ValueTooLarge { + length: prefixer.suffix().len(), + }); } + + Ok(()) + } } /// Decodes entire protocol frames containing values of type `T`. #[derive(Debug)] pub struct FrameDecoder { - // Only here to enable parameterizing `Decoder` by `T`. - phantom: PhantomData, + // Only here to enable parameterizing `Decoder` by `T`. + phantom: PhantomData, } impl FrameDecoder { - pub fn new() -> Self { - Self { - phantom: PhantomData, - } + pub fn new() -> Self { + Self { + phantom: PhantomData, + } + } + + /// Attempts to decode an entire frame from the given buffer. + /// + /// Returns `Ok(Some(frame))` if successful, in which case the frame's bytes + /// have been split off from the left of `bytes`. + /// + /// Returns `Ok(None)` if not enough bytes are available to decode an entire + /// frame yet, in which case `bytes` is untouched. + /// + /// Returns an error if the length prefix or the framed value are malformed, + /// in which case `bytes` is untouched. + pub fn decode_from( + &mut self, + bytes: &mut BytesMut, + ) -> Result, ValueDecodeError> { + if bytes.len() < U32_BYTE_LEN { + return Ok(None); // Not enough bytes yet. } - /// Attempts to decode an entire frame from the given buffer. - /// - /// Returns `Ok(Some(frame))` if successful, in which case the frame's bytes - /// have been split off from the left of `bytes`. - /// - /// Returns `Ok(None)` if not enough bytes are available to decode an entire - /// frame yet, in which case `bytes` is untouched. - /// - /// Returns an error if the length prefix or the framed value are malformed, - /// in which case `bytes` is untouched. - pub fn decode_from(&mut self, bytes: &mut BytesMut) -> Result, ValueDecodeError> { - if bytes.len() < U32_BYTE_LEN { - return Ok(None); // Not enough bytes yet. - } - - // Split the prefix off. After this: - // - // | bytes (len 4) | suffix | - // - // NOTE: This method would be simpler if we could use split_to() instead - // here such that `bytes` contained the suffix. At the end, we would not - // have to replace `bytes` with `suffix`. However, that would require - // calling `prefix.unsplit(*bytes)`, and that does not work since - // `bytes` is only borrowed, and unsplit() takes its argument by value. - let mut suffix = bytes.split_off(U32_BYTE_LEN); - - // unwrap() cannot panic because `bytes` is of the exact right length. - let array: [u8; U32_BYTE_LEN] = bytes.as_ref().try_into().unwrap(); - let length = decode_u32(array) as usize; - - if suffix.len() < length { - // Re-assemble `bytes` as it first was. - bytes.unsplit(suffix); - return Ok(None); // Not enough bytes yet. - } - - // Split off the right amount of bytes from the buffer. After this: - // - // | bytes (len 4) | contents | suffix | - // - let mut contents = suffix.split_to(length); - - // Attempt to decode the value. - let item = match ValueDecoder::new(&contents).decode() { - Ok(item) => item, - Err(error) => { - // Re-assemble `bytes` as it first was. - contents.unsplit(suffix); - bytes.unsplit(contents); - return Err(error); - } - }; - - // Remove the decoded bytes from the left of `bytes`. - *bytes = suffix; - Ok(Some(item)) + // Split the prefix off. After this: + // + // | bytes (len 4) | suffix | + // + // NOTE: This method would be simpler if we could use split_to() instead + // here such that `bytes` contained the suffix. At the end, we would not + // have to replace `bytes` with `suffix`. However, that would require + // calling `prefix.unsplit(*bytes)`, and that does not work since + // `bytes` is only borrowed, and unsplit() takes its argument by value. + let mut suffix = bytes.split_off(U32_BYTE_LEN); + + // unwrap() cannot panic because `bytes` is of the exact right length. + let array: [u8; U32_BYTE_LEN] = bytes.as_ref().try_into().unwrap(); + let length = decode_u32(array) as usize; + + if suffix.len() < length { + // Re-assemble `bytes` as it first was. + bytes.unsplit(suffix); + return Ok(None); // Not enough bytes yet. } + + // Split off the right amount of bytes from the buffer. After this: + // + // | bytes (len 4) | contents | suffix | + // + let mut contents = suffix.split_to(length); + + // Attempt to decode the value. + let item = match ValueDecoder::new(&contents).decode() { + Ok(item) => item, + Err(error) => { + // Re-assemble `bytes` as it first was. + contents.unsplit(suffix); + bytes.unsplit(contents); + return Err(error); + } + }; + + // Remove the decoded bytes from the left of `bytes`. + *bytes = suffix; + Ok(Some(item)) + } } /// An asynchronous sink for frames wrapping around a byte writer. #[derive(Debug)] pub struct FrameWriter { - encoder: FrameEncoder, - writer: Writer, + encoder: FrameEncoder, + writer: Writer, } impl FrameWriter where - Frame: ValueEncode + ?Sized, - Writer: AsyncWrite + Unpin, + Frame: ValueEncode + ?Sized, + Writer: AsyncWrite + Unpin, { - pub fn new(writer: Writer) -> Self { - FrameWriter { - encoder: FrameEncoder::new(), - writer, - } + pub fn new(writer: Writer) -> Self { + FrameWriter { + encoder: FrameEncoder::new(), + writer, } + } - pub async fn write(&mut self, frame: &Frame) -> io::Result<()> { - let mut bytes = BytesMut::new(); - self.encoder.encode_to(frame, &mut bytes)?; - self.writer.write_all(bytes.as_ref()).await - } + pub async fn write(&mut self, frame: &Frame) -> io::Result<()> { + let mut bytes = BytesMut::new(); + self.encoder.encode_to(frame, &mut bytes)?; + self.writer.write_all(bytes.as_ref()).await + } - pub async fn shutdown(&mut self) -> io::Result<()> { - self.writer.shutdown().await - } + pub async fn shutdown(&mut self) -> io::Result<()> { + self.writer.shutdown().await + } } /// An asynchronous stream of frames wrapping around a byte reader. #[derive(Debug)] pub struct FrameReader { - decoder: FrameDecoder, - reader: Reader, - read_buffer: BytesMut, + decoder: FrameDecoder, + reader: Reader, + read_buffer: BytesMut, } impl FrameReader where - Frame: ValueDecode, - Reader: AsyncRead + Unpin, + Frame: ValueDecode, + Reader: AsyncRead + Unpin, { - pub fn new(reader: Reader) -> Self { - FrameReader { - decoder: FrameDecoder::new(), - reader, - read_buffer: BytesMut::new(), - } + pub fn new(reader: Reader) -> Self { + FrameReader { + decoder: FrameDecoder::new(), + reader, + read_buffer: BytesMut::new(), } - - /// Attempts to read the next frame from the underlying byte stream. - /// - /// Returns `Ok(Some(frame))` on success. - /// Returns `Ok(None)` if the stream has reached the end-of-file event. - /// - /// Returns an error if reading from the stream returned an error or if an - /// invalid frame was received. - pub async fn read(&mut self) -> io::Result> { - loop { - if let Some(frame) = self.decoder.decode_from(&mut self.read_buffer)? { - return Ok(Some(frame)); - } - if self.reader.read_buf(&mut self.read_buffer).await? == 0 { - return Ok(None); - } - } + } + + /// Attempts to read the next frame from the underlying byte stream. + /// + /// Returns `Ok(Some(frame))` on success. + /// Returns `Ok(None)` if the stream has reached the end-of-file event. + /// + /// Returns an error if reading from the stream returned an error or if an + /// invalid frame was received. + pub async fn read(&mut self) -> io::Result> { + loop { + if let Some(frame) = self.decoder.decode_from(&mut self.read_buffer)? { + return Ok(Some(frame)); + } + if self.reader.read_buf(&mut self.read_buffer).await? == 0 { + return Ok(None); + } } + } } #[cfg(test)] mod tests { - use bytes::BytesMut; - use tokio::net::{TcpListener, TcpStream}; - - use super::{FrameDecoder, FrameEncoder, FrameReader, FrameWriter}; - - // Test value: [1, 3, 3, 7] in little-endian. - const U32_1337: u32 = 1 + (3 << 8) + (3 << 16) + (7 << 24); - - #[test] - fn encode_u32() { - let mut bytes = BytesMut::new(); - - FrameEncoder::new() - .encode_to(&U32_1337, &mut bytes) - .unwrap(); - - assert_eq!( - bytes, - vec![ - 4, 0, 0, 0, // 1 32-bit integer = 4 bytes. - 1, 3, 3, 7, // Little-endian integer. - ] - ); - } - - #[test] - fn encode_appends() { - let mut bytes = BytesMut::new(); - - let mut encoder = FrameEncoder::new(); - encoder.encode_to(&U32_1337, &mut bytes).unwrap(); - encoder.encode_to(&U32_1337, &mut bytes).unwrap(); - - assert_eq!( - bytes, - vec![ - 4, 0, 0, 0, // 1 32-bit integer = 4 bytes. - 1, 3, 3, 7, // Little-endian integer. - 4, 0, 0, 0, // Repeated. - 1, 3, 3, 7, - ] - ); - } - - #[test] - fn encode_vec() { - let v: Vec = vec![1, 3, 3, 7]; - - let mut bytes = BytesMut::new(); - FrameEncoder::new().encode_to(&v, &mut bytes).unwrap(); - - assert_eq!( - bytes, - vec![ - 20, 0, 0, 0, // 5 32-bit integers = 20 bytes. - 4, 0, 0, 0, // 4 elements in the vector. - 1, 0, 0, 0, // Little-endian vector elements. - 3, 0, 0, 0, // - 3, 0, 0, 0, // - 7, 0, 0, 0, // - ] - ); - } - - #[test] - fn decode_not_enough_data_for_prefix() { - let initial_bytes = vec![ - 4, 0, 0, // Incomplete 32-bit length prefix. - ]; - - let mut bytes = BytesMut::new(); - bytes.extend_from_slice(&initial_bytes); - - let value: Option = FrameDecoder::new().decode_from(&mut bytes).unwrap(); - - assert_eq!(value, None); - assert_eq!(bytes, initial_bytes); // Untouched. - } - - #[test] - fn decode_not_enough_data_for_contents() { - let initial_bytes = vec![ - 4, 0, 0, 0, // Length 4. - 1, 2, 3, // But there are only 3 bytes! - ]; - - let mut bytes = BytesMut::new(); - bytes.extend_from_slice(&initial_bytes); - - let value: Option = FrameDecoder::new().decode_from(&mut bytes).unwrap(); - - assert_eq!(value, None); - assert_eq!(bytes, initial_bytes); // Untouched. - } - - #[test] - fn decode_u32() { - let mut bytes = BytesMut::new(); - bytes.extend_from_slice(&[ - 4, 0, 0, 0, // 1 32-bit integer = 4 bytes. - 1, 3, 3, 7, // Little-endian integer. - 4, 2, // Trailing bytes. - ]); - - let value = FrameDecoder::new().decode_from(&mut bytes).unwrap(); - - assert_eq!(value, Some(U32_1337)); - assert_eq!(bytes, vec![4, 2]); // Decoded bytes were split off. - } - - #[test] - fn decode_vec() { - let mut bytes = BytesMut::new(); - bytes.extend_from_slice(&[ - 20, 0, 0, 0, // 5 32-bit integers = 20 bytes. - 4, 0, 0, 0, // 4 elements in the vector. - 1, 0, 0, 0, // Little-endian vector elements. - 3, 0, 0, 0, // - 3, 0, 0, 0, // - 7, 0, 0, 0, // - 4, 2, // Trailing bytes. - ]); - - let value = FrameDecoder::new().decode_from(&mut bytes).unwrap(); - - let expected_value: Vec = vec![1, 3, 3, 7]; - assert_eq!(value, Some(expected_value)); - assert_eq!(bytes, vec![4, 2]); // Decoded bytes were split off. - } - - #[test] - fn roundtrip() { - let value: Vec = vec![ - "apples".to_string(), // - "bananas".to_string(), // - "oranges".to_string(), // - "and cheese!".to_string(), // - ]; - - let mut buffer = BytesMut::new(); - - FrameEncoder::new().encode_to(&value, &mut buffer).unwrap(); - let decoded = FrameDecoder::new().decode_from(&mut buffer).unwrap(); - - assert_eq!(decoded, Some(value)); - assert_eq!(buffer, vec![]); - } - - #[tokio::test] - async fn ping_pong() { - let listener = TcpListener::bind("localhost:0").await.unwrap(); - let address = listener.local_addr().unwrap(); - - let server_task = tokio::spawn(async move { - let (mut stream, _peer_address) = listener.accept().await.unwrap(); - let (read_half, write_half) = stream.split(); - let mut reader = FrameReader::new(read_half); - let mut writer = FrameWriter::new(write_half); - - assert_eq!(reader.read().await.unwrap(), Some("ping".to_string())); - writer.write("pong").await.unwrap(); - assert_eq!(reader.read().await.unwrap(), Some("ping".to_string())); - writer.write("pong").await.unwrap(); - }); - - let mut stream = TcpStream::connect(address).await.unwrap(); - let (read_half, write_half) = stream.split(); - let mut reader = FrameReader::new(read_half); - let mut writer = FrameWriter::new(write_half); - - writer.write("ping").await.unwrap(); - assert_eq!(reader.read().await.unwrap(), Some("pong".to_string())); - writer.write("ping").await.unwrap(); - assert_eq!(reader.read().await.unwrap(), Some("pong".to_string())); - - server_task.await.unwrap(); - } - - #[tokio::test] - async fn very_large_message() { - let listener = TcpListener::bind("localhost:0").await.unwrap(); - let address = listener.local_addr().unwrap(); - - let server_task = tokio::spawn(async move { - let (mut stream, _peer_address) = listener.accept().await.unwrap(); - let (read_half, write_half) = stream.split(); - let mut reader = FrameReader::new(read_half); - let mut writer = FrameWriter::new(write_half); - - assert_eq!(reader.read().await.unwrap(), Some("ping".to_string())); - writer.write(&vec![0u32; 10 * 4096]).await.unwrap(); - }); - - let mut stream = TcpStream::connect(address).await.unwrap(); - let (read_half, write_half) = stream.split(); - let mut reader = FrameReader::new(read_half); - let mut writer = FrameWriter::new(write_half); - - writer.write("ping").await.unwrap(); - assert_eq!(reader.read().await.unwrap(), Some(vec![0u32; 10 * 4096])); - - server_task.await.unwrap(); - } + use bytes::BytesMut; + use tokio::net::{TcpListener, TcpStream}; + + use super::{FrameDecoder, FrameEncoder, FrameReader, FrameWriter}; + + // Test value: [1, 3, 3, 7] in little-endian. + const U32_1337: u32 = 1 + (3 << 8) + (3 << 16) + (7 << 24); + + #[test] + fn encode_u32() { + let mut bytes = BytesMut::new(); + + FrameEncoder::new() + .encode_to(&U32_1337, &mut bytes) + .unwrap(); + + assert_eq!( + bytes, + vec![ + 4, 0, 0, 0, // 1 32-bit integer = 4 bytes. + 1, 3, 3, 7, // Little-endian integer. + ] + ); + } + + #[test] + fn encode_appends() { + let mut bytes = BytesMut::new(); + + let mut encoder = FrameEncoder::new(); + encoder.encode_to(&U32_1337, &mut bytes).unwrap(); + encoder.encode_to(&U32_1337, &mut bytes).unwrap(); + + assert_eq!( + bytes, + vec![ + 4, 0, 0, 0, // 1 32-bit integer = 4 bytes. + 1, 3, 3, 7, // Little-endian integer. + 4, 0, 0, 0, // Repeated. + 1, 3, 3, 7, + ] + ); + } + + #[test] + fn encode_vec() { + let v: Vec = vec![1, 3, 3, 7]; + + let mut bytes = BytesMut::new(); + FrameEncoder::new().encode_to(&v, &mut bytes).unwrap(); + + assert_eq!( + bytes, + vec![ + 20, 0, 0, 0, // 5 32-bit integers = 20 bytes. + 4, 0, 0, 0, // 4 elements in the vector. + 1, 0, 0, 0, // Little-endian vector elements. + 3, 0, 0, 0, // + 3, 0, 0, 0, // + 7, 0, 0, 0, // + ] + ); + } + + #[test] + fn decode_not_enough_data_for_prefix() { + let initial_bytes = vec![ + 4, 0, 0, // Incomplete 32-bit length prefix. + ]; + + let mut bytes = BytesMut::new(); + bytes.extend_from_slice(&initial_bytes); + + let value: Option = + FrameDecoder::new().decode_from(&mut bytes).unwrap(); + + assert_eq!(value, None); + assert_eq!(bytes, initial_bytes); // Untouched. + } + + #[test] + fn decode_not_enough_data_for_contents() { + let initial_bytes = vec![ + 4, 0, 0, 0, // Length 4. + 1, 2, 3, // But there are only 3 bytes! + ]; + + let mut bytes = BytesMut::new(); + bytes.extend_from_slice(&initial_bytes); + + let value: Option = + FrameDecoder::new().decode_from(&mut bytes).unwrap(); + + assert_eq!(value, None); + assert_eq!(bytes, initial_bytes); // Untouched. + } + + #[test] + fn decode_u32() { + let mut bytes = BytesMut::new(); + bytes.extend_from_slice(&[ + 4, 0, 0, 0, // 1 32-bit integer = 4 bytes. + 1, 3, 3, 7, // Little-endian integer. + 4, 2, // Trailing bytes. + ]); + + let value = FrameDecoder::new().decode_from(&mut bytes).unwrap(); + + assert_eq!(value, Some(U32_1337)); + assert_eq!(bytes, vec![4, 2]); // Decoded bytes were split off. + } + + #[test] + fn decode_vec() { + let mut bytes = BytesMut::new(); + bytes.extend_from_slice(&[ + 20, 0, 0, 0, // 5 32-bit integers = 20 bytes. + 4, 0, 0, 0, // 4 elements in the vector. + 1, 0, 0, 0, // Little-endian vector elements. + 3, 0, 0, 0, // + 3, 0, 0, 0, // + 7, 0, 0, 0, // + 4, 2, // Trailing bytes. + ]); + + let value = FrameDecoder::new().decode_from(&mut bytes).unwrap(); + + let expected_value: Vec = vec![1, 3, 3, 7]; + assert_eq!(value, Some(expected_value)); + assert_eq!(bytes, vec![4, 2]); // Decoded bytes were split off. + } + + #[test] + fn roundtrip() { + let value: Vec = vec![ + "apples".to_string(), // + "bananas".to_string(), // + "oranges".to_string(), // + "and cheese!".to_string(), // + ]; + + let mut buffer = BytesMut::new(); + + FrameEncoder::new().encode_to(&value, &mut buffer).unwrap(); + let decoded = FrameDecoder::new().decode_from(&mut buffer).unwrap(); + + assert_eq!(decoded, Some(value)); + assert_eq!(buffer, vec![]); + } + + #[tokio::test] + async fn ping_pong() { + let listener = TcpListener::bind("localhost:0").await.unwrap(); + let address = listener.local_addr().unwrap(); + + let server_task = tokio::spawn(async move { + let (mut stream, _peer_address) = listener.accept().await.unwrap(); + let (read_half, write_half) = stream.split(); + let mut reader = FrameReader::new(read_half); + let mut writer = FrameWriter::new(write_half); + + assert_eq!(reader.read().await.unwrap(), Some("ping".to_string())); + writer.write("pong").await.unwrap(); + assert_eq!(reader.read().await.unwrap(), Some("ping".to_string())); + writer.write("pong").await.unwrap(); + }); + + let mut stream = TcpStream::connect(address).await.unwrap(); + let (read_half, write_half) = stream.split(); + let mut reader = FrameReader::new(read_half); + let mut writer = FrameWriter::new(write_half); + + writer.write("ping").await.unwrap(); + assert_eq!(reader.read().await.unwrap(), Some("pong".to_string())); + writer.write("ping").await.unwrap(); + assert_eq!(reader.read().await.unwrap(), Some("pong".to_string())); + + server_task.await.unwrap(); + } + + #[tokio::test] + async fn very_large_message() { + let listener = TcpListener::bind("localhost:0").await.unwrap(); + let address = listener.local_addr().unwrap(); + + let server_task = tokio::spawn(async move { + let (mut stream, _peer_address) = listener.accept().await.unwrap(); + let (read_half, write_half) = stream.split(); + let mut reader = FrameReader::new(read_half); + let mut writer = FrameWriter::new(write_half); + + assert_eq!(reader.read().await.unwrap(), Some("ping".to_string())); + writer.write(&vec![0u32; 10 * 4096]).await.unwrap(); + }); + + let mut stream = TcpStream::connect(address).await.unwrap(); + let (read_half, write_half) = stream.split(); + let mut reader = FrameReader::new(read_half); + let mut writer = FrameWriter::new(write_half); + + writer.write("ping").await.unwrap(); + assert_eq!(reader.read().await.unwrap(), Some(vec![0u32; 10 * 4096])); + + server_task.await.unwrap(); + } } diff --git a/proto/src/core/prefix.rs b/proto/src/core/prefix.rs index 6950988..04dfb3f 100644 --- a/proto/src/core/prefix.rs +++ b/proto/src/core/prefix.rs @@ -11,111 +11,111 @@ use crate::core::u32::{encode_u32, U32_BYTE_LEN}; /// know the length ahead of encoding time. #[derive(Debug)] pub struct Prefixer<'a> { - /// The prefix buffer. - /// - /// The length of the suffix buffer is written to the end of this buffer - /// when the prefixer is finalized. - /// - /// Contains any bytes with which this prefixer was constructed. - prefix: &'a mut BytesMut, - - /// The suffix buffer. - /// - /// This is the buffer into which data is written before finalization. - suffix: BytesMut, + /// The prefix buffer. + /// + /// The length of the suffix buffer is written to the end of this buffer + /// when the prefixer is finalized. + /// + /// Contains any bytes with which this prefixer was constructed. + prefix: &'a mut BytesMut, + + /// The suffix buffer. + /// + /// This is the buffer into which data is written before finalization. + suffix: BytesMut, } impl Prefixer<'_> { - /// Constructs a prefixer for easily appending a length prefixed value to - /// the given buffer. - pub fn new<'a>(buffer: &'a mut BytesMut) -> Prefixer<'a> { - // Reserve some space fot the prefix, but don't write it yet. - buffer.reserve(U32_BYTE_LEN); - - // Split off the suffix, into which bytes will be written. - let suffix = buffer.split_off(buffer.len() + U32_BYTE_LEN); - - Prefixer { - prefix: buffer, - suffix: suffix, - } - } - - /// Returns a reference to the buffer into which data is written. - pub fn suffix(&self) -> &BytesMut { - &self.suffix - } - - /// Returns a mutable reference to a buffer into which data can be written. - pub fn suffix_mut(&mut self) -> &mut BytesMut { - &mut self.suffix - } - - /// Returns a buffer containing the original data passed at construction - /// time, to which a length-prefixed value is appended. The value itself is - /// the data written into the buffer returned by `get_mut()`. - /// - /// Returns `Ok(length)` if successful, in which case the length of the - /// suffix is `length`. - /// - /// Returns `Err(self)` if the length of the suffix is too large to store as - /// a prefix. - pub fn finalize(self) -> Result { - // Check that the suffix's length is not too large. - let length = self.suffix.len(); - let length_u32 = match u32::try_from(length) { - Ok(value) => value, - Err(_) => return Err(self), - }; - - // Write the prefix. - self.prefix.extend_from_slice(&encode_u32(length_u32)); - - // Join the prefix and suffix back again. Because `self.prefix` is - // private, we are sure that this is O(1). - self.prefix.unsplit(self.suffix); - - Ok(length_u32) + /// Constructs a prefixer for easily appending a length prefixed value to + /// the given buffer. + pub fn new<'a>(buffer: &'a mut BytesMut) -> Prefixer<'a> { + // Reserve some space fot the prefix, but don't write it yet. + buffer.reserve(U32_BYTE_LEN); + + // Split off the suffix, into which bytes will be written. + let suffix = buffer.split_off(buffer.len() + U32_BYTE_LEN); + + Prefixer { + prefix: buffer, + suffix: suffix, } + } + + /// Returns a reference to the buffer into which data is written. + pub fn suffix(&self) -> &BytesMut { + &self.suffix + } + + /// Returns a mutable reference to a buffer into which data can be written. + pub fn suffix_mut(&mut self) -> &mut BytesMut { + &mut self.suffix + } + + /// Returns a buffer containing the original data passed at construction + /// time, to which a length-prefixed value is appended. The value itself is + /// the data written into the buffer returned by `get_mut()`. + /// + /// Returns `Ok(length)` if successful, in which case the length of the + /// suffix is `length`. + /// + /// Returns `Err(self)` if the length of the suffix is too large to store as + /// a prefix. + pub fn finalize(self) -> Result { + // Check that the suffix's length is not too large. + let length = self.suffix.len(); + let length_u32 = match u32::try_from(length) { + Ok(value) => value, + Err(_) => return Err(self), + }; + + // Write the prefix. + self.prefix.extend_from_slice(&encode_u32(length_u32)); + + // Join the prefix and suffix back again. Because `self.prefix` is + // private, we are sure that this is O(1). + self.prefix.unsplit(self.suffix); + + Ok(length_u32) + } } #[cfg(test)] mod tests { - use super::Prefixer; + use super::Prefixer; - use std::convert::TryInto; + use std::convert::TryInto; - use bytes::{BufMut, BytesMut}; + use bytes::{BufMut, BytesMut}; - use crate::core::u32::{decode_u32, U32_BYTE_LEN}; + use crate::core::u32::{decode_u32, U32_BYTE_LEN}; - #[test] - fn finalize_empty() { - let mut buffer = BytesMut::new(); - buffer.put_u8(13); + #[test] + fn finalize_empty() { + let mut buffer = BytesMut::new(); + buffer.put_u8(13); - Prefixer::new(&mut buffer).finalize().unwrap(); + Prefixer::new(&mut buffer).finalize().unwrap(); - assert_eq!(buffer.len(), U32_BYTE_LEN + 1); - let array: [u8; U32_BYTE_LEN] = buffer[1..].try_into().unwrap(); - assert_eq!(decode_u32(array), 0); - } + assert_eq!(buffer.len(), U32_BYTE_LEN + 1); + let array: [u8; U32_BYTE_LEN] = buffer[1..].try_into().unwrap(); + assert_eq!(decode_u32(array), 0); + } - #[test] - fn finalize_ok() { - let mut buffer = BytesMut::new(); - buffer.put_u8(13); + #[test] + fn finalize_ok() { + let mut buffer = BytesMut::new(); + buffer.put_u8(13); - let mut prefixer = Prefixer::new(&mut buffer); + let mut prefixer = Prefixer::new(&mut buffer); - prefixer.suffix_mut().extend_from_slice(&[0; 42]); + prefixer.suffix_mut().extend_from_slice(&[0; 42]); - prefixer.finalize().unwrap(); + prefixer.finalize().unwrap(); - // 1 junk prefix byte, length prefix, 42 bytes of value. - assert_eq!(buffer.len(), U32_BYTE_LEN + 43); - let prefix = &buffer[1..U32_BYTE_LEN + 1]; - let array: [u8; U32_BYTE_LEN] = prefix.try_into().unwrap(); - assert_eq!(decode_u32(array), 42); - } + // 1 junk prefix byte, length prefix, 42 bytes of value. + assert_eq!(buffer.len(), U32_BYTE_LEN + 43); + let prefix = &buffer[1..U32_BYTE_LEN + 1]; + let array: [u8; U32_BYTE_LEN] = prefix.try_into().unwrap(); + assert_eq!(decode_u32(array), 42); + } } diff --git a/proto/src/core/u32.rs b/proto/src/core/u32.rs index bc6999c..cc51f71 100644 --- a/proto/src/core/u32.rs +++ b/proto/src/core/u32.rs @@ -8,10 +8,10 @@ pub const U32_BYTE_LEN: usize = 4; /// Returns the byte representatio of the given integer value. pub fn encode_u32(value: u32) -> [u8; U32_BYTE_LEN] { - value.to_le_bytes() + value.to_le_bytes() } /// Returns the integer value corresponding to the given bytes. pub fn decode_u32(bytes: [u8; U32_BYTE_LEN]) -> u32 { - u32::from_le_bytes(bytes) + u32::from_le_bytes(bytes) } diff --git a/proto/src/core/user.rs b/proto/src/core/user.rs index 6fad354..90557c0 100644 --- a/proto/src/core/user.rs +++ b/proto/src/core/user.rs @@ -1,96 +1,114 @@ use std::io; use crate::core::value::{ - ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncodeError, ValueEncoder, + ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncodeError, + ValueEncoder, +}; +use crate::{ + MutPacket, Packet, PacketReadError, ReadFromPacket, WriteToPacket, }; -use crate::{MutPacket, Packet, PacketReadError, ReadFromPacket, WriteToPacket}; const STATUS_OFFLINE: u32 = 1; const STATUS_AWAY: u32 = 2; const STATUS_ONLINE: u32 = 3; /// This enumeration is the list of possible user statuses. -#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, RustcDecodable, RustcEncodable)] +#[derive( + Clone, + Copy, + Debug, + Eq, + Ord, + PartialEq, + PartialOrd, + RustcDecodable, + RustcEncodable, +)] pub enum UserStatus { - /// The user if offline. - Offline, - /// The user is connected, but AFK. - Away, - /// The user is present. - Online, + /// The user if offline. + Offline, + /// The user is connected, but AFK. + Away, + /// The user is present. + Online, } impl ReadFromPacket for UserStatus { - fn read_from_packet(packet: &mut Packet) -> Result { - let n: u32 = packet.read_value()?; - match n { - STATUS_OFFLINE => Ok(UserStatus::Offline), - STATUS_AWAY => Ok(UserStatus::Away), - STATUS_ONLINE => Ok(UserStatus::Online), - _ => Err(PacketReadError::InvalidUserStatusError(n)), - } + fn read_from_packet(packet: &mut Packet) -> Result { + let n: u32 = packet.read_value()?; + match n { + STATUS_OFFLINE => Ok(UserStatus::Offline), + STATUS_AWAY => Ok(UserStatus::Away), + STATUS_ONLINE => Ok(UserStatus::Online), + _ => Err(PacketReadError::InvalidUserStatusError(n)), } + } } impl WriteToPacket for UserStatus { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - let n = match *self { - UserStatus::Offline => STATUS_OFFLINE, - UserStatus::Away => STATUS_AWAY, - UserStatus::Online => STATUS_ONLINE, - }; - packet.write_value(&n)?; - Ok(()) - } + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + let n = match *self { + UserStatus::Offline => STATUS_OFFLINE, + UserStatus::Away => STATUS_AWAY, + UserStatus::Online => STATUS_ONLINE, + }; + packet.write_value(&n)?; + Ok(()) + } } impl ValueEncode for UserStatus { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - let value = match *self { - UserStatus::Offline => STATUS_OFFLINE, - UserStatus::Away => STATUS_AWAY, - UserStatus::Online => STATUS_ONLINE, - }; - encoder.encode_u32(value) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + let value = match *self { + UserStatus::Offline => STATUS_OFFLINE, + UserStatus::Away => STATUS_AWAY, + UserStatus::Online => STATUS_ONLINE, + }; + encoder.encode_u32(value) + } } impl ValueDecode for UserStatus { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let position = decoder.position(); - let value: u32 = decoder.decode()?; - match value { - STATUS_OFFLINE => Ok(UserStatus::Offline), - STATUS_AWAY => Ok(UserStatus::Away), - STATUS_ONLINE => Ok(UserStatus::Online), - _ => Err(ValueDecodeError::InvalidData { - value_name: "user status".to_string(), - cause: format!("unknown value {}", value), - position: position, - }), - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let position = decoder.position(); + let value: u32 = decoder.decode()?; + match value { + STATUS_OFFLINE => Ok(UserStatus::Offline), + STATUS_AWAY => Ok(UserStatus::Away), + STATUS_ONLINE => Ok(UserStatus::Online), + _ => Err(ValueDecodeError::InvalidData { + value_name: "user status".to_string(), + cause: format!("unknown value {}", value), + position: position, + }), } + } } /// This structure contains the last known information about a fellow user. -#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, RustcDecodable, RustcEncodable)] +#[derive( + Clone, Debug, Eq, Ord, PartialEq, PartialOrd, RustcDecodable, RustcEncodable, +)] pub struct User { - /// The name of the user. - pub name: String, - /// The last known status of the user. - pub status: UserStatus, - /// The average upload speed of the user. - pub average_speed: usize, - /// ??? Nicotine calls it downloadnum. - pub num_downloads: usize, - /// ??? Unknown field. - pub unknown: usize, - /// The number of files this user shares. - pub num_files: usize, - /// The number of folders this user shares. - pub num_folders: usize, - /// The number of free download slots of this user. - pub num_free_slots: usize, - /// The user's country code. - pub country: String, + /// The name of the user. + pub name: String, + /// The last known status of the user. + pub status: UserStatus, + /// The average upload speed of the user. + pub average_speed: usize, + /// ??? Nicotine calls it downloadnum. + pub num_downloads: usize, + /// ??? Unknown field. + pub unknown: usize, + /// The number of files this user shares. + pub num_files: usize, + /// The number of folders this user shares. + pub num_folders: usize, + /// The number of free download slots of this user. + pub num_free_slots: usize, + /// The user's country code. + pub country: String, } diff --git a/proto/src/core/value.rs b/proto/src/core/value.rs index b692974..bf585a3 100644 --- a/proto/src/core/value.rs +++ b/proto/src/core/value.rs @@ -28,13 +28,13 @@ use super::prefix::Prefixer; use super::u32::{decode_u32, encode_u32, U32_BYTE_LEN}; pub trait Decode { - /// Attempts to decode an instance of `T` from `self`. - fn decode(&mut self) -> io::Result; + /// Attempts to decode an instance of `T` from `self`. + fn decode(&mut self) -> io::Result; } pub trait Encode { - /// Attempts to encode `value` into `self`. - fn encode(&mut self, value: T) -> io::Result<()>; + /// Attempts to encode `value` into `self`. + fn encode(&mut self, value: T) -> io::Result<()>; } pub trait ComparableError: error::Error + PartialEq {} @@ -43,374 +43,393 @@ pub trait ComparableError: error::Error + PartialEq {} // stabilized. #[derive(PartialEq, Error, Debug)] pub enum ValueDecodeError { - #[error("at position {position}: not enough bytes to decode: expected {expected}, found {remaining}")] - NotEnoughData { - /// The number of bytes the decoder expected to read. - /// - /// Invariant: `remaining < expected`. - expected: usize, - - /// The number of bytes remaining in the input buffer. - /// - /// Invariant: `remaining < expected`. - remaining: usize, - - /// The decoder's position in the input buffer. - position: usize, - }, - #[error("at position {position}: invalid boolean value: {value}")] - InvalidBool { - /// The invalid value. Never equal to 0 nor 1. - value: u8, - - /// The decoder's position in the input buffer. - position: usize, - }, - #[error("at position {position}: invalid u16 value: {value}")] - InvalidU16 { - /// The invalid value. Always greater than u16::max_value(). - value: u32, - - /// The decoder's position in the input buffer. - position: usize, - }, - #[error("at position {position}: failed to decode string: {cause}")] - InvalidString { - /// The cause of the error, as reported by the encoding library. - cause: String, - - /// The decoder's position in the input buffer. - position: usize, - }, - #[error("at position {position}: invalid {value_name}: {cause}")] - InvalidData { - /// The name of the value the decoder failed to decode. - value_name: String, - - /// The cause of the error. - cause: String, - - /// The decoder's position in the input buffer. - position: usize, - }, + #[error("at position {position}: not enough bytes to decode: expected {expected}, found {remaining}")] + NotEnoughData { + /// The number of bytes the decoder expected to read. + /// + /// Invariant: `remaining < expected`. + expected: usize, + + /// The number of bytes remaining in the input buffer. + /// + /// Invariant: `remaining < expected`. + remaining: usize, + + /// The decoder's position in the input buffer. + position: usize, + }, + #[error("at position {position}: invalid boolean value: {value}")] + InvalidBool { + /// The invalid value. Never equal to 0 nor 1. + value: u8, + + /// The decoder's position in the input buffer. + position: usize, + }, + #[error("at position {position}: invalid u16 value: {value}")] + InvalidU16 { + /// The invalid value. Always greater than u16::max_value(). + value: u32, + + /// The decoder's position in the input buffer. + position: usize, + }, + #[error("at position {position}: failed to decode string: {cause}")] + InvalidString { + /// The cause of the error, as reported by the encoding library. + cause: String, + + /// The decoder's position in the input buffer. + position: usize, + }, + #[error("at position {position}: invalid {value_name}: {cause}")] + InvalidData { + /// The name of the value the decoder failed to decode. + value_name: String, + + /// The cause of the error. + cause: String, + + /// The decoder's position in the input buffer. + position: usize, + }, } impl From for io::Error { - fn from(error: ValueDecodeError) -> Self { - let kind = match &error { - &ValueDecodeError::NotEnoughData { .. } => io::ErrorKind::UnexpectedEof, - _ => io::ErrorKind::InvalidData, - }; - let message = format!("{}", &error); - io::Error::new(kind, message) - } + fn from(error: ValueDecodeError) -> Self { + let kind = match &error { + &ValueDecodeError::NotEnoughData { .. } => io::ErrorKind::UnexpectedEof, + _ => io::ErrorKind::InvalidData, + }; + let message = format!("{}", &error); + io::Error::new(kind, message) + } } /// A type for decoding various types of values from protocol messages. pub struct ValueDecoder<'a> { - // The buffer we are decoding from. - // - // Invariant: `position <= buffer.len()`. - buffer: &'a [u8], - - // Our current position within `buffer`. - // - // We could instead maintain this implicitly in `buffer` by splitting off - // decoded bytes from the start of the buffer, but we would then be unable - // to remember how many bytes we had decoded. This information is useful to - // have in error messages when encountering decoding errors. - // - // Invariant: `position <= buffer.len()`. - position: usize, + // The buffer we are decoding from. + // + // Invariant: `position <= buffer.len()`. + buffer: &'a [u8], + + // Our current position within `buffer`. + // + // We could instead maintain this implicitly in `buffer` by splitting off + // decoded bytes from the start of the buffer, but we would then be unable + // to remember how many bytes we had decoded. This information is useful to + // have in error messages when encountering decoding errors. + // + // Invariant: `position <= buffer.len()`. + position: usize, } /// This trait is implemented by types that can be decoded from messages using /// a `ValueDecoder`. pub trait ValueDecode: Sized { - /// Attempts to decode a value of this type with the given decoder. - fn decode_from(decoder: &mut ValueDecoder) -> Result; + /// Attempts to decode a value of this type with the given decoder. + fn decode_from(decoder: &mut ValueDecoder) -> Result; } impl<'a> ValueDecoder<'a> { - /// Wraps the given byte buffer. - pub fn new(buffer: &'a [u8]) -> Self { - Self { - buffer: buffer, - position: 0, - } - } - - /// The current position of this decoder in the input buffer. - pub fn position(&self) -> usize { - self.position - } - - /// Returns the number of bytes remaining to decode. - pub fn remaining(&self) -> usize { - self.buffer.len() - self.position - } - - /// Returns whether the underlying buffer has remaining bytes to decode. - /// - /// Shorthand for `remaining() > 0`. - pub fn has_remaining(&self) -> bool { - self.remaining() > 0 - } - - /// Returns a read-only view of the remaining bytes to decode. - /// - /// The returned slice is of size `remaining()`. - #[cfg(test)] - pub fn bytes(&self) -> &[u8] { - &self.buffer[self.position..] - } - - /// Attempts to consume the next `n` bytes from this buffer. - /// - /// Returns a slice of size `n` if successful, in which case this decoder - /// advances its internal position by `n`. - fn consume(&mut self, n: usize) -> Result<&[u8], ValueDecodeError> { - if self.remaining() < n { - return Err(ValueDecodeError::NotEnoughData { - expected: n, - remaining: self.remaining(), - position: self.position, - }); - } - - // Cannot use bytes() here as it borrows self immutably, which - // prevents us from mutating self.position afterwards. - let end = self.position + n; - let bytes = &self.buffer[self.position..end]; - self.position = end; - Ok(bytes) - } - - /// Attempts to decode a u32 value. - fn decode_u32(&mut self) -> Result { - let bytes = self.consume(U32_BYTE_LEN)?; - // The conversion from slice to fixed-size array cannot fail, because - // consume() guarantees that its return value is of size n. - let array: [u8; U32_BYTE_LEN] = bytes.try_into().unwrap(); - Ok(decode_u32(array)) - } - - /// Attempts to decode a u16 value. - fn decode_u16(&mut self) -> Result { - let position = self.position; - let n = self.decode_u32()?; - match u16::try_from(n) { - Ok(value) => Ok(value), - Err(_) => Err(ValueDecodeError::InvalidU16 { - value: n, - position: position, - }), - } - } - - /// Attempts to decode a boolean value. - fn decode_bool(&mut self) -> Result { - let position = self.position; - let bytes = self.consume(1)?; - match bytes[0] { - 0 => Ok(false), - 1 => Ok(true), - n => Err(ValueDecodeError::InvalidBool { - value: n, - position: position, - }), - } - } - - /// Attempts to decode a string value. - fn decode_string(&mut self) -> Result { - let length = self.decode_u32()? as usize; - - let position = self.position; - let bytes = self.consume(length)?; - - let result = WINDOWS_1252.decode_without_bom_handling_and_without_replacement(bytes); - match result { - Some(string) => Ok(string.into_owned()), - None => Err(ValueDecodeError::InvalidString { - cause: "malformed sequence in Windows-1252-encoded string".to_string(), - position: position, - }), - } - } - - /// Attempts to decode a value of the given type. - /// - /// Allows easy decoding of complex values using type inference. - pub fn decode(&mut self) -> Result { - T::decode_from(self) - } + /// Wraps the given byte buffer. + pub fn new(buffer: &'a [u8]) -> Self { + Self { + buffer: buffer, + position: 0, + } + } + + /// The current position of this decoder in the input buffer. + pub fn position(&self) -> usize { + self.position + } + + /// Returns the number of bytes remaining to decode. + pub fn remaining(&self) -> usize { + self.buffer.len() - self.position + } + + /// Returns whether the underlying buffer has remaining bytes to decode. + /// + /// Shorthand for `remaining() > 0`. + pub fn has_remaining(&self) -> bool { + self.remaining() > 0 + } + + /// Returns a read-only view of the remaining bytes to decode. + /// + /// The returned slice is of size `remaining()`. + #[cfg(test)] + pub fn bytes(&self) -> &[u8] { + &self.buffer[self.position..] + } + + /// Attempts to consume the next `n` bytes from this buffer. + /// + /// Returns a slice of size `n` if successful, in which case this decoder + /// advances its internal position by `n`. + fn consume(&mut self, n: usize) -> Result<&[u8], ValueDecodeError> { + if self.remaining() < n { + return Err(ValueDecodeError::NotEnoughData { + expected: n, + remaining: self.remaining(), + position: self.position, + }); + } + + // Cannot use bytes() here as it borrows self immutably, which + // prevents us from mutating self.position afterwards. + let end = self.position + n; + let bytes = &self.buffer[self.position..end]; + self.position = end; + Ok(bytes) + } + + /// Attempts to decode a u32 value. + fn decode_u32(&mut self) -> Result { + let bytes = self.consume(U32_BYTE_LEN)?; + // The conversion from slice to fixed-size array cannot fail, because + // consume() guarantees that its return value is of size n. + let array: [u8; U32_BYTE_LEN] = bytes.try_into().unwrap(); + Ok(decode_u32(array)) + } + + /// Attempts to decode a u16 value. + fn decode_u16(&mut self) -> Result { + let position = self.position; + let n = self.decode_u32()?; + match u16::try_from(n) { + Ok(value) => Ok(value), + Err(_) => Err(ValueDecodeError::InvalidU16 { + value: n, + position: position, + }), + } + } + + /// Attempts to decode a boolean value. + fn decode_bool(&mut self) -> Result { + let position = self.position; + let bytes = self.consume(1)?; + match bytes[0] { + 0 => Ok(false), + 1 => Ok(true), + n => Err(ValueDecodeError::InvalidBool { + value: n, + position: position, + }), + } + } + + /// Attempts to decode a string value. + fn decode_string(&mut self) -> Result { + let length = self.decode_u32()? as usize; + + let position = self.position; + let bytes = self.consume(length)?; + + let result = + WINDOWS_1252.decode_without_bom_handling_and_without_replacement(bytes); + match result { + Some(string) => Ok(string.into_owned()), + None => Err(ValueDecodeError::InvalidString { + cause: "malformed sequence in Windows-1252-encoded string".to_string(), + position: position, + }), + } + } + + /// Attempts to decode a value of the given type. + /// + /// Allows easy decoding of complex values using type inference. + pub fn decode(&mut self) -> Result { + T::decode_from(self) + } } impl ValueDecode for u32 { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - decoder.decode_u32() - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + decoder.decode_u32() + } } impl ValueDecode for u16 { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - decoder.decode_u16() - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + decoder.decode_u16() + } } impl ValueDecode for bool { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - decoder.decode_bool() - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + decoder.decode_bool() + } } impl ValueDecode for net::Ipv4Addr { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let ip = decoder.decode_u32()?; - Ok(net::Ipv4Addr::from(ip)) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let ip = decoder.decode_u32()?; + Ok(net::Ipv4Addr::from(ip)) + } } impl ValueDecode for String { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - decoder.decode_string() - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + decoder.decode_string() + } } impl ValueDecode for (T, U) { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let first = decoder.decode()?; - let second = decoder.decode()?; - Ok((first, second)) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let first = decoder.decode()?; + let second = decoder.decode()?; + Ok((first, second)) + } } impl ValueDecode for Vec { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let len = decoder.decode_u32()? as usize; - let mut vec = Vec::with_capacity(len); - for _ in 0..len { - let val = decoder.decode()?; - vec.push(val); - } - Ok(vec) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let len = decoder.decode_u32()? as usize; + let mut vec = Vec::with_capacity(len); + for _ in 0..len { + let val = decoder.decode()?; + vec.push(val); + } + Ok(vec) + } } #[derive(Debug, Error, PartialEq)] pub enum ValueEncodeError { - #[error("encoded string length {length} is too large: {string:?}")] - StringTooLong { - /// The string that is too long to encode. - string: String, - - /// The length of `string` in the Windows-1252 encoding. - /// Always larger than `u32::max_value()`. - length: usize, - }, + #[error("encoded string length {length} is too large: {string:?}")] + StringTooLong { + /// The string that is too long to encode. + string: String, + + /// The length of `string` in the Windows-1252 encoding. + /// Always larger than `u32::max_value()`. + length: usize, + }, } impl From for io::Error { - fn from(error: ValueEncodeError) -> Self { - io::Error::new(io::ErrorKind::InvalidData, format!("{}", error)) - } + fn from(error: ValueEncodeError) -> Self { + io::Error::new(io::ErrorKind::InvalidData, format!("{}", error)) + } } /// A type for encoding various types of values into protocol messages. pub struct ValueEncoder<'a> { - /// The buffer to which the encoder appends encoded bytes. - buffer: &'a mut BytesMut, + /// The buffer to which the encoder appends encoded bytes. + buffer: &'a mut BytesMut, } /// This trait is implemented by types that can be encoded into messages using /// a `ValueEncoder`. pub trait ValueEncode { - /// Attempts to encode `self` with the given encoder. - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError>; + /// Attempts to encode `self` with the given encoder. + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError>; } impl<'a> ValueEncoder<'a> { - /// Wraps the given buffer for encoding values into. - /// - /// Encoded bytes are appended. The buffer is not pre-cleared. - pub fn new(buffer: &'a mut BytesMut) -> Self { - ValueEncoder { buffer: buffer } - } - - /// Encodes the given u32 value into the underlying buffer. - pub fn encode_u32(&mut self, val: u32) -> Result<(), ValueEncodeError> { - self.buffer.extend_from_slice(&encode_u32(val)); - Ok(()) - } - - /// Encodes the given u16 value into the underlying buffer. - pub fn encode_u16(&mut self, val: u16) -> Result<(), ValueEncodeError> { - self.encode_u32(val as u32) - } - - /// Encodes the given boolean value into the underlying buffer. - pub fn encode_bool(&mut self, val: bool) -> Result<(), ValueEncodeError> { - self.buffer.put_u8(val as u8); - Ok(()) - } - - /// Encodes the given string into the underlying buffer. - pub fn encode_string(&mut self, val: &str) -> Result<(), ValueEncodeError> { - // Reserve space for the length prefix. - let mut prefixer = Prefixer::new(self.buffer); - - // Encode the string. This cannot fail because any unmappable characters - // are replaced. - let (bytes, encoding, _did_replace) = WINDOWS_1252.encode(val); - - // Encodings in full generality can have a different "output encoding" - // but that is not the case of Windows-1252. - assert_eq!(encoding, WINDOWS_1252); - - prefixer.suffix_mut().extend_from_slice(&bytes); - - // Write the length prefix in the space we initially reserved for it. - if let Err(prefixer) = prefixer.finalize() { - return Err(ValueEncodeError::StringTooLong { - string: val.to_string(), - length: prefixer.suffix().len(), - }); - } - - Ok(()) - } - - /// Encodes the given value into the underlying buffer. - /// - /// Allows for easy encoding with type inference. - pub fn encode(&mut self, val: &T) -> Result<(), ValueEncodeError> { - val.encode_to(self) - } + /// Wraps the given buffer for encoding values into. + /// + /// Encoded bytes are appended. The buffer is not pre-cleared. + pub fn new(buffer: &'a mut BytesMut) -> Self { + ValueEncoder { buffer: buffer } + } + + /// Encodes the given u32 value into the underlying buffer. + pub fn encode_u32(&mut self, val: u32) -> Result<(), ValueEncodeError> { + self.buffer.extend_from_slice(&encode_u32(val)); + Ok(()) + } + + /// Encodes the given u16 value into the underlying buffer. + pub fn encode_u16(&mut self, val: u16) -> Result<(), ValueEncodeError> { + self.encode_u32(val as u32) + } + + /// Encodes the given boolean value into the underlying buffer. + pub fn encode_bool(&mut self, val: bool) -> Result<(), ValueEncodeError> { + self.buffer.put_u8(val as u8); + Ok(()) + } + + /// Encodes the given string into the underlying buffer. + pub fn encode_string(&mut self, val: &str) -> Result<(), ValueEncodeError> { + // Reserve space for the length prefix. + let mut prefixer = Prefixer::new(self.buffer); + + // Encode the string. This cannot fail because any unmappable characters + // are replaced. + let (bytes, encoding, _did_replace) = WINDOWS_1252.encode(val); + + // Encodings in full generality can have a different "output encoding" + // but that is not the case of Windows-1252. + assert_eq!(encoding, WINDOWS_1252); + + prefixer.suffix_mut().extend_from_slice(&bytes); + + // Write the length prefix in the space we initially reserved for it. + if let Err(prefixer) = prefixer.finalize() { + return Err(ValueEncodeError::StringTooLong { + string: val.to_string(), + length: prefixer.suffix().len(), + }); + } + + Ok(()) + } + + /// Encodes the given value into the underlying buffer. + /// + /// Allows for easy encoding with type inference. + pub fn encode( + &mut self, + val: &T, + ) -> Result<(), ValueEncodeError> { + val.encode_to(self) + } } impl ValueEncode for u32 { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_u32(*self) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_u32(*self) + } } impl ValueEncode for u16 { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_u16(*self) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_u16(*self) + } } impl ValueEncode for bool { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_bool(*self) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_bool(*self) + } } impl ValueEncode for net::Ipv4Addr { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_u32(u32::from(*self)) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_u32(u32::from(*self)) + } } // It would be nice to use AsRef, or Deref for the following @@ -422,45 +441,63 @@ impl ValueEncode for net::Ipv4Addr { // Value{De,En}code) but it is not really worth the hassle. impl ValueEncode for str { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_string(self) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_string(self) + } } impl ValueEncode for String { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_string(self) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_string(self) + } } impl<'a> ValueEncode for &'a String { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_string(*self) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_string(*self) + } } impl ValueEncode for (T, U) { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - self.0.encode_to(encoder)?; - self.1.encode_to(encoder) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + self.0.encode_to(encoder)?; + self.1.encode_to(encoder) + } } impl ValueEncode for [T] { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_u32(self.len() as u32)?; - for ref item in self { - item.encode_to(encoder)?; - } - Ok(()) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_u32(self.len() as u32)?; + for ref item in self { + item.encode_to(encoder)?; + } + Ok(()) + } } impl ValueEncode for Vec { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - let slice: &[T] = &*self; - slice.encode_to(encoder) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + let slice: &[T] = &*self; + slice.encode_to(encoder) + } } /*=======* @@ -469,431 +506,433 @@ impl ValueEncode for Vec { #[cfg(test)] pub mod tests { - use std::fmt; - use std::net; - use std::u16; - use std::u32; - - use bytes::{BufMut, BytesMut}; - - use super::{ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncoder}; + use std::fmt; + use std::net; + use std::u16; + use std::u32; + + use bytes::{BufMut, BytesMut}; + + use super::{ + ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncoder, + }; - // Declared here because assert_eq!(bytes, &[]) fails to infer types. - const EMPTY_BYTES: &'static [u8] = &[]; + // Declared here because assert_eq!(bytes, &[]) fails to infer types. + const EMPTY_BYTES: &'static [u8] = &[]; - pub fn roundtrip(input: T) - where - T: fmt::Debug + Eq + PartialEq + ValueEncode + ValueDecode, - { - let mut bytes = BytesMut::new(); + pub fn roundtrip(input: T) + where + T: fmt::Debug + Eq + PartialEq + ValueEncode + ValueDecode, + { + let mut bytes = BytesMut::new(); - ValueEncoder::new(&mut bytes).encode(&input).unwrap(); - let output = ValueDecoder::new(&bytes).decode::().unwrap(); + ValueEncoder::new(&mut bytes).encode(&input).unwrap(); + let output = ValueDecoder::new(&bytes).decode::().unwrap(); - assert_eq!(output, input); - } - - // A few integers and their corresponding byte encodings. - const U32_ENCODINGS: [(u32, [u8; 4]); 8] = [ - (0, [0, 0, 0, 0]), - (255, [255, 0, 0, 0]), - (256, [0, 1, 0, 0]), - (65535, [255, 255, 0, 0]), - (65536, [0, 0, 1, 0]), - (16777215, [255, 255, 255, 0]), - (16777216, [0, 0, 0, 1]), - (u32::MAX, [255, 255, 255, 255]), - ]; - - #[test] - fn encode_u32() { - for &(val, ref encoded_bytes) in &U32_ENCODINGS { - let mut bytes = BytesMut::new(); - bytes.put_u8(13); - - let mut expected_bytes = BytesMut::new(); - expected_bytes.put_u8(13); - expected_bytes.extend_from_slice(encoded_bytes); - - ValueEncoder::new(&mut bytes).encode_u32(val).unwrap(); - assert_eq!(bytes, expected_bytes); - } - } - - #[test] - fn decode_u32() { - for &(expected_val, ref bytes) in &U32_ENCODINGS { - let buffer = bytes.to_vec(); - let mut decoder = ValueDecoder::new(&buffer); - - let val = decoder.decode::().unwrap(); - - assert_eq!(val, expected_val); - assert_eq!(decoder.bytes(), EMPTY_BYTES); - } - } - - #[test] - fn roundtrip_u32() { - for &(val, _) in &U32_ENCODINGS { - roundtrip(val) - } - } - - #[test] - fn decode_u32_unexpected_eof() { - let mut buffer = BytesMut::new(); - buffer.put_u8(13); + assert_eq!(output, input); + } - let mut decoder = ValueDecoder::new(&buffer); + // A few integers and their corresponding byte encodings. + const U32_ENCODINGS: [(u32, [u8; 4]); 8] = [ + (0, [0, 0, 0, 0]), + (255, [255, 0, 0, 0]), + (256, [0, 1, 0, 0]), + (65535, [255, 255, 0, 0]), + (65536, [0, 0, 1, 0]), + (16777215, [255, 255, 255, 0]), + (16777216, [0, 0, 0, 1]), + (u32::MAX, [255, 255, 255, 255]), + ]; - let result = decoder.decode::(); + #[test] + fn encode_u32() { + for &(val, ref encoded_bytes) in &U32_ENCODINGS { + let mut bytes = BytesMut::new(); + bytes.put_u8(13); - assert_eq!( - result, - Err(ValueDecodeError::NotEnoughData { - expected: 4, - remaining: 1, - position: 0, - }) - ); - assert_eq!(decoder.bytes(), &[13]); + let mut expected_bytes = BytesMut::new(); + expected_bytes.put_u8(13); + expected_bytes.extend_from_slice(encoded_bytes); + + ValueEncoder::new(&mut bytes).encode_u32(val).unwrap(); + assert_eq!(bytes, expected_bytes); } + } + + #[test] + fn decode_u32() { + for &(expected_val, ref bytes) in &U32_ENCODINGS { + let buffer = bytes.to_vec(); + let mut decoder = ValueDecoder::new(&buffer); - #[test] - fn encode_bool_false() { - let mut bytes = BytesMut::new(); - bytes.put_u8(13); + let val = decoder.decode::().unwrap(); + + assert_eq!(val, expected_val); + assert_eq!(decoder.bytes(), EMPTY_BYTES); + } + } + + #[test] + fn roundtrip_u32() { + for &(val, _) in &U32_ENCODINGS { + roundtrip(val) + } + } + + #[test] + fn decode_u32_unexpected_eof() { + let mut buffer = BytesMut::new(); + buffer.put_u8(13); + + let mut decoder = ValueDecoder::new(&buffer); + + let result = decoder.decode::(); + + assert_eq!( + result, + Err(ValueDecodeError::NotEnoughData { + expected: 4, + remaining: 1, + position: 0, + }) + ); + assert_eq!(decoder.bytes(), &[13]); + } + + #[test] + fn encode_bool_false() { + let mut bytes = BytesMut::new(); + bytes.put_u8(13); + + ValueEncoder::new(&mut bytes).encode_bool(false).unwrap(); + + assert_eq!(bytes, vec![13, 0]); + } + + #[test] + fn encode_bool_true() { + let mut bytes = BytesMut::new(); + bytes.put_u8(13); + + ValueEncoder::new(&mut bytes).encode_bool(true).unwrap(); + + assert_eq!(bytes, vec![13, 1]); + } + + #[test] + fn decode_bool_false() { + let buffer = vec![0]; + let mut decoder = ValueDecoder::new(&buffer); + + let val = decoder.decode::().unwrap(); + + assert!(!val); + assert_eq!(decoder.bytes(), EMPTY_BYTES); + } + + #[test] + fn decode_bool_true() { + let buffer = vec![1]; + let mut decoder = ValueDecoder::new(&buffer); + + let val = decoder.decode::().unwrap(); + + assert!(val); + assert_eq!(decoder.bytes(), EMPTY_BYTES); + } - ValueEncoder::new(&mut bytes).encode_bool(false).unwrap(); + #[test] + fn decode_bool_invalid() { + let buffer = vec![42]; - assert_eq!(bytes, vec![13, 0]); - } - - #[test] - fn encode_bool_true() { - let mut bytes = BytesMut::new(); - bytes.put_u8(13); + let result = ValueDecoder::new(&buffer).decode::(); - ValueEncoder::new(&mut bytes).encode_bool(true).unwrap(); + assert_eq!( + result, + Err(ValueDecodeError::InvalidBool { + value: 42, + position: 0, + }) + ); + } - assert_eq!(bytes, vec![13, 1]); - } + #[test] + fn decode_bool_unexpected_eof() { + let buffer = vec![]; - #[test] - fn decode_bool_false() { - let buffer = vec![0]; - let mut decoder = ValueDecoder::new(&buffer); + let result = ValueDecoder::new(&buffer).decode::(); - let val = decoder.decode::().unwrap(); + assert_eq!( + result, + Err(ValueDecodeError::NotEnoughData { + expected: 1, + remaining: 0, + position: 0, + }) + ); + } - assert!(!val); - assert_eq!(decoder.bytes(), EMPTY_BYTES); + #[test] + fn roundtrip_bool() { + roundtrip(false); + roundtrip(true); + } + + #[test] + fn encode_u16() { + for &(val, ref encoded_bytes) in &U32_ENCODINGS { + if val > u16::MAX as u32 { + continue; + } + + let mut bytes = BytesMut::new(); + bytes.put_u8(13); + + let mut expected_bytes = BytesMut::new(); + expected_bytes.put_u8(13); + expected_bytes.extend(encoded_bytes); + + ValueEncoder::new(&mut bytes).encode(&(val as u16)).unwrap(); + + assert_eq!(bytes, expected_bytes); } + } - #[test] - fn decode_bool_true() { - let buffer = vec![1]; - let mut decoder = ValueDecoder::new(&buffer); + #[test] + fn decode_u16() { + for &(expected_val, ref buffer) in &U32_ENCODINGS { + let mut decoder = ValueDecoder::new(buffer); - let val = decoder.decode::().unwrap(); - - assert!(val); + if expected_val <= u16::MAX as u32 { + let val = decoder.decode::().unwrap(); + assert_eq!(val, expected_val as u16); assert_eq!(decoder.bytes(), EMPTY_BYTES); - } - - #[test] - fn decode_bool_invalid() { - let buffer = vec![42]; - - let result = ValueDecoder::new(&buffer).decode::(); - + } else { assert_eq!( - result, - Err(ValueDecodeError::InvalidBool { - value: 42, - position: 0, - }) + decoder.decode::(), + Err(ValueDecodeError::InvalidU16 { + value: expected_val, + position: 0, + }) ); + } } + } - #[test] - fn decode_bool_unexpected_eof() { - let buffer = vec![]; + #[test] + fn decode_u16_unexpected_eof() { + let buffer = vec![]; + let mut decoder = ValueDecoder::new(&buffer); - let result = ValueDecoder::new(&buffer).decode::(); + let result = decoder.decode::(); - assert_eq!( - result, - Err(ValueDecodeError::NotEnoughData { - expected: 1, - remaining: 0, - position: 0, - }) - ); - } + assert_eq!( + result, + Err(ValueDecodeError::NotEnoughData { + expected: 4, + remaining: 0, + position: 0, + }) + ); + } - #[test] - fn roundtrip_bool() { - roundtrip(false); - roundtrip(true); + #[test] + fn roundtrip_u16() { + for &(val, _) in &U32_ENCODINGS { + if val <= u16::MAX as u32 { + roundtrip(val) + } } + } - #[test] - fn encode_u16() { - for &(val, ref encoded_bytes) in &U32_ENCODINGS { - if val > u16::MAX as u32 { - continue; - } - - let mut bytes = BytesMut::new(); - bytes.put_u8(13); + #[test] + fn encode_ipv4() { + for &(val, ref encoded_bytes) in &U32_ENCODINGS { + let mut bytes = BytesMut::new(); + bytes.put_u8(13); - let mut expected_bytes = BytesMut::new(); - expected_bytes.put_u8(13); - expected_bytes.extend(encoded_bytes); + let mut expected_bytes = BytesMut::new(); + expected_bytes.put_u8(13); + expected_bytes.extend(encoded_bytes); - ValueEncoder::new(&mut bytes).encode(&(val as u16)).unwrap(); + let addr = net::Ipv4Addr::from(val); - assert_eq!(bytes, expected_bytes); - } - } + ValueEncoder::new(&mut bytes).encode(&addr).unwrap(); - #[test] - fn decode_u16() { - for &(expected_val, ref buffer) in &U32_ENCODINGS { - let mut decoder = ValueDecoder::new(buffer); - - if expected_val <= u16::MAX as u32 { - let val = decoder.decode::().unwrap(); - assert_eq!(val, expected_val as u16); - assert_eq!(decoder.bytes(), EMPTY_BYTES); - } else { - assert_eq!( - decoder.decode::(), - Err(ValueDecodeError::InvalidU16 { - value: expected_val, - position: 0, - }) - ); - } - } + assert_eq!(bytes, expected_bytes); } + } - #[test] - fn decode_u16_unexpected_eof() { - let buffer = vec![]; - let mut decoder = ValueDecoder::new(&buffer); + #[test] + fn decode_ipv4() { + for &(expected_val, ref buffer) in &U32_ENCODINGS { + let mut decoder = ValueDecoder::new(buffer); - let result = decoder.decode::(); + let val = decoder.decode::().unwrap(); - assert_eq!( - result, - Err(ValueDecodeError::NotEnoughData { - expected: 4, - remaining: 0, - position: 0, - }) - ); + assert_eq!(val, net::Ipv4Addr::from(expected_val)); + assert_eq!(decoder.bytes(), EMPTY_BYTES); } + } - #[test] - fn roundtrip_u16() { - for &(val, _) in &U32_ENCODINGS { - if val <= u16::MAX as u32 { - roundtrip(val) - } - } + #[test] + fn roundtrip_ipv4() { + for &(val, _) in &U32_ENCODINGS { + roundtrip(net::Ipv4Addr::from(val)) } + } - #[test] - fn encode_ipv4() { - for &(val, ref encoded_bytes) in &U32_ENCODINGS { - let mut bytes = BytesMut::new(); - bytes.put_u8(13); + // A few strings and their corresponding encodings. + const STRING_ENCODINGS: [(&'static str, &'static [u8]); 4] = [ + ("", &[0, 0, 0, 0]), + ("hey!", &[4, 0, 0, 0, 104, 101, 121, 33]), + // Windows 1252 specific codepoints. + ("‘’“”€", &[5, 0, 0, 0, 145, 146, 147, 148, 128]), + // Undefined codepoints. They are not decoded to representable + // characters, but they do not generate errors either. In particular, + // they survive round-trips through the codec. + ( + "\u{81}\u{8D}\u{8F}\u{90}\u{9D}", + &[5, 0, 0, 0, 0x81, 0x8D, 0x8F, 0x90, 0x9D], + ), + ]; - let mut expected_bytes = BytesMut::new(); - expected_bytes.put_u8(13); - expected_bytes.extend(encoded_bytes); + #[test] + fn encode_string() { + for &(string, encoded_bytes) in &STRING_ENCODINGS { + let mut bytes = BytesMut::new(); + bytes.put_u8(13); - let addr = net::Ipv4Addr::from(val); + let mut expected_bytes = BytesMut::new(); + expected_bytes.put_u8(13); + expected_bytes.extend(encoded_bytes); - ValueEncoder::new(&mut bytes).encode(&addr).unwrap(); + ValueEncoder::new(&mut bytes).encode_string(string).unwrap(); - assert_eq!(bytes, expected_bytes); - } + assert_eq!(bytes, expected_bytes); } + } - #[test] - fn decode_ipv4() { - for &(expected_val, ref buffer) in &U32_ENCODINGS { - let mut decoder = ValueDecoder::new(buffer); - - let val = decoder.decode::().unwrap(); - - assert_eq!(val, net::Ipv4Addr::from(expected_val)); - assert_eq!(decoder.bytes(), EMPTY_BYTES); - } - } + #[test] + fn encode_string_with_unencodable_characters() { + let mut bytes = BytesMut::new(); - #[test] - fn roundtrip_ipv4() { - for &(val, _) in &U32_ENCODINGS { - roundtrip(net::Ipv4Addr::from(val)) - } - } + ValueEncoder::new(&mut bytes).encode_string("你好").unwrap(); - // A few strings and their corresponding encodings. - const STRING_ENCODINGS: [(&'static str, &'static [u8]); 4] = [ - ("", &[0, 0, 0, 0]), - ("hey!", &[4, 0, 0, 0, 104, 101, 121, 33]), - // Windows 1252 specific codepoints. - ("‘’“”€", &[5, 0, 0, 0, 145, 146, 147, 148, 128]), - // Undefined codepoints. They are not decoded to representable - // characters, but they do not generate errors either. In particular, - // they survive round-trips through the codec. - ( - "\u{81}\u{8D}\u{8F}\u{90}\u{9D}", - &[5, 0, 0, 0, 0x81, 0x8D, 0x8F, 0x90, 0x9D], - ), - ]; - - #[test] - fn encode_string() { - for &(string, encoded_bytes) in &STRING_ENCODINGS { - let mut bytes = BytesMut::new(); - bytes.put_u8(13); - - let mut expected_bytes = BytesMut::new(); - expected_bytes.put_u8(13); - expected_bytes.extend(encoded_bytes); - - ValueEncoder::new(&mut bytes).encode_string(string).unwrap(); - - assert_eq!(bytes, expected_bytes); - } - } + // Characters not in the Windows 1252 codepage are replaced with their + // decimal representations. Thus the output is longer than the input. + assert_eq!(bytes[0..4], [16, 0, 0, 0]); + assert_eq!(&bytes[4..], b"你好"); - #[test] - fn encode_string_with_unencodable_characters() { - let mut bytes = BytesMut::new(); + // The replaced characters are not decoded back to their original values. + assert_eq!( + ValueDecoder::new(&bytes).decode_string().unwrap(), + "你好" + ); + } - ValueEncoder::new(&mut bytes).encode_string("你好").unwrap(); + #[test] + fn decode_string() { + for &(expected_string, buffer) in &STRING_ENCODINGS { + let mut decoder = ValueDecoder::new(&buffer); - // Characters not in the Windows 1252 codepage are replaced with their - // decimal representations. Thus the output is longer than the input. - assert_eq!(bytes[0..4], [16, 0, 0, 0]); - assert_eq!(&bytes[4..], b"你好"); + let string = decoder.decode::().unwrap(); - // The replaced characters are not decoded back to their original values. - assert_eq!( - ValueDecoder::new(&bytes).decode_string().unwrap(), - "你好" - ); + assert_eq!(string, expected_string); + assert_eq!(decoder.bytes(), EMPTY_BYTES); } + } - #[test] - fn decode_string() { - for &(expected_string, buffer) in &STRING_ENCODINGS { - let mut decoder = ValueDecoder::new(&buffer); - - let string = decoder.decode::().unwrap(); - - assert_eq!(string, expected_string); - assert_eq!(decoder.bytes(), EMPTY_BYTES); - } + #[test] + fn roundtrip_string() { + for &(string, _) in &STRING_ENCODINGS { + roundtrip(string.to_string()) } + } - #[test] - fn roundtrip_string() { - for &(string, _) in &STRING_ENCODINGS { - roundtrip(string.to_string()) - } - } + #[test] + fn encode_pair_u32_string() { + let mut bytes = BytesMut::new(); + bytes.put_u8(13); - #[test] - fn encode_pair_u32_string() { - let mut bytes = BytesMut::new(); - bytes.put_u8(13); + let mut expected_bytes = BytesMut::new(); + expected_bytes.put_u8(13); - let mut expected_bytes = BytesMut::new(); - expected_bytes.put_u8(13); + let (integer, ref expected_integer_bytes) = U32_ENCODINGS[0]; + let (string, expected_string_bytes) = STRING_ENCODINGS[0]; - let (integer, ref expected_integer_bytes) = U32_ENCODINGS[0]; - let (string, expected_string_bytes) = STRING_ENCODINGS[0]; + expected_bytes.extend(expected_integer_bytes); + expected_bytes.extend(expected_string_bytes); - expected_bytes.extend(expected_integer_bytes); - expected_bytes.extend(expected_string_bytes); + ValueEncoder::new(&mut bytes) + .encode(&(integer, string.to_string())) + .unwrap(); - ValueEncoder::new(&mut bytes) - .encode(&(integer, string.to_string())) - .unwrap(); + assert_eq!(bytes, expected_bytes); + } - assert_eq!(bytes, expected_bytes); - } + #[test] + fn decode_pair_u32_string() { + let mut buffer = vec![]; - #[test] - fn decode_pair_u32_string() { - let mut buffer = vec![]; + let (expected_integer, ref integer_bytes) = U32_ENCODINGS[0]; + let (expected_string, string_bytes) = STRING_ENCODINGS[0]; - let (expected_integer, ref integer_bytes) = U32_ENCODINGS[0]; - let (expected_string, string_bytes) = STRING_ENCODINGS[0]; + buffer.extend(integer_bytes); + buffer.extend(string_bytes); - buffer.extend(integer_bytes); - buffer.extend(string_bytes); + let mut decoder = ValueDecoder::new(&buffer); - let mut decoder = ValueDecoder::new(&buffer); + let pair = decoder.decode::<(u32, String)>().unwrap(); - let pair = decoder.decode::<(u32, String)>().unwrap(); + assert_eq!(pair, (expected_integer, expected_string.to_string())); + assert_eq!(decoder.bytes(), EMPTY_BYTES); + } - assert_eq!(pair, (expected_integer, expected_string.to_string())); - assert_eq!(decoder.bytes(), EMPTY_BYTES); - } + #[test] + fn roundtrip_pair_u32_string() { + roundtrip((42u32, "hello world!".to_string())) + } - #[test] - fn roundtrip_pair_u32_string() { - roundtrip((42u32, "hello world!".to_string())) - } + #[test] + fn encode_u32_vector() { + let mut vec = vec![]; - #[test] - fn encode_u32_vector() { - let mut vec = vec![]; + let mut expected_bytes = BytesMut::new(); + expected_bytes.extend_from_slice(&[13, U32_ENCODINGS.len() as u8, 0, 0, 0]); - let mut expected_bytes = BytesMut::new(); - expected_bytes.extend_from_slice(&[13, U32_ENCODINGS.len() as u8, 0, 0, 0]); + for &(val, ref encoded_bytes) in &U32_ENCODINGS { + vec.push(val); + expected_bytes.extend(encoded_bytes); + } - for &(val, ref encoded_bytes) in &U32_ENCODINGS { - vec.push(val); - expected_bytes.extend(encoded_bytes); - } + let mut bytes = BytesMut::new(); + bytes.put_u8(13); - let mut bytes = BytesMut::new(); - bytes.put_u8(13); + ValueEncoder::new(&mut bytes).encode(&vec).unwrap(); - ValueEncoder::new(&mut bytes).encode(&vec).unwrap(); + assert_eq!(bytes, expected_bytes); + } - assert_eq!(bytes, expected_bytes); + #[test] + fn decode_u32_vector() { + let mut expected_vec = vec![]; + let mut buffer = vec![U32_ENCODINGS.len() as u8, 0, 0, 0]; + for &(expected_val, ref encoded_bytes) in &U32_ENCODINGS { + expected_vec.push(expected_val); + buffer.extend(encoded_bytes); } - #[test] - fn decode_u32_vector() { - let mut expected_vec = vec![]; - let mut buffer = vec![U32_ENCODINGS.len() as u8, 0, 0, 0]; - for &(expected_val, ref encoded_bytes) in &U32_ENCODINGS { - expected_vec.push(expected_val); - buffer.extend(encoded_bytes); - } + let mut decoder = ValueDecoder::new(&buffer); - let mut decoder = ValueDecoder::new(&buffer); + let vec = decoder.decode::>().unwrap(); - let vec = decoder.decode::>().unwrap(); + assert_eq!(vec, expected_vec); + assert_eq!(decoder.bytes(), EMPTY_BYTES); + } - assert_eq!(vec, expected_vec); - assert_eq!(decoder.bytes(), EMPTY_BYTES); - } - - #[test] - fn roundtrip_u32_vector() { - roundtrip(vec![0u32, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - } + #[test] + fn roundtrip_u32_vector() { + roundtrip(vec![0u32, 1, 2, 3, 4, 5, 6, 7, 8, 9]) + } } diff --git a/proto/src/handler.rs b/proto/src/handler.rs index 76b89a8..480c827 100644 --- a/proto/src/handler.rs +++ b/proto/src/handler.rs @@ -31,17 +31,17 @@ const LISTEN_TOKEN: usize = config::MAX_PEERS + 1; #[derive(Debug)] pub enum Request { - PeerConnect(usize, net::Ipv4Addr, u16), - PeerMessage(usize, peer::Message), - ServerRequest(ServerRequest), + PeerConnect(usize, net::Ipv4Addr, u16), + PeerMessage(usize, peer::Message), + ServerRequest(ServerRequest), } #[derive(Debug)] pub enum Response { - PeerConnectionClosed(usize), - PeerConnectionOpen(usize), - PeerMessage(usize, peer::Message), - ServerResponse(ServerResponse), + PeerConnectionClosed(usize), + PeerConnectionOpen(usize), + PeerMessage(usize, peer::Message), + ServerResponse(ServerResponse), } /*========================* @@ -51,16 +51,16 @@ pub enum Response { pub struct ServerResponseSender(crossbeam_channel::Sender); impl SendPacket for ServerResponseSender { - type Value = ServerResponse; - type Error = crossbeam_channel::SendError; + type Value = ServerResponse; + type Error = crossbeam_channel::SendError; - fn send_packet(&mut self, value: Self::Value) -> Result<(), Self::Error> { - self.0.send(Response::ServerResponse(value)) - } + fn send_packet(&mut self, value: Self::Value) -> Result<(), Self::Error> { + self.0.send(Response::ServerResponse(value)) + } - fn notify_open(&mut self) -> Result<(), Self::Error> { - Ok(()) - } + fn notify_open(&mut self) -> Result<(), Self::Error> { + Ok(()) + } } /*======================* @@ -68,21 +68,21 @@ impl SendPacket for ServerResponseSender { *======================*/ pub struct PeerResponseSender { - sender: crossbeam_channel::Sender, - peer_id: usize, + sender: crossbeam_channel::Sender, + peer_id: usize, } impl SendPacket for PeerResponseSender { - type Value = peer::Message; - type Error = crossbeam_channel::SendError; + type Value = peer::Message; + type Error = crossbeam_channel::SendError; - fn send_packet(&mut self, value: Self::Value) -> Result<(), Self::Error> { - self.sender.send(Response::PeerMessage(self.peer_id, value)) - } + fn send_packet(&mut self, value: Self::Value) -> Result<(), Self::Error> { + self.sender.send(Response::PeerMessage(self.peer_id, value)) + } - fn notify_open(&mut self) -> Result<(), Self::Error> { - self.sender.send(Response::PeerConnectionOpen(self.peer_id)) - } + fn notify_open(&mut self) -> Result<(), Self::Error> { + self.sender.send(Response::PeerConnectionOpen(self.peer_id)) + } } /*=========* @@ -92,293 +92,302 @@ impl SendPacket for PeerResponseSender { /// This struct handles all the soulseek connections, to the server and to /// peers. struct Handler { - server_stream: Stream, + server_stream: Stream, - peer_streams: slab::Slab, usize>, + peer_streams: slab::Slab, usize>, - listener: mio::tcp::TcpListener, + listener: mio::tcp::TcpListener, - client_tx: crossbeam_channel::Sender, + client_tx: crossbeam_channel::Sender, } fn listener_bind(addr_spec: U) -> io::Result where - U: ToSocketAddrs + fmt::Debug, + U: ToSocketAddrs + fmt::Debug, { - for socket_addr in addr_spec.to_socket_addrs()? { - if let Ok(listener) = mio::tcp::TcpListener::bind(&socket_addr) { - return Ok(listener); - } + for socket_addr in addr_spec.to_socket_addrs()? { + if let Ok(listener) = mio::tcp::TcpListener::bind(&socket_addr) { + return Ok(listener); } - Err(io::Error::new( - io::ErrorKind::Other, - format!("Cannot bind to {:?}", addr_spec), - )) + } + Err(io::Error::new( + io::ErrorKind::Other, + format!("Cannot bind to {:?}", addr_spec), + )) } impl Handler { - #[allow(deprecated)] - fn new( - client_tx: crossbeam_channel::Sender, - event_loop: &mut mio::deprecated::EventLoop, - ) -> io::Result { - let host = config::SERVER_HOST; - let port = config::SERVER_PORT; - let server_stream = Stream::new((host, port), ServerResponseSender(client_tx.clone()))?; - - info!("Connected to server at {}:{}", host, port); - - let listener = listener_bind((config::LISTEN_HOST, config::LISTEN_PORT))?; - info!( - "Listening for connections on {}:{}", - config::LISTEN_HOST, - config::LISTEN_PORT - ); - - event_loop.register( - server_stream.evented(), + #[allow(deprecated)] + fn new( + client_tx: crossbeam_channel::Sender, + event_loop: &mut mio::deprecated::EventLoop, + ) -> io::Result { + let host = config::SERVER_HOST; + let port = config::SERVER_PORT; + let server_stream = + Stream::new((host, port), ServerResponseSender(client_tx.clone()))?; + + info!("Connected to server at {}:{}", host, port); + + let listener = listener_bind((config::LISTEN_HOST, config::LISTEN_PORT))?; + info!( + "Listening for connections on {}:{}", + config::LISTEN_HOST, + config::LISTEN_PORT + ); + + event_loop.register( + server_stream.evented(), + mio::Token(SERVER_TOKEN), + mio::Ready::all(), + mio::PollOpt::edge() | mio::PollOpt::oneshot(), + )?; + + event_loop.register( + &listener, + mio::Token(LISTEN_TOKEN), + mio::Ready::all(), + mio::PollOpt::edge() | mio::PollOpt::oneshot(), + )?; + + Ok(Handler { + server_stream: server_stream, + + peer_streams: slab::Slab::new(config::MAX_PEERS), + + listener: listener, + + client_tx: client_tx, + }) + } + + #[allow(deprecated)] + fn connect_to_peer( + &mut self, + peer_id: usize, + ip: net::Ipv4Addr, + port: u16, + event_loop: &mut mio::deprecated::EventLoop, + ) -> Result<(), String> { + let vacant_entry = match self.peer_streams.entry(peer_id) { + None => return Err("id out of range".to_string()), + + Some(slab::Entry::Occupied(_occupied_entry)) => { + return Err("id already taken".to_string()); + } + + Some(slab::Entry::Vacant(vacant_entry)) => vacant_entry, + }; + + info!("Opening peer connection {} to {}:{}", peer_id, ip, port); + + let sender = PeerResponseSender { + sender: self.client_tx.clone(), + peer_id: peer_id, + }; + + let peer_stream = match Stream::new((ip, port), sender) { + Ok(peer_stream) => peer_stream, + + Err(err) => return Err(format!("i/o error: {}", err)), + }; + + event_loop + .register( + peer_stream.evented(), + mio::Token(peer_id), + mio::Ready::all(), + mio::PollOpt::edge() | mio::PollOpt::oneshot(), + ) + .unwrap(); + + vacant_entry.insert(peer_stream); + + Ok(()) + } + + #[allow(deprecated)] + fn process_server_intent( + &mut self, + intent: Intent, + event_loop: &mut mio::deprecated::EventLoop, + ) { + match intent { + Intent::Done => { + error!("Server connection closed"); + // TODO notify client and shut down + } + Intent::Continue(event_set) => { + event_loop + .reregister( + self.server_stream.evented(), mio::Token(SERVER_TOKEN), - mio::Ready::all(), + event_set, mio::PollOpt::edge() | mio::PollOpt::oneshot(), - )?; - - event_loop.register( - &listener, - mio::Token(LISTEN_TOKEN), - mio::Ready::all(), - mio::PollOpt::edge() | mio::PollOpt::oneshot(), - )?; - - Ok(Handler { - server_stream: server_stream, - - peer_streams: slab::Slab::new(config::MAX_PEERS), - - listener: listener, - - client_tx: client_tx, - }) + ) + .unwrap(); + } } - - #[allow(deprecated)] - fn connect_to_peer( - &mut self, - peer_id: usize, - ip: net::Ipv4Addr, - port: u16, - event_loop: &mut mio::deprecated::EventLoop, - ) -> Result<(), String> { - let vacant_entry = match self.peer_streams.entry(peer_id) { - None => return Err("id out of range".to_string()), - - Some(slab::Entry::Occupied(_occupied_entry)) => { - return Err("id already taken".to_string()); - } - - Some(slab::Entry::Vacant(vacant_entry)) => vacant_entry, - }; - - info!("Opening peer connection {} to {}:{}", peer_id, ip, port); - - let sender = PeerResponseSender { - sender: self.client_tx.clone(), - peer_id: peer_id, - }; - - let peer_stream = match Stream::new((ip, port), sender) { - Ok(peer_stream) => peer_stream, - - Err(err) => return Err(format!("i/o error: {}", err)), - }; - - event_loop - .register( - peer_stream.evented(), - mio::Token(peer_id), - mio::Ready::all(), - mio::PollOpt::edge() | mio::PollOpt::oneshot(), + } + + #[allow(deprecated)] + fn process_peer_intent( + &mut self, + intent: Intent, + token: mio::Token, + event_loop: &mut mio::deprecated::EventLoop, + ) { + match intent { + Intent::Done => { + self.peer_streams.remove(token.0); + self + .client_tx + .send(Response::PeerConnectionClosed(token.0)) + .unwrap(); + } + + Intent::Continue(event_set) => { + if let Some(peer_stream) = self.peer_streams.get_mut(token.0) { + event_loop + .reregister( + peer_stream.evented(), + token, + event_set, + mio::PollOpt::edge() | mio::PollOpt::oneshot(), ) .unwrap(); - - vacant_entry.insert(peer_stream); - - Ok(()) - } - - #[allow(deprecated)] - fn process_server_intent( - &mut self, - intent: Intent, - event_loop: &mut mio::deprecated::EventLoop, - ) { - match intent { - Intent::Done => { - error!("Server connection closed"); - // TODO notify client and shut down - } - Intent::Continue(event_set) => { - event_loop - .reregister( - self.server_stream.evented(), - mio::Token(SERVER_TOKEN), - event_set, - mio::PollOpt::edge() | mio::PollOpt::oneshot(), - ) - .unwrap(); - } - } - } - - #[allow(deprecated)] - fn process_peer_intent( - &mut self, - intent: Intent, - token: mio::Token, - event_loop: &mut mio::deprecated::EventLoop, - ) { - match intent { - Intent::Done => { - self.peer_streams.remove(token.0); - self.client_tx - .send(Response::PeerConnectionClosed(token.0)) - .unwrap(); - } - - Intent::Continue(event_set) => { - if let Some(peer_stream) = self.peer_streams.get_mut(token.0) { - event_loop - .reregister( - peer_stream.evented(), - token, - event_set, - mio::PollOpt::edge() | mio::PollOpt::oneshot(), - ) - .unwrap(); - } - } } + } } + } } #[allow(deprecated)] impl mio::deprecated::Handler for Handler { - type Timeout = (); - type Message = Request; - - fn ready( - &mut self, - event_loop: &mut mio::deprecated::EventLoop, - token: mio::Token, - event_set: mio::Ready, - ) { - match token { - mio::Token(LISTEN_TOKEN) => { - if event_set.is_readable() { - // A peer wants to connect to us. - match self.listener.accept() { - Ok((_sock, addr)) => { - // TODO add it to peer streams - info!("Peer connection accepted from {}", addr); - } - - Err(err) => { - error!("Cannot accept peer connection: {}", err); - } - } - } - event_loop - .reregister( - &self.listener, - token, - mio::Ready::all(), - mio::PollOpt::edge() | mio::PollOpt::oneshot(), - ) - .unwrap(); + type Timeout = (); + type Message = Request; + + fn ready( + &mut self, + event_loop: &mut mio::deprecated::EventLoop, + token: mio::Token, + event_set: mio::Ready, + ) { + match token { + mio::Token(LISTEN_TOKEN) => { + if event_set.is_readable() { + // A peer wants to connect to us. + match self.listener.accept() { + Ok((_sock, addr)) => { + // TODO add it to peer streams + info!("Peer connection accepted from {}", addr); } - mio::Token(SERVER_TOKEN) => { - let intent = self.server_stream.on_ready(event_set); - self.process_server_intent(intent, event_loop); - } - - mio::Token(peer_id) => { - let intent = match self.peer_streams.get_mut(peer_id) { - Some(peer_stream) => peer_stream.on_ready(event_set), - - None => unreachable!("Unknown peer {} is ready", peer_id), - }; - self.process_peer_intent(intent, token, event_loop); + Err(err) => { + error!("Cannot accept peer connection: {}", err); } + } } - } + event_loop + .reregister( + &self.listener, + token, + mio::Ready::all(), + mio::PollOpt::edge() | mio::PollOpt::oneshot(), + ) + .unwrap(); + } - fn notify(&mut self, event_loop: &mut mio::deprecated::EventLoop, request: Request) { - match request { - Request::PeerConnect(peer_id, ip, port) => { - if let Err(err) = self.connect_to_peer(peer_id, ip, port, event_loop) { - error!( - "Cannot open peer connection {} to {}:{}: {}", - peer_id, ip, port, err - ); - self.client_tx - .send(Response::PeerConnectionClosed(peer_id)) - .unwrap(); - } - } + mio::Token(SERVER_TOKEN) => { + let intent = self.server_stream.on_ready(event_set); + self.process_server_intent(intent, event_loop); + } - Request::PeerMessage(peer_id, message) => { - let intent = match self.peer_streams.get_mut(peer_id) { - Some(peer_stream) => peer_stream.on_notify(&message), - None => { - error!( - "Cannot send peer message {:?}: unknown id {}", - message, peer_id - ); - return; - } - }; - self.process_peer_intent(intent, mio::Token(peer_id), event_loop); - } + mio::Token(peer_id) => { + let intent = match self.peer_streams.get_mut(peer_id) { + Some(peer_stream) => peer_stream.on_ready(event_set), - Request::ServerRequest(server_request) => { - let intent = self.server_stream.on_notify(&server_request); - self.process_server_intent(intent, event_loop); - } + None => unreachable!("Unknown peer {} is ready", peer_id), + }; + self.process_peer_intent(intent, token, event_loop); + } + } + } + + fn notify( + &mut self, + event_loop: &mut mio::deprecated::EventLoop, + request: Request, + ) { + match request { + Request::PeerConnect(peer_id, ip, port) => { + if let Err(err) = self.connect_to_peer(peer_id, ip, port, event_loop) { + error!( + "Cannot open peer connection {} to {}:{}: {}", + peer_id, ip, port, err + ); + self + .client_tx + .send(Response::PeerConnectionClosed(peer_id)) + .unwrap(); } + } + + Request::PeerMessage(peer_id, message) => { + let intent = match self.peer_streams.get_mut(peer_id) { + Some(peer_stream) => peer_stream.on_notify(&message), + None => { + error!( + "Cannot send peer message {:?}: unknown id {}", + message, peer_id + ); + return; + } + }; + self.process_peer_intent(intent, mio::Token(peer_id), event_loop); + } + + Request::ServerRequest(server_request) => { + let intent = self.server_stream.on_notify(&server_request); + self.process_server_intent(intent, event_loop); + } } + } } #[allow(deprecated)] pub type Sender = mio::deprecated::Sender; pub struct Agent { - #[allow(deprecated)] - event_loop: mio::deprecated::EventLoop, - handler: Handler, + #[allow(deprecated)] + event_loop: mio::deprecated::EventLoop, + handler: Handler, } impl Agent { - pub fn new(client_tx: crossbeam_channel::Sender) -> io::Result { - // Create the event loop. - #[allow(deprecated)] - let mut event_loop = mio::deprecated::EventLoop::new()?; - // Create the handler for the event loop and register the handler's - // sockets with the event loop. - let handler = Handler::new(client_tx, &mut event_loop)?; - - Ok(Agent { - event_loop: event_loop, - handler: handler, - }) - } - - pub fn channel(&self) -> Sender { - #[allow(deprecated)] - self.event_loop.channel() - } + pub fn new( + client_tx: crossbeam_channel::Sender, + ) -> io::Result { + // Create the event loop. + #[allow(deprecated)] + let mut event_loop = mio::deprecated::EventLoop::new()?; + // Create the handler for the event loop and register the handler's + // sockets with the event loop. + let handler = Handler::new(client_tx, &mut event_loop)?; + + Ok(Agent { + event_loop: event_loop, + handler: handler, + }) + } + + pub fn channel(&self) -> Sender { + #[allow(deprecated)] + self.event_loop.channel() + } - pub fn run(&mut self) -> io::Result<()> { - #[allow(deprecated)] - self.event_loop.run(&mut self.handler) - } + pub fn run(&mut self) -> io::Result<()> { + #[allow(deprecated)] + self.event_loop.run(&mut self.handler) + } } diff --git a/proto/src/packet.rs b/proto/src/packet.rs index d428a4a..085749e 100644 --- a/proto/src/packet.rs +++ b/proto/src/packet.rs @@ -19,46 +19,46 @@ use crate::core::constants::*; #[derive(Debug)] pub struct Packet { - /// The current read position in the byte buffer. - cursor: usize, - /// The underlying bytes. - bytes: Vec, + /// The current read position in the byte buffer. + cursor: usize, + /// The underlying bytes. + bytes: Vec, } impl io::Read for Packet { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - let bytes_read = { - let mut slice = &self.bytes[self.cursor..]; - slice.read(buf)? - }; - self.cursor += bytes_read; - Ok(bytes_read) - } + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let bytes_read = { + let mut slice = &self.bytes[self.cursor..]; + slice.read(buf)? + }; + self.cursor += bytes_read; + Ok(bytes_read) + } } impl Packet { - /// Returns a readable packet struct from the wire representation of a - /// packet. - /// Assumes that the given vector is a valid length-prefixed packet. - fn from_wire(bytes: Vec) -> Self { - Packet { - cursor: U32_SIZE, - bytes: bytes, - } - } - - /// Provides the main way to read data out of a binary packet. - pub fn read_value(&mut self) -> Result - where - T: ReadFromPacket, - { - T::read_from_packet(self) - } - - /// Returns the number of unread bytes remaining in the packet. - pub fn bytes_remaining(&self) -> usize { - self.bytes.len() - self.cursor + /// Returns a readable packet struct from the wire representation of a + /// packet. + /// Assumes that the given vector is a valid length-prefixed packet. + fn from_wire(bytes: Vec) -> Self { + Packet { + cursor: U32_SIZE, + bytes: bytes, } + } + + /// Provides the main way to read data out of a binary packet. + pub fn read_value(&mut self) -> Result + where + T: ReadFromPacket, + { + T::read_from_packet(self) + } + + /// Returns the number of unread bytes remaining in the packet. + pub fn bytes_remaining(&self) -> usize { + self.bytes.len() - self.cursor + } } /*===================* @@ -67,45 +67,45 @@ impl Packet { #[derive(Debug)] pub struct MutPacket { - bytes: Vec, + bytes: Vec, } impl MutPacket { - /// Returns an empty packet with the given packet code. - pub fn new() -> Self { - // Leave space for the eventual size of the packet. - MutPacket { - bytes: vec![0; U32_SIZE], - } + /// Returns an empty packet with the given packet code. + pub fn new() -> Self { + // Leave space for the eventual size of the packet. + MutPacket { + bytes: vec![0; U32_SIZE], } - - /// Provides the main way to write data into a binary packet. - pub fn write_value(&mut self, val: &T) -> io::Result<()> - where - T: WriteToPacket + ?Sized, + } + + /// Provides the main way to write data into a binary packet. + pub fn write_value(&mut self, val: &T) -> io::Result<()> + where + T: WriteToPacket + ?Sized, + { + val.write_to_packet(self) + } + + /// Consumes the mutable packet and returns its wire representation. + pub fn into_bytes(mut self) -> Vec { + let length = (self.bytes.len() - U32_SIZE) as u32; { - val.write_to_packet(self) - } - - /// Consumes the mutable packet and returns its wire representation. - pub fn into_bytes(mut self) -> Vec { - let length = (self.bytes.len() - U32_SIZE) as u32; - { - let mut first_word = &mut self.bytes[..U32_SIZE]; - first_word.write_u32::(length).unwrap(); - } - self.bytes + let mut first_word = &mut self.bytes[..U32_SIZE]; + first_word.write_u32::(length).unwrap(); } + self.bytes + } } impl io::Write for MutPacket { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.bytes.write(buf) - } + fn write(&mut self, buf: &[u8]) -> io::Result { + self.bytes.write(buf) + } - fn flush(&mut self) -> io::Result<()> { - self.bytes.flush() - } + fn flush(&mut self) -> io::Result<()> { + self.bytes.flush() + } } /*===================* @@ -115,68 +115,68 @@ impl io::Write for MutPacket { /// This enum contains an error that arose when reading data out of a Packet. #[derive(Debug)] pub enum PacketReadError { - /// Attempted to read a boolean, but the value was not 0 nor 1. - InvalidBoolError(u8), - /// Attempted to read an unsigned 16-bit integer, but the value was too - /// large. - InvalidU16Error(u32), - /// Attempted to read a string, but a character was invalid. - InvalidStringError(Vec), - /// Attempted to read a user::Status, but the value was not a valid - /// representation of an enum variant. - InvalidUserStatusError(u32), - /// Encountered an I/O error while reading. - IOError(io::Error), + /// Attempted to read a boolean, but the value was not 0 nor 1. + InvalidBoolError(u8), + /// Attempted to read an unsigned 16-bit integer, but the value was too + /// large. + InvalidU16Error(u32), + /// Attempted to read a string, but a character was invalid. + InvalidStringError(Vec), + /// Attempted to read a user::Status, but the value was not a valid + /// representation of an enum variant. + InvalidUserStatusError(u32), + /// Encountered an I/O error while reading. + IOError(io::Error), } impl fmt::Display for PacketReadError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match *self { - PacketReadError::InvalidBoolError(n) => { - write!(fmt, "InvalidBoolError: {}", n) - } - PacketReadError::InvalidU16Error(n) => { - write!(fmt, "InvalidU16Error: {}", n) - } - PacketReadError::InvalidStringError(ref bytes) => { - write!(fmt, "InvalidStringError: {:?}", bytes) - } - PacketReadError::InvalidUserStatusError(n) => { - write!(fmt, "InvalidUserStatusError: {}", n) - } - PacketReadError::IOError(ref err) => { - write!(fmt, "IOError: {}", err) - } - } + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match *self { + PacketReadError::InvalidBoolError(n) => { + write!(fmt, "InvalidBoolError: {}", n) + } + PacketReadError::InvalidU16Error(n) => { + write!(fmt, "InvalidU16Error: {}", n) + } + PacketReadError::InvalidStringError(ref bytes) => { + write!(fmt, "InvalidStringError: {:?}", bytes) + } + PacketReadError::InvalidUserStatusError(n) => { + write!(fmt, "InvalidUserStatusError: {}", n) + } + PacketReadError::IOError(ref err) => { + write!(fmt, "IOError: {}", err) + } } + } } impl error::Error for PacketReadError { - fn description(&self) -> &str { - match *self { - PacketReadError::InvalidBoolError(_) => "InvalidBoolError", - PacketReadError::InvalidU16Error(_) => "InvalidU16Error", - PacketReadError::InvalidStringError(_) => "InvalidStringError", - PacketReadError::InvalidUserStatusError(_) => "InvalidUserStatusError", - PacketReadError::IOError(_) => "IOError", - } + fn description(&self) -> &str { + match *self { + PacketReadError::InvalidBoolError(_) => "InvalidBoolError", + PacketReadError::InvalidU16Error(_) => "InvalidU16Error", + PacketReadError::InvalidStringError(_) => "InvalidStringError", + PacketReadError::InvalidUserStatusError(_) => "InvalidUserStatusError", + PacketReadError::IOError(_) => "IOError", } - - fn cause(&self) -> Option<&dyn error::Error> { - match *self { - PacketReadError::InvalidBoolError(_) => None, - PacketReadError::InvalidU16Error(_) => None, - PacketReadError::InvalidStringError(_) => None, - PacketReadError::InvalidUserStatusError(_) => None, - PacketReadError::IOError(ref err) => Some(err), - } + } + + fn cause(&self) -> Option<&dyn error::Error> { + match *self { + PacketReadError::InvalidBoolError(_) => None, + PacketReadError::InvalidU16Error(_) => None, + PacketReadError::InvalidStringError(_) => None, + PacketReadError::InvalidUserStatusError(_) => None, + PacketReadError::IOError(ref err) => Some(err), } + } } impl From for PacketReadError { - fn from(err: io::Error) -> Self { - PacketReadError::IOError(err) - } + fn from(err: io::Error) -> Self { + PacketReadError::IOError(err) + } } /*==================* @@ -186,81 +186,81 @@ impl From for PacketReadError { /// This trait is implemented by types that can be deserialized from binary /// Packets. pub trait ReadFromPacket: Sized { - fn read_from_packet(_: &mut Packet) -> Result; + fn read_from_packet(_: &mut Packet) -> Result; } /// 32-bit integers are serialized in 4 bytes, little-endian. impl ReadFromPacket for u32 { - fn read_from_packet(packet: &mut Packet) -> Result { - Ok(packet.read_u32::()?) - } + fn read_from_packet(packet: &mut Packet) -> Result { + Ok(packet.read_u32::()?) + } } /// For convenience, usize's are deserialized as u32's then casted. impl ReadFromPacket for usize { - fn read_from_packet(packet: &mut Packet) -> Result { - Ok(u32::read_from_packet(packet)? as usize) - } + fn read_from_packet(packet: &mut Packet) -> Result { + Ok(u32::read_from_packet(packet)? as usize) + } } /// Booleans are serialized as single bytes, containing either 0 or 1. impl ReadFromPacket for bool { - fn read_from_packet(packet: &mut Packet) -> Result { - match packet.read_u8()? { - 0 => Ok(false), - 1 => Ok(true), - n => Err(PacketReadError::InvalidBoolError(n)), - } + fn read_from_packet(packet: &mut Packet) -> Result { + match packet.read_u8()? { + 0 => Ok(false), + 1 => Ok(true), + n => Err(PacketReadError::InvalidBoolError(n)), } + } } /// 16-bit integers are serialized as 32-bit integers. impl ReadFromPacket for u16 { - fn read_from_packet(packet: &mut Packet) -> Result { - let n = u32::read_from_packet(packet)?; - if n > MAX_PORT { - return Err(PacketReadError::InvalidU16Error(n)); - } - Ok(n as u16) + fn read_from_packet(packet: &mut Packet) -> Result { + let n = u32::read_from_packet(packet)?; + if n > MAX_PORT { + return Err(PacketReadError::InvalidU16Error(n)); } + Ok(n as u16) + } } /// IPv4 addresses are serialized directly as 32-bit integers. impl ReadFromPacket for net::Ipv4Addr { - fn read_from_packet(packet: &mut Packet) -> Result { - let ip = u32::read_from_packet(packet)?; - Ok(net::Ipv4Addr::from(ip)) - } + fn read_from_packet(packet: &mut Packet) -> Result { + let ip = u32::read_from_packet(packet)?; + Ok(net::Ipv4Addr::from(ip)) + } } /// Strings are serialized as length-prefixed arrays of ISO-8859-1 encoded /// characters. impl ReadFromPacket for String { - fn read_from_packet(packet: &mut Packet) -> Result { - let len = usize::read_from_packet(packet)?; + fn read_from_packet(packet: &mut Packet) -> Result { + let len = usize::read_from_packet(packet)?; - let mut buffer = vec![0; len]; - packet.read_exact(&mut buffer)?; + let mut buffer = vec![0; len]; + packet.read_exact(&mut buffer)?; - match ISO_8859_1.decode(&buffer, DecoderTrap::Strict) { - Ok(string) => Ok(string), - Err(_) => Err(PacketReadError::InvalidStringError(buffer)), - } + match ISO_8859_1.decode(&buffer, DecoderTrap::Strict) { + Ok(string) => Ok(string), + Err(_) => Err(PacketReadError::InvalidStringError(buffer)), } + } } /// Vectors are serialized as length-prefixed arrays of values. impl ReadFromPacket for Vec { - fn read_from_packet(packet: &mut Packet) -> Result { - let len = usize::read_from_packet(packet)?; + fn read_from_packet(packet: &mut Packet) -> Result { + let len = usize::read_from_packet(packet)?; - let mut vec = Vec::new(); - for _ in 0..len { - vec.push(T::read_from_packet(packet)?); - } - - Ok(vec) + let mut vec = Vec::new(); + for _ in 0..len { + vec.push(T::read_from_packet(packet)?); } + + Ok(vec) + } } /*=================* @@ -270,55 +270,55 @@ impl ReadFromPacket for Vec { /// This trait is implemented by types that can be serialized to a binary /// MutPacket. pub trait WriteToPacket { - fn write_to_packet(&self, _: &mut MutPacket) -> io::Result<()>; + fn write_to_packet(&self, _: &mut MutPacket) -> io::Result<()>; } /// 32-bit integers are serialized in 4 bytes, little-endian. impl WriteToPacket for u32 { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - packet.write_u32::(*self) - } + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + packet.write_u32::(*self) + } } /// Booleans are serialized as single bytes, containing either 0 or 1. impl WriteToPacket for bool { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - packet.write_u8(*self as u8)?; - Ok(()) - } + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + packet.write_u8(*self as u8)?; + Ok(()) + } } /// 16-bit integers are serialized as 32-bit integers. impl WriteToPacket for u16 { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - (*self as u32).write_to_packet(packet) - } + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + (*self as u32).write_to_packet(packet) + } } /// Strings are serialized as a length-prefixed array of ISO-8859-1 encoded /// characters. impl WriteToPacket for str { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - // Encode the string. - let bytes = match ISO_8859_1.encode(self, EncoderTrap::Strict) { - Ok(bytes) => bytes, - Err(_) => { - let copy = self.to_string(); - return Err(io::Error::new(io::ErrorKind::Other, copy)); - } - }; - // Then write the bytes to the packet. - (bytes.len() as u32).write_to_packet(packet)?; - packet.write(&bytes)?; - Ok(()) - } + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + // Encode the string. + let bytes = match ISO_8859_1.encode(self, EncoderTrap::Strict) { + Ok(bytes) => bytes, + Err(_) => { + let copy = self.to_string(); + return Err(io::Error::new(io::ErrorKind::Other, copy)); + } + }; + // Then write the bytes to the packet. + (bytes.len() as u32).write_to_packet(packet)?; + packet.write(&bytes)?; + Ok(()) + } } /// Deref coercion does not happen for trait methods apparently. impl WriteToPacket for String { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - (self as &str).write_to_packet(packet) - } + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + (self as &str).write_to_packet(packet) + } } /*========* @@ -328,86 +328,86 @@ impl WriteToPacket for String { /// This enum defines the possible states of a packet parser state machine. #[derive(Debug, Clone, Copy)] enum State { - /// The parser is waiting to read enough bytes to determine the - /// length of the following packet. - ReadingLength, - /// The parser is waiting to read enough bytes to form the entire - /// packet. - ReadingPacket, + /// The parser is waiting to read enough bytes to determine the + /// length of the following packet. + ReadingLength, + /// The parser is waiting to read enough bytes to form the entire + /// packet. + ReadingPacket, } #[derive(Debug)] pub struct Parser { - state: State, - num_bytes_left: usize, - buffer: Vec, + state: State, + num_bytes_left: usize, + buffer: Vec, } impl Parser { - pub fn new() -> Self { - Parser { - state: State::ReadingLength, - num_bytes_left: U32_SIZE, - buffer: vec![0; U32_SIZE], - } + pub fn new() -> Self { + Parser { + state: State::ReadingLength, + num_bytes_left: U32_SIZE, + buffer: vec![0; U32_SIZE], + } + } + + /// Attemps to read a packet in a non-blocking fashion. + /// If enough bytes can be read from the given byte stream to form a + /// complete packet `p`, returns `Ok(Some(p))`. + /// If not enough bytes are available, returns `Ok(None)`. + /// If an I/O error `e` arises when trying to read the underlying stream, + /// returns `Err(e)`. + /// Note: as long as this function returns `Ok(Some(p))`, the caller is + /// responsible for calling it once more to ensure that all packets are + /// read as soon as possible. + pub fn try_read(&mut self, stream: &mut U) -> io::Result> + where + U: io::Read, + { + // Try to read as many bytes as we currently need from the underlying + // byte stream. + let offset = self.buffer.len() - self.num_bytes_left; + + #[allow(deprecated)] + match stream.try_read(&mut self.buffer[offset..])? { + None => (), + + Some(num_bytes_read) => { + self.num_bytes_left -= num_bytes_read; + } } - /// Attemps to read a packet in a non-blocking fashion. - /// If enough bytes can be read from the given byte stream to form a - /// complete packet `p`, returns `Ok(Some(p))`. - /// If not enough bytes are available, returns `Ok(None)`. - /// If an I/O error `e` arises when trying to read the underlying stream, - /// returns `Err(e)`. - /// Note: as long as this function returns `Ok(Some(p))`, the caller is - /// responsible for calling it once more to ensure that all packets are - /// read as soon as possible. - pub fn try_read(&mut self, stream: &mut U) -> io::Result> - where - U: io::Read, - { - // Try to read as many bytes as we currently need from the underlying - // byte stream. - let offset = self.buffer.len() - self.num_bytes_left; - - #[allow(deprecated)] - match stream.try_read(&mut self.buffer[offset..])? { - None => (), - - Some(num_bytes_read) => { - self.num_bytes_left -= num_bytes_read; - } - } - - // If we haven't read enough bytes, return. - if self.num_bytes_left > 0 { - return Ok(None); - } - - // Otherwise, the behavior depends on what state we were in. - match self.state { - State::ReadingLength => { - // If we have finished reading the length prefix, then - // deserialize it, switch states and try to read the packet - // bytes. - let message_len = LittleEndian::read_u32(&mut self.buffer) as usize; - if message_len > MAX_MESSAGE_SIZE { - unimplemented!(); - }; - self.state = State::ReadingPacket; - self.num_bytes_left = message_len; - self.buffer.resize(message_len + U32_SIZE, 0); - self.try_read(stream) - } - - State::ReadingPacket => { - // If we have finished reading the packet, swap the full buffer - // out and return the packet made from the full buffer. - self.state = State::ReadingLength; - self.num_bytes_left = U32_SIZE; - let new_buffer = vec![0; U32_SIZE]; - let old_buffer = mem::replace(&mut self.buffer, new_buffer); - Ok(Some(Packet::from_wire(old_buffer))) - } - } + // If we haven't read enough bytes, return. + if self.num_bytes_left > 0 { + return Ok(None); + } + + // Otherwise, the behavior depends on what state we were in. + match self.state { + State::ReadingLength => { + // If we have finished reading the length prefix, then + // deserialize it, switch states and try to read the packet + // bytes. + let message_len = LittleEndian::read_u32(&mut self.buffer) as usize; + if message_len > MAX_MESSAGE_SIZE { + unimplemented!(); + }; + self.state = State::ReadingPacket; + self.num_bytes_left = message_len; + self.buffer.resize(message_len + U32_SIZE, 0); + self.try_read(stream) + } + + State::ReadingPacket => { + // If we have finished reading the packet, swap the full buffer + // out and return the packet made from the full buffer. + self.state = State::ReadingLength; + self.num_bytes_left = U32_SIZE; + let new_buffer = vec![0; U32_SIZE]; + let old_buffer = mem::replace(&mut self.buffer, new_buffer); + Ok(Some(Packet::from_wire(old_buffer))) + } } + } } diff --git a/proto/src/peer/message.rs b/proto/src/peer/message.rs index 24196b0..a9444a2 100644 --- a/proto/src/peer/message.rs +++ b/proto/src/peer/message.rs @@ -3,10 +3,13 @@ use std::io; use log::warn; use crate::core::value::{ - ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncodeError, ValueEncoder, + ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncodeError, + ValueEncoder, }; use crate::peer::constants::*; -use crate::{MutPacket, Packet, PacketReadError, ReadFromPacket, WriteToPacket}; +use crate::{ + MutPacket, Packet, PacketReadError, ReadFromPacket, WriteToPacket, +}; /*=========* * MESSAGE * @@ -15,183 +18,189 @@ use crate::{MutPacket, Packet, PacketReadError, ReadFromPacket, WriteToPacket}; /// This enum contains all the possible messages peers can exchange. #[derive(Clone, Debug, Eq, PartialEq)] pub enum Message { - PierceFirewall(u32), - PeerInit(PeerInit), - Unknown(u32), + PierceFirewall(u32), + PeerInit(PeerInit), + Unknown(u32), } impl ReadFromPacket for Message { - fn read_from_packet(packet: &mut Packet) -> Result { - let code: u32 = packet.read_value()?; - let message = match code { - CODE_PIERCE_FIREWALL => Message::PierceFirewall(packet.read_value()?), - - CODE_PEER_INIT => Message::PeerInit(packet.read_value()?), - - code => Message::Unknown(code), - }; - - let bytes_remaining = packet.bytes_remaining(); - if bytes_remaining > 0 { - warn!( - "Peer message with code {} contains {} extra bytes", - code, bytes_remaining - ) - } - - Ok(message) + fn read_from_packet(packet: &mut Packet) -> Result { + let code: u32 = packet.read_value()?; + let message = match code { + CODE_PIERCE_FIREWALL => Message::PierceFirewall(packet.read_value()?), + + CODE_PEER_INIT => Message::PeerInit(packet.read_value()?), + + code => Message::Unknown(code), + }; + + let bytes_remaining = packet.bytes_remaining(); + if bytes_remaining > 0 { + warn!( + "Peer message with code {} contains {} extra bytes", + code, bytes_remaining + ) } + + Ok(message) + } } impl ValueDecode for Message { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let position = decoder.position(); - let code: u32 = decoder.decode()?; - let message = match code { - CODE_PIERCE_FIREWALL => { - let val = decoder.decode()?; - Message::PierceFirewall(val) - } - CODE_PEER_INIT => { - let peer_init = decoder.decode()?; - Message::PeerInit(peer_init) - } - _ => { - return Err(ValueDecodeError::InvalidData { - value_name: "peer message code".to_string(), - cause: format!("unknown value {}", code), - position: position, - }) - } - }; - Ok(message) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let position = decoder.position(); + let code: u32 = decoder.decode()?; + let message = match code { + CODE_PIERCE_FIREWALL => { + let val = decoder.decode()?; + Message::PierceFirewall(val) + } + CODE_PEER_INIT => { + let peer_init = decoder.decode()?; + Message::PeerInit(peer_init) + } + _ => { + return Err(ValueDecodeError::InvalidData { + value_name: "peer message code".to_string(), + cause: format!("unknown value {}", code), + position: position, + }) + } + }; + Ok(message) + } } impl ValueEncode for Message { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - match *self { - Message::PierceFirewall(token) => { - encoder.encode_u32(CODE_PIERCE_FIREWALL)?; - encoder.encode_u32(token)?; - } - Message::PeerInit(ref request) => { - encoder.encode_u32(CODE_PEER_INIT)?; - request.encode_to(encoder)?; - } - Message::Unknown(_) => unreachable!(), - } - Ok(()) + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + match *self { + Message::PierceFirewall(token) => { + encoder.encode_u32(CODE_PIERCE_FIREWALL)?; + encoder.encode_u32(token)?; + } + Message::PeerInit(ref request) => { + encoder.encode_u32(CODE_PEER_INIT)?; + request.encode_to(encoder)?; + } + Message::Unknown(_) => unreachable!(), } + Ok(()) + } } impl WriteToPacket for Message { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - match *self { - Message::PierceFirewall(ref token) => { - packet.write_value(&CODE_PIERCE_FIREWALL)?; - packet.write_value(token)?; - } - - Message::PeerInit(ref request) => { - packet.write_value(&CODE_PEER_INIT)?; - packet.write_value(request)?; - } - - Message::Unknown(_) => unreachable!(), - } - Ok(()) + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + match *self { + Message::PierceFirewall(ref token) => { + packet.write_value(&CODE_PIERCE_FIREWALL)?; + packet.write_value(token)?; + } + + Message::PeerInit(ref request) => { + packet.write_value(&CODE_PEER_INIT)?; + packet.write_value(request)?; + } + + Message::Unknown(_) => unreachable!(), } + Ok(()) + } } #[derive(Clone, Debug, Eq, PartialEq)] pub struct PeerInit { - pub user_name: String, - pub connection_type: String, - pub token: u32, + pub user_name: String, + pub connection_type: String, + pub token: u32, } impl ReadFromPacket for PeerInit { - fn read_from_packet(packet: &mut Packet) -> Result { - let user_name = packet.read_value()?; - let connection_type = packet.read_value()?; - let token = packet.read_value()?; - Ok(PeerInit { - user_name, - connection_type, - token, - }) - } + fn read_from_packet(packet: &mut Packet) -> Result { + let user_name = packet.read_value()?; + let connection_type = packet.read_value()?; + let token = packet.read_value()?; + Ok(PeerInit { + user_name, + connection_type, + token, + }) + } } impl WriteToPacket for PeerInit { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - packet.write_value(&self.user_name)?; - packet.write_value(&self.connection_type)?; - packet.write_value(&self.token)?; - Ok(()) - } + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + packet.write_value(&self.user_name)?; + packet.write_value(&self.connection_type)?; + packet.write_value(&self.token)?; + Ok(()) + } } impl ValueEncode for PeerInit { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_string(&self.user_name)?; - encoder.encode_string(&self.connection_type)?; - encoder.encode_u32(self.token)?; - Ok(()) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_string(&self.user_name)?; + encoder.encode_string(&self.connection_type)?; + encoder.encode_u32(self.token)?; + Ok(()) + } } impl ValueDecode for PeerInit { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let user_name = decoder.decode()?; - let connection_type = decoder.decode()?; - let token = decoder.decode()?; - Ok(PeerInit { - user_name, - connection_type, - token, - }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let user_name = decoder.decode()?; + let connection_type = decoder.decode()?; + let token = decoder.decode()?; + Ok(PeerInit { + user_name, + connection_type, + token, + }) + } } #[cfg(test)] mod tests { - use bytes::BytesMut; - - use crate::core::value::tests::roundtrip; - use crate::core::value::{ValueDecodeError, ValueDecoder}; - - use super::*; - - #[test] - fn invalid_code() { - let mut bytes = BytesMut::new(); - bytes.extend_from_slice(&[57, 5, 0, 0]); - - let result = ValueDecoder::new(&bytes).decode::(); - - assert_eq!( - result, - Err(ValueDecodeError::InvalidData { - value_name: "peer message code".to_string(), - cause: "unknown value 1337".to_string(), - position: 0, - }) - ); - } - - #[test] - fn roundtrip_pierce_firewall() { - roundtrip(Message::PierceFirewall(1337)) - } - - #[test] - fn roundtrip_peer_init() { - roundtrip(Message::PeerInit(PeerInit { - user_name: "alice".to_string(), - connection_type: "P".to_string(), - token: 1337, - })); - } + use bytes::BytesMut; + + use crate::core::value::tests::roundtrip; + use crate::core::value::{ValueDecodeError, ValueDecoder}; + + use super::*; + + #[test] + fn invalid_code() { + let mut bytes = BytesMut::new(); + bytes.extend_from_slice(&[57, 5, 0, 0]); + + let result = ValueDecoder::new(&bytes).decode::(); + + assert_eq!( + result, + Err(ValueDecodeError::InvalidData { + value_name: "peer message code".to_string(), + cause: "unknown value 1337".to_string(), + position: 0, + }) + ); + } + + #[test] + fn roundtrip_pierce_firewall() { + roundtrip(Message::PierceFirewall(1337)) + } + + #[test] + fn roundtrip_peer_init() { + roundtrip(Message::PeerInit(PeerInit { + user_name: "alice".to_string(), + connection_type: "P".to_string(), + token: 1337, + })); + } } diff --git a/proto/src/server/client.rs b/proto/src/server/client.rs index b3f6d3e..a50d1ab 100644 --- a/proto/src/server/client.rs +++ b/proto/src/server/client.rs @@ -7,214 +7,217 @@ use thiserror::Error; use tokio::net::TcpStream; use crate::core::channel::{Channel, ChannelError}; -use crate::server::{Credentials, LoginResponse, ServerRequest, ServerResponse, Version}; +use crate::server::{ + Credentials, LoginResponse, ServerRequest, ServerResponse, Version, +}; /// A client for the client-server protocol. #[derive(Debug)] pub struct Client { - channel: Channel, - version: Version, + channel: Channel, + version: Version, } /// An error that arose while logging in to a remote server. #[derive(Debug, Error)] pub enum ClientLoginError { - #[error("login failed: {0}")] - LoginFailed(String, Client), + #[error("login failed: {0}")] + LoginFailed(String, Client), - #[error("unexpected response: {0:?}")] - UnexpectedResponse(ServerResponse), + #[error("unexpected response: {0:?}")] + UnexpectedResponse(ServerResponse), - #[error("channel error: {0}")] - ChannelError(#[from] ChannelError), + #[error("channel error: {0}")] + ChannelError(#[from] ChannelError), } impl From for ClientLoginError { - fn from(error: io::Error) -> Self { - ClientLoginError::from(ChannelError::from(error)) - } + fn from(error: io::Error) -> Self { + ClientLoginError::from(ChannelError::from(error)) + } } /// A `Channel` that sends `ServerRequest`s and receives `ServerResponse`s. pub type ClientChannel = Channel; impl Client { - /// Instantiates a new client - pub fn new(tcp_stream: TcpStream) -> Self { - Client { - channel: Channel::new(tcp_stream), - version: Version::default(), - } + /// Instantiates a new client + pub fn new(tcp_stream: TcpStream) -> Self { + Client { + channel: Channel::new(tcp_stream), + version: Version::default(), } - - /// Sets a custom version to identify as to the server. - pub fn with_version(mut self, version: Version) -> Self { - self.version = version; - self - } - - /// Performs the login exchange, presenting `credentials` to the server. - pub async fn login( - mut self, - credentials: Credentials, - ) -> Result { - let login_request = credentials.into_login_request(self.version); - debug!("Client: sending login request: {:?}", login_request); - - let request = login_request.into(); - self.channel.write(&request).await?; - - let response = self.channel.read().await?; - debug!("Client: received first response: {:?}", response); - - match response { - ServerResponse::LoginResponse(LoginResponse::LoginOk { - motd, - ip, - password_md5_opt, - }) => { - info!("Client: Logged in successfully!"); - info!("Client: Message Of The Day: {}", motd); - info!("Client: Public IP address: {}", ip); - info!("Client: Password MD5: {:?}", password_md5_opt); - Ok(self.channel) - } - ServerResponse::LoginResponse(LoginResponse::LoginFail { reason }) => { - Err(ClientLoginError::LoginFailed(reason, self)) - } - response => Err(ClientLoginError::UnexpectedResponse(response)), - } + } + + /// Sets a custom version to identify as to the server. + pub fn with_version(mut self, version: Version) -> Self { + self.version = version; + self + } + + /// Performs the login exchange, presenting `credentials` to the server. + pub async fn login( + mut self, + credentials: Credentials, + ) -> Result { + let login_request = credentials.into_login_request(self.version); + debug!("Client: sending login request: {:?}", login_request); + + let request = login_request.into(); + self.channel.write(&request).await?; + + let response = self.channel.read().await?; + debug!("Client: received first response: {:?}", response); + + match response { + ServerResponse::LoginResponse(LoginResponse::LoginOk { + motd, + ip, + password_md5_opt, + }) => { + info!("Client: Logged in successfully!"); + info!("Client: Message Of The Day: {}", motd); + info!("Client: Public IP address: {}", ip); + info!("Client: Password MD5: {:?}", password_md5_opt); + Ok(self.channel) + } + ServerResponse::LoginResponse(LoginResponse::LoginFail { reason }) => { + Err(ClientLoginError::LoginFailed(reason, self)) + } + response => Err(ClientLoginError::UnexpectedResponse(response)), } + } } #[cfg(test)] mod tests { - use futures::stream::{empty, StreamExt}; - use tokio::net::TcpStream; - use tokio::sync::mpsc; - - use crate::server::testing::{ServerBuilder, ShutdownType, UserStatusMap}; - use crate::server::{ - Credentials, ServerRequest, ServerResponse, UserStatusRequest, UserStatusResponse, - }; - use crate::UserStatus; - - use super::Client; - - // Enable capturing logs in tests. - fn init() { - let _ = env_logger::builder().is_test(true).try_init(); - } + use futures::stream::{empty, StreamExt}; + use tokio::net::TcpStream; + use tokio::sync::mpsc; - // Returns default `Credentials` suitable for testing. - fn credentials() -> Credentials { - let user_name = "alice".to_string(); - let password = "sekrit".to_string(); - Credentials::new(user_name, password).unwrap() - } - - #[tokio::test] - async fn login() { - init(); + use crate::server::testing::{ServerBuilder, ShutdownType, UserStatusMap}; + use crate::server::{ + Credentials, ServerRequest, ServerResponse, UserStatusRequest, + UserStatusResponse, + }; + use crate::UserStatus; - let (server, handle) = ServerBuilder::default().bind().await.unwrap(); - let server_task = tokio::spawn(server.serve()); + use super::Client; - let stream = TcpStream::connect(handle.address()).await.unwrap(); + // Enable capturing logs in tests. + fn init() { + let _ = env_logger::builder().is_test(true).try_init(); + } - let channel = Client::new(stream).login(credentials()).await.unwrap(); + // Returns default `Credentials` suitable for testing. + fn credentials() -> Credentials { + let user_name = "alice".to_string(); + let password = "sekrit".to_string(); + Credentials::new(user_name, password).unwrap() + } - // Send nothing, receive no responses. - let inbound = channel.run(empty()); - tokio::pin!(inbound); + #[tokio::test] + async fn login() { + init(); - assert!(inbound.next().await.is_none()); + let (server, handle) = ServerBuilder::default().bind().await.unwrap(); + let server_task = tokio::spawn(server.serve()); - handle.shutdown(ShutdownType::LameDuck); - server_task.await.unwrap().unwrap(); - } - - #[tokio::test] - async fn simple_exchange() { - init(); - - let response = UserStatusResponse { - user_name: "alice".to_string(), - status: UserStatus::Online, - is_privileged: false, - }; - - let mut user_status_map = UserStatusMap::default(); - user_status_map.insert(response.clone()); - - let (server, handle) = ServerBuilder::default() - .with_user_status_map(user_status_map) - .bind() - .await - .unwrap(); - let server_task = tokio::spawn(server.serve()); - - let stream = TcpStream::connect(handle.address()).await.unwrap(); - - let channel = Client::new(stream).login(credentials()).await.unwrap(); - - let outbound = Box::pin(async_stream::stream! { - yield ServerRequest::UserStatusRequest(UserStatusRequest { - user_name: "bob".to_string(), - }); - yield ServerRequest::UserStatusRequest(UserStatusRequest { - user_name: "alice".to_string(), - }); - }); - - let inbound = channel.run(outbound); - tokio::pin!(inbound); - - assert_eq!( - inbound.next().await.unwrap().unwrap(), - ServerResponse::UserStatusResponse(response) - ); - assert!(inbound.next().await.is_none()); - - handle.shutdown(ShutdownType::LameDuck); - server_task.await.unwrap().unwrap(); - } + let stream = TcpStream::connect(handle.address()).await.unwrap(); - #[tokio::test] - async fn stream_closed() { - init(); + let channel = Client::new(stream).login(credentials()).await.unwrap(); - let (server, handle) = ServerBuilder::default().bind().await.unwrap(); - let server_task = tokio::spawn(server.serve()); + // Send nothing, receive no responses. + let inbound = channel.run(empty()); + tokio::pin!(inbound); - let stream = TcpStream::connect(handle.address()).await.unwrap(); + assert!(inbound.next().await.is_none()); - let channel = Client::new(stream).login(credentials()).await.unwrap(); + handle.shutdown(ShutdownType::LameDuck); + server_task.await.unwrap().unwrap(); + } - let (_request_tx, mut request_rx) = mpsc::channel(1); - let outbound = Box::pin(async_stream::stream! { - while let Some(request) = request_rx.recv().await { - yield request; - } - }); + #[tokio::test] + async fn simple_exchange() { + init(); - let inbound = channel.run(outbound); - tokio::pin!(inbound); - - // Server shuts down, closing its connection before the client has had a - // chance to send all of `outbound`. - handle.shutdown(ShutdownType::Immediate); - - // Wait for the server to terminate, to avoid race conditions. - server_task.await.unwrap().unwrap(); + let response = UserStatusResponse { + user_name: "alice".to_string(), + status: UserStatus::Online, + is_privileged: false, + }; - // Check that the client returns the correct error, then stops running. - assert!(inbound - .next() - .await - .unwrap() - .unwrap_err() - .is_unexpected_eof()); - assert!(inbound.next().await.is_none()); - } + let mut user_status_map = UserStatusMap::default(); + user_status_map.insert(response.clone()); + + let (server, handle) = ServerBuilder::default() + .with_user_status_map(user_status_map) + .bind() + .await + .unwrap(); + let server_task = tokio::spawn(server.serve()); + + let stream = TcpStream::connect(handle.address()).await.unwrap(); + + let channel = Client::new(stream).login(credentials()).await.unwrap(); + + let outbound = Box::pin(async_stream::stream! { + yield ServerRequest::UserStatusRequest(UserStatusRequest { + user_name: "bob".to_string(), + }); + yield ServerRequest::UserStatusRequest(UserStatusRequest { + user_name: "alice".to_string(), + }); + }); + + let inbound = channel.run(outbound); + tokio::pin!(inbound); + + assert_eq!( + inbound.next().await.unwrap().unwrap(), + ServerResponse::UserStatusResponse(response) + ); + assert!(inbound.next().await.is_none()); + + handle.shutdown(ShutdownType::LameDuck); + server_task.await.unwrap().unwrap(); + } + + #[tokio::test] + async fn stream_closed() { + init(); + + let (server, handle) = ServerBuilder::default().bind().await.unwrap(); + let server_task = tokio::spawn(server.serve()); + + let stream = TcpStream::connect(handle.address()).await.unwrap(); + + let channel = Client::new(stream).login(credentials()).await.unwrap(); + + let (_request_tx, mut request_rx) = mpsc::channel(1); + let outbound = Box::pin(async_stream::stream! { + while let Some(request) = request_rx.recv().await { + yield request; + } + }); + + let inbound = channel.run(outbound); + tokio::pin!(inbound); + + // Server shuts down, closing its connection before the client has had a + // chance to send all of `outbound`. + handle.shutdown(ShutdownType::Immediate); + + // Wait for the server to terminate, to avoid race conditions. + server_task.await.unwrap().unwrap(); + + // Check that the client returns the correct error, then stops running. + assert!(inbound + .next() + .await + .unwrap() + .unwrap_err() + .is_unexpected_eof()); + assert!(inbound.next().await.is_none()); + } } diff --git a/proto/src/server/credentials.rs b/proto/src/server/credentials.rs index a804af9..15a723d 100644 --- a/proto/src/server/credentials.rs +++ b/proto/src/server/credentials.rs @@ -8,119 +8,120 @@ use crate::server::{LoginRequest, Version}; /// Credentials for logging in a client to a server. #[derive(Debug, Eq, PartialEq)] pub struct Credentials { - user_name: String, - password: String, - digest: String, + user_name: String, + password: String, + digest: String, } impl Credentials { - /// Attempts to build credentials. - /// - /// Returns `None` if `password` is empty, `Some(credentials)` otherwise. - pub fn new(user_name: String, password: String) -> Option { - if password.is_empty() { - return None; - } - - let mut hasher = Md5::new(); - hasher.input_str(&user_name); - hasher.input_str(&password); - let digest = hasher.result_str(); - - Some(Credentials { - user_name, - password, - digest, - }) + /// Attempts to build credentials. + /// + /// Returns `None` if `password` is empty, `Some(credentials)` otherwise. + pub fn new(user_name: String, password: String) -> Option { + if password.is_empty() { + return None; } - /// The user name to log in as. - pub fn user_name(&self) -> &str { - &self.user_name - } - - /// The password to log in with. - pub fn password(&self) -> &str { - &self.password - } - - /// Returns md5(user_name + password). - pub fn digest(&self) -> &str { - &self.digest - } - - pub fn into_login_request(self, version: Version) -> LoginRequest { - LoginRequest { - user_name: self.user_name, - password: self.password, - digest: self.digest, - major: version.major, - minor: version.minor, - } + let mut hasher = Md5::new(); + hasher.input_str(&user_name); + hasher.input_str(&password); + let digest = hasher.result_str(); + + Some(Credentials { + user_name, + password, + digest, + }) + } + + /// The user name to log in as. + pub fn user_name(&self) -> &str { + &self.user_name + } + + /// The password to log in with. + pub fn password(&self) -> &str { + &self.password + } + + /// Returns md5(user_name + password). + pub fn digest(&self) -> &str { + &self.digest + } + + pub fn into_login_request(self, version: Version) -> LoginRequest { + LoginRequest { + user_name: self.user_name, + password: self.password, + digest: self.digest, + major: version.major, + minor: version.minor, } + } } #[cfg(test)] mod tests { - use crate::server::{LoginRequest, Version}; - - use super::Credentials; - - #[test] - fn empty_password() { - assert_eq!(Credentials::new("alice".to_string(), String::new()), None); - } - - #[test] - fn new_success() { - let user_name = "alice".to_string(); - let password = "sekrit".to_string(); - - let credentials = Credentials::new(user_name, password).unwrap(); - - assert_eq!(credentials.user_name(), "alice"); - assert_eq!(credentials.password(), "sekrit"); - } - - #[test] - fn digest() { - let user_name = "alice".to_string(); - let password = "sekrit".to_string(); - - let credentials = Credentials::new(user_name, password).unwrap(); - - // To generate the expected value on the command line; - // - // ```sh - // $ user_name="alice" - // $ password="sekrit" - // $ echo -e "${user_name}${password}" | md5sum - // ``` - assert_eq!(credentials.digest(), "286da88eb442032bdd3913979af76e8a"); - } - - #[test] - fn into_login_request() { - let user_name = "alice".to_string(); - let password = "sekrit".to_string(); - - let credentials = Credentials::new(user_name.clone(), password.clone()).unwrap(); - - let digest = credentials.digest().to_string(); - let version = Version { - major: 13, - minor: 37, - }; - - assert_eq!( - credentials.into_login_request(version), - LoginRequest { - user_name, - password, - digest, - major: 13, - minor: 37, - } - ); - } + use crate::server::{LoginRequest, Version}; + + use super::Credentials; + + #[test] + fn empty_password() { + assert_eq!(Credentials::new("alice".to_string(), String::new()), None); + } + + #[test] + fn new_success() { + let user_name = "alice".to_string(); + let password = "sekrit".to_string(); + + let credentials = Credentials::new(user_name, password).unwrap(); + + assert_eq!(credentials.user_name(), "alice"); + assert_eq!(credentials.password(), "sekrit"); + } + + #[test] + fn digest() { + let user_name = "alice".to_string(); + let password = "sekrit".to_string(); + + let credentials = Credentials::new(user_name, password).unwrap(); + + // To generate the expected value on the command line; + // + // ```sh + // $ user_name="alice" + // $ password="sekrit" + // $ echo -e "${user_name}${password}" | md5sum + // ``` + assert_eq!(credentials.digest(), "286da88eb442032bdd3913979af76e8a"); + } + + #[test] + fn into_login_request() { + let user_name = "alice".to_string(); + let password = "sekrit".to_string(); + + let credentials = + Credentials::new(user_name.clone(), password.clone()).unwrap(); + + let digest = credentials.digest().to_string(); + let version = Version { + major: 13, + minor: 37, + }; + + assert_eq!( + credentials.into_login_request(version), + LoginRequest { + user_name, + password, + digest, + major: 13, + minor: 37, + } + ); + } } diff --git a/proto/src/server/request.rs b/proto/src/server/request.rs index 425e919..5c3d64f 100644 --- a/proto/src/server/request.rs +++ b/proto/src/server/request.rs @@ -1,7 +1,8 @@ use std::io; use crate::core::value::{ - ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncodeError, ValueEncoder, + ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncodeError, + ValueEncoder, }; use crate::packet::{MutPacket, WriteToPacket}; use crate::server::constants::*; @@ -12,247 +13,250 @@ use crate::server::constants::*; #[derive(Clone, Debug, Eq, PartialEq)] pub enum ServerRequest { - CannotConnectRequest(CannotConnectRequest), - ConnectToPeerRequest(ConnectToPeerRequest), - FileSearchRequest(FileSearchRequest), - LoginRequest(LoginRequest), - PeerAddressRequest(PeerAddressRequest), - RoomJoinRequest(RoomJoinRequest), - RoomLeaveRequest(RoomLeaveRequest), - RoomListRequest, - RoomMessageRequest(RoomMessageRequest), - SetListenPortRequest(SetListenPortRequest), - UserStatusRequest(UserStatusRequest), + CannotConnectRequest(CannotConnectRequest), + ConnectToPeerRequest(ConnectToPeerRequest), + FileSearchRequest(FileSearchRequest), + LoginRequest(LoginRequest), + PeerAddressRequest(PeerAddressRequest), + RoomJoinRequest(RoomJoinRequest), + RoomLeaveRequest(RoomLeaveRequest), + RoomListRequest, + RoomMessageRequest(RoomMessageRequest), + SetListenPortRequest(SetListenPortRequest), + UserStatusRequest(UserStatusRequest), } impl From for ServerRequest { - fn from(inner: CannotConnectRequest) -> ServerRequest { - ServerRequest::CannotConnectRequest(inner) - } + fn from(inner: CannotConnectRequest) -> ServerRequest { + ServerRequest::CannotConnectRequest(inner) + } } impl From for ServerRequest { - fn from(inner: ConnectToPeerRequest) -> ServerRequest { - ServerRequest::ConnectToPeerRequest(inner) - } + fn from(inner: ConnectToPeerRequest) -> ServerRequest { + ServerRequest::ConnectToPeerRequest(inner) + } } impl From for ServerRequest { - fn from(inner: FileSearchRequest) -> ServerRequest { - ServerRequest::FileSearchRequest(inner) - } + fn from(inner: FileSearchRequest) -> ServerRequest { + ServerRequest::FileSearchRequest(inner) + } } impl From for ServerRequest { - fn from(inner: LoginRequest) -> ServerRequest { - ServerRequest::LoginRequest(inner) - } + fn from(inner: LoginRequest) -> ServerRequest { + ServerRequest::LoginRequest(inner) + } } impl From for ServerRequest { - fn from(inner: PeerAddressRequest) -> ServerRequest { - ServerRequest::PeerAddressRequest(inner) - } + fn from(inner: PeerAddressRequest) -> ServerRequest { + ServerRequest::PeerAddressRequest(inner) + } } impl From for ServerRequest { - fn from(inner: RoomJoinRequest) -> ServerRequest { - ServerRequest::RoomJoinRequest(inner) - } + fn from(inner: RoomJoinRequest) -> ServerRequest { + ServerRequest::RoomJoinRequest(inner) + } } impl From for ServerRequest { - fn from(inner: RoomLeaveRequest) -> ServerRequest { - ServerRequest::RoomLeaveRequest(inner) - } + fn from(inner: RoomLeaveRequest) -> ServerRequest { + ServerRequest::RoomLeaveRequest(inner) + } } impl From for ServerRequest { - fn from(inner: RoomMessageRequest) -> ServerRequest { - ServerRequest::RoomMessageRequest(inner) - } + fn from(inner: RoomMessageRequest) -> ServerRequest { + ServerRequest::RoomMessageRequest(inner) + } } impl From for ServerRequest { - fn from(inner: SetListenPortRequest) -> ServerRequest { - ServerRequest::SetListenPortRequest(inner) - } + fn from(inner: SetListenPortRequest) -> ServerRequest { + ServerRequest::SetListenPortRequest(inner) + } } impl From for ServerRequest { - fn from(inner: UserStatusRequest) -> ServerRequest { - ServerRequest::UserStatusRequest(inner) - } + fn from(inner: UserStatusRequest) -> ServerRequest { + ServerRequest::UserStatusRequest(inner) + } } impl WriteToPacket for ServerRequest { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - match *self { - ServerRequest::CannotConnectRequest(ref request) => { - packet.write_value(&CODE_CANNOT_CONNECT)?; - packet.write_value(request)?; - } - - ServerRequest::ConnectToPeerRequest(ref request) => { - packet.write_value(&CODE_CONNECT_TO_PEER)?; - packet.write_value(request)?; - } - - ServerRequest::FileSearchRequest(ref request) => { - packet.write_value(&CODE_FILE_SEARCH)?; - packet.write_value(request)?; - } - - ServerRequest::LoginRequest(ref request) => { - packet.write_value(&CODE_LOGIN)?; - packet.write_value(request)?; - } - - ServerRequest::PeerAddressRequest(ref request) => { - packet.write_value(&CODE_PEER_ADDRESS)?; - packet.write_value(request)?; - } - - ServerRequest::RoomJoinRequest(ref request) => { - packet.write_value(&CODE_ROOM_JOIN)?; - packet.write_value(request)?; - } - - ServerRequest::RoomLeaveRequest(ref request) => { - packet.write_value(&CODE_ROOM_LEAVE)?; - packet.write_value(request)?; - } - - ServerRequest::RoomListRequest => { - packet.write_value(&CODE_ROOM_LIST)?; - } - - ServerRequest::RoomMessageRequest(ref request) => { - packet.write_value(&CODE_ROOM_MESSAGE)?; - packet.write_value(request)?; - } - - ServerRequest::SetListenPortRequest(ref request) => { - packet.write_value(&CODE_SET_LISTEN_PORT)?; - packet.write_value(request)?; - } - - ServerRequest::UserStatusRequest(ref request) => { - packet.write_value(&CODE_USER_STATUS)?; - packet.write_value(request)?; - } - } - Ok(()) - } + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + match *self { + ServerRequest::CannotConnectRequest(ref request) => { + packet.write_value(&CODE_CANNOT_CONNECT)?; + packet.write_value(request)?; + } + + ServerRequest::ConnectToPeerRequest(ref request) => { + packet.write_value(&CODE_CONNECT_TO_PEER)?; + packet.write_value(request)?; + } + + ServerRequest::FileSearchRequest(ref request) => { + packet.write_value(&CODE_FILE_SEARCH)?; + packet.write_value(request)?; + } + + ServerRequest::LoginRequest(ref request) => { + packet.write_value(&CODE_LOGIN)?; + packet.write_value(request)?; + } + + ServerRequest::PeerAddressRequest(ref request) => { + packet.write_value(&CODE_PEER_ADDRESS)?; + packet.write_value(request)?; + } + + ServerRequest::RoomJoinRequest(ref request) => { + packet.write_value(&CODE_ROOM_JOIN)?; + packet.write_value(request)?; + } + + ServerRequest::RoomLeaveRequest(ref request) => { + packet.write_value(&CODE_ROOM_LEAVE)?; + packet.write_value(request)?; + } + + ServerRequest::RoomListRequest => { + packet.write_value(&CODE_ROOM_LIST)?; + } + + ServerRequest::RoomMessageRequest(ref request) => { + packet.write_value(&CODE_ROOM_MESSAGE)?; + packet.write_value(request)?; + } + + ServerRequest::SetListenPortRequest(ref request) => { + packet.write_value(&CODE_SET_LISTEN_PORT)?; + packet.write_value(request)?; + } + + ServerRequest::UserStatusRequest(ref request) => { + packet.write_value(&CODE_USER_STATUS)?; + packet.write_value(request)?; + } + } + Ok(()) + } } impl ValueEncode for ServerRequest { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - match *self { - ServerRequest::CannotConnectRequest(ref request) => { - encoder.encode_u32(CODE_CANNOT_CONNECT)?; - request.encode_to(encoder)?; - } - ServerRequest::ConnectToPeerRequest(ref request) => { - encoder.encode_u32(CODE_CONNECT_TO_PEER)?; - request.encode_to(encoder)?; - } - ServerRequest::FileSearchRequest(ref request) => { - encoder.encode_u32(CODE_FILE_SEARCH)?; - request.encode_to(encoder)?; - } - ServerRequest::LoginRequest(ref request) => { - encoder.encode_u32(CODE_LOGIN)?; - request.encode_to(encoder)?; - } - ServerRequest::PeerAddressRequest(ref request) => { - encoder.encode_u32(CODE_PEER_ADDRESS)?; - request.encode_to(encoder)?; - } - ServerRequest::RoomJoinRequest(ref request) => { - encoder.encode_u32(CODE_ROOM_JOIN)?; - request.encode_to(encoder)?; - } - ServerRequest::RoomLeaveRequest(ref request) => { - encoder.encode_u32(CODE_ROOM_LEAVE)?; - request.encode_to(encoder)?; - } - ServerRequest::RoomListRequest => { - encoder.encode_u32(CODE_ROOM_LIST)?; - } - ServerRequest::RoomMessageRequest(ref request) => { - encoder.encode_u32(CODE_ROOM_MESSAGE)?; - request.encode_to(encoder)?; - } - ServerRequest::SetListenPortRequest(ref request) => { - encoder.encode_u32(CODE_SET_LISTEN_PORT)?; - request.encode_to(encoder)?; - } - ServerRequest::UserStatusRequest(ref request) => { - encoder.encode_u32(CODE_USER_STATUS)?; - request.encode_to(encoder)?; - } - } - Ok(()) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + match *self { + ServerRequest::CannotConnectRequest(ref request) => { + encoder.encode_u32(CODE_CANNOT_CONNECT)?; + request.encode_to(encoder)?; + } + ServerRequest::ConnectToPeerRequest(ref request) => { + encoder.encode_u32(CODE_CONNECT_TO_PEER)?; + request.encode_to(encoder)?; + } + ServerRequest::FileSearchRequest(ref request) => { + encoder.encode_u32(CODE_FILE_SEARCH)?; + request.encode_to(encoder)?; + } + ServerRequest::LoginRequest(ref request) => { + encoder.encode_u32(CODE_LOGIN)?; + request.encode_to(encoder)?; + } + ServerRequest::PeerAddressRequest(ref request) => { + encoder.encode_u32(CODE_PEER_ADDRESS)?; + request.encode_to(encoder)?; + } + ServerRequest::RoomJoinRequest(ref request) => { + encoder.encode_u32(CODE_ROOM_JOIN)?; + request.encode_to(encoder)?; + } + ServerRequest::RoomLeaveRequest(ref request) => { + encoder.encode_u32(CODE_ROOM_LEAVE)?; + request.encode_to(encoder)?; + } + ServerRequest::RoomListRequest => { + encoder.encode_u32(CODE_ROOM_LIST)?; + } + ServerRequest::RoomMessageRequest(ref request) => { + encoder.encode_u32(CODE_ROOM_MESSAGE)?; + request.encode_to(encoder)?; + } + ServerRequest::SetListenPortRequest(ref request) => { + encoder.encode_u32(CODE_SET_LISTEN_PORT)?; + request.encode_to(encoder)?; + } + ServerRequest::UserStatusRequest(ref request) => { + encoder.encode_u32(CODE_USER_STATUS)?; + request.encode_to(encoder)?; + } + } + Ok(()) + } } impl ValueDecode for ServerRequest { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let position = decoder.position(); - let code: u32 = decoder.decode()?; - let request = match code { - CODE_CANNOT_CONNECT => { - let request = decoder.decode()?; - ServerRequest::CannotConnectRequest(request) - } - CODE_CONNECT_TO_PEER => { - let request = decoder.decode()?; - ServerRequest::ConnectToPeerRequest(request) - } - CODE_FILE_SEARCH => { - let request = decoder.decode()?; - ServerRequest::FileSearchRequest(request) - } - CODE_LOGIN => { - let request = decoder.decode()?; - ServerRequest::LoginRequest(request) - } - CODE_PEER_ADDRESS => { - let request = decoder.decode()?; - ServerRequest::PeerAddressRequest(request) - } - CODE_ROOM_JOIN => { - let request = decoder.decode()?; - ServerRequest::RoomJoinRequest(request) - } - CODE_ROOM_LEAVE => { - let request = decoder.decode()?; - ServerRequest::RoomLeaveRequest(request) - } - CODE_ROOM_LIST => ServerRequest::RoomListRequest, - CODE_ROOM_MESSAGE => { - let request = decoder.decode()?; - ServerRequest::RoomMessageRequest(request) - } - CODE_SET_LISTEN_PORT => { - let request = decoder.decode()?; - ServerRequest::SetListenPortRequest(request) - } - CODE_USER_STATUS => { - let request = decoder.decode()?; - ServerRequest::UserStatusRequest(request) - } - _ => { - return Err(ValueDecodeError::InvalidData { - value_name: "server request code".to_string(), - cause: format!("unknown value {}", code), - position: position, - }) - } - }; - Ok(request) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let position = decoder.position(); + let code: u32 = decoder.decode()?; + let request = match code { + CODE_CANNOT_CONNECT => { + let request = decoder.decode()?; + ServerRequest::CannotConnectRequest(request) + } + CODE_CONNECT_TO_PEER => { + let request = decoder.decode()?; + ServerRequest::ConnectToPeerRequest(request) + } + CODE_FILE_SEARCH => { + let request = decoder.decode()?; + ServerRequest::FileSearchRequest(request) + } + CODE_LOGIN => { + let request = decoder.decode()?; + ServerRequest::LoginRequest(request) + } + CODE_PEER_ADDRESS => { + let request = decoder.decode()?; + ServerRequest::PeerAddressRequest(request) + } + CODE_ROOM_JOIN => { + let request = decoder.decode()?; + ServerRequest::RoomJoinRequest(request) + } + CODE_ROOM_LEAVE => { + let request = decoder.decode()?; + ServerRequest::RoomLeaveRequest(request) + } + CODE_ROOM_LIST => ServerRequest::RoomListRequest, + CODE_ROOM_MESSAGE => { + let request = decoder.decode()?; + ServerRequest::RoomMessageRequest(request) + } + CODE_SET_LISTEN_PORT => { + let request = decoder.decode()?; + ServerRequest::SetListenPortRequest(request) + } + CODE_USER_STATUS => { + let request = decoder.decode()?; + ServerRequest::UserStatusRequest(request) + } + _ => { + return Err(ValueDecodeError::InvalidData { + value_name: "server request code".to_string(), + cause: format!("unknown value {}", code), + position: position, + }) + } + }; + Ok(request) + } } /*================* @@ -261,31 +265,34 @@ impl ValueDecode for ServerRequest { #[derive(Clone, Debug, Eq, PartialEq)] pub struct CannotConnectRequest { - pub token: u32, - pub user_name: String, + pub token: u32, + pub user_name: String, } impl WriteToPacket for CannotConnectRequest { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - packet.write_value(&self.token)?; - packet.write_value(&self.user_name)?; - Ok(()) - } + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + packet.write_value(&self.token)?; + packet.write_value(&self.user_name)?; + Ok(()) + } } impl ValueEncode for CannotConnectRequest { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_u32(self.token)?; - encoder.encode_string(&self.user_name) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_u32(self.token)?; + encoder.encode_string(&self.user_name) + } } impl ValueDecode for CannotConnectRequest { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let token = decoder.decode()?; - let user_name = decoder.decode()?; - Ok(CannotConnectRequest { token, user_name }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let token = decoder.decode()?; + let user_name = decoder.decode()?; + Ok(CannotConnectRequest { token, user_name }) + } } /*=================* @@ -294,39 +301,42 @@ impl ValueDecode for CannotConnectRequest { #[derive(Clone, Debug, Eq, PartialEq)] pub struct ConnectToPeerRequest { - pub token: u32, - pub user_name: String, - pub connection_type: String, + pub token: u32, + pub user_name: String, + pub connection_type: String, } impl WriteToPacket for ConnectToPeerRequest { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - packet.write_value(&self.token)?; - packet.write_value(&self.user_name)?; - packet.write_value(&self.connection_type)?; - Ok(()) - } + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + packet.write_value(&self.token)?; + packet.write_value(&self.user_name)?; + packet.write_value(&self.connection_type)?; + Ok(()) + } } impl ValueEncode for ConnectToPeerRequest { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_u32(self.token)?; - encoder.encode_string(&self.user_name)?; - encoder.encode_string(&self.connection_type) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_u32(self.token)?; + encoder.encode_string(&self.user_name)?; + encoder.encode_string(&self.connection_type) + } } impl ValueDecode for ConnectToPeerRequest { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let token = decoder.decode()?; - let user_name = decoder.decode()?; - let connection_type = decoder.decode()?; - Ok(ConnectToPeerRequest { - token, - user_name, - connection_type, - }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let token = decoder.decode()?; + let user_name = decoder.decode()?; + let connection_type = decoder.decode()?; + Ok(ConnectToPeerRequest { + token, + user_name, + connection_type, + }) + } } /*=============* @@ -335,31 +345,34 @@ impl ValueDecode for ConnectToPeerRequest { #[derive(Clone, Debug, Eq, PartialEq)] pub struct FileSearchRequest { - pub ticket: u32, - pub query: String, + pub ticket: u32, + pub query: String, } impl WriteToPacket for FileSearchRequest { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - packet.write_value(&self.ticket)?; - packet.write_value(&self.query)?; - Ok(()) - } + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + packet.write_value(&self.ticket)?; + packet.write_value(&self.query)?; + Ok(()) + } } impl ValueEncode for FileSearchRequest { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_u32(self.ticket)?; - encoder.encode_string(&self.query) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_u32(self.ticket)?; + encoder.encode_string(&self.query) + } } impl ValueDecode for FileSearchRequest { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let ticket = decoder.decode()?; - let query = decoder.decode()?; - Ok(FileSearchRequest { ticket, query }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let ticket = decoder.decode()?; + let query = decoder.decode()?; + Ok(FileSearchRequest { ticket, query }) + } } /*=======* @@ -368,49 +381,52 @@ impl ValueDecode for FileSearchRequest { #[derive(Clone, Debug, Eq, PartialEq)] pub struct LoginRequest { - pub user_name: String, - pub password: String, - pub digest: String, - pub major: u32, - pub minor: u32, + pub user_name: String, + pub password: String, + pub digest: String, + pub major: u32, + pub minor: u32, } impl WriteToPacket for LoginRequest { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - packet.write_value(&self.user_name)?; - packet.write_value(&self.password)?; - packet.write_value(&self.major)?; - packet.write_value(&self.digest)?; - packet.write_value(&self.minor)?; - Ok(()) - } + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + packet.write_value(&self.user_name)?; + packet.write_value(&self.password)?; + packet.write_value(&self.major)?; + packet.write_value(&self.digest)?; + packet.write_value(&self.minor)?; + Ok(()) + } } impl ValueEncode for LoginRequest { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_string(&self.user_name)?; - encoder.encode_string(&self.password)?; - encoder.encode_u32(self.major)?; - encoder.encode_string(&self.digest)?; - encoder.encode_u32(self.minor) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_string(&self.user_name)?; + encoder.encode_string(&self.password)?; + encoder.encode_u32(self.major)?; + encoder.encode_string(&self.digest)?; + encoder.encode_u32(self.minor) + } } impl ValueDecode for LoginRequest { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let user_name = decoder.decode()?; - let password = decoder.decode()?; - let major = decoder.decode()?; - let digest = decoder.decode()?; - let minor = decoder.decode()?; - Ok(LoginRequest { - user_name, - password, - digest, - major, - minor, - }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let user_name = decoder.decode()?; + let password = decoder.decode()?; + let major = decoder.decode()?; + let digest = decoder.decode()?; + let minor = decoder.decode()?; + Ok(LoginRequest { + user_name, + password, + digest, + major, + minor, + }) + } } /*==============* @@ -419,27 +435,30 @@ impl ValueDecode for LoginRequest { #[derive(Clone, Debug, Eq, PartialEq)] pub struct PeerAddressRequest { - pub user_name: String, + pub user_name: String, } impl WriteToPacket for PeerAddressRequest { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - packet.write_value(&self.user_name)?; - Ok(()) - } + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + packet.write_value(&self.user_name)?; + Ok(()) + } } impl ValueEncode for PeerAddressRequest { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_string(&self.user_name) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_string(&self.user_name) + } } impl ValueDecode for PeerAddressRequest { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let user_name = decoder.decode()?; - Ok(PeerAddressRequest { user_name }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let user_name = decoder.decode()?; + Ok(PeerAddressRequest { user_name }) + } } /*===========* @@ -448,29 +467,32 @@ impl ValueDecode for PeerAddressRequest { #[derive(Clone, Debug, Eq, PartialEq)] pub struct RoomJoinRequest { - pub room_name: String, + pub room_name: String, } impl WriteToPacket for RoomJoinRequest { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - packet.write_value(&self.room_name)?; - Ok(()) - } + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + packet.write_value(&self.room_name)?; + Ok(()) + } } impl ValueEncode for RoomJoinRequest { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_string(&self.room_name) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_string(&self.room_name) + } } impl ValueDecode for RoomJoinRequest { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let room_name = decoder.decode()?; - Ok(RoomJoinRequest { - room_name: room_name, - }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let room_name = decoder.decode()?; + Ok(RoomJoinRequest { + room_name: room_name, + }) + } } /*============* @@ -479,29 +501,32 @@ impl ValueDecode for RoomJoinRequest { #[derive(Clone, Debug, Eq, PartialEq)] pub struct RoomLeaveRequest { - pub room_name: String, + pub room_name: String, } impl WriteToPacket for RoomLeaveRequest { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - packet.write_value(&self.room_name)?; - Ok(()) - } + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + packet.write_value(&self.room_name)?; + Ok(()) + } } impl ValueEncode for RoomLeaveRequest { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_string(&self.room_name) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_string(&self.room_name) + } } impl ValueDecode for RoomLeaveRequest { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let room_name = decoder.decode()?; - Ok(RoomLeaveRequest { - room_name: room_name, - }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let room_name = decoder.decode()?; + Ok(RoomLeaveRequest { + room_name: room_name, + }) + } } /*==============* @@ -510,31 +535,34 @@ impl ValueDecode for RoomLeaveRequest { #[derive(Clone, Debug, Eq, PartialEq)] pub struct RoomMessageRequest { - pub room_name: String, - pub message: String, + pub room_name: String, + pub message: String, } impl WriteToPacket for RoomMessageRequest { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - packet.write_value(&self.room_name)?; - packet.write_value(&self.message)?; - Ok(()) - } + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + packet.write_value(&self.room_name)?; + packet.write_value(&self.message)?; + Ok(()) + } } impl ValueEncode for RoomMessageRequest { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_string(&self.room_name)?; - encoder.encode_string(&self.message) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_string(&self.room_name)?; + encoder.encode_string(&self.message) + } } impl ValueDecode for RoomMessageRequest { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let room_name = decoder.decode()?; - let message = decoder.decode()?; - Ok(RoomMessageRequest { room_name, message }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let room_name = decoder.decode()?; + let message = decoder.decode()?; + Ok(RoomMessageRequest { room_name, message }) + } } /*=================* @@ -543,27 +571,30 @@ impl ValueDecode for RoomMessageRequest { #[derive(Clone, Debug, Eq, PartialEq)] pub struct SetListenPortRequest { - pub port: u16, + pub port: u16, } impl WriteToPacket for SetListenPortRequest { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - packet.write_value(&self.port)?; - Ok(()) - } + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + packet.write_value(&self.port)?; + Ok(()) + } } impl ValueEncode for SetListenPortRequest { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode(&self.port) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode(&self.port) + } } impl ValueDecode for SetListenPortRequest { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let port = decoder.decode()?; - Ok(SetListenPortRequest { port: port }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let port = decoder.decode()?; + Ok(SetListenPortRequest { port: port }) + } } /*=============* @@ -572,29 +603,32 @@ impl ValueDecode for SetListenPortRequest { #[derive(Clone, Debug, Eq, PartialEq)] pub struct UserStatusRequest { - pub user_name: String, + pub user_name: String, } impl WriteToPacket for UserStatusRequest { - fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { - packet.write_value(&self.user_name)?; - Ok(()) - } + fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { + packet.write_value(&self.user_name)?; + Ok(()) + } } impl ValueEncode for UserStatusRequest { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_string(&self.user_name) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_string(&self.user_name) + } } impl ValueDecode for UserStatusRequest { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let user_name = decoder.decode()?; - Ok(UserStatusRequest { - user_name: user_name, - }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let user_name = decoder.decode()?; + Ok(UserStatusRequest { + user_name: user_name, + }) + } } /*=======* @@ -603,228 +637,228 @@ impl ValueDecode for UserStatusRequest { #[cfg(test)] mod tests { - use bytes::BytesMut; - - use crate::core::value::tests::roundtrip; - use crate::core::value::{ValueDecodeError, ValueDecoder}; - - use super::*; - - #[test] - fn invalid_code() { - let mut bytes = BytesMut::new(); - bytes.extend_from_slice(&[57, 5, 0, 0]); - - let result = ValueDecoder::new(&bytes).decode::(); - - assert_eq!( - result, - Err(ValueDecodeError::InvalidData { - value_name: "server request code".to_string(), - cause: "unknown value 1337".to_string(), - position: 0, - }) - ); - } - - #[test] - fn from_cannot_connect_request() { - let request = CannotConnectRequest { - token: 1337, - user_name: "alice".to_string(), - }; - assert_eq!( - ServerRequest::from(request.clone()), - ServerRequest::CannotConnectRequest(request) - ); - } - - #[test] - fn roundtrip_cannot_connect_request() { - roundtrip(ServerRequest::CannotConnectRequest(CannotConnectRequest { - token: 1337, - user_name: "alice".to_string(), - })) - } - - #[test] - fn from_connect_to_peer_request() { - let request = ConnectToPeerRequest { - token: 1337, - user_name: "alice".to_string(), - connection_type: "P".to_string(), - }; - assert_eq!( - ServerRequest::from(request.clone()), - ServerRequest::ConnectToPeerRequest(request) - ); - } - - #[test] - fn roundtrip_connect_to_peer_request() { - roundtrip(ServerRequest::ConnectToPeerRequest(ConnectToPeerRequest { - token: 1337, - user_name: "alice".to_string(), - connection_type: "P".to_string(), - })) - } - - #[test] - fn from_file_search_request() { - let request = FileSearchRequest { - ticket: 1337, - query: "foo.txt".to_string(), - }; - assert_eq!( - ServerRequest::from(request.clone()), - ServerRequest::FileSearchRequest(request) - ); - } - - #[test] - fn roundtrip_file_search_request() { - roundtrip(ServerRequest::FileSearchRequest(FileSearchRequest { - ticket: 1337, - query: "foo.txt".to_string(), - })) - } - - #[test] - fn from_login_request() { - let request = LoginRequest { - user_name: "alice".to_string(), - password: "sekrit".to_string(), - digest: "abcdef".to_string(), - major: 13, - minor: 37, - }; - assert_eq!( - ServerRequest::from(request.clone()), - ServerRequest::LoginRequest(request) - ); - } - - #[test] - fn roundtrip_login_request() { - roundtrip(ServerRequest::LoginRequest(LoginRequest { - user_name: "alice".to_string(), - password: "sekrit".to_string(), - digest: "abcdef".to_string(), - major: 13, - minor: 37, - })) - } - - #[test] - fn from_peer_address_request() { - let request = PeerAddressRequest { - user_name: "alice".to_string(), - }; - assert_eq!( - ServerRequest::from(request.clone()), - ServerRequest::PeerAddressRequest(request) - ); - } - - #[test] - fn roundtrip_peer_address_request() { - roundtrip(ServerRequest::PeerAddressRequest(PeerAddressRequest { - user_name: "alice".to_string(), - })) - } - - #[test] - fn from_room_join_request() { - let request = RoomJoinRequest { - room_name: "best room ever".to_string(), - }; - assert_eq!( - ServerRequest::from(request.clone()), - ServerRequest::RoomJoinRequest(request) - ); - } - - #[test] - fn roundtrip_room_join_request() { - roundtrip(ServerRequest::RoomJoinRequest(RoomJoinRequest { - room_name: "best room ever".to_string(), - })) - } - - #[test] - fn from_room_leave_request() { - let request = RoomLeaveRequest { - room_name: "worst room ever".to_string(), - }; - assert_eq!( - ServerRequest::from(request.clone()), - ServerRequest::RoomLeaveRequest(request) - ); - } - - #[test] - fn roundtrip_room_leave_request() { - roundtrip(ServerRequest::RoomLeaveRequest(RoomLeaveRequest { - room_name: "worst room ever".to_string(), - })) - } - - #[test] - fn roundtrip_room_list_request() { - roundtrip(ServerRequest::RoomListRequest) - } - - #[test] - fn from_room_message_request() { - let request = RoomMessageRequest { - room_name: "best room ever".to_string(), - message: "hello world!".to_string(), - }; - assert_eq!( - ServerRequest::from(request.clone()), - ServerRequest::RoomMessageRequest(request) - ); - } - - #[test] - fn roundtrip_room_message_request() { - roundtrip(ServerRequest::RoomMessageRequest(RoomMessageRequest { - room_name: "best room ever".to_string(), - message: "hello world!".to_string(), - })) - } - - #[test] - fn from_set_listen_port_request() { - let request = SetListenPortRequest { port: 1337 }; - assert_eq!( - ServerRequest::from(request.clone()), - ServerRequest::SetListenPortRequest(request) - ); - } - - #[test] - fn roundtrip_set_listen_port_request() { - roundtrip(ServerRequest::SetListenPortRequest(SetListenPortRequest { - port: 1337, - })) - } - - #[test] - fn from_user_status_request() { - let request = UserStatusRequest { - user_name: "alice".to_string(), - }; - assert_eq!( - ServerRequest::from(request.clone()), - ServerRequest::UserStatusRequest(request) - ); - } - - #[test] - fn roundtrip_user_status_request() { - roundtrip(ServerRequest::UserStatusRequest(UserStatusRequest { - user_name: "alice".to_string(), - })) - } + use bytes::BytesMut; + + use crate::core::value::tests::roundtrip; + use crate::core::value::{ValueDecodeError, ValueDecoder}; + + use super::*; + + #[test] + fn invalid_code() { + let mut bytes = BytesMut::new(); + bytes.extend_from_slice(&[57, 5, 0, 0]); + + let result = ValueDecoder::new(&bytes).decode::(); + + assert_eq!( + result, + Err(ValueDecodeError::InvalidData { + value_name: "server request code".to_string(), + cause: "unknown value 1337".to_string(), + position: 0, + }) + ); + } + + #[test] + fn from_cannot_connect_request() { + let request = CannotConnectRequest { + token: 1337, + user_name: "alice".to_string(), + }; + assert_eq!( + ServerRequest::from(request.clone()), + ServerRequest::CannotConnectRequest(request) + ); + } + + #[test] + fn roundtrip_cannot_connect_request() { + roundtrip(ServerRequest::CannotConnectRequest(CannotConnectRequest { + token: 1337, + user_name: "alice".to_string(), + })) + } + + #[test] + fn from_connect_to_peer_request() { + let request = ConnectToPeerRequest { + token: 1337, + user_name: "alice".to_string(), + connection_type: "P".to_string(), + }; + assert_eq!( + ServerRequest::from(request.clone()), + ServerRequest::ConnectToPeerRequest(request) + ); + } + + #[test] + fn roundtrip_connect_to_peer_request() { + roundtrip(ServerRequest::ConnectToPeerRequest(ConnectToPeerRequest { + token: 1337, + user_name: "alice".to_string(), + connection_type: "P".to_string(), + })) + } + + #[test] + fn from_file_search_request() { + let request = FileSearchRequest { + ticket: 1337, + query: "foo.txt".to_string(), + }; + assert_eq!( + ServerRequest::from(request.clone()), + ServerRequest::FileSearchRequest(request) + ); + } + + #[test] + fn roundtrip_file_search_request() { + roundtrip(ServerRequest::FileSearchRequest(FileSearchRequest { + ticket: 1337, + query: "foo.txt".to_string(), + })) + } + + #[test] + fn from_login_request() { + let request = LoginRequest { + user_name: "alice".to_string(), + password: "sekrit".to_string(), + digest: "abcdef".to_string(), + major: 13, + minor: 37, + }; + assert_eq!( + ServerRequest::from(request.clone()), + ServerRequest::LoginRequest(request) + ); + } + + #[test] + fn roundtrip_login_request() { + roundtrip(ServerRequest::LoginRequest(LoginRequest { + user_name: "alice".to_string(), + password: "sekrit".to_string(), + digest: "abcdef".to_string(), + major: 13, + minor: 37, + })) + } + + #[test] + fn from_peer_address_request() { + let request = PeerAddressRequest { + user_name: "alice".to_string(), + }; + assert_eq!( + ServerRequest::from(request.clone()), + ServerRequest::PeerAddressRequest(request) + ); + } + + #[test] + fn roundtrip_peer_address_request() { + roundtrip(ServerRequest::PeerAddressRequest(PeerAddressRequest { + user_name: "alice".to_string(), + })) + } + + #[test] + fn from_room_join_request() { + let request = RoomJoinRequest { + room_name: "best room ever".to_string(), + }; + assert_eq!( + ServerRequest::from(request.clone()), + ServerRequest::RoomJoinRequest(request) + ); + } + + #[test] + fn roundtrip_room_join_request() { + roundtrip(ServerRequest::RoomJoinRequest(RoomJoinRequest { + room_name: "best room ever".to_string(), + })) + } + + #[test] + fn from_room_leave_request() { + let request = RoomLeaveRequest { + room_name: "worst room ever".to_string(), + }; + assert_eq!( + ServerRequest::from(request.clone()), + ServerRequest::RoomLeaveRequest(request) + ); + } + + #[test] + fn roundtrip_room_leave_request() { + roundtrip(ServerRequest::RoomLeaveRequest(RoomLeaveRequest { + room_name: "worst room ever".to_string(), + })) + } + + #[test] + fn roundtrip_room_list_request() { + roundtrip(ServerRequest::RoomListRequest) + } + + #[test] + fn from_room_message_request() { + let request = RoomMessageRequest { + room_name: "best room ever".to_string(), + message: "hello world!".to_string(), + }; + assert_eq!( + ServerRequest::from(request.clone()), + ServerRequest::RoomMessageRequest(request) + ); + } + + #[test] + fn roundtrip_room_message_request() { + roundtrip(ServerRequest::RoomMessageRequest(RoomMessageRequest { + room_name: "best room ever".to_string(), + message: "hello world!".to_string(), + })) + } + + #[test] + fn from_set_listen_port_request() { + let request = SetListenPortRequest { port: 1337 }; + assert_eq!( + ServerRequest::from(request.clone()), + ServerRequest::SetListenPortRequest(request) + ); + } + + #[test] + fn roundtrip_set_listen_port_request() { + roundtrip(ServerRequest::SetListenPortRequest(SetListenPortRequest { + port: 1337, + })) + } + + #[test] + fn from_user_status_request() { + let request = UserStatusRequest { + user_name: "alice".to_string(), + }; + assert_eq!( + ServerRequest::from(request.clone()), + ServerRequest::UserStatusRequest(request) + ); + } + + #[test] + fn roundtrip_user_status_request() { + roundtrip(ServerRequest::UserStatusRequest(UserStatusRequest { + user_name: "alice".to_string(), + })) + } } diff --git a/proto/src/server/response.rs b/proto/src/server/response.rs index 179c597..53505be 100644 --- a/proto/src/server/response.rs +++ b/proto/src/server/response.rs @@ -3,7 +3,8 @@ use std::net; use log::{debug, warn}; use crate::core::value::{ - ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncodeError, ValueEncoder, + ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncodeError, + ValueEncoder, }; use crate::packet::{Packet, PacketReadError, ReadFromPacket}; use crate::server::constants::*; @@ -15,246 +16,271 @@ use crate::{User, UserStatus}; #[derive(Debug, Eq, PartialEq)] pub enum ServerResponse { - ConnectToPeerResponse(ConnectToPeerResponse), - FileSearchResponse(FileSearchResponse), - LoginResponse(LoginResponse), - PeerAddressResponse(PeerAddressResponse), - PrivilegedUsersResponse(PrivilegedUsersResponse), - RoomJoinResponse(RoomJoinResponse), - RoomLeaveResponse(RoomLeaveResponse), - RoomListResponse(RoomListResponse), - RoomMessageResponse(RoomMessageResponse), - RoomTickersResponse(RoomTickersResponse), - RoomUserJoinedResponse(RoomUserJoinedResponse), - RoomUserLeftResponse(RoomUserLeftResponse), - UserInfoResponse(UserInfoResponse), - UserStatusResponse(UserStatusResponse), - WishlistIntervalResponse(WishlistIntervalResponse), - - // Unknown purpose - ParentMinSpeedResponse(ParentMinSpeedResponse), - ParentSpeedRatioResponse(ParentSpeedRatioResponse), - - UnknownResponse(u32), + ConnectToPeerResponse(ConnectToPeerResponse), + FileSearchResponse(FileSearchResponse), + LoginResponse(LoginResponse), + PeerAddressResponse(PeerAddressResponse), + PrivilegedUsersResponse(PrivilegedUsersResponse), + RoomJoinResponse(RoomJoinResponse), + RoomLeaveResponse(RoomLeaveResponse), + RoomListResponse(RoomListResponse), + RoomMessageResponse(RoomMessageResponse), + RoomTickersResponse(RoomTickersResponse), + RoomUserJoinedResponse(RoomUserJoinedResponse), + RoomUserLeftResponse(RoomUserLeftResponse), + UserInfoResponse(UserInfoResponse), + UserStatusResponse(UserStatusResponse), + WishlistIntervalResponse(WishlistIntervalResponse), + + // Unknown purpose + ParentMinSpeedResponse(ParentMinSpeedResponse), + ParentSpeedRatioResponse(ParentSpeedRatioResponse), + + UnknownResponse(u32), } impl ReadFromPacket for ServerResponse { - fn read_from_packet(packet: &mut Packet) -> Result { - let code: u32 = packet.read_value()?; - let resp = match code { - CODE_CONNECT_TO_PEER => ServerResponse::ConnectToPeerResponse(packet.read_value()?), + fn read_from_packet(packet: &mut Packet) -> Result { + let code: u32 = packet.read_value()?; + let resp = match code { + CODE_CONNECT_TO_PEER => { + ServerResponse::ConnectToPeerResponse(packet.read_value()?) + } - CODE_FILE_SEARCH => ServerResponse::FileSearchResponse(packet.read_value()?), + CODE_FILE_SEARCH => { + ServerResponse::FileSearchResponse(packet.read_value()?) + } - CODE_LOGIN => ServerResponse::LoginResponse(packet.read_value()?), + CODE_LOGIN => ServerResponse::LoginResponse(packet.read_value()?), - CODE_PEER_ADDRESS => ServerResponse::PeerAddressResponse(packet.read_value()?), + CODE_PEER_ADDRESS => { + ServerResponse::PeerAddressResponse(packet.read_value()?) + } - CODE_PRIVILEGED_USERS => ServerResponse::PrivilegedUsersResponse(packet.read_value()?), + CODE_PRIVILEGED_USERS => { + ServerResponse::PrivilegedUsersResponse(packet.read_value()?) + } - CODE_ROOM_JOIN => ServerResponse::RoomJoinResponse(packet.read_value()?), + CODE_ROOM_JOIN => ServerResponse::RoomJoinResponse(packet.read_value()?), - CODE_ROOM_LEAVE => ServerResponse::RoomLeaveResponse(packet.read_value()?), + CODE_ROOM_LEAVE => { + ServerResponse::RoomLeaveResponse(packet.read_value()?) + } - CODE_ROOM_LIST => ServerResponse::RoomListResponse(packet.read_value()?), + CODE_ROOM_LIST => ServerResponse::RoomListResponse(packet.read_value()?), - CODE_ROOM_MESSAGE => ServerResponse::RoomMessageResponse(packet.read_value()?), + CODE_ROOM_MESSAGE => { + ServerResponse::RoomMessageResponse(packet.read_value()?) + } - CODE_ROOM_TICKERS => ServerResponse::RoomTickersResponse(packet.read_value()?), + CODE_ROOM_TICKERS => { + ServerResponse::RoomTickersResponse(packet.read_value()?) + } - CODE_ROOM_USER_JOINED => ServerResponse::RoomUserJoinedResponse(packet.read_value()?), + CODE_ROOM_USER_JOINED => { + ServerResponse::RoomUserJoinedResponse(packet.read_value()?) + } - CODE_ROOM_USER_LEFT => ServerResponse::RoomUserLeftResponse(packet.read_value()?), + CODE_ROOM_USER_LEFT => { + ServerResponse::RoomUserLeftResponse(packet.read_value()?) + } - CODE_USER_INFO => ServerResponse::UserInfoResponse(packet.read_value()?), + CODE_USER_INFO => ServerResponse::UserInfoResponse(packet.read_value()?), - CODE_USER_STATUS => ServerResponse::UserStatusResponse(packet.read_value()?), + CODE_USER_STATUS => { + ServerResponse::UserStatusResponse(packet.read_value()?) + } - CODE_WISHLIST_INTERVAL => { - ServerResponse::WishlistIntervalResponse(packet.read_value()?) - } + CODE_WISHLIST_INTERVAL => { + ServerResponse::WishlistIntervalResponse(packet.read_value()?) + } - CODE_PARENT_MIN_SPEED => ServerResponse::ParentMinSpeedResponse(packet.read_value()?), + CODE_PARENT_MIN_SPEED => { + ServerResponse::ParentMinSpeedResponse(packet.read_value()?) + } - CODE_PARENT_SPEED_RATIO => { - ServerResponse::ParentSpeedRatioResponse(packet.read_value()?) - } + CODE_PARENT_SPEED_RATIO => { + ServerResponse::ParentSpeedRatioResponse(packet.read_value()?) + } - code => ServerResponse::UnknownResponse(code), - }; - let bytes_remaining = packet.bytes_remaining(); - if bytes_remaining > 0 { - warn!( - "Packet with code {} contains {} extra bytes", - code, bytes_remaining - ) - } - Ok(resp) + code => ServerResponse::UnknownResponse(code), + }; + let bytes_remaining = packet.bytes_remaining(); + if bytes_remaining > 0 { + warn!( + "Packet with code {} contains {} extra bytes", + code, bytes_remaining + ) } + Ok(resp) + } } impl ValueEncode for ServerResponse { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - match *self { - ServerResponse::ConnectToPeerResponse(ref response) => { - encoder.encode_u32(CODE_CONNECT_TO_PEER)?; - response.encode_to(encoder)?; - } - ServerResponse::FileSearchResponse(ref response) => { - encoder.encode_u32(CODE_FILE_SEARCH)?; - response.encode_to(encoder)?; - } - ServerResponse::LoginResponse(ref response) => { - encoder.encode_u32(CODE_LOGIN)?; - response.encode_to(encoder)?; - } - ServerResponse::ParentMinSpeedResponse(ref response) => { - encoder.encode_u32(CODE_PARENT_MIN_SPEED)?; - response.encode_to(encoder)?; - } - ServerResponse::ParentSpeedRatioResponse(ref response) => { - encoder.encode_u32(CODE_PARENT_SPEED_RATIO)?; - response.encode_to(encoder)?; - } - ServerResponse::PeerAddressResponse(ref response) => { - encoder.encode_u32(CODE_PEER_ADDRESS)?; - response.encode_to(encoder)?; - } - ServerResponse::PrivilegedUsersResponse(ref response) => { - encoder.encode_u32(CODE_PRIVILEGED_USERS)?; - response.encode_to(encoder)?; - } - ServerResponse::RoomJoinResponse(ref response) => { - encoder.encode_u32(CODE_ROOM_JOIN)?; - response.encode_to(encoder)?; - } - ServerResponse::RoomLeaveResponse(ref response) => { - encoder.encode_u32(CODE_ROOM_LEAVE)?; - response.encode_to(encoder)?; - } - ServerResponse::RoomListResponse(ref response) => { - encoder.encode_u32(CODE_ROOM_LIST)?; - response.encode_to(encoder)?; - } - ServerResponse::RoomMessageResponse(ref response) => { - encoder.encode_u32(CODE_ROOM_MESSAGE)?; - response.encode_to(encoder)?; - } - ServerResponse::RoomTickersResponse(ref response) => { - encoder.encode_u32(CODE_ROOM_TICKERS)?; - response.encode_to(encoder)?; - } - ServerResponse::RoomUserJoinedResponse(ref response) => { - encoder.encode_u32(CODE_ROOM_USER_JOINED)?; - response.encode_to(encoder)?; - } - ServerResponse::RoomUserLeftResponse(ref response) => { - encoder.encode_u32(CODE_ROOM_USER_LEFT)?; - response.encode_to(encoder)?; - } - ServerResponse::UserInfoResponse(ref response) => { - encoder.encode_u32(CODE_USER_INFO)?; - response.encode_to(encoder)?; - } - ServerResponse::UserStatusResponse(ref response) => { - encoder.encode_u32(CODE_USER_STATUS)?; - response.encode_to(encoder)?; - } - ServerResponse::WishlistIntervalResponse(ref response) => { - encoder.encode_u32(CODE_WISHLIST_INTERVAL)?; - response.encode_to(encoder)?; - } - _ => { - unimplemented!(); - } - }; - Ok(()) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + match *self { + ServerResponse::ConnectToPeerResponse(ref response) => { + encoder.encode_u32(CODE_CONNECT_TO_PEER)?; + response.encode_to(encoder)?; + } + ServerResponse::FileSearchResponse(ref response) => { + encoder.encode_u32(CODE_FILE_SEARCH)?; + response.encode_to(encoder)?; + } + ServerResponse::LoginResponse(ref response) => { + encoder.encode_u32(CODE_LOGIN)?; + response.encode_to(encoder)?; + } + ServerResponse::ParentMinSpeedResponse(ref response) => { + encoder.encode_u32(CODE_PARENT_MIN_SPEED)?; + response.encode_to(encoder)?; + } + ServerResponse::ParentSpeedRatioResponse(ref response) => { + encoder.encode_u32(CODE_PARENT_SPEED_RATIO)?; + response.encode_to(encoder)?; + } + ServerResponse::PeerAddressResponse(ref response) => { + encoder.encode_u32(CODE_PEER_ADDRESS)?; + response.encode_to(encoder)?; + } + ServerResponse::PrivilegedUsersResponse(ref response) => { + encoder.encode_u32(CODE_PRIVILEGED_USERS)?; + response.encode_to(encoder)?; + } + ServerResponse::RoomJoinResponse(ref response) => { + encoder.encode_u32(CODE_ROOM_JOIN)?; + response.encode_to(encoder)?; + } + ServerResponse::RoomLeaveResponse(ref response) => { + encoder.encode_u32(CODE_ROOM_LEAVE)?; + response.encode_to(encoder)?; + } + ServerResponse::RoomListResponse(ref response) => { + encoder.encode_u32(CODE_ROOM_LIST)?; + response.encode_to(encoder)?; + } + ServerResponse::RoomMessageResponse(ref response) => { + encoder.encode_u32(CODE_ROOM_MESSAGE)?; + response.encode_to(encoder)?; + } + ServerResponse::RoomTickersResponse(ref response) => { + encoder.encode_u32(CODE_ROOM_TICKERS)?; + response.encode_to(encoder)?; + } + ServerResponse::RoomUserJoinedResponse(ref response) => { + encoder.encode_u32(CODE_ROOM_USER_JOINED)?; + response.encode_to(encoder)?; + } + ServerResponse::RoomUserLeftResponse(ref response) => { + encoder.encode_u32(CODE_ROOM_USER_LEFT)?; + response.encode_to(encoder)?; + } + ServerResponse::UserInfoResponse(ref response) => { + encoder.encode_u32(CODE_USER_INFO)?; + response.encode_to(encoder)?; + } + ServerResponse::UserStatusResponse(ref response) => { + encoder.encode_u32(CODE_USER_STATUS)?; + response.encode_to(encoder)?; + } + ServerResponse::WishlistIntervalResponse(ref response) => { + encoder.encode_u32(CODE_WISHLIST_INTERVAL)?; + response.encode_to(encoder)?; + } + _ => { + unimplemented!(); + } + }; + Ok(()) + } } impl ValueDecode for ServerResponse { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let position = decoder.position(); - let code: u32 = decoder.decode()?; - let response = match code { - CODE_CONNECT_TO_PEER => { - let response = decoder.decode()?; - ServerResponse::ConnectToPeerResponse(response) - } - CODE_FILE_SEARCH => { - let response = decoder.decode()?; - ServerResponse::FileSearchResponse(response) - } - CODE_LOGIN => { - let response = decoder.decode()?; - ServerResponse::LoginResponse(response) - } - CODE_PARENT_MIN_SPEED => { - let response = decoder.decode()?; - ServerResponse::ParentMinSpeedResponse(response) - } - CODE_PARENT_SPEED_RATIO => { - let response = decoder.decode()?; - ServerResponse::ParentSpeedRatioResponse(response) - } - CODE_PEER_ADDRESS => { - let response = decoder.decode()?; - ServerResponse::PeerAddressResponse(response) - } - CODE_PRIVILEGED_USERS => { - let response = decoder.decode()?; - ServerResponse::PrivilegedUsersResponse(response) - } - CODE_ROOM_JOIN => { - let response = decoder.decode()?; - ServerResponse::RoomJoinResponse(response) - } - CODE_ROOM_LEAVE => { - let response = decoder.decode()?; - ServerResponse::RoomLeaveResponse(response) - } - CODE_ROOM_LIST => { - let response = decoder.decode()?; - ServerResponse::RoomListResponse(response) - } - CODE_ROOM_MESSAGE => { - let response = decoder.decode()?; - ServerResponse::RoomMessageResponse(response) - } - CODE_ROOM_TICKERS => { - let response = decoder.decode()?; - ServerResponse::RoomTickersResponse(response) - } - CODE_ROOM_USER_JOINED => { - let response = decoder.decode()?; - ServerResponse::RoomUserJoinedResponse(response) - } - CODE_ROOM_USER_LEFT => { - let response = decoder.decode()?; - ServerResponse::RoomUserLeftResponse(response) - } - CODE_USER_INFO => { - let response = decoder.decode()?; - ServerResponse::UserInfoResponse(response) - } - CODE_USER_STATUS => { - let response = decoder.decode()?; - ServerResponse::UserStatusResponse(response) - } - CODE_WISHLIST_INTERVAL => { - let response = decoder.decode()?; - ServerResponse::WishlistIntervalResponse(response) - } - _ => { - return Err(ValueDecodeError::InvalidData { - value_name: "server response code".to_string(), - cause: format!("unknown value {}", code), - position: position, - }); - } - }; - Ok(response) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let position = decoder.position(); + let code: u32 = decoder.decode()?; + let response = match code { + CODE_CONNECT_TO_PEER => { + let response = decoder.decode()?; + ServerResponse::ConnectToPeerResponse(response) + } + CODE_FILE_SEARCH => { + let response = decoder.decode()?; + ServerResponse::FileSearchResponse(response) + } + CODE_LOGIN => { + let response = decoder.decode()?; + ServerResponse::LoginResponse(response) + } + CODE_PARENT_MIN_SPEED => { + let response = decoder.decode()?; + ServerResponse::ParentMinSpeedResponse(response) + } + CODE_PARENT_SPEED_RATIO => { + let response = decoder.decode()?; + ServerResponse::ParentSpeedRatioResponse(response) + } + CODE_PEER_ADDRESS => { + let response = decoder.decode()?; + ServerResponse::PeerAddressResponse(response) + } + CODE_PRIVILEGED_USERS => { + let response = decoder.decode()?; + ServerResponse::PrivilegedUsersResponse(response) + } + CODE_ROOM_JOIN => { + let response = decoder.decode()?; + ServerResponse::RoomJoinResponse(response) + } + CODE_ROOM_LEAVE => { + let response = decoder.decode()?; + ServerResponse::RoomLeaveResponse(response) + } + CODE_ROOM_LIST => { + let response = decoder.decode()?; + ServerResponse::RoomListResponse(response) + } + CODE_ROOM_MESSAGE => { + let response = decoder.decode()?; + ServerResponse::RoomMessageResponse(response) + } + CODE_ROOM_TICKERS => { + let response = decoder.decode()?; + ServerResponse::RoomTickersResponse(response) + } + CODE_ROOM_USER_JOINED => { + let response = decoder.decode()?; + ServerResponse::RoomUserJoinedResponse(response) + } + CODE_ROOM_USER_LEFT => { + let response = decoder.decode()?; + ServerResponse::RoomUserLeftResponse(response) + } + CODE_USER_INFO => { + let response = decoder.decode()?; + ServerResponse::UserInfoResponse(response) + } + CODE_USER_STATUS => { + let response = decoder.decode()?; + ServerResponse::UserStatusResponse(response) + } + CODE_WISHLIST_INTERVAL => { + let response = decoder.decode()?; + ServerResponse::WishlistIntervalResponse(response) + } + _ => { + return Err(ValueDecodeError::InvalidData { + value_name: "server response code".to_string(), + cause: format!("unknown value {}", code), + position: position, + }); + } + }; + Ok(response) + } } /*=================* @@ -263,69 +289,72 @@ impl ValueDecode for ServerResponse { #[derive(Debug, Eq, PartialEq)] pub struct ConnectToPeerResponse { - pub user_name: String, - pub connection_type: String, - pub ip: net::Ipv4Addr, - pub port: u16, - pub token: u32, - pub is_privileged: bool, + pub user_name: String, + pub connection_type: String, + pub ip: net::Ipv4Addr, + pub port: u16, + pub token: u32, + pub is_privileged: bool, } impl From for ServerResponse { - fn from(response: ConnectToPeerResponse) -> Self { - Self::ConnectToPeerResponse(response) - } + fn from(response: ConnectToPeerResponse) -> Self { + Self::ConnectToPeerResponse(response) + } } impl ReadFromPacket for ConnectToPeerResponse { - fn read_from_packet(packet: &mut Packet) -> Result { - let user_name = packet.read_value()?; - let connection_type = packet.read_value()?; - let ip = packet.read_value()?; - let port = packet.read_value()?; - let token = packet.read_value()?; - let is_privileged = packet.read_value()?; - - Ok(ConnectToPeerResponse { - user_name, - connection_type, - ip, - port, - token, - is_privileged, - }) - } + fn read_from_packet(packet: &mut Packet) -> Result { + let user_name = packet.read_value()?; + let connection_type = packet.read_value()?; + let ip = packet.read_value()?; + let port = packet.read_value()?; + let token = packet.read_value()?; + let is_privileged = packet.read_value()?; + + Ok(ConnectToPeerResponse { + user_name, + connection_type, + ip, + port, + token, + is_privileged, + }) + } } impl ValueEncode for ConnectToPeerResponse { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode(&self.user_name)?; - encoder.encode(&self.connection_type)?; - encoder.encode(&self.ip)?; - encoder.encode_u16(self.port)?; - encoder.encode_u32(self.token)?; - encoder.encode_bool(self.is_privileged) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode(&self.user_name)?; + encoder.encode(&self.connection_type)?; + encoder.encode(&self.ip)?; + encoder.encode_u16(self.port)?; + encoder.encode_u32(self.token)?; + encoder.encode_bool(self.is_privileged) + } } impl ValueDecode for ConnectToPeerResponse { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let user_name = decoder.decode()?; - let connection_type = decoder.decode()?; - let ip = decoder.decode()?; - let port = decoder.decode()?; - let token = decoder.decode()?; - let is_privileged = decoder.decode()?; - - Ok(ConnectToPeerResponse { - user_name, - connection_type, - ip, - port, - token, - is_privileged, - }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let user_name = decoder.decode()?; + let connection_type = decoder.decode()?; + let ip = decoder.decode()?; + let port = decoder.decode()?; + let token = decoder.decode()?; + let is_privileged = decoder.decode()?; + + Ok(ConnectToPeerResponse { + user_name, + connection_type, + ip, + port, + token, + is_privileged, + }) + } } /*=============* @@ -334,51 +363,54 @@ impl ValueDecode for ConnectToPeerResponse { #[derive(Debug, Eq, PartialEq)] pub struct FileSearchResponse { - pub user_name: String, - pub ticket: u32, - pub query: String, + pub user_name: String, + pub ticket: u32, + pub query: String, } impl From for ServerResponse { - fn from(response: FileSearchResponse) -> Self { - Self::FileSearchResponse(response) - } + fn from(response: FileSearchResponse) -> Self { + Self::FileSearchResponse(response) + } } impl ReadFromPacket for FileSearchResponse { - fn read_from_packet(packet: &mut Packet) -> Result { - let user_name = packet.read_value()?; - let ticket = packet.read_value()?; - let query = packet.read_value()?; - - Ok(FileSearchResponse { - user_name, - ticket, - query, - }) - } + fn read_from_packet(packet: &mut Packet) -> Result { + let user_name = packet.read_value()?; + let ticket = packet.read_value()?; + let query = packet.read_value()?; + + Ok(FileSearchResponse { + user_name, + ticket, + query, + }) + } } impl ValueEncode for FileSearchResponse { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_string(&self.user_name)?; - encoder.encode_u32(self.ticket)?; - encoder.encode_string(&self.query) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_string(&self.user_name)?; + encoder.encode_u32(self.ticket)?; + encoder.encode_string(&self.query) + } } impl ValueDecode for FileSearchResponse { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let user_name = decoder.decode()?; - let ticket = decoder.decode()?; - let query = decoder.decode()?; - - Ok(FileSearchResponse { - user_name, - ticket, - query, - }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let user_name = decoder.decode()?; + let ticket = decoder.decode()?; + let query = decoder.decode()?; + + Ok(FileSearchResponse { + user_name, + ticket, + query, + }) + } } /*=======* @@ -387,91 +419,94 @@ impl ValueDecode for FileSearchResponse { #[derive(Debug, Eq, PartialEq)] pub enum LoginResponse { - LoginOk { - motd: String, - ip: net::Ipv4Addr, - password_md5_opt: Option, - }, - LoginFail { - reason: String, - }, + LoginOk { + motd: String, + ip: net::Ipv4Addr, + password_md5_opt: Option, + }, + LoginFail { + reason: String, + }, } impl From for ServerResponse { - fn from(response: LoginResponse) -> Self { - Self::LoginResponse(response) - } + fn from(response: LoginResponse) -> Self { + Self::LoginResponse(response) + } } impl ReadFromPacket for LoginResponse { - fn read_from_packet(packet: &mut Packet) -> Result { - let ok = packet.read_value()?; - if ok { - let motd = packet.read_value()?; - let ip = packet.read_value()?; - - match packet.read_value::() { - Ok(value) => debug!("LoginResponse last field: {}", value), - Err(e) => debug!("Error reading LoginResponse field: {:?}", e), - } - - Ok(LoginResponse::LoginOk { - motd, - ip, - password_md5_opt: None, - }) - } else { - Ok(LoginResponse::LoginFail { - reason: packet.read_value()?, - }) - } - } + fn read_from_packet(packet: &mut Packet) -> Result { + let ok = packet.read_value()?; + if ok { + let motd = packet.read_value()?; + let ip = packet.read_value()?; + + match packet.read_value::() { + Ok(value) => debug!("LoginResponse last field: {}", value), + Err(e) => debug!("Error reading LoginResponse field: {:?}", e), + } + + Ok(LoginResponse::LoginOk { + motd, + ip, + password_md5_opt: None, + }) + } else { + Ok(LoginResponse::LoginFail { + reason: packet.read_value()?, + }) + } + } } impl ValueEncode for LoginResponse { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - match *self { - LoginResponse::LoginOk { - ref motd, - ip, - password_md5_opt: _, - } => { - encoder.encode_bool(true)?; - encoder.encode(motd)?; - encoder.encode(&ip)?; - } - LoginResponse::LoginFail { ref reason } => { - encoder.encode_bool(false)?; - encoder.encode(reason)?; - } - }; - Ok(()) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + match *self { + LoginResponse::LoginOk { + ref motd, + ip, + password_md5_opt: _, + } => { + encoder.encode_bool(true)?; + encoder.encode(motd)?; + encoder.encode(&ip)?; + } + LoginResponse::LoginFail { ref reason } => { + encoder.encode_bool(false)?; + encoder.encode(reason)?; + } + }; + Ok(()) + } } impl ValueDecode for LoginResponse { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let ok: bool = decoder.decode()?; - if !ok { - let reason = decoder.decode()?; - return Ok(LoginResponse::LoginFail { reason }); - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let ok: bool = decoder.decode()?; + if !ok { + let reason = decoder.decode()?; + return Ok(LoginResponse::LoginFail { reason }); + } - let motd = decoder.decode()?; - let ip = decoder.decode()?; + let motd = decoder.decode()?; + let ip = decoder.decode()?; - let result = decoder.decode::(); - match result { - Ok(value) => debug!("LoginResponse last field: {}", value), - Err(e) => debug!("Error reading LoginResponse field: {:?}", e), - } - - Ok(LoginResponse::LoginOk { - motd, - ip, - password_md5_opt: None, - }) + let result = decoder.decode::(); + match result { + Ok(value) => debug!("LoginResponse last field: {}", value), + Err(e) => debug!("Error reading LoginResponse field: {:?}", e), } + + Ok(LoginResponse::LoginOk { + motd, + ip, + password_md5_opt: None, + }) + } } /*==================* @@ -480,33 +515,36 @@ impl ValueDecode for LoginResponse { #[derive(Debug, Eq, PartialEq)] pub struct ParentMinSpeedResponse { - pub value: u32, + pub value: u32, } impl From for ServerResponse { - fn from(response: ParentMinSpeedResponse) -> Self { - Self::ParentMinSpeedResponse(response) - } + fn from(response: ParentMinSpeedResponse) -> Self { + Self::ParentMinSpeedResponse(response) + } } impl ReadFromPacket for ParentMinSpeedResponse { - fn read_from_packet(packet: &mut Packet) -> Result { - let value = packet.read_value()?; - Ok(ParentMinSpeedResponse { value }) - } + fn read_from_packet(packet: &mut Packet) -> Result { + let value = packet.read_value()?; + Ok(ParentMinSpeedResponse { value }) + } } impl ValueEncode for ParentMinSpeedResponse { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_u32(self.value) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_u32(self.value) + } } impl ValueDecode for ParentMinSpeedResponse { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let value = decoder.decode()?; - Ok(ParentMinSpeedResponse { value }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let value = decoder.decode()?; + Ok(ParentMinSpeedResponse { value }) + } } /*====================* @@ -515,33 +553,36 @@ impl ValueDecode for ParentMinSpeedResponse { #[derive(Debug, Eq, PartialEq)] pub struct ParentSpeedRatioResponse { - pub value: u32, + pub value: u32, } impl From for ServerResponse { - fn from(response: ParentSpeedRatioResponse) -> Self { - Self::ParentSpeedRatioResponse(response) - } + fn from(response: ParentSpeedRatioResponse) -> Self { + Self::ParentSpeedRatioResponse(response) + } } impl ReadFromPacket for ParentSpeedRatioResponse { - fn read_from_packet(packet: &mut Packet) -> Result { - let value = packet.read_value()?; - Ok(ParentSpeedRatioResponse { value }) - } + fn read_from_packet(packet: &mut Packet) -> Result { + let value = packet.read_value()?; + Ok(ParentSpeedRatioResponse { value }) + } } impl ValueEncode for ParentSpeedRatioResponse { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_u32(self.value) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_u32(self.value) + } } impl ValueDecode for ParentSpeedRatioResponse { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let value = decoder.decode()?; - Ok(ParentSpeedRatioResponse { value }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let value = decoder.decode()?; + Ok(ParentSpeedRatioResponse { value }) + } } /*==============* @@ -550,50 +591,53 @@ impl ValueDecode for ParentSpeedRatioResponse { #[derive(Debug, Eq, PartialEq)] pub struct PeerAddressResponse { - user_name: String, - ip: net::Ipv4Addr, - port: u16, + user_name: String, + ip: net::Ipv4Addr, + port: u16, } impl From for ServerResponse { - fn from(response: PeerAddressResponse) -> Self { - Self::PeerAddressResponse(response) - } + fn from(response: PeerAddressResponse) -> Self { + Self::PeerAddressResponse(response) + } } impl ReadFromPacket for PeerAddressResponse { - fn read_from_packet(packet: &mut Packet) -> Result { - let user_name = packet.read_value()?; - let ip = packet.read_value()?; - let port = packet.read_value()?; - - Ok(PeerAddressResponse { - user_name, - ip, - port, - }) - } + fn read_from_packet(packet: &mut Packet) -> Result { + let user_name = packet.read_value()?; + let ip = packet.read_value()?; + let port = packet.read_value()?; + + Ok(PeerAddressResponse { + user_name, + ip, + port, + }) + } } impl ValueEncode for PeerAddressResponse { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode(&self.user_name)?; - encoder.encode(&self.ip)?; - encoder.encode_u16(self.port) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode(&self.user_name)?; + encoder.encode(&self.ip)?; + encoder.encode_u16(self.port) + } } impl ValueDecode for PeerAddressResponse { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let user_name = decoder.decode()?; - let ip = decoder.decode()?; - let port = decoder.decode()?; - Ok(PeerAddressResponse { - user_name, - ip, - port, - }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let user_name = decoder.decode()?; + let ip = decoder.decode()?; + let port = decoder.decode()?; + Ok(PeerAddressResponse { + user_name, + ip, + port, + }) + } } /*==================* @@ -602,33 +646,36 @@ impl ValueDecode for PeerAddressResponse { #[derive(Debug, Eq, PartialEq)] pub struct PrivilegedUsersResponse { - pub users: Vec, + pub users: Vec, } impl From for ServerResponse { - fn from(response: PrivilegedUsersResponse) -> Self { - Self::PrivilegedUsersResponse(response) - } + fn from(response: PrivilegedUsersResponse) -> Self { + Self::PrivilegedUsersResponse(response) + } } impl ReadFromPacket for PrivilegedUsersResponse { - fn read_from_packet(packet: &mut Packet) -> Result { - let users = packet.read_value()?; - Ok(PrivilegedUsersResponse { users }) - } + fn read_from_packet(packet: &mut Packet) -> Result { + let users = packet.read_value()?; + Ok(PrivilegedUsersResponse { users }) + } } impl ValueEncode for PrivilegedUsersResponse { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode(&self.users) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode(&self.users) + } } impl ValueDecode for PrivilegedUsersResponse { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let users = decoder.decode()?; - Ok(PrivilegedUsersResponse { users }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let users = decoder.decode()?; + Ok(PrivilegedUsersResponse { users }) + } } /*===========* @@ -637,107 +684,110 @@ impl ValueDecode for PrivilegedUsersResponse { #[derive(Debug, Eq, PartialEq)] pub struct RoomJoinResponse { - pub room_name: String, - pub users: Vec, - pub owner: Option, - pub operators: Vec, + pub room_name: String, + pub users: Vec, + pub owner: Option, + pub operators: Vec, } impl From for ServerResponse { - fn from(response: RoomJoinResponse) -> Self { - Self::RoomJoinResponse(response) - } + fn from(response: RoomJoinResponse) -> Self { + Self::RoomJoinResponse(response) + } } impl ReadFromPacket for RoomJoinResponse { - fn read_from_packet(packet: &mut Packet) -> Result { - let mut response = RoomJoinResponse { - room_name: packet.read_value()?, - users: Vec::new(), - owner: None, - operators: Vec::new(), - }; - - let num_users: usize = packet.read_value()?; - for _ in 0..num_users { - let name: String = packet.read_value()?; - let user = User { - name, - status: UserStatus::Offline, - average_speed: 0, - num_downloads: 0, - unknown: 0, - num_files: 0, - num_folders: 0, - num_free_slots: 0, - country: String::new(), - }; - response.users.push(user); - } - - response.read_user_infos(packet)?; + fn read_from_packet(packet: &mut Packet) -> Result { + let mut response = RoomJoinResponse { + room_name: packet.read_value()?, + users: Vec::new(), + owner: None, + operators: Vec::new(), + }; + + let num_users: usize = packet.read_value()?; + for _ in 0..num_users { + let name: String = packet.read_value()?; + let user = User { + name, + status: UserStatus::Offline, + average_speed: 0, + num_downloads: 0, + unknown: 0, + num_files: 0, + num_folders: 0, + num_free_slots: 0, + country: String::new(), + }; + response.users.push(user); + } - if packet.bytes_remaining() > 0 { - response.owner = Some(packet.read_value()?); + response.read_user_infos(packet)?; - let num_operators: usize = packet.read_value()?; - for _ in 0..num_operators { - response.operators.push(packet.read_value()?); - } - } + if packet.bytes_remaining() > 0 { + response.owner = Some(packet.read_value()?); - Ok(response) + let num_operators: usize = packet.read_value()?; + for _ in 0..num_operators { + response.operators.push(packet.read_value()?); + } } + + Ok(response) + } } impl RoomJoinResponse { - fn read_user_infos(&mut self, packet: &mut Packet) -> Result<(), PacketReadError> { - let num_statuses: usize = packet.read_value()?; - for i in 0..num_statuses { - if let Some(user) = self.users.get_mut(i) { - user.status = packet.read_value()?; - } - } - - let num_infos: usize = packet.read_value()?; - for i in 0..num_infos { - if let Some(user) = self.users.get_mut(i) { - user.average_speed = packet.read_value()?; - user.num_downloads = packet.read_value()?; - user.unknown = packet.read_value()?; - user.num_files = packet.read_value()?; - user.num_folders = packet.read_value()?; - } - } - - let num_free_slots: usize = packet.read_value()?; - for i in 0..num_free_slots { - if let Some(user) = self.users.get_mut(i) { - user.num_free_slots = packet.read_value()?; - } - } - - let num_countries: usize = packet.read_value()?; - for i in 0..num_countries { - if let Some(user) = self.users.get_mut(i) { - user.country = packet.read_value()?; - } - } - - let num_users = self.users.len(); - if num_users != num_statuses - || num_users != num_infos - || num_users != num_free_slots - || num_users != num_countries - { - warn!( - "RoomJoinResponse: mismatched vector sizes {}, {}, {}, {}, {}", - num_users, num_statuses, num_infos, num_free_slots, num_countries - ); - } - - Ok(()) - } + fn read_user_infos( + &mut self, + packet: &mut Packet, + ) -> Result<(), PacketReadError> { + let num_statuses: usize = packet.read_value()?; + for i in 0..num_statuses { + if let Some(user) = self.users.get_mut(i) { + user.status = packet.read_value()?; + } + } + + let num_infos: usize = packet.read_value()?; + for i in 0..num_infos { + if let Some(user) = self.users.get_mut(i) { + user.average_speed = packet.read_value()?; + user.num_downloads = packet.read_value()?; + user.unknown = packet.read_value()?; + user.num_files = packet.read_value()?; + user.num_folders = packet.read_value()?; + } + } + + let num_free_slots: usize = packet.read_value()?; + for i in 0..num_free_slots { + if let Some(user) = self.users.get_mut(i) { + user.num_free_slots = packet.read_value()?; + } + } + + let num_countries: usize = packet.read_value()?; + for i in 0..num_countries { + if let Some(user) = self.users.get_mut(i) { + user.country = packet.read_value()?; + } + } + + let num_users = self.users.len(); + if num_users != num_statuses + || num_users != num_infos + || num_users != num_free_slots + || num_users != num_countries + { + warn!( + "RoomJoinResponse: mismatched vector sizes {}, {}, {}, {}, {}", + num_users, num_statuses, num_infos, num_free_slots, num_countries + ); + } + + Ok(()) + } } // This struct is defined to enable decoding a vector of such values for @@ -745,162 +795,168 @@ impl RoomJoinResponse { // For details about individual fields, see said `User` struct. #[derive(Debug, Eq, PartialEq)] struct UserInfo { - average_speed: u32, - num_downloads: u32, - unknown: u32, - num_files: u32, - num_folders: u32, + average_speed: u32, + num_downloads: u32, + unknown: u32, + num_files: u32, + num_folders: u32, } impl UserInfo { - fn from_user(user: &User) -> Self { - Self { - average_speed: user.average_speed as u32, - num_downloads: user.num_downloads as u32, - unknown: user.unknown as u32, - num_files: user.num_files as u32, - num_folders: user.num_folders as u32, - } + fn from_user(user: &User) -> Self { + Self { + average_speed: user.average_speed as u32, + num_downloads: user.num_downloads as u32, + unknown: user.unknown as u32, + num_files: user.num_files as u32, + num_folders: user.num_folders as u32, } + } } fn build_user( - name: String, - status: UserStatus, - info: UserInfo, - num_free_slots: u32, - country: String, + name: String, + status: UserStatus, + info: UserInfo, + num_free_slots: u32, + country: String, ) -> User { - User { - name, - status, - average_speed: info.average_speed as usize, - num_downloads: info.num_downloads as usize, - unknown: info.unknown as usize, - num_files: info.num_files as usize, - num_folders: info.num_folders as usize, - num_free_slots: num_free_slots as usize, - country, - } + User { + name, + status, + average_speed: info.average_speed as usize, + num_downloads: info.num_downloads as usize, + unknown: info.unknown as usize, + num_files: info.num_files as usize, + num_folders: info.num_folders as usize, + num_free_slots: num_free_slots as usize, + country, + } } impl ValueEncode for UserInfo { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_u32(self.average_speed)?; - encoder.encode_u32(self.num_downloads)?; - encoder.encode_u32(self.unknown)?; - encoder.encode_u32(self.num_files)?; - encoder.encode_u32(self.num_folders) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_u32(self.average_speed)?; + encoder.encode_u32(self.num_downloads)?; + encoder.encode_u32(self.unknown)?; + encoder.encode_u32(self.num_files)?; + encoder.encode_u32(self.num_folders) + } } impl ValueDecode for UserInfo { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let average_speed = decoder.decode()?; - let num_downloads = decoder.decode()?; - let unknown = decoder.decode()?; - let num_files = decoder.decode()?; - let num_folders = decoder.decode()?; - Ok(UserInfo { - average_speed, - num_downloads, - unknown, - num_files, - num_folders, - }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let average_speed = decoder.decode()?; + let num_downloads = decoder.decode()?; + let unknown = decoder.decode()?; + let num_files = decoder.decode()?; + let num_folders = decoder.decode()?; + Ok(UserInfo { + average_speed, + num_downloads, + unknown, + num_files, + num_folders, + }) + } } impl ValueEncode for RoomJoinResponse { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - let mut user_names = vec![]; - let mut user_statuses = vec![]; - let mut user_infos = vec![]; - let mut user_free_slots = vec![]; - let mut user_countries = vec![]; - for user in &self.users { - user_names.push(&user.name); - user_statuses.push(user.status); - user_infos.push(UserInfo::from_user(user)); - user_free_slots.push(user.num_free_slots as u32); - user_countries.push(&user.country); - } - - encoder.encode_string(&self.room_name)?; - encoder.encode(&user_names)?; - encoder.encode(&user_statuses)?; - encoder.encode(&user_infos)?; - encoder.encode(&user_free_slots)?; - encoder.encode(&user_countries)?; - - if let Some(ref owner) = self.owner { - encoder.encode_string(owner)?; - encoder.encode(&self.operators)?; - } - - Ok(()) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + let mut user_names = vec![]; + let mut user_statuses = vec![]; + let mut user_infos = vec![]; + let mut user_free_slots = vec![]; + let mut user_countries = vec![]; + for user in &self.users { + user_names.push(&user.name); + user_statuses.push(user.status); + user_infos.push(UserInfo::from_user(user)); + user_free_slots.push(user.num_free_slots as u32); + user_countries.push(&user.country); + } + + encoder.encode_string(&self.room_name)?; + encoder.encode(&user_names)?; + encoder.encode(&user_statuses)?; + encoder.encode(&user_infos)?; + encoder.encode(&user_free_slots)?; + encoder.encode(&user_countries)?; + + if let Some(ref owner) = self.owner { + encoder.encode_string(owner)?; + encoder.encode(&self.operators)?; + } + + Ok(()) + } } fn build_users( - mut names: Vec, - mut statuses: Vec, - mut infos: Vec, - mut free_slots: Vec, - mut countries: Vec, + mut names: Vec, + mut statuses: Vec, + mut infos: Vec, + mut free_slots: Vec, + mut countries: Vec, ) -> Vec { - let mut users = vec![]; + let mut users = vec![]; - loop { - let name_opt = names.pop(); - let status_opt = statuses.pop(); - let info_opt = infos.pop(); - let slots_opt = free_slots.pop(); - let country_opt = countries.pop(); - - match (name_opt, status_opt, info_opt, slots_opt, country_opt) { - (Some(name), Some(status), Some(info), Some(slots), Some(country)) => { - users.push(build_user(name, status, info, slots, country)) - } - _ => break, - } + loop { + let name_opt = names.pop(); + let status_opt = statuses.pop(); + let info_opt = infos.pop(); + let slots_opt = free_slots.pop(); + let country_opt = countries.pop(); + + match (name_opt, status_opt, info_opt, slots_opt, country_opt) { + (Some(name), Some(status), Some(info), Some(slots), Some(country)) => { + users.push(build_user(name, status, info, slots, country)) + } + _ => break, } + } - users.reverse(); - users + users.reverse(); + users } impl ValueDecode for RoomJoinResponse { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let room_name = decoder.decode()?; - let user_names = decoder.decode()?; - let user_statuses = decoder.decode()?; - let user_infos = decoder.decode()?; - let user_free_slots = decoder.decode()?; - let user_countries = decoder.decode()?; - - let mut owner = None; - let mut operators = vec![]; - if decoder.has_remaining() { - owner = Some(decoder.decode()?); - operators = decoder.decode()?; - } - - let users = build_users( - user_names, - user_statuses, - user_infos, - user_free_slots, - user_countries, - ); - - Ok(RoomJoinResponse { - room_name, - users, - owner, - operators, - }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let room_name = decoder.decode()?; + let user_names = decoder.decode()?; + let user_statuses = decoder.decode()?; + let user_infos = decoder.decode()?; + let user_free_slots = decoder.decode()?; + let user_countries = decoder.decode()?; + + let mut owner = None; + let mut operators = vec![]; + if decoder.has_remaining() { + owner = Some(decoder.decode()?); + operators = decoder.decode()?; + } + + let users = build_users( + user_names, + user_statuses, + user_infos, + user_free_slots, + user_countries, + ); + + Ok(RoomJoinResponse { + room_name, + users, + owner, + operators, + }) + } } /*============* @@ -909,34 +965,37 @@ impl ValueDecode for RoomJoinResponse { #[derive(Debug, Eq, PartialEq)] pub struct RoomLeaveResponse { - pub room_name: String, + pub room_name: String, } impl From for ServerResponse { - fn from(response: RoomLeaveResponse) -> Self { - Self::RoomLeaveResponse(response) - } + fn from(response: RoomLeaveResponse) -> Self { + Self::RoomLeaveResponse(response) + } } impl ReadFromPacket for RoomLeaveResponse { - fn read_from_packet(packet: &mut Packet) -> Result { - Ok(RoomLeaveResponse { - room_name: packet.read_value()?, - }) - } + fn read_from_packet(packet: &mut Packet) -> Result { + Ok(RoomLeaveResponse { + room_name: packet.read_value()?, + }) + } } impl ValueEncode for RoomLeaveResponse { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_string(&self.room_name) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_string(&self.room_name) + } } impl ValueDecode for RoomLeaveResponse { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let room_name = decoder.decode()?; - Ok(RoomLeaveResponse { room_name }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let room_name = decoder.decode()?; + Ok(RoomLeaveResponse { room_name }) + } } /*===========* @@ -945,134 +1004,146 @@ impl ValueDecode for RoomLeaveResponse { #[derive(Debug, Eq, PartialEq)] pub struct RoomListResponse { - pub rooms: Vec<(String, u32)>, - pub owned_private_rooms: Vec<(String, u32)>, - pub other_private_rooms: Vec<(String, u32)>, - pub operated_private_room_names: Vec, + pub rooms: Vec<(String, u32)>, + pub owned_private_rooms: Vec<(String, u32)>, + pub other_private_rooms: Vec<(String, u32)>, + pub operated_private_room_names: Vec, } impl From for ServerResponse { - fn from(response: RoomListResponse) -> Self { - Self::RoomListResponse(response) - } + fn from(response: RoomListResponse) -> Self { + Self::RoomListResponse(response) + } } impl ReadFromPacket for RoomListResponse { - fn read_from_packet(packet: &mut Packet) -> Result { - let rooms = Self::read_rooms(packet)?; - let owned_private_rooms = Self::read_rooms(packet)?; - let other_private_rooms = Self::read_rooms(packet)?; - let operated_private_room_names = packet.read_value()?; - Ok(RoomListResponse { - rooms, - owned_private_rooms, - other_private_rooms, - operated_private_room_names, - }) - } + fn read_from_packet(packet: &mut Packet) -> Result { + let rooms = Self::read_rooms(packet)?; + let owned_private_rooms = Self::read_rooms(packet)?; + let other_private_rooms = Self::read_rooms(packet)?; + let operated_private_room_names = packet.read_value()?; + Ok(RoomListResponse { + rooms, + owned_private_rooms, + other_private_rooms, + operated_private_room_names, + }) + } } impl RoomListResponse { - fn read_rooms(packet: &mut Packet) -> Result, PacketReadError> { - let num_rooms: usize = packet.read_value()?; - let mut rooms = Vec::new(); - for _ in 0..num_rooms { - let room_name = packet.read_value()?; - rooms.push((room_name, 0)); - } - - let num_user_counts: usize = packet.read_value()?; - for i in 0..num_user_counts { - if let Some(&mut (_, ref mut count)) = rooms.get_mut(i) { - *count = packet.read_value()?; - } - } + fn read_rooms( + packet: &mut Packet, + ) -> Result, PacketReadError> { + let num_rooms: usize = packet.read_value()?; + let mut rooms = Vec::new(); + for _ in 0..num_rooms { + let room_name = packet.read_value()?; + rooms.push((room_name, 0)); + } - if num_rooms != num_user_counts { - warn!( - "Numbers of rooms and user counts do not match: {} != {}", - num_rooms, num_user_counts - ); - } + let num_user_counts: usize = packet.read_value()?; + for i in 0..num_user_counts { + if let Some(&mut (_, ref mut count)) = rooms.get_mut(i) { + *count = packet.read_value()?; + } + } - Ok(rooms) + if num_rooms != num_user_counts { + warn!( + "Numbers of rooms and user counts do not match: {} != {}", + num_rooms, num_user_counts + ); } - fn build_rooms(mut room_names: Vec, mut user_counts: Vec) -> Vec<(String, u32)> { - let mut rooms = vec![]; + Ok(rooms) + } - loop { - let room_name_opt = room_names.pop(); - let user_count_opt = user_counts.pop(); + fn build_rooms( + mut room_names: Vec, + mut user_counts: Vec, + ) -> Vec<(String, u32)> { + let mut rooms = vec![]; - match (room_name_opt, user_count_opt) { - (Some(room_name), Some(user_count)) => rooms.push((room_name, user_count)), - _ => break, - } - } + loop { + let room_name_opt = room_names.pop(); + let user_count_opt = user_counts.pop(); - if !room_names.is_empty() { - warn!( - "Unmatched room names in room list response: {:?}", - room_names - ) - } - if !user_counts.is_empty() { - warn!( - "Unmatched user counts in room list response: {:?}", - user_counts - ) + match (room_name_opt, user_count_opt) { + (Some(room_name), Some(user_count)) => { + rooms.push((room_name, user_count)) } - - rooms.reverse(); - rooms + _ => break, + } } - fn decode_rooms(decoder: &mut ValueDecoder) -> Result, ValueDecodeError> { - let room_names = decoder.decode()?; - let user_counts = decoder.decode()?; - Ok(Self::build_rooms(room_names, user_counts)) + if !room_names.is_empty() { + warn!( + "Unmatched room names in room list response: {:?}", + room_names + ) + } + if !user_counts.is_empty() { + warn!( + "Unmatched user counts in room list response: {:?}", + user_counts + ) } - fn encode_rooms( - rooms: &[(String, u32)], - encoder: &mut ValueEncoder, - ) -> Result<(), ValueEncodeError> { - let mut room_names = vec![]; - let mut user_counts = vec![]; + rooms.reverse(); + rooms + } - for &(ref room_name, user_count) in rooms { - room_names.push(room_name); - user_counts.push(user_count); - } + fn decode_rooms( + decoder: &mut ValueDecoder, + ) -> Result, ValueDecodeError> { + let room_names = decoder.decode()?; + let user_counts = decoder.decode()?; + Ok(Self::build_rooms(room_names, user_counts)) + } - encoder.encode(&room_names)?; - encoder.encode(&user_counts) + fn encode_rooms( + rooms: &[(String, u32)], + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + let mut room_names = vec![]; + let mut user_counts = vec![]; + + for &(ref room_name, user_count) in rooms { + room_names.push(room_name); + user_counts.push(user_count); } + + encoder.encode(&room_names)?; + encoder.encode(&user_counts) + } } impl ValueEncode for RoomListResponse { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - Self::encode_rooms(&self.rooms, encoder)?; - Self::encode_rooms(&self.owned_private_rooms, encoder)?; - Self::encode_rooms(&self.other_private_rooms, encoder)?; - encoder.encode(&self.operated_private_room_names) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + Self::encode_rooms(&self.rooms, encoder)?; + Self::encode_rooms(&self.owned_private_rooms, encoder)?; + Self::encode_rooms(&self.other_private_rooms, encoder)?; + encoder.encode(&self.operated_private_room_names) + } } impl ValueDecode for RoomListResponse { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let rooms = RoomListResponse::decode_rooms(decoder)?; - let owned_private_rooms = RoomListResponse::decode_rooms(decoder)?; - let other_private_rooms = RoomListResponse::decode_rooms(decoder)?; - let operated_private_room_names = decoder.decode()?; - Ok(RoomListResponse { - rooms, - owned_private_rooms, - other_private_rooms, - operated_private_room_names, - }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let rooms = RoomListResponse::decode_rooms(decoder)?; + let owned_private_rooms = RoomListResponse::decode_rooms(decoder)?; + let other_private_rooms = RoomListResponse::decode_rooms(decoder)?; + let operated_private_room_names = decoder.decode()?; + Ok(RoomListResponse { + rooms, + owned_private_rooms, + other_private_rooms, + operated_private_room_names, + }) + } } /*==============* @@ -1081,49 +1152,52 @@ impl ValueDecode for RoomListResponse { #[derive(Debug, Eq, PartialEq)] pub struct RoomMessageResponse { - pub room_name: String, - pub user_name: String, - pub message: String, + pub room_name: String, + pub user_name: String, + pub message: String, } impl From for ServerResponse { - fn from(response: RoomMessageResponse) -> Self { - Self::RoomMessageResponse(response) - } + fn from(response: RoomMessageResponse) -> Self { + Self::RoomMessageResponse(response) + } } impl ReadFromPacket for RoomMessageResponse { - fn read_from_packet(packet: &mut Packet) -> Result { - let room_name = packet.read_value()?; - let user_name = packet.read_value()?; - let message = packet.read_value()?; - Ok(RoomMessageResponse { - room_name, - user_name, - message, - }) - } + fn read_from_packet(packet: &mut Packet) -> Result { + let room_name = packet.read_value()?; + let user_name = packet.read_value()?; + let message = packet.read_value()?; + Ok(RoomMessageResponse { + room_name, + user_name, + message, + }) + } } impl ValueEncode for RoomMessageResponse { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_string(&self.room_name)?; - encoder.encode_string(&self.user_name)?; - encoder.encode_string(&self.message) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_string(&self.room_name)?; + encoder.encode_string(&self.user_name)?; + encoder.encode_string(&self.message) + } } impl ValueDecode for RoomMessageResponse { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let room_name = decoder.decode()?; - let user_name = decoder.decode()?; - let message = decoder.decode()?; - Ok(RoomMessageResponse { - room_name, - user_name, - message, - }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let room_name = decoder.decode()?; + let user_name = decoder.decode()?; + let message = decoder.decode()?; + Ok(RoomMessageResponse { + room_name, + user_name, + message, + }) + } } /*==============* @@ -1132,45 +1206,48 @@ impl ValueDecode for RoomMessageResponse { #[derive(Debug, Eq, PartialEq)] pub struct RoomTickersResponse { - pub room_name: String, - pub tickers: Vec<(String, String)>, + pub room_name: String, + pub tickers: Vec<(String, String)>, } impl From for ServerResponse { - fn from(response: RoomTickersResponse) -> Self { - Self::RoomTickersResponse(response) - } + fn from(response: RoomTickersResponse) -> Self { + Self::RoomTickersResponse(response) + } } impl ReadFromPacket for RoomTickersResponse { - fn read_from_packet(packet: &mut Packet) -> Result { - let room_name = packet.read_value()?; - - let num_tickers: usize = packet.read_value()?; - let mut tickers = Vec::new(); - for _ in 0..num_tickers { - let user_name = packet.read_value()?; - let message = packet.read_value()?; - tickers.push((user_name, message)) - } + fn read_from_packet(packet: &mut Packet) -> Result { + let room_name = packet.read_value()?; - Ok(RoomTickersResponse { room_name, tickers }) + let num_tickers: usize = packet.read_value()?; + let mut tickers = Vec::new(); + for _ in 0..num_tickers { + let user_name = packet.read_value()?; + let message = packet.read_value()?; + tickers.push((user_name, message)) } + + Ok(RoomTickersResponse { room_name, tickers }) + } } impl ValueEncode for RoomTickersResponse { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_string(&self.room_name)?; - encoder.encode(&self.tickers) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_string(&self.room_name)?; + encoder.encode(&self.tickers) + } } impl ValueDecode for RoomTickersResponse { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let room_name = decoder.decode()?; - let tickers = decoder.decode()?; - Ok(RoomTickersResponse { room_name, tickers }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let room_name = decoder.decode()?; + let tickers = decoder.decode()?; + Ok(RoomTickersResponse { room_name, tickers }) + } } /*==================* @@ -1179,73 +1256,76 @@ impl ValueDecode for RoomTickersResponse { #[derive(Debug, Eq, PartialEq)] pub struct RoomUserJoinedResponse { - pub room_name: String, - pub user: User, + pub room_name: String, + pub user: User, } impl From for ServerResponse { - fn from(response: RoomUserJoinedResponse) -> Self { - Self::RoomUserJoinedResponse(response) - } + fn from(response: RoomUserJoinedResponse) -> Self { + Self::RoomUserJoinedResponse(response) + } } impl ReadFromPacket for RoomUserJoinedResponse { - fn read_from_packet(packet: &mut Packet) -> Result { - let room_name = packet.read_value()?; - let user_name = packet.read_value()?; - - let status = packet.read_value()?; - - let average_speed = packet.read_value()?; - let num_downloads = packet.read_value()?; - let unknown = packet.read_value()?; - let num_files = packet.read_value()?; - let num_folders = packet.read_value()?; - let num_free_slots = packet.read_value()?; - - let country = packet.read_value()?; - - Ok(RoomUserJoinedResponse { - room_name, - user: User { - name: user_name, - status, - average_speed, - num_downloads, - unknown, - num_files, - num_folders, - num_free_slots, - country, - }, - }) - } + fn read_from_packet(packet: &mut Packet) -> Result { + let room_name = packet.read_value()?; + let user_name = packet.read_value()?; + + let status = packet.read_value()?; + + let average_speed = packet.read_value()?; + let num_downloads = packet.read_value()?; + let unknown = packet.read_value()?; + let num_files = packet.read_value()?; + let num_folders = packet.read_value()?; + let num_free_slots = packet.read_value()?; + + let country = packet.read_value()?; + + Ok(RoomUserJoinedResponse { + room_name, + user: User { + name: user_name, + status, + average_speed, + num_downloads, + unknown, + num_files, + num_folders, + num_free_slots, + country, + }, + }) + } } impl ValueEncode for RoomUserJoinedResponse { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_string(&self.room_name)?; - encoder.encode_string(&self.user.name)?; - self.user.status.encode_to(encoder)?; - UserInfo::from_user(&self.user).encode_to(encoder)?; - encoder.encode_u32(self.user.num_free_slots as u32)?; - encoder.encode_string(&self.user.country) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_string(&self.room_name)?; + encoder.encode_string(&self.user.name)?; + self.user.status.encode_to(encoder)?; + UserInfo::from_user(&self.user).encode_to(encoder)?; + encoder.encode_u32(self.user.num_free_slots as u32)?; + encoder.encode_string(&self.user.country) + } } impl ValueDecode for RoomUserJoinedResponse { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let room_name = decoder.decode()?; - let user_name = decoder.decode()?; - let status = decoder.decode()?; - let info = decoder.decode()?; - let num_free_slots = decoder.decode()?; - let country = decoder.decode()?; - Ok(RoomUserJoinedResponse { - room_name, - user: build_user(user_name, status, info, num_free_slots, country), - }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let room_name = decoder.decode()?; + let user_name = decoder.decode()?; + let status = decoder.decode()?; + let info = decoder.decode()?; + let num_free_slots = decoder.decode()?; + let country = decoder.decode()?; + Ok(RoomUserJoinedResponse { + room_name, + user: build_user(user_name, status, info, num_free_slots, country), + }) + } } /*================* @@ -1254,43 +1334,46 @@ impl ValueDecode for RoomUserJoinedResponse { #[derive(Debug, Eq, PartialEq)] pub struct RoomUserLeftResponse { - pub room_name: String, - pub user_name: String, + pub room_name: String, + pub user_name: String, } impl From for ServerResponse { - fn from(response: RoomUserLeftResponse) -> Self { - Self::RoomUserLeftResponse(response) - } + fn from(response: RoomUserLeftResponse) -> Self { + Self::RoomUserLeftResponse(response) + } } impl ReadFromPacket for RoomUserLeftResponse { - fn read_from_packet(packet: &mut Packet) -> Result { - let room_name = packet.read_value()?; - let user_name = packet.read_value()?; - Ok(RoomUserLeftResponse { - room_name, - user_name, - }) - } + fn read_from_packet(packet: &mut Packet) -> Result { + let room_name = packet.read_value()?; + let user_name = packet.read_value()?; + Ok(RoomUserLeftResponse { + room_name, + user_name, + }) + } } impl ValueEncode for RoomUserLeftResponse { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_string(&self.room_name)?; - encoder.encode_string(&self.user_name) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_string(&self.room_name)?; + encoder.encode_string(&self.user_name) + } } impl ValueDecode for RoomUserLeftResponse { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let room_name = decoder.decode()?; - let user_name = decoder.decode()?; - Ok(RoomUserLeftResponse { - room_name, - user_name, - }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let room_name = decoder.decode()?; + let user_name = decoder.decode()?; + Ok(RoomUserLeftResponse { + room_name, + user_name, + }) + } } /*===========* @@ -1299,61 +1382,64 @@ impl ValueDecode for RoomUserLeftResponse { #[derive(Debug, Eq, PartialEq)] pub struct UserInfoResponse { - pub user_name: String, - pub average_speed: usize, - pub num_downloads: usize, - pub num_files: usize, - pub num_folders: usize, + pub user_name: String, + pub average_speed: usize, + pub num_downloads: usize, + pub num_files: usize, + pub num_folders: usize, } impl From for ServerResponse { - fn from(response: UserInfoResponse) -> Self { - Self::UserInfoResponse(response) - } + fn from(response: UserInfoResponse) -> Self { + Self::UserInfoResponse(response) + } } impl ReadFromPacket for UserInfoResponse { - fn read_from_packet(packet: &mut Packet) -> Result { - let user_name = packet.read_value()?; - let average_speed = packet.read_value()?; - let num_downloads = packet.read_value()?; - let num_files = packet.read_value()?; - let num_folders = packet.read_value()?; - Ok(UserInfoResponse { - user_name, - average_speed, - num_downloads, - num_files, - num_folders, - }) - } + fn read_from_packet(packet: &mut Packet) -> Result { + let user_name = packet.read_value()?; + let average_speed = packet.read_value()?; + let num_downloads = packet.read_value()?; + let num_files = packet.read_value()?; + let num_folders = packet.read_value()?; + Ok(UserInfoResponse { + user_name, + average_speed, + num_downloads, + num_files, + num_folders, + }) + } } impl ValueEncode for UserInfoResponse { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_string(&self.user_name)?; - encoder.encode_u32(self.average_speed as u32)?; - encoder.encode_u32(self.num_downloads as u32)?; - encoder.encode_u32(self.num_files as u32)?; - encoder.encode_u32(self.num_folders as u32) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_string(&self.user_name)?; + encoder.encode_u32(self.average_speed as u32)?; + encoder.encode_u32(self.num_downloads as u32)?; + encoder.encode_u32(self.num_files as u32)?; + encoder.encode_u32(self.num_folders as u32) + } } impl ValueDecode for UserInfoResponse { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let user_name = decoder.decode()?; - let average_speed: u32 = decoder.decode()?; - let num_downloads: u32 = decoder.decode()?; - let num_files: u32 = decoder.decode()?; - let num_folders: u32 = decoder.decode()?; - Ok(UserInfoResponse { - user_name, - average_speed: average_speed as usize, - num_downloads: num_downloads as usize, - num_files: num_files as usize, - num_folders: num_folders as usize, - }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let user_name = decoder.decode()?; + let average_speed: u32 = decoder.decode()?; + let num_downloads: u32 = decoder.decode()?; + let num_files: u32 = decoder.decode()?; + let num_folders: u32 = decoder.decode()?; + Ok(UserInfoResponse { + user_name, + average_speed: average_speed as usize, + num_downloads: num_downloads as usize, + num_files: num_files as usize, + num_folders: num_folders as usize, + }) + } } /*=============* @@ -1362,49 +1448,52 @@ impl ValueDecode for UserInfoResponse { #[derive(Clone, Debug, Eq, PartialEq)] pub struct UserStatusResponse { - pub user_name: String, - pub status: UserStatus, - pub is_privileged: bool, + pub user_name: String, + pub status: UserStatus, + pub is_privileged: bool, } impl From for ServerResponse { - fn from(response: UserStatusResponse) -> Self { - Self::UserStatusResponse(response) - } + fn from(response: UserStatusResponse) -> Self { + Self::UserStatusResponse(response) + } } impl ReadFromPacket for UserStatusResponse { - fn read_from_packet(packet: &mut Packet) -> Result { - let user_name = packet.read_value()?; - let status = packet.read_value()?; - let is_privileged = packet.read_value()?; - Ok(UserStatusResponse { - user_name, - status, - is_privileged, - }) - } + fn read_from_packet(packet: &mut Packet) -> Result { + let user_name = packet.read_value()?; + let status = packet.read_value()?; + let is_privileged = packet.read_value()?; + Ok(UserStatusResponse { + user_name, + status, + is_privileged, + }) + } } impl ValueEncode for UserStatusResponse { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_string(&self.user_name)?; - self.status.encode_to(encoder)?; - encoder.encode_bool(self.is_privileged) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_string(&self.user_name)?; + self.status.encode_to(encoder)?; + encoder.encode_bool(self.is_privileged) + } } impl ValueDecode for UserStatusResponse { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let user_name = decoder.decode()?; - let status = decoder.decode()?; - let is_privileged = decoder.decode()?; - Ok(UserStatusResponse { - user_name, - status, - is_privileged, - }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let user_name = decoder.decode()?; + let status = decoder.decode()?; + let is_privileged = decoder.decode()?; + Ok(UserStatusResponse { + user_name, + status, + is_privileged, + }) + } } /*===================* @@ -1413,33 +1502,36 @@ impl ValueDecode for UserStatusResponse { #[derive(Debug, Eq, PartialEq)] pub struct WishlistIntervalResponse { - pub seconds: u32, + pub seconds: u32, } impl From for ServerResponse { - fn from(response: WishlistIntervalResponse) -> Self { - Self::WishlistIntervalResponse(response) - } + fn from(response: WishlistIntervalResponse) -> Self { + Self::WishlistIntervalResponse(response) + } } impl ReadFromPacket for WishlistIntervalResponse { - fn read_from_packet(packet: &mut Packet) -> Result { - let seconds = packet.read_value()?; - Ok(WishlistIntervalResponse { seconds }) - } + fn read_from_packet(packet: &mut Packet) -> Result { + let seconds = packet.read_value()?; + Ok(WishlistIntervalResponse { seconds }) + } } impl ValueEncode for WishlistIntervalResponse { - fn encode_to(&self, encoder: &mut ValueEncoder) -> Result<(), ValueEncodeError> { - encoder.encode_u32(self.seconds) - } + fn encode_to( + &self, + encoder: &mut ValueEncoder, + ) -> Result<(), ValueEncodeError> { + encoder.encode_u32(self.seconds) + } } impl ValueDecode for WishlistIntervalResponse { - fn decode_from(decoder: &mut ValueDecoder) -> Result { - let seconds = decoder.decode()?; - Ok(WishlistIntervalResponse { seconds }) - } + fn decode_from(decoder: &mut ValueDecoder) -> Result { + let seconds = decoder.decode()?; + Ok(WishlistIntervalResponse { seconds }) + } } /*=======* @@ -1448,240 +1540,249 @@ impl ValueDecode for WishlistIntervalResponse { #[cfg(test)] mod tests { - use std::net; - - use bytes::BytesMut; - - use crate::core::value::tests::roundtrip; - use crate::core::value::{ValueDecodeError, ValueDecoder}; - - use super::*; - - #[test] - fn invalid_code() { - let mut bytes = BytesMut::new(); - bytes.extend_from_slice(&[57, 5, 0, 0]); - - let result = ValueDecoder::new(&bytes).decode::(); - - assert_eq!( - result, - Err(ValueDecodeError::InvalidData { - value_name: "server response code".to_string(), - cause: "unknown value 1337".to_string(), - position: 0, - }) - ); - } - - #[test] - fn roundtrip_connect_to_peer() { - roundtrip(ServerResponse::ConnectToPeerResponse( - ConnectToPeerResponse { - user_name: "alice".to_string(), - connection_type: "P".to_string(), - ip: net::Ipv4Addr::new(192, 168, 254, 1), - port: 1337, - token: 42, - is_privileged: true, - }, - )) - } - - #[test] - fn roundtrip_file_search() { - roundtrip(ServerResponse::FileSearchResponse(FileSearchResponse { - user_name: "alice".to_string(), - ticket: 1337, - query: "foo.txt".to_string(), - })) - } - - #[test] - fn roundtrip_login_ok() { - roundtrip(ServerResponse::LoginResponse(LoginResponse::LoginOk { - motd: "welcome one welcome all!".to_string(), - ip: net::Ipv4Addr::new(127, 0, 0, 1), - password_md5_opt: None, - })) - } - - #[test] - fn roundtrip_login_fail() { - roundtrip(ServerResponse::LoginResponse(LoginResponse::LoginFail { - reason: "I just don't like you".to_string(), - })) - } - - #[test] - fn roundtrip_parent_min_speed() { - roundtrip(ServerResponse::ParentMinSpeedResponse( - ParentMinSpeedResponse { value: 1337 }, - )) - } - - #[test] - fn roundtrip_parent_speed_ratio() { - roundtrip(ServerResponse::ParentSpeedRatioResponse( - ParentSpeedRatioResponse { value: 1337 }, - )) - } - - #[test] - fn roundtrip_peer_address() { - roundtrip(ServerResponse::PeerAddressResponse(PeerAddressResponse { - user_name: "alice".to_string(), - ip: net::Ipv4Addr::new(127, 0, 0, 1), - port: 1337, - })) - } - - #[test] - fn roundtrip_privileged_users() { - roundtrip(ServerResponse::PrivilegedUsersResponse( - PrivilegedUsersResponse { - users: vec![ - "alice".to_string(), - "bob".to_string(), - "chris".to_string(), - "dory".to_string(), - ], - }, - )) - } - - #[test] - fn roundtrip_room_join() { - roundtrip(ServerResponse::RoomJoinResponse(RoomJoinResponse { - room_name: "red".to_string(), - users: vec![ - User { - name: "alice".to_string(), - status: UserStatus::Online, - average_speed: 1000, - num_downloads: 1001, - unknown: 1002, - num_files: 1003, - num_folders: 1004, - num_free_slots: 1005, - country: "US".to_string(), - }, - User { - name: "barbara".to_string(), - status: UserStatus::Away, - average_speed: 2000, - num_downloads: 2001, - unknown: 2002, - num_files: 2003, - num_folders: 2004, - num_free_slots: 2005, - country: "DE".to_string(), - }, - ], - owner: Some("carol".to_string()), - operators: vec!["deirdre".to_string(), "erica".to_string()], - })) - } - - #[test] - fn roundtrip_room_join_no_owner() { - roundtrip(ServerResponse::RoomJoinResponse(RoomJoinResponse { - room_name: "red".to_string(), - users: vec![], - owner: None, - operators: vec![], - })) - } - - #[test] - fn roundtrip_room_leave() { - roundtrip(ServerResponse::RoomLeaveResponse(RoomLeaveResponse { - room_name: "red".to_string(), - })) - } - - #[test] - fn roundtrip_room_list() { - roundtrip(ServerResponse::RoomListResponse(RoomListResponse { - rooms: vec![("red".to_string(), 12), ("blue".to_string(), 13)], - owned_private_rooms: vec![("green".to_string(), 14), ("purple".to_string(), 15)], - other_private_rooms: vec![("yellow".to_string(), 16), ("orange".to_string(), 17)], - operated_private_room_names: vec!["brown".to_string(), "pink".to_string()], - })) - } - - #[test] - fn roundtrip_room_message() { - roundtrip(ServerResponse::RoomMessageResponse(RoomMessageResponse { - room_name: "red".to_string(), - user_name: "alice".to_string(), - message: "hello world!".to_string(), - })) - } - - #[test] - fn roundtrip_room_tickers() { - roundtrip(ServerResponse::RoomTickersResponse(RoomTickersResponse { - room_name: "red".to_string(), - tickers: vec![ - ("alice".to_string(), "hello world!".to_string()), - ("bob".to_string(), "hi alice :)".to_string()), - ], - })) - } - - #[test] - fn roundtrip_room_user_joined() { - roundtrip(ServerResponse::RoomUserJoinedResponse( - RoomUserJoinedResponse { - room_name: "red".to_string(), - user: User { - name: "alice".to_string(), - status: UserStatus::Online, - average_speed: 1000, - num_downloads: 1001, - unknown: 1002, - num_files: 1003, - num_folders: 1004, - num_free_slots: 1005, - country: "AR".to_string(), - }, - }, - )) - } - - #[test] - fn roundtrip_room_user_left() { - roundtrip(ServerResponse::RoomUserLeftResponse(RoomUserLeftResponse { - room_name: "red".to_string(), - user_name: "alice".to_string(), - })) - } - - #[test] - fn roundtrip_user_info() { - roundtrip(ServerResponse::UserInfoResponse(UserInfoResponse { - user_name: "alice".to_string(), - average_speed: 1000, - num_downloads: 1001, - num_files: 1002, - num_folders: 1003, - })) - } - - #[test] - fn roundtrip_user_status() { - roundtrip(ServerResponse::UserStatusResponse(UserStatusResponse { - user_name: "alice".to_string(), - status: UserStatus::Offline, - is_privileged: true, - })) - } - - #[test] - fn roundtrip_wishlist_interval() { - roundtrip(ServerResponse::WishlistIntervalResponse( - WishlistIntervalResponse { seconds: 1337 }, - )) - } + use std::net; + + use bytes::BytesMut; + + use crate::core::value::tests::roundtrip; + use crate::core::value::{ValueDecodeError, ValueDecoder}; + + use super::*; + + #[test] + fn invalid_code() { + let mut bytes = BytesMut::new(); + bytes.extend_from_slice(&[57, 5, 0, 0]); + + let result = ValueDecoder::new(&bytes).decode::(); + + assert_eq!( + result, + Err(ValueDecodeError::InvalidData { + value_name: "server response code".to_string(), + cause: "unknown value 1337".to_string(), + position: 0, + }) + ); + } + + #[test] + fn roundtrip_connect_to_peer() { + roundtrip(ServerResponse::ConnectToPeerResponse( + ConnectToPeerResponse { + user_name: "alice".to_string(), + connection_type: "P".to_string(), + ip: net::Ipv4Addr::new(192, 168, 254, 1), + port: 1337, + token: 42, + is_privileged: true, + }, + )) + } + + #[test] + fn roundtrip_file_search() { + roundtrip(ServerResponse::FileSearchResponse(FileSearchResponse { + user_name: "alice".to_string(), + ticket: 1337, + query: "foo.txt".to_string(), + })) + } + + #[test] + fn roundtrip_login_ok() { + roundtrip(ServerResponse::LoginResponse(LoginResponse::LoginOk { + motd: "welcome one welcome all!".to_string(), + ip: net::Ipv4Addr::new(127, 0, 0, 1), + password_md5_opt: None, + })) + } + + #[test] + fn roundtrip_login_fail() { + roundtrip(ServerResponse::LoginResponse(LoginResponse::LoginFail { + reason: "I just don't like you".to_string(), + })) + } + + #[test] + fn roundtrip_parent_min_speed() { + roundtrip(ServerResponse::ParentMinSpeedResponse( + ParentMinSpeedResponse { value: 1337 }, + )) + } + + #[test] + fn roundtrip_parent_speed_ratio() { + roundtrip(ServerResponse::ParentSpeedRatioResponse( + ParentSpeedRatioResponse { value: 1337 }, + )) + } + + #[test] + fn roundtrip_peer_address() { + roundtrip(ServerResponse::PeerAddressResponse(PeerAddressResponse { + user_name: "alice".to_string(), + ip: net::Ipv4Addr::new(127, 0, 0, 1), + port: 1337, + })) + } + + #[test] + fn roundtrip_privileged_users() { + roundtrip(ServerResponse::PrivilegedUsersResponse( + PrivilegedUsersResponse { + users: vec![ + "alice".to_string(), + "bob".to_string(), + "chris".to_string(), + "dory".to_string(), + ], + }, + )) + } + + #[test] + fn roundtrip_room_join() { + roundtrip(ServerResponse::RoomJoinResponse(RoomJoinResponse { + room_name: "red".to_string(), + users: vec![ + User { + name: "alice".to_string(), + status: UserStatus::Online, + average_speed: 1000, + num_downloads: 1001, + unknown: 1002, + num_files: 1003, + num_folders: 1004, + num_free_slots: 1005, + country: "US".to_string(), + }, + User { + name: "barbara".to_string(), + status: UserStatus::Away, + average_speed: 2000, + num_downloads: 2001, + unknown: 2002, + num_files: 2003, + num_folders: 2004, + num_free_slots: 2005, + country: "DE".to_string(), + }, + ], + owner: Some("carol".to_string()), + operators: vec!["deirdre".to_string(), "erica".to_string()], + })) + } + + #[test] + fn roundtrip_room_join_no_owner() { + roundtrip(ServerResponse::RoomJoinResponse(RoomJoinResponse { + room_name: "red".to_string(), + users: vec![], + owner: None, + operators: vec![], + })) + } + + #[test] + fn roundtrip_room_leave() { + roundtrip(ServerResponse::RoomLeaveResponse(RoomLeaveResponse { + room_name: "red".to_string(), + })) + } + + #[test] + fn roundtrip_room_list() { + roundtrip(ServerResponse::RoomListResponse(RoomListResponse { + rooms: vec![("red".to_string(), 12), ("blue".to_string(), 13)], + owned_private_rooms: vec![ + ("green".to_string(), 14), + ("purple".to_string(), 15), + ], + other_private_rooms: vec![ + ("yellow".to_string(), 16), + ("orange".to_string(), 17), + ], + operated_private_room_names: vec![ + "brown".to_string(), + "pink".to_string(), + ], + })) + } + + #[test] + fn roundtrip_room_message() { + roundtrip(ServerResponse::RoomMessageResponse(RoomMessageResponse { + room_name: "red".to_string(), + user_name: "alice".to_string(), + message: "hello world!".to_string(), + })) + } + + #[test] + fn roundtrip_room_tickers() { + roundtrip(ServerResponse::RoomTickersResponse(RoomTickersResponse { + room_name: "red".to_string(), + tickers: vec![ + ("alice".to_string(), "hello world!".to_string()), + ("bob".to_string(), "hi alice :)".to_string()), + ], + })) + } + + #[test] + fn roundtrip_room_user_joined() { + roundtrip(ServerResponse::RoomUserJoinedResponse( + RoomUserJoinedResponse { + room_name: "red".to_string(), + user: User { + name: "alice".to_string(), + status: UserStatus::Online, + average_speed: 1000, + num_downloads: 1001, + unknown: 1002, + num_files: 1003, + num_folders: 1004, + num_free_slots: 1005, + country: "AR".to_string(), + }, + }, + )) + } + + #[test] + fn roundtrip_room_user_left() { + roundtrip(ServerResponse::RoomUserLeftResponse(RoomUserLeftResponse { + room_name: "red".to_string(), + user_name: "alice".to_string(), + })) + } + + #[test] + fn roundtrip_user_info() { + roundtrip(ServerResponse::UserInfoResponse(UserInfoResponse { + user_name: "alice".to_string(), + average_speed: 1000, + num_downloads: 1001, + num_files: 1002, + num_folders: 1003, + })) + } + + #[test] + fn roundtrip_user_status() { + roundtrip(ServerResponse::UserStatusResponse(UserStatusResponse { + user_name: "alice".to_string(), + status: UserStatus::Offline, + is_privileged: true, + })) + } + + #[test] + fn roundtrip_wishlist_interval() { + roundtrip(ServerResponse::WishlistIntervalResponse( + WishlistIntervalResponse { seconds: 1337 }, + )) + } } diff --git a/proto/src/server/testing.rs b/proto/src/server/testing.rs index 2dd967e..857a36d 100644 --- a/proto/src/server/testing.rs +++ b/proto/src/server/testing.rs @@ -8,8 +8,8 @@ use std::sync::Arc; use log::{debug, info, warn}; use parking_lot::Mutex; use tokio::net::{ - tcp::{OwnedReadHalf, OwnedWriteHalf}, - TcpListener, TcpStream, + tcp::{OwnedReadHalf, OwnedWriteHalf}, + TcpListener, TcpStream, }; use tokio::sync::mpsc; use tokio::sync::oneshot; @@ -17,381 +17,385 @@ use tokio::sync::watch; use crate::core::frame::{FrameReader, FrameWriter}; use crate::server::{ - LoginResponse, ServerRequest, ServerResponse, UserStatusRequest, UserStatusResponse, + LoginResponse, ServerRequest, ServerResponse, UserStatusRequest, + UserStatusResponse, }; #[derive(Debug, Default)] pub struct UserStatusMap { - map: HashMap, + map: HashMap, } // IDEA: impl FromIterator for UserStatusMap. impl UserStatusMap { - pub fn insert(&mut self, response: UserStatusResponse) { - self.map.insert(response.user_name.clone(), response); - } + pub fn insert(&mut self, response: UserStatusResponse) { + self.map.insert(response.user_name.clone(), response); + } - pub fn get(&self, user_name: &str) -> Option { - self.map.get(user_name).map(|response| response.clone()) - } + pub fn get(&self, user_name: &str) -> Option { + self.map.get(user_name).map(|response| response.clone()) + } } struct Handler { - reader: FrameReader, - writer: FrameWriter, - peer_address: SocketAddr, - user_status_map: Arc>, + reader: FrameReader, + writer: FrameWriter, + peer_address: SocketAddr, + user_status_map: Arc>, } impl Handler { - fn ipv4_address(&self) -> Ipv4Addr { - match self.peer_address.ip() { - IpAddr::V4(ipv4_addr) => ipv4_addr, - IpAddr::V6(_) => Ipv4Addr::UNSPECIFIED, - } - } - - async fn send_response(&mut self, response: &ServerResponse) -> io::Result<()> { - debug!("Handler: sending response: {:?}", response); - self.writer.write(response).await - } - - async fn handle_login(&mut self) -> io::Result<()> { - match self.reader.read().await? { - Some(ServerRequest::LoginRequest(request)) => { - info!("Handler: Received login request: {:?}", request); - } - Some(request) => { - return Err(io::Error::new( - io::ErrorKind::InvalidData, - format!("expected login request, got: {:?}", request), - )); - } - None => { - return Err(io::Error::new( - io::ErrorKind::UnexpectedEof, - "expected login request".to_string(), - )); - } - }; - - let response = ServerResponse::LoginResponse(LoginResponse::LoginOk { - motd: "hi there".to_string(), - ip: self.ipv4_address(), - password_md5_opt: None, - }); - self.send_response(&response).await + fn ipv4_address(&self) -> Ipv4Addr { + match self.peer_address.ip() { + IpAddr::V4(ipv4_addr) => ipv4_addr, + IpAddr::V6(_) => Ipv4Addr::UNSPECIFIED, } - - async fn handle_request(&mut self, request: ServerRequest) -> io::Result<()> { - debug!("Handler: received request: {:?}", request); - - match request { - ServerRequest::UserStatusRequest(UserStatusRequest { user_name }) => { - let entry = self.user_status_map.lock().get(&user_name); - if let Some(response) = entry { - let response = ServerResponse::UserStatusResponse(response); - self.send_response(&response).await?; - } - } - _ => { - warn!("Handler: unhandled request: {:?}", request); - } + } + + async fn send_response( + &mut self, + response: &ServerResponse, + ) -> io::Result<()> { + debug!("Handler: sending response: {:?}", response); + self.writer.write(response).await + } + + async fn handle_login(&mut self) -> io::Result<()> { + match self.reader.read().await? { + Some(ServerRequest::LoginRequest(request)) => { + info!("Handler: Received login request: {:?}", request); + } + Some(request) => { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + format!("expected login request, got: {:?}", request), + )); + } + None => { + return Err(io::Error::new( + io::ErrorKind::UnexpectedEof, + "expected login request".to_string(), + )); + } + }; + + let response = ServerResponse::LoginResponse(LoginResponse::LoginOk { + motd: "hi there".to_string(), + ip: self.ipv4_address(), + password_md5_opt: None, + }); + self.send_response(&response).await + } + + async fn handle_request(&mut self, request: ServerRequest) -> io::Result<()> { + debug!("Handler: received request: {:?}", request); + + match request { + ServerRequest::UserStatusRequest(UserStatusRequest { user_name }) => { + let entry = self.user_status_map.lock().get(&user_name); + if let Some(response) = entry { + let response = ServerResponse::UserStatusResponse(response); + self.send_response(&response).await?; } - - Ok(()) + } + _ => { + warn!("Handler: unhandled request: {:?}", request); + } } - async fn run(mut self) -> io::Result<()> { - self.handle_login().await?; + Ok(()) + } - while let Some(request) = self.reader.read().await? { - self.handle_request(request).await?; - } + async fn run(mut self) -> io::Result<()> { + self.handle_login().await?; - info!("Handler: client disconnecting, shutting down"); - Ok(()) + while let Some(request) = self.reader.read().await? { + self.handle_request(request).await?; } + + info!("Handler: client disconnecting, shutting down"); + Ok(()) + } } struct GracefulHandler { - handler: Handler, - shutdown_rx: watch::Receiver<()>, + handler: Handler, + shutdown_rx: watch::Receiver<()>, } impl GracefulHandler { - async fn run(mut self) -> io::Result<()> { - tokio::select!( - result = self.handler.run() => { - if let Err(ref error) = result { - warn!("GracefulHandler: handler returned error {:?}", error); - } - result - }, - // Ignore receive errors - if shutdown_rx's sender is dropped, we take - // that as a signal to shut down too. - _ = self.shutdown_rx.changed() => { - info!("GracefulHandler: shutting down."); - Ok(()) - }, - ) - } + async fn run(mut self) -> io::Result<()> { + tokio::select!( + result = self.handler.run() => { + if let Err(ref error) = result { + warn!("GracefulHandler: handler returned error {:?}", error); + } + result + }, + // Ignore receive errors - if shutdown_rx's sender is dropped, we take + // that as a signal to shut down too. + _ = self.shutdown_rx.changed() => { + info!("GracefulHandler: shutting down."); + Ok(()) + }, + ) + } } struct SenderHandler { - handler: GracefulHandler, - result_tx: mpsc::Sender>, + handler: GracefulHandler, + result_tx: mpsc::Sender>, } impl SenderHandler { - async fn run(self) { - let result = self.handler.run().await; - let _ = self.result_tx.send(result).await; - } + async fn run(self) { + let result = self.handler.run().await; + let _ = self.result_tx.send(result).await; + } } /// A builder for Server instances. #[derive(Default)] pub struct ServerBuilder { - user_status_map: Option>>, + user_status_map: Option>>, } impl ServerBuilder { - /// Sets the UserStatusMap which the server will use to respond to - /// UserStatusRequest messages. - pub fn with_user_status_map(mut self, map: UserStatusMap) -> Self { - self.user_status_map = Some(Arc::new(Mutex::new(map))); - self - } - - /// Binds to a localhost port, then returns a server and its handle. - pub async fn bind(self) -> io::Result<(Server, ServerHandle)> { - let listener = TcpListener::bind("localhost:0").await?; - let address = listener.local_addr()?; - - let user_status_map = match self.user_status_map { - Some(user_status_map) => user_status_map, - None => Arc::new(Mutex::new(UserStatusMap::default())), - }; - - let (shutdown_tx, shutdown_rx) = oneshot::channel(); - let (handler_shutdown_tx, handler_shutdown_rx) = watch::channel(()); - let (result_tx, result_rx) = mpsc::channel(1); - - Ok(( - Server { - listener, - shutdown_rx, - handler_shutdown_tx, - handler_shutdown_rx, - result_tx, - result_rx, - user_status_map, - }, - ServerHandle { - shutdown_tx, - address, - }, - )) - } + /// Sets the UserStatusMap which the server will use to respond to + /// UserStatusRequest messages. + pub fn with_user_status_map(mut self, map: UserStatusMap) -> Self { + self.user_status_map = Some(Arc::new(Mutex::new(map))); + self + } + + /// Binds to a localhost port, then returns a server and its handle. + pub async fn bind(self) -> io::Result<(Server, ServerHandle)> { + let listener = TcpListener::bind("localhost:0").await?; + let address = listener.local_addr()?; + + let user_status_map = match self.user_status_map { + Some(user_status_map) => user_status_map, + None => Arc::new(Mutex::new(UserStatusMap::default())), + }; + + let (shutdown_tx, shutdown_rx) = oneshot::channel(); + let (handler_shutdown_tx, handler_shutdown_rx) = watch::channel(()); + let (result_tx, result_rx) = mpsc::channel(1); + + Ok(( + Server { + listener, + shutdown_rx, + handler_shutdown_tx, + handler_shutdown_rx, + result_tx, + result_rx, + user_status_map, + }, + ServerHandle { + shutdown_tx, + address, + }, + )) + } } /// Specifies how to shut down a server. pub enum ShutdownType { - /// Shut down immediately, sever open connections. - Immediate, + /// Shut down immediately, sever open connections. + Immediate, - /// Stop accepting new connections, wait for open connections to close. - LameDuck, + /// Stop accepting new connections, wait for open connections to close. + LameDuck, } /// A simple server for connecting to in tests. pub struct Server { - // Listener for new connections. - listener: TcpListener, + // Listener for new connections. + listener: TcpListener, - // Receiver for ServerHandle shutdown() notification. - shutdown_rx: oneshot::Receiver, + // Receiver for ServerHandle shutdown() notification. + shutdown_rx: oneshot::Receiver, - // Watch channel for signalling immediate termination to handlers. - handler_shutdown_tx: watch::Sender<()>, - handler_shutdown_rx: watch::Receiver<()>, + // Watch channel for signalling immediate termination to handlers. + handler_shutdown_tx: watch::Sender<()>, + handler_shutdown_rx: watch::Receiver<()>, - // Channel for receiving results back from handlers. - result_tx: mpsc::Sender>, - result_rx: mpsc::Receiver>, + // Channel for receiving results back from handlers. + result_tx: mpsc::Sender>, + result_rx: mpsc::Receiver>, - // Shared state for handlers to use when serving responses. - user_status_map: Arc>, + // Shared state for handlers to use when serving responses. + user_status_map: Arc>, } /// Allows interacting with a running `Server`. pub struct ServerHandle { - shutdown_tx: oneshot::Sender, - address: SocketAddr, + shutdown_tx: oneshot::Sender, + address: SocketAddr, } impl ServerHandle { - /// Returns the address on which the server is accepting connections. - pub fn address(&self) -> SocketAddr { - self.address - } - - /// Starts shutting down the server. - /// Does nothing if the server is already shutting down or even dropped. - pub fn shutdown(self, how: ShutdownType) { - // Ignore send errors, which mean that the server has been dropped. - let _ = self.shutdown_tx.send(how); - } + /// Returns the address on which the server is accepting connections. + pub fn address(&self) -> SocketAddr { + self.address + } + + /// Starts shutting down the server. + /// Does nothing if the server is already shutting down or even dropped. + pub fn shutdown(self, how: ShutdownType) { + // Ignore send errors, which mean that the server has been dropped. + let _ = self.shutdown_tx.send(how); + } } impl Server { - /// Returns the address to which this server is bound. - /// This is always localhost and a random port chosen by the OS. - pub fn address(&self) -> io::Result { - self.listener.local_addr() - } - - /// Spawns a handler for the given new stream, initiated by a remote peer. - fn spawn_handler(&mut self, stream: TcpStream, peer_address: SocketAddr) { - let (read_half, write_half) = stream.into_split(); - - let handler = SenderHandler { - handler: GracefulHandler { - handler: Handler { - reader: FrameReader::new(read_half), - writer: FrameWriter::new(write_half), - peer_address, - user_status_map: self.user_status_map.clone(), - }, - shutdown_rx: self.handler_shutdown_rx.clone(), - }, - result_tx: self.result_tx.clone(), - }; - - tokio::spawn(handler.run()); + /// Returns the address to which this server is bound. + /// This is always localhost and a random port chosen by the OS. + pub fn address(&self) -> io::Result { + self.listener.local_addr() + } + + /// Spawns a handler for the given new stream, initiated by a remote peer. + fn spawn_handler(&mut self, stream: TcpStream, peer_address: SocketAddr) { + let (read_half, write_half) = stream.into_split(); + + let handler = SenderHandler { + handler: GracefulHandler { + handler: Handler { + reader: FrameReader::new(read_half), + writer: FrameWriter::new(write_half), + peer_address, + user_status_map: self.user_status_map.clone(), + }, + shutdown_rx: self.handler_shutdown_rx.clone(), + }, + result_tx: self.result_tx.clone(), + }; + + tokio::spawn(handler.run()); + } + + /// Accepts a single connection, spawns a handler for it and returns. + /// + /// Useful for tests who need to guarantee a handler is spawned before the + /// server shuts down. + async fn accept(&mut self) -> io::Result<()> { + let (stream, peer_address) = self.listener.accept().await?; + self.spawn_handler(stream, peer_address); + Ok(()) + } + + /// Runs the server: accepts incoming connections and responds to requests. + /// + /// Returns an error if: + /// + /// - an error was encountered while listening + /// - an error was encountered while serving a request + /// + pub async fn serve(mut self) -> io::Result<()> { + loop { + tokio::select!( + result = self.listener.accept() => { + let (stream, peer_address) = result?; + self.spawn_handler(stream, peer_address); + }, + result = &mut self.shutdown_rx => { + // If shutdown_rx's sender is dropped and we receive an error, we take + // that as a signal to shut down immediately too. + match result.unwrap_or(ShutdownType::Immediate) { + ShutdownType::LameDuck => break, + ShutdownType::Immediate => { + // Send errors cannot happen, since we hold onto a receiver in + // `self.handler_shutdown_rx`. + self.handler_shutdown_tx.send(()).unwrap(); + break + } + } + }, + optional_result = self.result_rx.recv() => { + // We can never exhaust the result channel because we hold onto a + // sender in `self.result_tx`. + let result = optional_result.unwrap(); + + // Return an error if a handler returns an error. + result?; + } + ); } - /// Accepts a single connection, spawns a handler for it and returns. - /// - /// Useful for tests who need to guarantee a handler is spawned before the - /// server shuts down. - async fn accept(&mut self) -> io::Result<()> { - let (stream, peer_address) = self.listener.accept().await?; - self.spawn_handler(stream, peer_address); - Ok(()) + info!("Server: shutting down"); + drop(self.result_tx); + while let Some(result) = self.result_rx.recv().await { + result?; } - /// Runs the server: accepts incoming connections and responds to requests. - /// - /// Returns an error if: - /// - /// - an error was encountered while listening - /// - an error was encountered while serving a request - /// - pub async fn serve(mut self) -> io::Result<()> { - loop { - tokio::select!( - result = self.listener.accept() => { - let (stream, peer_address) = result?; - self.spawn_handler(stream, peer_address); - }, - result = &mut self.shutdown_rx => { - // If shutdown_rx's sender is dropped and we receive an error, we take - // that as a signal to shut down immediately too. - match result.unwrap_or(ShutdownType::Immediate) { - ShutdownType::LameDuck => break, - ShutdownType::Immediate => { - // Send errors cannot happen, since we hold onto a receiver in - // `self.handler_shutdown_rx`. - self.handler_shutdown_tx.send(()).unwrap(); - break - } - } - }, - optional_result = self.result_rx.recv() => { - // We can never exhaust the result channel because we hold onto a - // sender in `self.result_tx`. - let result = optional_result.unwrap(); - - // Return an error if a handler returns an error. - result?; - } - ); - } - - info!("Server: shutting down"); - drop(self.result_tx); - while let Some(result) = self.result_rx.recv().await { - result?; - } - - Ok(()) - } + Ok(()) + } } #[cfg(test)] mod tests { - use std::io; + use std::io; - use tokio::net::TcpStream; + use tokio::net::TcpStream; - use super::{ServerBuilder, ShutdownType}; + use super::{ServerBuilder, ShutdownType}; - // Enable capturing logs in tests. - fn init() { - let _ = env_logger::builder().is_test(true).try_init(); - } + // Enable capturing logs in tests. + fn init() { + let _ = env_logger::builder().is_test(true).try_init(); + } - #[tokio::test] - async fn new_binds_to_localhost() { - init(); + #[tokio::test] + async fn new_binds_to_localhost() { + init(); - let (server, handle) = ServerBuilder::default().bind().await.unwrap(); - assert!(server.address().unwrap().ip().is_loopback()); - assert_eq!(server.address().unwrap(), handle.address()); - } + let (server, handle) = ServerBuilder::default().bind().await.unwrap(); + assert!(server.address().unwrap().ip().is_loopback()); + assert_eq!(server.address().unwrap(), handle.address()); + } - #[tokio::test] - async fn accepts_incoming_connections() { - init(); + #[tokio::test] + async fn accepts_incoming_connections() { + init(); - let (server, handle) = ServerBuilder::default().bind().await.unwrap(); - let server_task = tokio::spawn(server.serve()); + let (server, handle) = ServerBuilder::default().bind().await.unwrap(); + let server_task = tokio::spawn(server.serve()); - // The connection succeeds. - let _ = TcpStream::connect(handle.address()).await.unwrap(); + // The connection succeeds. + let _ = TcpStream::connect(handle.address()).await.unwrap(); - handle.shutdown(ShutdownType::Immediate); + handle.shutdown(ShutdownType::Immediate); - // Ignore errors, which can happen when the handler task is spawned right - // before we call `handle.shutdown()`. See `serve_yields_handler_error`. - let _ = server_task.await.unwrap(); - } + // Ignore errors, which can happen when the handler task is spawned right + // before we call `handle.shutdown()`. See `serve_yields_handler_error`. + let _ = server_task.await.unwrap(); + } - // This test verifies that when a handler encounters an error, it is - // reflected in `Server::serve()`'s return value. - #[tokio::test] - async fn serve_yields_handler_error() { - init(); + // This test verifies that when a handler encounters an error, it is + // reflected in `Server::serve()`'s return value. + #[tokio::test] + async fn serve_yields_handler_error() { + init(); - let (mut server, handle) = ServerBuilder::default().bind().await.unwrap(); + let (mut server, handle) = ServerBuilder::default().bind().await.unwrap(); - // The connection is accepted, then immediately closed. - let address = handle.address(); - tokio::spawn(async move { - let _ = TcpStream::connect(address).await.unwrap(); - }); + // The connection is accepted, then immediately closed. + let address = handle.address(); + tokio::spawn(async move { + let _ = TcpStream::connect(address).await.unwrap(); + }); - // Accept the connection on the server and spawn a handler for it. - server.accept().await.unwrap(); + // Accept the connection on the server and spawn a handler for it. + server.accept().await.unwrap(); - // Signal that the server should stop accepting incoming connections. - handle.shutdown(ShutdownType::LameDuck); + // Signal that the server should stop accepting incoming connections. + handle.shutdown(ShutdownType::LameDuck); - // Drain outstanding requests, encountering the error. - let error = server.serve().await.unwrap_err(); - assert_eq!(error.kind(), io::ErrorKind::UnexpectedEof); - } + // Drain outstanding requests, encountering the error. + let error = server.serve().await.unwrap_err(); + assert_eq!(error.kind(), io::ErrorKind::UnexpectedEof); + } } diff --git a/proto/src/server/version.rs b/proto/src/server/version.rs index e0da3c2..2c28a47 100644 --- a/proto/src/server/version.rs +++ b/proto/src/server/version.rs @@ -3,18 +3,18 @@ /// Specifies a protocol version. #[derive(Clone, Copy, Debug)] pub struct Version { - /// The major version number. - pub major: u32, + /// The major version number. + pub major: u32, - /// The minor version number. - pub minor: u32, + /// The minor version number. + pub minor: u32, } impl Default for Version { - fn default() -> Self { - Self { - major: 181, - minor: 100, - } + fn default() -> Self { + Self { + major: 181, + minor: 100, } + } } diff --git a/proto/src/stream.rs b/proto/src/stream.rs index af91dde..11835b5 100644 --- a/proto/src/stream.rs +++ b/proto/src/stream.rs @@ -16,41 +16,41 @@ use super::packet::{MutPacket, Parser, ReadFromPacket, WriteToPacket}; /// A struct used for writing bytes to a TryWrite sink. #[derive(Debug)] struct OutBuf { - cursor: usize, - bytes: Vec, + cursor: usize, + bytes: Vec, } impl From> for OutBuf { - fn from(bytes: Vec) -> Self { - OutBuf { - cursor: 0, - bytes: bytes, - } + fn from(bytes: Vec) -> Self { + OutBuf { + cursor: 0, + bytes: bytes, } + } } impl OutBuf { - #[inline] - fn remaining(&self) -> usize { - self.bytes.len() - self.cursor - } - - #[inline] - fn has_remaining(&self) -> bool { - self.remaining() > 0 - } - - #[allow(deprecated)] - fn try_write_to(&mut self, mut writer: T) -> io::Result> - where - T: mio::deprecated::TryWrite, - { - let result = writer.try_write(&self.bytes[self.cursor..]); - if let Ok(Some(bytes_written)) = result { - self.cursor += bytes_written; - } - result + #[inline] + fn remaining(&self) -> usize { + self.bytes.len() - self.cursor + } + + #[inline] + fn has_remaining(&self) -> bool { + self.remaining() > 0 + } + + #[allow(deprecated)] + fn try_write_to(&mut self, mut writer: T) -> io::Result> + where + T: mio::deprecated::TryWrite, + { + let result = writer.try_write(&self.bytes[self.cursor..]); + if let Ok(Some(bytes_written)) = result { + self.cursor += bytes_written; } + result + } } /*========* @@ -60,170 +60,171 @@ impl OutBuf { /// This trait is implemented by packet sinks to which a stream can forward /// the packets it reads. pub trait SendPacket { - type Value: ReadFromPacket; - type Error: error::Error; + type Value: ReadFromPacket; + type Error: error::Error; - fn send_packet(&mut self, _: Self::Value) -> Result<(), Self::Error>; + fn send_packet(&mut self, _: Self::Value) -> Result<(), Self::Error>; - fn notify_open(&mut self) -> Result<(), Self::Error>; + fn notify_open(&mut self) -> Result<(), Self::Error>; } /// This enum defines the possible actions the stream wants to take after /// processing an event. #[derive(Debug, Clone, Copy)] pub enum Intent { - /// The stream is done, the event loop handler can drop it. - Done, - /// The stream wants to wait for the next event matching the given - /// `EventSet`. - Continue(mio::Ready), + /// The stream is done, the event loop handler can drop it. + Done, + /// The stream wants to wait for the next event matching the given + /// `EventSet`. + Continue(mio::Ready), } /// This struct wraps around an mio tcp stream and handles packet reads and /// writes. #[derive(Debug)] pub struct Stream { - parser: Parser, - queue: VecDeque, - sender: T, - stream: mio::tcp::TcpStream, + parser: Parser, + queue: VecDeque, + sender: T, + stream: mio::tcp::TcpStream, - is_connected: bool, + is_connected: bool, } impl Stream { - /// Returns a new stream, asynchronously connected to the given address, - /// which forwards incoming packets to the given sender. - /// If an error occurs when connecting, returns an error. - pub fn new(addr_spec: U, sender: T) -> io::Result - where - U: ToSocketAddrs + fmt::Debug, - { - for sock_addr in addr_spec.to_socket_addrs()? { - if let Ok(stream) = mio::tcp::TcpStream::connect(&sock_addr) { - return Ok(Stream { - parser: Parser::new(), - queue: VecDeque::new(), - sender: sender, - stream: stream, - - is_connected: false, - }); - } - } - Err(io::Error::new( - io::ErrorKind::Other, - format!("Cannot connect to {:?}", addr_spec), - )) + /// Returns a new stream, asynchronously connected to the given address, + /// which forwards incoming packets to the given sender. + /// If an error occurs when connecting, returns an error. + pub fn new(addr_spec: U, sender: T) -> io::Result + where + U: ToSocketAddrs + fmt::Debug, + { + for sock_addr in addr_spec.to_socket_addrs()? { + if let Ok(stream) = mio::tcp::TcpStream::connect(&sock_addr) { + return Ok(Stream { + parser: Parser::new(), + queue: VecDeque::new(), + sender: sender, + stream: stream, + + is_connected: false, + }); + } } - - /// Returns a reference to the underlying byte stream, to allow it to be - /// registered with an event loop. - pub fn evented(&self) -> &mio::tcp::TcpStream { - &self.stream + Err(io::Error::new( + io::ErrorKind::Other, + format!("Cannot connect to {:?}", addr_spec), + )) + } + + /// Returns a reference to the underlying byte stream, to allow it to be + /// registered with an event loop. + pub fn evented(&self) -> &mio::tcp::TcpStream { + &self.stream + } + + /// The stream is ready to be read from. + fn on_readable(&mut self) -> Result<(), String> { + loop { + let mut packet = match self.parser.try_read(&mut self.stream) { + Ok(Some(packet)) => packet, + Ok(None) => break, + Err(e) => return Err(format!("Error reading stream: {}", e)), + }; + let value = match packet.read_value() { + Ok(value) => value, + Err(e) => return Err(format!("Error parsing packet: {}", e)), + }; + if let Err(e) = self.sender.send_packet(value) { + return Err(format!("Error sending parsed packet: {}", e)); + } } - - /// The stream is ready to be read from. - fn on_readable(&mut self) -> Result<(), String> { - loop { - let mut packet = match self.parser.try_read(&mut self.stream) { - Ok(Some(packet)) => packet, - Ok(None) => break, - Err(e) => return Err(format!("Error reading stream: {}", e)), - }; - let value = match packet.read_value() { - Ok(value) => value, - Err(e) => return Err(format!("Error parsing packet: {}", e)), - }; - if let Err(e) = self.sender.send_packet(value) { - return Err(format!("Error sending parsed packet: {}", e)); - } + Ok(()) + } + + /// The stream is ready to be written to. + fn on_writable(&mut self) -> io::Result<()> { + loop { + let mut outbuf = match self.queue.pop_front() { + Some(outbuf) => outbuf, + None => break, + }; + + let option = outbuf.try_write_to(&mut self.stream)?; + match option { + Some(_) => { + if outbuf.has_remaining() { + self.queue.push_front(outbuf) + } + // Continue looping } - Ok(()) - } - - /// The stream is ready to be written to. - fn on_writable(&mut self) -> io::Result<()> { - loop { - let mut outbuf = match self.queue.pop_front() { - Some(outbuf) => outbuf, - None => break, - }; - - let option = outbuf.try_write_to(&mut self.stream)?; - match option { - Some(_) => { - if outbuf.has_remaining() { - self.queue.push_front(outbuf) - } - // Continue looping - } - None => { - self.queue.push_front(outbuf); - break; - } - } + None => { + self.queue.push_front(outbuf); + break; } - Ok(()) + } } + Ok(()) + } - /// The stream is ready to read, write, or both. - pub fn on_ready(&mut self, event_set: mio::Ready) -> Intent { - #[allow(deprecated)] - if event_set.is_hup() || event_set.is_error() { - return Intent::Done; - } - if event_set.is_readable() { - let result = self.on_readable(); - if let Err(e) = result { - error!("Stream input error: {}", e); - return Intent::Done; - } - } - if event_set.is_writable() { - let result = self.on_writable(); - if let Err(e) = result { - error!("Stream output error: {}", e); - return Intent::Done; - } - } - - // We must have read or written something succesfully if we're here, - // so the stream must be connected. - if !self.is_connected { - // If we weren't already connected, notify the sink. - if let Err(err) = self.sender.notify_open() { - error!("Cannot notify client that stream is open: {}", err); - return Intent::Done; - } - // And record the fact that we are now connected. - self.is_connected = true; - } + /// The stream is ready to read, write, or both. + pub fn on_ready(&mut self, event_set: mio::Ready) -> Intent { + #[allow(deprecated)] + if event_set.is_hup() || event_set.is_error() { + return Intent::Done; + } + if event_set.is_readable() { + let result = self.on_readable(); + if let Err(e) = result { + error!("Stream input error: {}", e); + return Intent::Done; + } + } + if event_set.is_writable() { + let result = self.on_writable(); + if let Err(e) = result { + error!("Stream output error: {}", e); + return Intent::Done; + } + } - // We're always interested in reading more. - #[allow(deprecated)] - let mut event_set = mio::Ready::readable() | mio::Ready::hup() | mio::Ready::error(); - // If there is still stuff to write in the queue, we're interested in - // the socket becoming writable too. - if self.queue.len() > 0 { - event_set = event_set | mio::Ready::writable(); - } + // We must have read or written something succesfully if we're here, + // so the stream must be connected. + if !self.is_connected { + // If we weren't already connected, notify the sink. + if let Err(err) = self.sender.notify_open() { + error!("Cannot notify client that stream is open: {}", err); + return Intent::Done; + } + // And record the fact that we are now connected. + self.is_connected = true; + } - Intent::Continue(event_set) + // We're always interested in reading more. + #[allow(deprecated)] + let mut event_set = + mio::Ready::readable() | mio::Ready::hup() | mio::Ready::error(); + // If there is still stuff to write in the queue, we're interested in + // the socket becoming writable too. + if self.queue.len() > 0 { + event_set = event_set | mio::Ready::writable(); } - /// The stream has been notified. - pub fn on_notify(&mut self, payload: &V) -> Intent - where - V: WriteToPacket, - { - let mut packet = MutPacket::new(); - let result = packet.write_value(payload); - if let Err(e) = result { - error!("Error writing payload to packet: {}", e); - return Intent::Done; - } - self.queue.push_back(OutBuf::from(packet.into_bytes())); - Intent::Continue(mio::Ready::readable() | mio::Ready::writable()) + Intent::Continue(event_set) + } + + /// The stream has been notified. + pub fn on_notify(&mut self, payload: &V) -> Intent + where + V: WriteToPacket, + { + let mut packet = MutPacket::new(); + let result = packet.write_value(payload); + if let Err(e) = result { + error!("Error writing payload to packet: {}", e); + return Intent::Done; } + self.queue.push_back(OutBuf::from(packet.into_bytes())); + Intent::Continue(mio::Ready::readable() | mio::Ready::writable()) + } } diff --git a/proto/tests/connect.rs b/proto/tests/connect.rs index e750045..510d070 100644 --- a/proto/tests/connect.rs +++ b/proto/tests/connect.rs @@ -3,79 +3,81 @@ use tokio::io; use tokio::net; use tokio::sync::mpsc; -use solstice_proto::server::{Client, Credentials, ServerResponse, UserStatusRequest}; +use solstice_proto::server::{ + Client, Credentials, ServerResponse, UserStatusRequest, +}; // Enable capturing logs in tests. fn init() { - let _ = env_logger::builder().is_test(true).try_init(); + let _ = env_logger::builder().is_test(true).try_init(); } async fn connect() -> io::Result { - net::TcpStream::connect("server.slsknet.org:2242").await + net::TcpStream::connect("server.slsknet.org:2242").await } fn make_user_name(test_name: &str) -> String { - format!("st_{}", test_name) + format!("st_{}", test_name) } fn make_credentials(user_name: String) -> Credentials { - let password = "abcdefgh".to_string(); - Credentials::new(user_name, password).unwrap() + let password = "abcdefgh".to_string(); + Credentials::new(user_name, password).unwrap() } #[tokio::test] async fn integration_connect() { - init(); + init(); - let stream = connect().await.unwrap(); + let stream = connect().await.unwrap(); - let credentials = make_credentials(make_user_name("connect")); - let channel = Client::new(stream).login(credentials).await.unwrap(); + let credentials = make_credentials(make_user_name("connect")); + let channel = Client::new(stream).login(credentials).await.unwrap(); - let inbound = channel.run(stream::pending()); - tokio::pin!(inbound); + let inbound = channel.run(stream::pending()); + tokio::pin!(inbound); - assert!(inbound.next().await.is_some()); + assert!(inbound.next().await.is_some()); } #[tokio::test] async fn integration_check_user_status() { - init(); + init(); - let stream = connect().await.unwrap(); + let stream = connect().await.unwrap(); - let user_name = make_user_name("check_user_status"); - let credentials = make_credentials(user_name.clone()); - let channel = Client::new(stream).login(credentials).await.unwrap(); + let user_name = make_user_name("check_user_status"); + let credentials = make_credentials(user_name.clone()); + let channel = Client::new(stream).login(credentials).await.unwrap(); - let (request_tx, mut request_rx) = mpsc::channel(1); + let (request_tx, mut request_rx) = mpsc::channel(1); - let outbound = async_stream::stream! { - while let Some(request) = request_rx.recv().await { - yield request; + let outbound = async_stream::stream! { + while let Some(request) = request_rx.recv().await { + yield request; + } + }; + + let inbound = channel.run(outbound); + tokio::pin!(inbound); + + request_tx + .send( + UserStatusRequest { + user_name: user_name.clone(), } - }; - - let inbound = channel.run(outbound); - tokio::pin!(inbound); - - request_tx - .send( - UserStatusRequest { - user_name: user_name.clone(), - } - .into(), - ) - .await - .unwrap(); - - while let Some(result) = inbound.next().await { - let response = result.unwrap(); - if let ServerResponse::UserStatusResponse(response) = response { - assert_eq!(response.user_name, user_name); - return; - } + .into(), + ) + .await + .unwrap(); + + while let Some(result) = inbound.next().await { + let response = result.unwrap(); + if let ServerResponse::UserStatusResponse(response) = response { + assert_eq!(response.user_name, user_name); + return; } + } - unreachable!(); + unreachable!(); } diff --git a/client/rustfmt.toml b/rustfmt.toml similarity index 100% rename from client/rustfmt.toml rename to rustfmt.toml