From d3e6ebc20b26a1863f1443884413b72e3605ec3d Mon Sep 17 00:00:00 2001 From: Joey Sacchini Date: Thu, 3 Dec 2020 15:55:08 -0500 Subject: updates based on testing with async libs --- Cargo.lock | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 6 +- src/connection.rs | 31 +++++---- src/reader.rs | 71 ++++++++++++++++--- src/tcp.rs | 33 +++++++-- src/writer.rs | 46 ++++++++++--- 6 files changed, 344 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f2a02f5..c87396c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,6 +60,18 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "bytes" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" + [[package]] name = "cc" version = "1.0.65" @@ -97,6 +109,7 @@ dependencies = [ "futures", "mcproto-rs", "thiserror", + "tokio", ] [[package]] @@ -121,6 +134,22 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + [[package]] name = "futures" version = "0.3.8" @@ -237,12 +266,46 @@ dependencies = [ "wasi", ] +[[package]] +name = "hermit-abi" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" +dependencies = [ + "libc", +] + +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + [[package]] name = "itoa" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.80" @@ -260,6 +323,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "log" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" +dependencies = [ + "cfg-if 0.1.10", +] + [[package]] name = "mcproto-rs" version = "0.2.0" @@ -287,6 +359,58 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow", + "net2", + "slab", + "winapi 0.2.8", +] + +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + +[[package]] +name = "net2" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7cf75f38f16cb05ea017784dc6dbfd354f76c223dba37701734c4f5a9337d02" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "once_cell" version = "1.5.2" @@ -319,6 +443,12 @@ dependencies = [ "syn", ] +[[package]] +name = "pin-project-lite" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b" + [[package]] name = "pin-utils" version = "0.1.0" @@ -482,6 +612,34 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6d7ad61edd59bfcc7e80dababf0f4aed2e6d5e0ba1659356ae889752dfc12ff" +dependencies = [ + "bytes", + "iovec", + "lazy_static", + "memchr", + "mio", + "num_cpus", + "pin-project-lite", + "slab", + "tokio-macros", +] + +[[package]] +name = "tokio-macros" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "typenum" version = "1.12.0" @@ -511,3 +669,47 @@ name = "wasi" version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] diff --git a/Cargo.toml b/Cargo.toml index 6124744..e94367f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,8 +14,10 @@ thiserror = "1.0" futures = { version = "0.3.8", optional = true } async-trait = { version = "0.1.42", optional = true } +tokio = { version = "0.2", features = ["rt-threaded", "tcp", "io-util", "macros", "dns"], optional = true } [features] -default = ["async"] +default = [] -async = ["futures", "async-trait"] \ No newline at end of file +futures-io = ["futures", "async-trait"] +tokio-io = ["tokio", "async-trait"] \ No newline at end of file diff --git a/src/connection.rs b/src/connection.rs index af6f4a9..4da97bb 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,11 +1,14 @@ use crate::cfb8::CipherError; -use crate::reader::{CraftAsyncReader, CraftReader, CraftSyncReader, ReadResult}; +use crate::reader::{CraftReader, CraftSyncReader, ReadResult}; use crate::wrapper::{CraftIo, CraftWrapper}; -use crate::writer::{CraftAsyncWriter, CraftSyncWriter, CraftWriter, WriteResult}; +use crate::writer::{CraftSyncWriter, CraftWriter, WriteResult}; use mcproto_rs::protocol::{Packet, RawPacket, State}; -#[cfg(feature = "async")] -use async_trait::async_trait; +#[cfg(any(feature = "futures-io", feature = "tokio-io"))] +use { + crate::{reader::CraftAsyncReader, writer::CraftAsyncWriter}, + async_trait::async_trait +}; pub struct CraftConnection { pub(crate) reader: CraftReader, @@ -76,7 +79,7 @@ where } } -#[cfg(feature = "async")] +#[cfg(any(feature = "futures-io", feature = "tokio-io"))] #[async_trait] impl CraftAsyncReader for CraftConnection where @@ -85,22 +88,22 @@ where CraftWriter: CraftAsyncWriter, W: Send + Sync, { - async fn read_packet<'a, P>(&'a mut self) -> ReadResult<

>::Packet> + async fn read_packet_async<'a, P>(&'a mut self) -> ReadResult<

>::Packet> where P: RawPacket<'a>, { - self.reader.read_packet::

().await + self.reader.read_packet_async::

().await } - async fn read_raw_packet<'a, P>(&'a mut self) -> ReadResult

+ async fn read_raw_packet_async<'a, P>(&'a mut self) -> ReadResult

where P: RawPacket<'a>, { - self.reader.read_raw_packet::

().await + self.reader.read_raw_packet_async::

().await } } -#[cfg(feature = "async")] +#[cfg(any(feature = "futures-io", feature = "tokio-io"))] #[async_trait] impl CraftAsyncWriter for CraftConnection where @@ -109,17 +112,17 @@ where CraftWriter: CraftAsyncWriter, W: Send + Sync, { - async fn write_packet

(&mut self, packet: P) -> WriteResult<()> + async fn write_packet_async

(&mut self, packet: P) -> WriteResult<()> where P: Packet + Send + Sync, { - self.writer.write_packet(packet).await + self.writer.write_packet_async(packet).await } - async fn write_raw_packet<'a, P>(&mut self, packet: P) -> WriteResult<()> + async fn write_raw_packet_async<'a, P>(&mut self, packet: P) -> WriteResult<()> where P: RawPacket<'a> + Send + Sync, { - self.writer.write_raw_packet(packet).await + self.writer.write_raw_packet_async(packet).await } } diff --git a/src/reader.rs b/src/reader.rs index dd27440..5b302aa 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -9,8 +9,8 @@ use std::backtrace::Backtrace; use std::io; use thiserror::Error; -#[cfg(feature = "async")] -use {async_trait::async_trait, futures::AsyncReadExt}; +#[cfg(any(feature = "futures-io", feature = "tokio-io"))] +use async_trait::async_trait; #[derive(Debug, Error)] pub enum ReadError { @@ -50,17 +50,17 @@ pub enum DecompressErr { pub type ReadResult

= Result, ReadError>; -#[cfg(feature = "async")] +#[cfg(any(feature = "futures-io", feature = "tokio-io"))] #[async_trait] pub trait CraftAsyncReader { - async fn read_packet<'a, P>(&'a mut self) -> ReadResult<

>::Packet> + async fn read_packet_async<'a, P>(&'a mut self) -> ReadResult<

>::Packet> where P: RawPacket<'a>, { - deserialize_raw_packet(self.read_raw_packet::

().await) + deserialize_raw_packet(self.read_raw_packet_async::

().await) } - async fn read_raw_packet<'a, P>(&'a mut self) -> ReadResult

+ async fn read_raw_packet_async<'a, P>(&'a mut self) -> ReadResult

where P: RawPacket<'a>; } @@ -147,13 +147,13 @@ where } } -#[cfg(feature = "async")] +#[cfg(any(feature = "futures-io", feature = "tokio-io"))] #[async_trait] impl CraftAsyncReader for CraftReader where - R: futures::AsyncRead + Unpin + Sync + Send, + R: AsyncReadExact, { - async fn read_raw_packet<'a, P>(&'a mut self) -> ReadResult

+ async fn read_raw_packet_async<'a, P>(&'a mut self) -> ReadResult

where P: RawPacket<'a>, { @@ -190,10 +190,10 @@ where } } -#[cfg(feature = "async")] +#[cfg(any(feature = "futures-io", feature = "tokio-io"))] impl CraftReader where - R: futures::io::AsyncRead + Unpin + Sync + Send, + R: AsyncReadExact, { async fn read_packet_len_async(&mut self) -> ReadResult { self.move_ready_data_to_front(); @@ -218,6 +218,55 @@ where } } +#[cfg(any(feature = "futures-io", feature = "tokio-io"))] +pub trait IntoBufferedAsyncRead { + + type Target: AsyncReadExact; + + fn into_buffered(self, capacity: usize) -> Self::Target; +} + +#[cfg(all(feature = "futures-io", not(feature = "tokio-io")))] +impl IntoBufferedAsyncRead for R where R: futures::io::AsyncRead + Send + Sync + Unpin { + type Target = futures::io::BufReader; + + fn into_buffered(self, capacity: usize) -> Self::Target { + futures::io::BufReader::with_capacity(capacity, self) + } +} + +#[cfg(feature = "tokio-io")] +impl IntoBufferedAsyncRead for R where R: tokio::io::AsyncRead + Send + Sync + Unpin { + type Target = tokio::io::BufReader; + + fn into_buffered(self, capacity: usize) -> Self::Target { + tokio::io::BufReader::with_capacity(capacity, self) + } +} + +#[cfg(any(feature = "futures-io", feature = "tokio-io"))] +#[async_trait] +pub trait AsyncReadExact: Unpin + Sync + Send { + async fn read_exact(&mut self, to: &mut [u8]) -> Result<(), io::Error>; +} + +#[cfg(all(feature = "futures-io", not(feature = "tokio-io")))] +#[async_trait] +impl AsyncReadExact for R where R: futures::AsyncReadExt + Unpin + Sync + Send { + async fn read_exact(&mut self, to: &mut [u8]) -> Result<(), io::Error> { + futures::AsyncReadExt::read_exact(self, to).await + } +} + +#[cfg(feature = "tokio-io")] +#[async_trait] +impl AsyncReadExact for R where R: tokio::io::AsyncRead + Unpin + Sync + Send { + async fn read_exact(&mut self, to: &mut [u8]) -> Result<(), io::Error> { + tokio::io::AsyncReadExt::read_exact(self, to).await?; + Ok(()) + } +} + macro_rules! dsz_unwrap { ($bnam: expr, $k: ty) => { match <$k>::mc_deserialize($bnam) { diff --git a/src/tcp.rs b/src/tcp.rs index 49490b7..37a94c5 100644 --- a/src/tcp.rs +++ b/src/tcp.rs @@ -5,8 +5,8 @@ use mcproto_rs::protocol::{PacketDirection, State}; use std::io::BufReader as StdBufReader; use std::net::TcpStream; -#[cfg(feature = "async")] -use futures::io::{AsyncRead, AsyncWrite, BufReader as AsyncBufReader}; +#[cfg(any(feature = "futures-io", feature = "tokio-io"))] +use crate::{CraftAsyncWriter, CraftAsyncReader, IntoBufferedAsyncRead}; pub const BUF_SIZE: usize = 8192; @@ -43,12 +43,32 @@ impl CraftConnection, TcpStream> { } } -#[cfg(feature = "async")] -impl CraftConnection, W> +#[cfg(any(feature = "futures-io", feature = "tokio-io"))] +impl CraftConnection where - R: AsyncRead + Send + Sync + Unpin, - W: AsyncWrite + Send + Sync + Unpin, + CraftReader: CraftAsyncReader, + CraftWriter: CraftAsyncWriter, { + pub fn from_unbuffered_async(tuple: (U, W), read_direction: PacketDirection) -> Self + where + U: IntoBufferedAsyncRead, + { + Self::from_unbuffered_async_with_state(tuple, read_direction, State::Handshaking) + } + + pub fn from_unbuffered_async_with_state( + tuple: (U, W), + read_direction: PacketDirection, + state: State, + ) -> Self + where + U: IntoBufferedAsyncRead, + { + let (ru, writer) = tuple; + let reader = ru.into_buffered(BUF_SIZE); + Self::from_async_with_state((reader, writer), read_direction, state) + } + pub fn from_async(tuple: (R, W), read_direction: PacketDirection) -> Self { Self::from_async_with_state(tuple, read_direction, State::Handshaking) } @@ -59,7 +79,6 @@ where state: State, ) -> Self { let (reader, writer) = tuple; - let reader = AsyncBufReader::with_capacity(BUF_SIZE, reader); Self { reader: CraftReader::wrap_with_state(reader, read_direction, state), writer: CraftWriter::wrap_with_state(writer, read_direction.opposite(), state), diff --git a/src/writer.rs b/src/writer.rs index d4e6027..e1f71c3 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -9,8 +9,8 @@ use std::backtrace::Backtrace; use std::ops::{Deref, DerefMut}; use thiserror::Error; -#[cfg(feature = "async")] -use {async_trait::async_trait, futures::AsyncWriteExt}; +#[cfg(any(feature = "futures-io", feature = "tokio-io"))] +use async_trait::async_trait; #[derive(Debug, Error)] pub enum WriteError { @@ -90,14 +90,14 @@ impl Into for PacketSerializeFail { pub type WriteResult

= Result; -#[cfg(feature = "async")] +#[cfg(any(feature = "futures-io", feature = "tokio-io"))] #[async_trait] pub trait CraftAsyncWriter { - async fn write_packet

(&mut self, packet: P) -> WriteResult<()> + async fn write_packet_async

(&mut self, packet: P) -> WriteResult<()> where P: Packet + Send + Sync; - async fn write_raw_packet<'a, P>(&mut self, packet: P) -> WriteResult<()> + async fn write_raw_packet_async<'a, P>(&mut self, packet: P) -> WriteResult<()> where P: RawPacket<'a> + Send + Sync; } @@ -174,13 +174,37 @@ where target.write_all(data) } -#[cfg(feature = "async")] +#[cfg(any(feature = "tokio-io", feature = "futures-io"))] +#[async_trait] +pub trait AsyncWriteAll: Unpin + Send + Sync { + async fn write_all(&mut self, data: &[u8]) -> Result<(), std::io::Error>; +} + +#[cfg(all(feature = "futures-io", not(feature = "tokio-io")))] +#[async_trait] +impl AsyncWriteAll for W where W: futures::AsyncWrite + Unpin + Send + Sync { + async fn write_all(&mut self, data: &[u8]) -> Result<(), std::io::Error> { + futures::AsyncWriteExt::write_all(self, data).await?; + Ok(()) + } +} + +#[cfg(feature = "tokio-io")] +#[async_trait] +impl AsyncWriteAll for W where W: tokio::io::AsyncWrite + Unpin + Send + Sync { + async fn write_all(&mut self, data: &[u8]) -> Result<(), std::io::Error> { + tokio::io::AsyncWriteExt::write_all(self, data).await?; + Ok(()) + } +} + +#[cfg(any(feature = "futures-io", feature = "tokio-io"))] #[async_trait] impl CraftAsyncWriter for CraftWriter where - W: futures::AsyncWrite + Unpin + Send + Sync, + W: AsyncWriteAll, { - async fn write_packet

(&mut self, packet: P) -> WriteResult<()> + async fn write_packet_async

(&mut self, packet: P) -> WriteResult<()> where P: Packet + Send + Sync, { @@ -189,7 +213,7 @@ where Ok(()) } - async fn write_raw_packet<'a, P>(&mut self, packet: P) -> WriteResult<()> + async fn write_raw_packet_async<'a, P>(&mut self, packet: P) -> WriteResult<()> where P: RawPacket<'a> + Send + Sync, { @@ -199,12 +223,12 @@ where } } -#[cfg(feature = "async")] +#[cfg(any(feature = "futures-io", feature = "tokio-io"))] async fn write_data_to_target_async<'a, W>( tuple: (&'a [u8], &'a mut W), ) -> Result<(), std::io::Error> where - W: futures::AsyncWrite + Unpin + Send + Sync, + W: AsyncWriteAll, { let (data, target) = tuple; target.write_all(data).await -- cgit