Port/rename to async-std / async-tungstenite

This commit is contained in:
Sebastian Dröge 2019-11-12 14:52:54 +01:00
parent 0c2779965d
commit b76d8cbc03
16 changed files with 166 additions and 136 deletions

View File

@ -1,6 +1,8 @@
language: rust language: rust
rust: rust:
- nightly-2019-09-05 - stable
- beta
- nightly
before_script: before_script:
- export PATH="$PATH:$HOME/.cargo/bin" - export PATH="$PATH:$HOME/.cargo/bin"

View File

@ -1,30 +1,29 @@
[package] [package]
name = "tokio-tungstenite" name = "async-tungstenite"
description = "Tokio binding for Tungstenite, the Lightweight stream-based WebSocket implementation" description = "async-std binding for Tungstenite, the Lightweight stream-based WebSocket implementation"
categories = ["web-programming::websocket", "network-programming", "asynchronous", "concurrency"] categories = ["web-programming::websocket", "network-programming", "asynchronous", "concurrency"]
keywords = ["websocket", "io", "web"] keywords = ["websocket", "io", "web"]
authors = ["Daniel Abramov <dabramov@snapview.de>", "Alexey Galakhov <agalakhov@snapview.de>"] authors = ["Sebastian Dröge <sebastian@centricular.com>"]
license = "MIT" license = "MIT"
homepage = "https://github.com/snapview/tokio-tungstenite" homepage = "https://github.com/sdroege/async-tungstenite"
documentation = "https://docs.rs/tokio-tungstenite/0.9.0" repository = "https://github.com/sdroege/async-tungstenite"
repository = "https://github.com/snapview/tokio-tungstenite" version = "0.1.0"
version = "0.10.0-alpha.1"
edition = "2018" edition = "2018"
[features] [features]
default = ["connect", "tls"] default = ["connect", "tls", "async_std_runtime"]
connect = ["tokio-net", "stream"] connect = ["stream"]
tls = ["tokio-tls", "native-tls", "stream", "tungstenite/tls"] async_std_runtime = ["connect", "tls", "async-std"]
tls = ["async-tls", "stream"]
stream = ["bytes"] stream = ["bytes"]
[dependencies] [dependencies]
log = "0.4" log = "0.4"
futures-preview = { version = "0.3.0-alpha.19", features = ["async-await"] } futures = { version = "0.3", features = ["async-await"] }
pin-project = "0.4.0-alpha.9" pin-project = "0.4.0-alpha.9"
tokio-io = "0.2.0-alpha.6"
[dependencies.tungstenite] [dependencies.tungstenite]
#version = "0.9.1" #version = "0.9.2"
git = "https://github.com/snapview/tungstenite-rs.git" git = "https://github.com/snapview/tungstenite-rs.git"
branch = "master" branch = "master"
default-features = false default-features = false
@ -33,20 +32,15 @@ default-features = false
optional = true optional = true
version = "0.4.8" version = "0.4.8"
[dependencies.native-tls] [dependencies.async-std]
optional = true optional = true
version = "0.2.0" version = "1.0"
[dependencies.tokio-net] [dependencies.async-tls]
optional = true optional = true
version = "0.2.0-alpha.6" version = "0.6.0"
features = ["tcp"]
[dependencies.tokio-tls]
optional = true
version = "0.3.0-alpha.6"
[dev-dependencies] [dev-dependencies]
tokio = "0.2.0-alpha.6"
url = "2.0.0" url = "2.0.0"
env_logger = "0.6.1" env_logger = "0.7"
async-std = { version = "1.0", features = ["attributes"] }

View File

@ -1,5 +1,6 @@
Copyright (c) 2017 Daniel Abramov Copyright (c) 2017 Daniel Abramov
Copyright (c) 2017 Alexey Galakhov Copyright (c) 2017 Alexey Galakhov
Copyright (c) 2019 Sebastian Dröge
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -1,12 +1,12 @@
# tokio-tungstenite # async-tungstenite
Asynchronous WebSockets for Tokio stack. Asynchronous WebSockets for [async-std](https://async.rs) and `std` `Future`s.
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
[![Crates.io](https://img.shields.io/crates/v/tokio-tungstenite.svg?maxAge=2592000)](https://crates.io/crates/tokio-tungstenite) [![Crates.io](https://img.shields.io/crates/v/async-tungstenite.svg?maxAge=2592000)](https://crates.io/crates/async-tungstenite)
[![Build Status](https://travis-ci.org/snapview/tokio-tungstenite.svg?branch=master)](https://travis-ci.org/snapview/tokio-tungstenite) [![Build Status](https://travis-ci.org/sdroege/async-tungstenite.svg?branch=master)](https://travis-ci.org/sdroege/async-tungstenite)
[Documentation](https://docs.rs/tokio-tungstenite) [Documentation](https://docs.rs/async-tungstenite)
## Usage ## Usage
@ -14,13 +14,18 @@ Add this in your `Cargo.toml`:
```toml ```toml
[dependencies] [dependencies]
tokio-tungstenite = "*" async-tungstenite = "*"
``` ```
Take a look at the `examples/` directory for client and server examples. You may also want to get familiar with Take a look at the `examples/` directory for client and server examples. You may also want to get familiar with
[tokio](https://tokio.rs/) if you don't have any experience with it. [`async-std`](https://async.rs/) if you don't have any experience with it.
## What is tokio-tungstenite? ## What is async-tungstenite?
This crate is based on `tungstenite-rs` Rust WebSocket library and provides `tokio` bindings and wrappers for it, so you This crate is based on `tungstenite-rs` Rust WebSocket library and provides async-std bindings and wrappers for it, so you
can use it with non-blocking/asynchronous `TcpStream`s from and couple it together with other crates from `tokio` stack. can use it with non-blocking/asynchronous `TcpStream`s from and couple it together with other crates from the async-std stack.
## tokio-tungstenite
Originally this crate was created as a fork of [tokio-tungstenite](https://github.com/snapview/tokio-tungstenite)
and ported to [async-std](https://async.rs).

View File

@ -1,6 +1,6 @@
use futures::StreamExt; use futures::StreamExt;
use log::*; use log::*;
use tokio_tungstenite::{connect_async, tungstenite::Result}; use async_tungstenite::{connect_async, tungstenite::Result};
use url::Url; use url::Url;
const AGENT: &'static str = "Tungstenite"; const AGENT: &'static str = "Tungstenite";
@ -43,8 +43,7 @@ async fn run_test(case: u32) {
} }
} }
#[tokio::main] async fn run() {
async fn main() {
env_logger::init(); env_logger::init();
let total = get_case_count().await.unwrap(); let total = get_case_count().await.unwrap();
@ -55,3 +54,7 @@ async fn main() {
update_reports().await.unwrap(); update_reports().await.unwrap();
} }
fn main() {
async_std::task::block_on(run());
}

View File

@ -1,8 +1,7 @@
use futures::StreamExt; use futures::StreamExt;
use log::*; use log::*;
use std::net::{SocketAddr, ToSocketAddrs}; use async_std::net::{TcpListener, TcpStream, SocketAddr, ToSocketAddrs};
use tokio::net::{TcpListener, TcpStream}; use async_tungstenite::accept_async;
use tokio_tungstenite::accept_async;
async fn accept_connection(peer: SocketAddr, stream: TcpStream) { async fn accept_connection(peer: SocketAddr, stream: TcpStream) {
let mut ws_stream = accept_async(stream).await.expect("Failed to accept"); let mut ws_stream = accept_async(stream).await.expect("Failed to accept");
@ -17,12 +16,12 @@ async fn accept_connection(peer: SocketAddr, stream: TcpStream) {
} }
} }
#[tokio::main] async fn run() {
async fn main() {
env_logger::init(); env_logger::init();
let addr = "127.0.0.1:9002" let addr = "127.0.0.1:9002"
.to_socket_addrs() .to_socket_addrs()
.await
.expect("Not a valid address") .expect("Not a valid address")
.next() .next()
.expect("Not a socket address"); .expect("Not a socket address");
@ -37,6 +36,10 @@ async fn main() {
.expect("connected streams should have a peer address"); .expect("connected streams should have a peer address");
info!("Peer address: {}", peer); info!("Peer address: {}", peer);
tokio::spawn(accept_connection(peer, stream)); async_std::task::spawn(accept_connection(peer, stream));
} }
} }
fn main() {
async_std::task::block_on(run());
}

View File

@ -11,17 +11,17 @@
//! You can use this example together with the `server` example. //! You can use this example together with the `server` example.
use std::env; use std::env;
use std::io::{self, Write};
use futures::StreamExt; use futures::StreamExt;
use log::*; use log::*;
use tungstenite::protocol::Message; use tungstenite::protocol::Message;
use tokio::io::AsyncReadExt; use async_std::prelude::*;
use tokio_tungstenite::connect_async; use async_std::io;
use async_std::task;
use async_tungstenite::connect_async;
#[tokio::main] async fn run() {
async fn main() {
let _ = env_logger::try_init(); let _ = env_logger::try_init();
// Specify the server address to which the client will be connecting. // Specify the server address to which the client will be connecting.
@ -31,12 +31,10 @@ async fn main() {
let url = url::Url::parse(&connect_addr).unwrap(); let url = url::Url::parse(&connect_addr).unwrap();
// Right now Tokio doesn't support a handle to stdin running on the event // Spawn a new task that will will read data from stdin and then send it to the event loop over
// loop, so we farm out that work to a separate thread. This thread will // a standard futures channel.
// read data from stdin and then send it to the event loop over a standard
// futures channel.
let (stdin_tx, mut stdin_rx) = futures::channel::mpsc::unbounded(); let (stdin_tx, mut stdin_rx) = futures::channel::mpsc::unbounded();
tokio::spawn(read_stdin(stdin_tx)); task::spawn(read_stdin(stdin_tx));
// After the TCP connection has been established, we set up our client to // After the TCP connection has been established, we set up our client to
// start forwarding data. // start forwarding data.
@ -61,7 +59,7 @@ async fn main() {
ws_stream.send(msg).await.expect("Failed to send request"); ws_stream.send(msg).await.expect("Failed to send request");
if let Some(msg) = ws_stream.next().await { if let Some(msg) = ws_stream.next().await {
let msg = msg.expect("Failed to get response"); let msg = msg.expect("Failed to get response");
stdout.write_all(&msg.into_data()).unwrap(); stdout.write_all(&msg.into_data()).await.unwrap();
} }
} }
} }
@ -69,7 +67,7 @@ async fn main() {
// Our helper method which will read data from stdin and send it along the // Our helper method which will read data from stdin and send it along the
// sender provided. // sender provided.
async fn read_stdin(tx: futures::channel::mpsc::UnboundedSender<Message>) { async fn read_stdin(tx: futures::channel::mpsc::UnboundedSender<Message>) {
let mut stdin = tokio::io::stdin(); let mut stdin = io::stdin();
loop { loop {
let mut buf = vec![0; 1024]; let mut buf = vec![0; 1024];
let n = match stdin.read(&mut buf).await { let n = match stdin.read(&mut buf).await {
@ -80,3 +78,7 @@ async fn read_stdin(tx: futures::channel::mpsc::UnboundedSender<Message>) {
tx.unbounded_send(Message::binary(buf)).unwrap(); tx.unbounded_send(Message::binary(buf)).unwrap();
} }
} }
fn main() {
task::block_on(run())
}

View File

@ -23,8 +23,9 @@ use std::io::Error;
use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender}; use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
use futures::StreamExt; use futures::StreamExt;
use log::*; use log::*;
use std::net::{SocketAddr, ToSocketAddrs}; use async_std::task;
use tokio::net::{TcpListener, TcpStream}; use async_std::net::{SocketAddr, ToSocketAddrs};
use async_std::net::{TcpListener, TcpStream};
use tungstenite::protocol::Message; use tungstenite::protocol::Message;
struct Connection { struct Connection {
@ -50,7 +51,7 @@ async fn accept_connection(stream: TcpStream) {
.expect("connected streams should have a peer address"); .expect("connected streams should have a peer address");
info!("Peer address: {}", addr); info!("Peer address: {}", addr);
let mut ws_stream = tokio_tungstenite::accept_async(stream) let mut ws_stream = async_tungstenite::accept_async(stream)
.await .await
.expect("Error during the websocket handshake occurred"); .expect("Error during the websocket handshake occurred");
@ -66,7 +67,7 @@ async fn accept_connection(stream: TcpStream) {
rx: msg_rx, rx: msg_rx,
tx: response_tx, tx: response_tx,
}; };
tokio::spawn(handle_connection(c)); task::spawn(handle_connection(c));
while let Some(message) = ws_stream.next().await { while let Some(message) = ws_stream.next().await {
let message = message.expect("Failed to get request"); let message = message.expect("Failed to get request");
@ -78,12 +79,13 @@ async fn accept_connection(stream: TcpStream) {
} }
} }
} }
#[tokio::main]
async fn main() -> Result<(), Error> { async fn run() -> Result<(), Error> {
let _ = env_logger::try_init(); let _ = env_logger::try_init();
let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string()); let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
let addr = addr let addr = addr
.to_socket_addrs() .to_socket_addrs()
.await
.expect("Not a valid address") .expect("Not a valid address")
.next() .next()
.expect("Not a socket address"); .expect("Not a socket address");
@ -96,8 +98,12 @@ async fn main() -> Result<(), Error> {
while let Some(stream) = incoming.next().await { while let Some(stream) = incoming.next().await {
let stream = stream.expect("Failed to accept stream"); let stream = stream.expect("Failed to accept stream");
tokio::spawn(accept_connection(stream)); task::spawn(accept_connection(stream));
} }
Ok(()) Ok(())
} }
fn main() -> Result<(), Error> {
task::block_on(run())
}

View File

@ -11,17 +11,16 @@
//! You can use this example together with the `server` example. //! You can use this example together with the `server` example.
use std::env; use std::env;
use std::io::{self, Write};
use futures::{SinkExt, StreamExt}; use futures::{SinkExt, StreamExt};
use log::*; use log::*;
use tungstenite::protocol::Message; use tungstenite::protocol::Message;
use async_std::prelude::*;
use async_std::io;
use async_std::task;
use async_tungstenite::connect_async;
use tokio::io::AsyncReadExt; async fn run() {
use tokio_tungstenite::connect_async;
#[tokio::main]
async fn main() {
let _ = env_logger::try_init(); let _ = env_logger::try_init();
// Specify the server address to which the client will be connecting. // Specify the server address to which the client will be connecting.
@ -31,12 +30,10 @@ async fn main() {
let url = url::Url::parse(&connect_addr).unwrap(); let url = url::Url::parse(&connect_addr).unwrap();
// Right now Tokio doesn't support a handle to stdin running on the event // Spawn a new task that will read data from stdin and then send it to the event loop over a
// loop, so we farm out that work to a separate thread. This thread will // standard futures channel.
// read data from stdin and then send it to the event loop over a standard
// futures channel.
let (stdin_tx, mut stdin_rx) = futures::channel::mpsc::unbounded(); let (stdin_tx, mut stdin_rx) = futures::channel::mpsc::unbounded();
tokio::spawn(read_stdin(stdin_tx)); task::spawn(read_stdin(stdin_tx));
// After the TCP connection has been established, we set up our client to // After the TCP connection has been established, we set up our client to
// start forwarding data. // start forwarding data.
@ -62,7 +59,7 @@ async fn main() {
ws_tx.send(msg).await.expect("Failed to send request"); ws_tx.send(msg).await.expect("Failed to send request");
if let Some(msg) = ws_rx.next().await { if let Some(msg) = ws_rx.next().await {
let msg = msg.expect("Failed to get response"); let msg = msg.expect("Failed to get response");
stdout.write_all(&msg.into_data()).unwrap(); stdout.write_all(&msg.into_data()).await.unwrap();
} }
} }
} }
@ -70,7 +67,7 @@ async fn main() {
// Our helper method which will read data from stdin and send it along the // Our helper method which will read data from stdin and send it along the
// sender provided. // sender provided.
async fn read_stdin(tx: futures::channel::mpsc::UnboundedSender<Message>) { async fn read_stdin(tx: futures::channel::mpsc::UnboundedSender<Message>) {
let mut stdin = tokio::io::stdin(); let mut stdin = io::stdin();
loop { loop {
let mut buf = vec![0; 1024]; let mut buf = vec![0; 1024];
let n = match stdin.read(&mut buf).await { let n = match stdin.read(&mut buf).await {
@ -81,3 +78,7 @@ async fn read_stdin(tx: futures::channel::mpsc::UnboundedSender<Message>) {
tx.unbounded_send(Message::binary(buf)).unwrap(); tx.unbounded_send(Message::binary(buf)).unwrap();
} }
} }
fn main() {
task::block_on(run())
}

View File

@ -3,7 +3,7 @@ use std::io::{Read, Write};
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use tokio_io::{AsyncRead, AsyncWrite}; use futures::io::{AsyncRead, AsyncWrite};
use tungstenite::{Error as WsError, WebSocket}; use tungstenite::{Error as WsError, WebSocket};
pub(crate) trait HasContext { pub(crate) trait HasContext {

View File

@ -1,23 +1,22 @@
//! Connection helper. //! Connection helper.
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_net::tcp::TcpStream;
use tungstenite::client::url_mode; use tungstenite::client::url_mode;
use tungstenite::handshake::client::Response; use tungstenite::handshake::client::Response;
use tungstenite::Error; use tungstenite::Error;
use futures::io::{AsyncRead, AsyncWrite};
use super::{client_async, Request, WebSocketStream}; use super::{client_async, Request, WebSocketStream};
#[cfg(feature = "tls")] #[cfg(feature = "tls")]
pub(crate) mod encryption { pub(crate) mod encryption {
use native_tls::TlsConnector; use async_tls::TlsConnector as AsyncTlsConnector;
use tokio_tls::{TlsConnector as TokioTlsConnector, TlsStream}; use async_tls::client::TlsStream;
use tokio_io::{AsyncRead, AsyncWrite};
use tungstenite::stream::Mode; use tungstenite::stream::Mode;
use tungstenite::Error; use tungstenite::Error;
use futures::io::{AsyncRead, AsyncWrite};
use crate::stream::Stream as StreamSwitcher; use crate::stream::Stream as StreamSwitcher;
/// A stream that might be protected with TLS. /// A stream that might be protected with TLS.
@ -36,12 +35,10 @@ pub(crate) mod encryption {
match mode { match mode {
Mode::Plain => Ok(StreamSwitcher::Plain(socket)), Mode::Plain => Ok(StreamSwitcher::Plain(socket)),
Mode::Tls => { Mode::Tls => {
let try_connector = TlsConnector::new(); let stream = AsyncTlsConnector::new();
let connector = try_connector.map_err(Error::Tls)?; let connected = stream.connect(&domain, socket)?.await;
let stream = TokioTlsConnector::from(connector);
let connected = stream.connect(&domain, socket).await;
match connected { match connected {
Err(e) => Err(Error::Tls(e)), Err(e) => Err(Error::Io(e)),
Ok(s) => Ok(StreamSwitcher::Tls(s)), Ok(s) => Ok(StreamSwitcher::Tls(s)),
} }
} }
@ -55,7 +52,7 @@ pub use self::encryption::MaybeTlsStream;
#[cfg(not(feature = "tls"))] #[cfg(not(feature = "tls"))]
pub(crate) mod encryption { pub(crate) mod encryption {
use futures::{future, Future}; use futures::{future, Future};
use tokio_io::{AsyncRead, AsyncWrite}; use futures::io::{AsyncRead, AsyncWrite};
use tungstenite::stream::Mode; use tungstenite::stream::Mode;
use tungstenite::Error; use tungstenite::Error;
@ -110,22 +107,31 @@ where
client_async(request, stream).await client_async(request, stream).await
} }
/// Connect to a given URL. #[cfg(feature = "async_std_runtime")]
pub async fn connect_async<R>( pub(crate) mod async_std_runtime {
request: R, use super::*;
) -> Result<(WebSocketStream<AutoStream<TcpStream>>, Response), Error> use async_std::net::TcpStream;
where
R: Into<Request<'static>> + Unpin,
{
let request: Request = request.into();
let domain = domain(&request)?; /// Connect to a given URL.
let port = request pub async fn connect_async<R>(
.url request: R,
.port_or_known_default() ) -> Result<(WebSocketStream<AutoStream<TcpStream>>, Response), Error>
.expect("Bug: port unknown"); where
R: Into<Request<'static>> + Unpin,
{
let request: Request = request.into();
let try_socket = TcpStream::connect((domain.as_str(), port)).await; let domain = domain(&request)?;
let socket = try_socket.map_err(Error::Io)?; let port = request
client_async_tls(request, socket).await .url
.port_or_known_default()
.expect("Bug: port unknown");
let try_socket = TcpStream::connect((domain.as_str(), port)).await;
let socket = try_socket.map_err(Error::Io)?;
client_async_tls(request, socket).await
}
} }
#[cfg(feature = "async_std_runtime")]
pub use async_std_runtime::connect_async;

View File

@ -6,7 +6,7 @@ use std::future::Future;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use tokio_io::{AsyncRead, AsyncWrite}; use futures::io::{AsyncRead, AsyncWrite};
use tungstenite::handshake::client::Response; use tungstenite::handshake::client::Response;
use tungstenite::handshake::server::Callback; use tungstenite::handshake::server::Callback;
use tungstenite::handshake::{HandshakeError as Error, HandshakeRole, MidHandshake as WsHandshake}; use tungstenite::handshake::{HandshakeError as Error, HandshakeRole, MidHandshake as WsHandshake};

View File

@ -2,7 +2,7 @@
//! //!
//! This library is an implementation of WebSocket handshakes and streams. It //! This library is an implementation of WebSocket handshakes and streams. It
//! is based on the crate which implements all required WebSocket protocol //! is based on the crate which implements all required WebSocket protocol
//! logic. So this crate basically just brings tokio support / tokio integration //! logic. So this crate basically just brings async_std support / async_std integration
//! to it. //! to it.
//! //!
//! Each WebSocket stream implements the required `Stream` and `Sink` traits, //! Each WebSocket stream implements the required `Stream` and `Sink` traits,
@ -34,7 +34,7 @@ use pin_project::pin_project;
use std::future::Future; use std::future::Future;
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use tokio_io::{AsyncRead, AsyncWrite}; use futures::io::{AsyncRead, AsyncWrite};
use tungstenite::{ use tungstenite::{
error::Error as WsError, error::Error as WsError,
@ -47,7 +47,9 @@ use tungstenite::{
}; };
#[cfg(feature = "connect")] #[cfg(feature = "connect")]
pub use connect::{client_async_tls, connect_async}; pub use connect::client_async_tls;
#[cfg(feature = "async_std_runtime")]
pub use connect::connect_async;
#[cfg(all(feature = "connect", feature = "tls"))] #[cfg(all(feature = "connect", feature = "tls"))]
pub use connect::MaybeTlsStream; pub use connect::MaybeTlsStream;
@ -382,7 +384,7 @@ mod tests {
use crate::connect::encryption::AutoStream; use crate::connect::encryption::AutoStream;
use crate::WebSocketStream; use crate::WebSocketStream;
use std::io::{Read, Write}; use std::io::{Read, Write};
use tokio_io::{AsyncReadExt, AsyncWriteExt}; use futures::io::{AsyncReadExt, AsyncWriteExt};
fn is_read<T: Read>() {} fn is_read<T: Read>() {}
fn is_write<T: Write>() {} fn is_write<T: Write>() {}
@ -392,13 +394,13 @@ mod tests {
#[test] #[test]
fn web_socket_stream_has_traits() { fn web_socket_stream_has_traits() {
is_read::<AllowStd<tokio::net::TcpStream>>(); is_read::<AllowStd<async_std::net::TcpStream>>();
is_write::<AllowStd<tokio::net::TcpStream>>(); is_write::<AllowStd<async_std::net::TcpStream>>();
is_async_read::<AutoStream<tokio::net::TcpStream>>(); is_async_read::<AutoStream<async_std::net::TcpStream>>();
is_async_write::<AutoStream<tokio::net::TcpStream>>(); is_async_write::<AutoStream<async_std::net::TcpStream>>();
is_unpin::<WebSocketStream<tokio::net::TcpStream>>(); is_unpin::<WebSocketStream<async_std::net::TcpStream>>();
is_unpin::<WebSocketStream<AutoStream<tokio::net::TcpStream>>>(); is_unpin::<WebSocketStream<AutoStream<async_std::net::TcpStream>>>();
} }
} }

View File

@ -2,11 +2,11 @@
//! //!
//! There is no dependency on actual TLS implementations. Everything like //! There is no dependency on actual TLS implementations. Everything like
//! `native_tls` or `openssl` will work as long as there is a TLS stream supporting standard //! `native_tls` or `openssl` will work as long as there is a TLS stream supporting standard
//! `Read + Write` traits. //! `AsyncRead + AsyncWrite` traits.
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use tokio_io::{AsyncRead, AsyncWrite}; use futures::io::{AsyncRead, AsyncWrite};
/// Stream, either plain TCP or TLS. /// Stream, either plain TCP or TLS.
pub enum Stream<S, T> { pub enum Stream<S, T> {
@ -69,18 +69,18 @@ impl<S: AsyncWrite + Unpin, T: AsyncWrite + Unpin> AsyncWrite for Stream<S, T> {
} }
} }
fn poll_shutdown( fn poll_close(
mut self: Pin<&mut Self>, mut self: Pin<&mut Self>,
cx: &mut Context<'_>, cx: &mut Context<'_>,
) -> Poll<Result<(), std::io::Error>> { ) -> Poll<Result<(), std::io::Error>> {
match *self { match *self {
Stream::Plain(ref mut s) => { Stream::Plain(ref mut s) => {
let pinned = unsafe { Pin::new_unchecked(s) }; let pinned = unsafe { Pin::new_unchecked(s) };
pinned.poll_shutdown(cx) pinned.poll_close(cx)
} }
Stream::Tls(ref mut s) => { Stream::Tls(ref mut s) => {
let pinned = unsafe { Pin::new_unchecked(s) }; let pinned = unsafe { Pin::new_unchecked(s) };
pinned.poll_shutdown(cx) pinned.poll_close(cx)
} }
} }
} }

View File

@ -1,9 +1,8 @@
use futures::{SinkExt, StreamExt}; use futures::{SinkExt, StreamExt, AsyncRead, AsyncWrite};
use log::*; use log::*;
use std::net::ToSocketAddrs; use async_std::task;
use tokio::io::{AsyncRead, AsyncWrite}; use async_std::net::{TcpListener, TcpStream, ToSocketAddrs};
use tokio::net::tcp::{TcpListener, TcpStream}; use async_tungstenite::{accept_async, client_async, WebSocketStream};
use tokio_tungstenite::{accept_async, client_async, WebSocketStream};
use tungstenite::Message; use tungstenite::Message;
async fn run_connection<S>( async fn run_connection<S>(
@ -23,7 +22,7 @@ async fn run_connection<S>(
msg_tx.send(messages).expect("Failed to send results"); msg_tx.send(messages).expect("Failed to send results");
} }
#[tokio::test] #[async_std::test]
async fn communication() { async fn communication() {
let _ = env_logger::try_init(); let _ = env_logger::try_init();
@ -33,6 +32,7 @@ async fn communication() {
let f = async move { let f = async move {
let address = "0.0.0.0:12345" let address = "0.0.0.0:12345"
.to_socket_addrs() .to_socket_addrs()
.await
.expect("Not a valid address") .expect("Not a valid address")
.next() .next()
.expect("No address resolved"); .expect("No address resolved");
@ -48,13 +48,14 @@ async fn communication() {
run_connection(stream, msg_tx).await; run_connection(stream, msg_tx).await;
}; };
tokio::spawn(f); task::spawn(f);
info!("Waiting for server to be ready"); info!("Waiting for server to be ready");
con_rx.await.expect("Server not ready"); con_rx.await.expect("Server not ready");
let address = "0.0.0.0:12345" let address = "0.0.0.0:12345"
.to_socket_addrs() .to_socket_addrs()
.await
.expect("Not a valid address") .expect("Not a valid address")
.next() .next()
.expect("No address resolved"); .expect("No address resolved");
@ -78,7 +79,7 @@ async fn communication() {
assert_eq!(messages.len(), 10); assert_eq!(messages.len(), 10);
} }
#[tokio::test] #[async_std::test]
async fn split_communication() { async fn split_communication() {
let _ = env_logger::try_init(); let _ = env_logger::try_init();
@ -88,6 +89,7 @@ async fn split_communication() {
let f = async move { let f = async move {
let address = "0.0.0.0:12346" let address = "0.0.0.0:12346"
.to_socket_addrs() .to_socket_addrs()
.await
.expect("Not a valid address") .expect("Not a valid address")
.next() .next()
.expect("No address resolved"); .expect("No address resolved");
@ -103,13 +105,14 @@ async fn split_communication() {
run_connection(stream, msg_tx).await; run_connection(stream, msg_tx).await;
}; };
tokio::spawn(f); task::spawn(f);
info!("Waiting for server to be ready"); info!("Waiting for server to be ready");
con_rx.await.expect("Server not ready"); con_rx.await.expect("Server not ready");
let address = "0.0.0.0:12346" let address = "0.0.0.0:12346"
.to_socket_addrs() .to_socket_addrs()
.await
.expect("Not a valid address") .expect("Not a valid address")
.next() .next()
.expect("No address resolved"); .expect("No address resolved");

View File

@ -1,15 +1,16 @@
use futures::StreamExt; use futures::StreamExt;
use std::net::ToSocketAddrs; use async_std::task;
use tokio::net::tcp::{TcpListener, TcpStream}; use async_std::net::{TcpListener, TcpStream, ToSocketAddrs};
use tokio_tungstenite::{accept_async, client_async}; use async_tungstenite::{accept_async, client_async};
#[tokio::test] #[async_std::test]
async fn handshakes() { async fn handshakes() {
let (tx, rx) = futures::channel::oneshot::channel(); let (tx, rx) = futures::channel::oneshot::channel();
let f = async move { let f = async move {
let address = "0.0.0.0:12345" let address = "0.0.0.0:12345"
.to_socket_addrs() .to_socket_addrs()
.await
.expect("Not a valid address") .expect("Not a valid address")
.next() .next()
.expect("No address resolved"); .expect("No address resolved");
@ -23,11 +24,12 @@ async fn handshakes() {
} }
}; };
tokio::spawn(f); task::spawn(f);
rx.await.expect("Failed to wait for server to be ready"); rx.await.expect("Failed to wait for server to be ready");
let address = "0.0.0.0:12345" let address = "0.0.0.0:12345"
.to_socket_addrs() .to_socket_addrs()
.await
.expect("Not a valid address") .expect("Not a valid address")
.next() .next()
.expect("No address resolved"); .expect("No address resolved");