parent
5613f9e47d
commit
c2ff77b446
@ -0,0 +1,31 @@ |
||||
use async_tungstenite::{async_std::connect_async, tungstenite::Message}; |
||||
use futures::prelude::*; |
||||
|
||||
use async_std::task; |
||||
|
||||
async fn run() -> Result<(), Box<dyn std::error::Error>> { |
||||
#[cfg(any(feature = "async-tls", feature = "async-native-tls"))] |
||||
let url = url::Url::parse("wss://echo.websocket.org").unwrap(); |
||||
#[cfg(not(any(feature = "async-tls", feature = "async-native-tls")))] |
||||
let url = url::Url::parse("ws://echo.websocket.org").unwrap(); |
||||
|
||||
let (mut ws_stream, _) = connect_async(url).await?; |
||||
|
||||
let text = "Hello, World!"; |
||||
|
||||
println!("Sending: \"{}\"", text); |
||||
ws_stream.send(Message::text(text)).await?; |
||||
|
||||
let msg = ws_stream |
||||
.next() |
||||
.await |
||||
.ok_or_else(|| "didn't receive anything")??; |
||||
|
||||
println!("Received: {:?}", msg); |
||||
|
||||
Ok(()) |
||||
} |
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> { |
||||
task::block_on(run()) |
||||
} |
@ -0,0 +1,28 @@ |
||||
use async_tungstenite::{gio::connect_async, tungstenite::Message}; |
||||
use futures::prelude::*; |
||||
|
||||
async fn run() -> Result<(), Box<dyn std::error::Error>> { |
||||
let url = url::Url::parse("wss://echo.websocket.org").unwrap(); |
||||
|
||||
let (mut ws_stream, _) = connect_async(url).await?; |
||||
|
||||
let text = "Hello, World!"; |
||||
|
||||
println!("Sending: \"{}\"", text); |
||||
ws_stream.send(Message::text(text)).await?; |
||||
|
||||
let msg = ws_stream |
||||
.next() |
||||
.await |
||||
.ok_or_else(|| "didn't receive anything")??; |
||||
|
||||
println!("Received: {:?}", msg); |
||||
|
||||
Ok(()) |
||||
} |
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> { |
||||
// Get the default main context and run our async function on it
|
||||
let main_context = glib::MainContext::default(); |
||||
main_context.block_on(run()) |
||||
} |
@ -0,0 +1,30 @@ |
||||
use async_tungstenite::{tokio::connect_async, tungstenite::Message}; |
||||
use futures::prelude::*; |
||||
|
||||
async fn run() -> Result<(), Box<dyn std::error::Error>> { |
||||
#[cfg(any(feature = "async-tls", feature = "tokio-tls"))] |
||||
let url = url::Url::parse("wss://echo.websocket.org").unwrap(); |
||||
#[cfg(not(any(feature = "async-tls", feature = "tokio-tls")))] |
||||
let url = url::Url::parse("ws://echo.websocket.org").unwrap(); |
||||
|
||||
let (mut ws_stream, _) = connect_async(url).await?; |
||||
|
||||
let text = "Hello, World!"; |
||||
|
||||
println!("Sending: \"{}\"", text); |
||||
ws_stream.send(Message::text(text)).await?; |
||||
|
||||
let msg = ws_stream |
||||
.next() |
||||
.await |
||||
.ok_or_else(|| "didn't receive anything")??; |
||||
|
||||
println!("Received: {:?}", msg); |
||||
|
||||
Ok(()) |
||||
} |
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> { |
||||
let mut rt = tokio::runtime::Runtime::new()?; |
||||
rt.block_on(run()) |
||||
} |
@ -0,0 +1,268 @@ |
||||
//! `async-std` integration.
|
||||
use tungstenite::handshake::client::Response; |
||||
use tungstenite::protocol::WebSocketConfig; |
||||
use tungstenite::Error; |
||||
|
||||
use async_std::net::TcpStream; |
||||
|
||||
use super::{domain, Request, WebSocketStream}; |
||||
|
||||
#[cfg(feature = "async-native-tls")] |
||||
use futures::io::{AsyncRead, AsyncWrite}; |
||||
|
||||
#[cfg(feature = "async-native-tls")] |
||||
pub(crate) mod async_native_tls { |
||||
use async_native_tls::TlsConnector as AsyncTlsConnector; |
||||
use async_native_tls::TlsStream; |
||||
use real_async_native_tls as async_native_tls; |
||||
|
||||
use tungstenite::client::url_mode; |
||||
use tungstenite::stream::Mode; |
||||
use tungstenite::Error; |
||||
|
||||
use futures::io::{AsyncRead, AsyncWrite}; |
||||
|
||||
use crate::stream::Stream as StreamSwitcher; |
||||
use crate::{ |
||||
client_async_with_config, domain, Request, Response, WebSocketConfig, WebSocketStream, |
||||
}; |
||||
|
||||
/// A stream that might be protected with TLS.
|
||||
pub type MaybeTlsStream<S> = StreamSwitcher<S, TlsStream<S>>; |
||||
|
||||
pub type AutoStream<S> = MaybeTlsStream<S>; |
||||
|
||||
pub type Connector = AsyncTlsConnector; |
||||
|
||||
async fn wrap_stream<S>( |
||||
socket: S, |
||||
domain: String, |
||||
connector: Option<Connector>, |
||||
mode: Mode, |
||||
) -> Result<AutoStream<S>, Error> |
||||
where |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
{ |
||||
match mode { |
||||
Mode::Plain => Ok(StreamSwitcher::Plain(socket)), |
||||
Mode::Tls => { |
||||
let stream = { |
||||
let connector = if let Some(connector) = connector { |
||||
connector |
||||
} else { |
||||
AsyncTlsConnector::new() |
||||
}; |
||||
connector |
||||
.connect(&domain, socket) |
||||
.await |
||||
.map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))? |
||||
}; |
||||
Ok(StreamSwitcher::Tls(stream)) |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// Creates a WebSocket handshake from a request and a stream,
|
||||
/// upgrading the stream to TLS if required and using the given
|
||||
/// connector and WebSocket configuration.
|
||||
pub async fn client_async_tls_with_connector_and_config<R, S>( |
||||
request: R, |
||||
stream: S, |
||||
connector: Option<AsyncTlsConnector>, |
||||
config: Option<WebSocketConfig>, |
||||
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
AutoStream<S>: Unpin, |
||||
{ |
||||
let request: Request = request.into(); |
||||
|
||||
let domain = domain(&request)?; |
||||
|
||||
// Make sure we check domain and mode first. URL must be valid.
|
||||
let mode = url_mode(&request.url)?; |
||||
|
||||
let stream = wrap_stream(stream, domain, connector, mode).await?; |
||||
client_async_with_config(request, stream, config).await |
||||
} |
||||
} |
||||
|
||||
#[cfg(not(any(feature = "async-tls", feature = "async-native-tls")))] |
||||
pub(crate) mod dummy_tls { |
||||
use futures::io::{AsyncRead, AsyncWrite}; |
||||
|
||||
use tungstenite::client::url_mode; |
||||
use tungstenite::stream::Mode; |
||||
use tungstenite::Error; |
||||
|
||||
use crate::{ |
||||
client_async_with_config, domain, Request, Response, WebSocketConfig, WebSocketStream, |
||||
}; |
||||
|
||||
pub type AutoStream<S> = S; |
||||
type Connector = (); |
||||
|
||||
async fn wrap_stream<S>( |
||||
socket: S, |
||||
_domain: String, |
||||
_connector: Option<()>, |
||||
mode: Mode, |
||||
) -> Result<AutoStream<S>, Error> |
||||
where |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
{ |
||||
match mode { |
||||
Mode::Plain => Ok(socket), |
||||
Mode::Tls => Err(Error::Url("TLS support not compiled in.".into())), |
||||
} |
||||
} |
||||
|
||||
pub(crate) async fn client_async_tls_with_connector_and_config<R, S>( |
||||
request: R, |
||||
stream: S, |
||||
connector: Option<Connector>, |
||||
config: Option<WebSocketConfig>, |
||||
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
AutoStream<S>: Unpin, |
||||
{ |
||||
let request: Request = request.into(); |
||||
|
||||
let domain = domain(&request)?; |
||||
|
||||
// Make sure we check domain and mode first. URL must be valid.
|
||||
let mode = url_mode(&request.url)?; |
||||
|
||||
let stream = wrap_stream(stream, domain, connector, mode).await?; |
||||
client_async_with_config(request, stream, config).await |
||||
} |
||||
} |
||||
|
||||
#[cfg(not(any(feature = "async-tls", feature = "async-native-tls")))] |
||||
use self::dummy_tls::{client_async_tls_with_connector_and_config, AutoStream}; |
||||
|
||||
#[cfg(all(feature = "async-tls", not(feature = "async-native-tls")))] |
||||
use crate::async_tls::{client_async_tls_with_connector_and_config, AutoStream}; |
||||
#[cfg(all(feature = "async-tls", not(feature = "async-native-tls")))] |
||||
type Connector = real_async_tls::TlsConnector; |
||||
|
||||
#[cfg(feature = "async-native-tls")] |
||||
use self::async_native_tls::{client_async_tls_with_connector_and_config, AutoStream, Connector}; |
||||
|
||||
#[cfg(feature = "async-native-tls")] |
||||
/// Creates a WebSocket handshake from a request and a stream,
|
||||
/// upgrading the stream to TLS if required.
|
||||
pub async fn client_async_tls<R, S>( |
||||
request: R, |
||||
stream: S, |
||||
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
AutoStream<S>: Unpin, |
||||
{ |
||||
client_async_tls_with_connector_and_config(request, stream, None, None).await |
||||
} |
||||
|
||||
#[cfg(feature = "async-native-tls")] |
||||
/// Creates a WebSocket handshake from a request and a stream,
|
||||
/// upgrading the stream to TLS if required and using the given
|
||||
/// WebSocket configuration.
|
||||
pub async fn client_async_tls_with_config<R, S>( |
||||
request: R, |
||||
stream: S, |
||||
config: Option<WebSocketConfig>, |
||||
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
AutoStream<S>: Unpin, |
||||
{ |
||||
client_async_tls_with_connector_and_config(request, stream, None, config).await |
||||
} |
||||
|
||||
#[cfg(feature = "async-native-tls")] |
||||
/// Creates a WebSocket handshake from a request and a stream,
|
||||
/// upgrading the stream to TLS if required and using the given
|
||||
/// connector.
|
||||
pub async fn client_async_tls_with_connector<R, S>( |
||||
request: R, |
||||
stream: S, |
||||
connector: Option<Connector>, |
||||
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
AutoStream<S>: Unpin, |
||||
{ |
||||
client_async_tls_with_connector_and_config(request, stream, connector, None).await |
||||
} |
||||
|
||||
/// Connect to a given URL.
|
||||
pub async fn connect_async<R>( |
||||
request: R, |
||||
) -> Result<(WebSocketStream<AutoStream<TcpStream>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
{ |
||||
connect_async_with_config(request, None).await |
||||
} |
||||
|
||||
/// Connect to a given URL with a given WebSocket configuration.
|
||||
pub async fn connect_async_with_config<R>( |
||||
request: R, |
||||
config: Option<WebSocketConfig>, |
||||
) -> Result<(WebSocketStream<AutoStream<TcpStream>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
{ |
||||
let request: Request = request.into(); |
||||
|
||||
let domain = domain(&request)?; |
||||
let port = request |
||||
.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_with_connector_and_config(request, socket, None, config).await |
||||
} |
||||
|
||||
#[cfg(any(feature = "async-tls", feature = "async-native-tls"))] |
||||
/// Connect to a given URL using the provided TLS connector.
|
||||
pub async fn connect_async_with_tls_connector<R>( |
||||
request: R, |
||||
connector: Option<Connector>, |
||||
) -> Result<(WebSocketStream<AutoStream<TcpStream>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
{ |
||||
connect_async_with_tls_connector_and_config(request, connector, None).await |
||||
} |
||||
|
||||
#[cfg(any(feature = "async-tls", feature = "async-native-tls"))] |
||||
/// Connect to a given URL using the provided TLS connector.
|
||||
pub async fn connect_async_with_tls_connector_and_config<R>( |
||||
request: R, |
||||
connector: Option<Connector>, |
||||
config: Option<WebSocketConfig>, |
||||
) -> Result<(WebSocketStream<AutoStream<TcpStream>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
{ |
||||
let request: Request = request.into(); |
||||
|
||||
let domain = domain(&request)?; |
||||
let port = request |
||||
.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_with_connector_and_config(request, socket, connector, config).await |
||||
} |
@ -0,0 +1,114 @@ |
||||
//! `async-tls` integration.
|
||||
use tungstenite::client::url_mode; |
||||
use tungstenite::handshake::client::Response; |
||||
use tungstenite::protocol::WebSocketConfig; |
||||
use tungstenite::Error; |
||||
|
||||
use futures::io::{AsyncRead, AsyncWrite}; |
||||
|
||||
use super::{client_async_with_config, Request, WebSocketStream}; |
||||
|
||||
use async_tls::client::TlsStream; |
||||
use async_tls::TlsConnector as AsyncTlsConnector; |
||||
use real_async_tls as async_tls; |
||||
|
||||
use tungstenite::stream::Mode; |
||||
|
||||
use crate::domain; |
||||
use crate::stream::Stream as StreamSwitcher; |
||||
|
||||
type MaybeTlsStream<S> = StreamSwitcher<S, TlsStream<S>>; |
||||
|
||||
pub(crate) type AutoStream<S> = MaybeTlsStream<S>; |
||||
|
||||
async fn wrap_stream<S>( |
||||
socket: S, |
||||
domain: String, |
||||
connector: Option<AsyncTlsConnector>, |
||||
mode: Mode, |
||||
) -> Result<AutoStream<S>, Error> |
||||
where |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
{ |
||||
match mode { |
||||
Mode::Plain => Ok(StreamSwitcher::Plain(socket)), |
||||
Mode::Tls => { |
||||
let stream = { |
||||
let connector = connector.unwrap_or_else(AsyncTlsConnector::new); |
||||
connector.connect(&domain, socket)?.await? |
||||
}; |
||||
Ok(StreamSwitcher::Tls(stream)) |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// Creates a WebSocket handshake from a request and a stream,
|
||||
/// upgrading the stream to TLS if required.
|
||||
pub async fn client_async_tls<R, S>( |
||||
request: R, |
||||
stream: S, |
||||
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
AutoStream<S>: Unpin, |
||||
{ |
||||
client_async_tls_with_connector_and_config(request, stream, None, None).await |
||||
} |
||||
|
||||
/// Creates a WebSocket handshake from a request and a stream,
|
||||
/// upgrading the stream to TLS if required and using the given
|
||||
/// WebSocket configuration.
|
||||
pub async fn client_async_tls_with_config<R, S>( |
||||
request: R, |
||||
stream: S, |
||||
config: Option<WebSocketConfig>, |
||||
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
AutoStream<S>: Unpin, |
||||
{ |
||||
client_async_tls_with_connector_and_config(request, stream, None, config).await |
||||
} |
||||
|
||||
/// Creates a WebSocket handshake from a request and a stream,
|
||||
/// upgrading the stream to TLS if required and using the given
|
||||
/// connector.
|
||||
pub async fn client_async_tls_with_connector<R, S>( |
||||
request: R, |
||||
stream: S, |
||||
connector: Option<AsyncTlsConnector>, |
||||
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
AutoStream<S>: Unpin, |
||||
{ |
||||
client_async_tls_with_connector_and_config(request, stream, connector, None).await |
||||
} |
||||
|
||||
/// Creates a WebSocket handshake from a request and a stream,
|
||||
/// upgrading the stream to TLS if required and using the given
|
||||
/// connector and WebSocket configuration.
|
||||
pub async fn client_async_tls_with_connector_and_config<R, S>( |
||||
request: R, |
||||
stream: S, |
||||
connector: Option<AsyncTlsConnector>, |
||||
config: Option<WebSocketConfig>, |
||||
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
AutoStream<S>: Unpin, |
||||
{ |
||||
let request: Request = request.into(); |
||||
|
||||
let domain = domain(&request)?; |
||||
|
||||
// Make sure we check domain and mode first. URL must be valid.
|
||||
let mode = url_mode(&request.url)?; |
||||
|
||||
let stream = wrap_stream(stream, domain, connector, mode).await?; |
||||
client_async_with_config(request, stream, config).await |
||||
} |
@ -1,263 +0,0 @@ |
||||
//! Connection helper.
|
||||
use tungstenite::client::url_mode; |
||||
use tungstenite::handshake::client::Response; |
||||
use tungstenite::protocol::WebSocketConfig; |
||||
use tungstenite::Error; |
||||
|
||||
use futures::io::{AsyncRead, AsyncWrite}; |
||||
|
||||
use super::{client_async_with_config, Request, WebSocketStream}; |
||||
|
||||
#[cfg(feature = "tls-base")] |
||||
pub(crate) mod encryption { |
||||
#[cfg(feature = "tls")] |
||||
use async_tls::client::TlsStream; |
||||
#[cfg(feature = "tls")] |
||||
use async_tls::TlsConnector as AsyncTlsConnector; |
||||
|
||||
#[cfg(feature = "native-tls")] |
||||
use async_native_tls::TlsConnector as AsyncTlsConnector; |
||||
#[cfg(feature = "native-tls")] |
||||
use async_native_tls::TlsStream; |
||||
|
||||
use tungstenite::stream::Mode; |
||||
use tungstenite::Error; |
||||
|
||||
use futures::io::{AsyncRead, AsyncWrite}; |
||||
|
||||
use crate::stream::Stream as StreamSwitcher; |
||||
|
||||
/// A stream that might be protected with TLS.
|
||||
pub type MaybeTlsStream<S> = StreamSwitcher<S, TlsStream<S>>; |
||||
|
||||
pub type AutoStream<S> = MaybeTlsStream<S>; |
||||
#[cfg(feature = "tls")] |
||||
pub type Connector = async_tls::TlsConnector; |
||||
#[cfg(feature = "native-tls")] |
||||
pub type Connector = real_native_tls::TlsConnector; |
||||
|
||||
pub async fn wrap_stream<S>( |
||||
socket: S, |
||||
domain: String, |
||||
connector: Option<Connector>, |
||||
mode: Mode, |
||||
) -> Result<AutoStream<S>, Error> |
||||
where |
||||
S: 'static + AsyncRead + AsyncWrite + Send + Unpin, |
||||
{ |
||||
match mode { |
||||
Mode::Plain => Ok(StreamSwitcher::Plain(socket)), |
||||
Mode::Tls => { |
||||
#[cfg(feature = "tls")] |
||||
let stream = { |
||||
let connector = connector.unwrap_or_else(AsyncTlsConnector::new); |
||||
connector.connect(&domain, socket)?.await? |
||||
}; |
||||
#[cfg(feature = "native-tls")] |
||||
let stream = { |
||||
let connector = if let Some(connector) = connector { |
||||
connector |
||||
} else { |
||||
let builder = real_native_tls::TlsConnector::builder(); |
||||
builder.build()? |
||||
}; |
||||
let connector = AsyncTlsConnector::from(connector); |
||||
connector.connect(&domain, socket).await? |
||||
}; |
||||
Ok(StreamSwitcher::Tls(stream)) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
#[cfg(feature = "tls-base")] |
||||
pub use self::encryption::MaybeTlsStream; |
||||
|
||||
#[cfg(not(feature = "tls-base"))] |
||||
pub(crate) mod encryption { |
||||
use futures::io::{AsyncRead, AsyncWrite}; |
||||
|
||||
use tungstenite::stream::Mode; |
||||
use tungstenite::Error; |
||||
|
||||
pub type AutoStream<S> = S; |
||||
pub type Connector = (); |
||||
|
||||
pub(crate) async fn wrap_stream<S>( |
||||
socket: S, |
||||
_domain: String, |
||||
_connector: Option<()>, |
||||
mode: Mode, |
||||
) -> Result<AutoStream<S>, Error> |
||||
where |
||||
S: 'static + AsyncRead + AsyncWrite + Send + Unpin, |
||||
{ |
||||
match mode { |
||||
Mode::Plain => Ok(socket), |
||||
Mode::Tls => Err(Error::Url("TLS support not compiled in.".into())), |
||||
} |
||||
} |
||||
} |
||||
|
||||
use self::encryption::AutoStream; |
||||
|
||||
/// Get a domain from an URL.
|
||||
#[inline] |
||||
fn domain(request: &Request) -> Result<String, Error> { |
||||
match request.url.host_str() { |
||||
Some(d) => Ok(d.to_string()), |
||||
None => Err(Error::Url("no host name in the url".into())), |
||||
} |
||||
} |
||||
|
||||
/// Creates a WebSocket handshake from a request and a stream,
|
||||
/// upgrading the stream to TLS if required.
|
||||
pub async fn client_async_tls<R, S>( |
||||
request: R, |
||||
stream: S, |
||||
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
S: 'static + AsyncRead + AsyncWrite + Send + Unpin, |
||||
AutoStream<S>: Unpin, |
||||
{ |
||||
client_async_tls_with_connector_and_config(request, stream, None, None).await |
||||
} |
||||
|
||||
/// Creates a WebSocket handshake from a request and a stream,
|
||||
/// upgrading the stream to TLS if required and using the given
|
||||
/// WebSocket configuration.
|
||||
pub async fn client_async_tls_with_config<R, S>( |
||||
request: R, |
||||
stream: S, |
||||
config: Option<WebSocketConfig>, |
||||
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
S: 'static + AsyncRead + AsyncWrite + Send + Unpin, |
||||
AutoStream<S>: Unpin, |
||||
{ |
||||
client_async_tls_with_connector_and_config(request, stream, None, config).await |
||||
} |
||||
|
||||
/// Creates a WebSocket handshake from a request and a stream,
|
||||
/// upgrading the stream to TLS if required and using the given
|
||||
/// connector.
|
||||
pub async fn client_async_tls_with_connector<R, S>( |
||||
request: R, |
||||
stream: S, |
||||
connector: Option<self::encryption::Connector>, |
||||
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
S: 'static + AsyncRead + AsyncWrite + Send + Unpin, |
||||
AutoStream<S>: Unpin, |
||||
{ |
||||
client_async_tls_with_connector_and_config(request, stream, connector, None).await |
||||
} |
||||
|
||||
/// Creates a WebSocket handshake from a request and a stream,
|
||||
/// upgrading the stream to TLS if required and using the given
|
||||
/// connector and WebSocket configuration.
|
||||
pub async fn client_async_tls_with_connector_and_config<R, S>( |
||||
request: R, |
||||
stream: S, |
||||
connector: Option<self::encryption::Connector>, |
||||
config: Option<WebSocketConfig>, |
||||
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
S: 'static + AsyncRead + AsyncWrite + Send + Unpin, |
||||
AutoStream<S>: Unpin, |
||||
{ |
||||
let request: Request = request.into(); |
||||
|
||||
let domain = domain(&request)?; |
||||
|
||||
// Make sure we check domain and mode first. URL must be valid.
|
||||
let mode = url_mode(&request.url)?; |
||||
|
||||
let stream = self::encryption::wrap_stream(stream, domain, connector, mode).await?; |
||||
client_async_with_config(request, stream, config).await |
||||
} |
||||
|
||||
#[cfg(feature = "async_std_runtime")] |
||||
pub(crate) mod async_std_runtime { |
||||
use super::*; |
||||
use async_std::net::TcpStream; |
||||
|
||||
/// Connect to a given URL.
|
||||
pub async fn connect_async<R>( |
||||
request: R, |
||||
) -> Result<(WebSocketStream<AutoStream<TcpStream>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
{ |
||||
connect_async_with_config(request, None).await |
||||
} |
||||
|
||||
/// Connect to a given URL with a given WebSocket configuration.
|
||||
pub async fn connect_async_with_config<R>( |
||||
request: R, |
||||
config: Option<WebSocketConfig>, |
||||
) -> Result<(WebSocketStream<AutoStream<TcpStream>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
{ |
||||
let request: Request = request.into(); |
||||
|
||||
let domain = domain(&request)?; |
||||
let port = request |
||||
.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_with_config(request, socket, config).await |
||||
} |
||||
|
||||
#[cfg(any(feature = "tls", feature = "native-tls"))] |
||||
/// Connect to a given URL using the provided TLS connector.
|
||||
pub async fn connect_async_with_tls_connector<R>( |
||||
request: R, |
||||
connector: Option<super::encryption::Connector>, |
||||
) -> Result<(WebSocketStream<AutoStream<TcpStream>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
{ |
||||
connect_async_with_tls_connector_and_config(request, connector, None).await |
||||
} |
||||
|
||||
#[cfg(any(feature = "tls", feature = "native-tls"))] |
||||
/// Connect to a given URL using the provided TLS connector.
|
||||
pub async fn connect_async_with_tls_connector_and_config<R>( |
||||
request: R, |
||||
connector: Option<super::encryption::Connector>, |
||||
config: Option<WebSocketConfig>, |
||||
) -> Result<(WebSocketStream<AutoStream<TcpStream>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
{ |
||||
let request: Request = request.into(); |
||||
|
||||
let domain = domain(&request)?; |
||||
let port = request |
||||
.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_with_connector_and_config(request, socket, connector, config).await |
||||
} |
||||
} |
||||
|
||||
#[cfg(feature = "async_std_runtime")] |
||||
pub use async_std_runtime::{connect_async, connect_async_with_config}; |
||||
#[cfg(all(
|
||||
feature = "async_std_runtime", |
||||
any(feature = "tls", feature = "native-tls") |
||||
))] |
||||
pub use async_std_runtime::{ |
||||
connect_async_with_tls_connector, connect_async_with_tls_connector_and_config, |
||||
}; |
@ -0,0 +1,137 @@ |
||||
//! `gio` integration.
|
||||
use tungstenite::Error; |
||||
|
||||
use std::io; |
||||
|
||||
use gio::prelude::*; |
||||
|
||||
use futures::io::{AsyncRead, AsyncWrite}; |
||||
|
||||
use tungstenite::client::url_mode; |
||||
use tungstenite::stream::Mode; |
||||
|
||||
use crate::{ |
||||
client_async_with_config, domain, Request, Response, WebSocketConfig, WebSocketStream, |
||||
}; |
||||
|
||||
type MaybeTlsStream = IOStreamAsyncReadWrite<gio::SocketConnection>; |
||||
|
||||
/// Connect to a given URL.
|
||||
pub async fn connect_async<R>( |
||||
request: R, |
||||
) -> Result<(WebSocketStream<MaybeTlsStream>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
{ |
||||
connect_async_with_config(request, None).await |
||||
} |
||||
|
||||
/// Connect to a given URL with a given WebSocket configuration.
|
||||
pub async fn connect_async_with_config<R>( |
||||
request: R, |
||||
config: Option<WebSocketConfig>, |
||||
) -> Result<(WebSocketStream<MaybeTlsStream>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
{ |
||||
let request: Request = request.into(); |
||||
|
||||
let domain = domain(&request)?; |
||||
let port = request |
||||
.url |
||||
.port_or_known_default() |
||||
.expect("Bug: port unknown"); |
||||
|
||||
let client = gio::SocketClient::new(); |
||||
|
||||
// Make sure we check domain and mode first. URL must be valid.
|
||||
let mode = url_mode(&request.url)?; |
||||
if let Mode::Tls = mode { |
||||
client.set_tls(true); |
||||
} else { |
||||
client.set_tls(false); |
||||
} |
||||
|
||||
let connectable = gio::NetworkAddress::new(domain.as_str(), port); |
||||
|
||||
let socket = client |
||||
.connect_async_future(&connectable) |
||||
.await |
||||
.map_err(|err| to_std_io_error(err))?; |
||||
let socket = IOStreamAsyncReadWrite::new(socket) |
||||
.map_err(|_| io::Error::new(io::ErrorKind::Other, "Unsupported gio::IOStream"))?; |
||||
|
||||
client_async_with_config(request, socket, config).await |
||||
} |
||||
|
||||
/// Adapter for `gio::IOStream` to provide `AsyncRead` and `AsyncWrite`.
|
||||
#[derive(Debug)] |
||||
pub struct IOStreamAsyncReadWrite<T: IsA<gio::IOStream>> { |
||||
io_stream: T, |
||||
read: gio::InputStreamAsyncRead<gio::PollableInputStream>, |
||||
write: gio::OutputStreamAsyncWrite<gio::PollableOutputStream>, |
||||
} |
||||
|
||||
impl<T: IsA<gio::IOStream>> IOStreamAsyncReadWrite<T> { |
||||
/// Create a new `gio::IOStream` adapter
|
||||
pub fn new(stream: T) -> Result<IOStreamAsyncReadWrite<T>, T> { |
||||
let write = stream |
||||
.get_output_stream() |
||||
.and_then(|s| s.dynamic_cast::<gio::PollableOutputStream>().ok()) |
||||
.and_then(|s| s.into_async_write().ok()); |
||||
|
||||
let read = stream |
||||
.get_input_stream() |
||||
.and_then(|s| s.dynamic_cast::<gio::PollableInputStream>().ok()) |
||||
.and_then(|s| s.into_async_read().ok()); |
||||
|
||||
let (read, write) = match (read, write) { |
||||
(Some(read), Some(write)) => (read, write), |
||||
_ => return Err(stream), |
||||
}; |
||||
|
||||
Ok(IOStreamAsyncReadWrite { |
||||
io_stream: stream, |
||||
read, |
||||
write, |
||||
}) |
||||
} |
||||
} |
||||
|
||||
use std::pin::Pin; |
||||
use std::task::{Context, Poll}; |
||||
|
||||
impl<T: IsA<gio::IOStream> + Unpin> AsyncRead for IOStreamAsyncReadWrite<T> { |
||||
fn poll_read( |
||||
self: Pin<&mut Self>, |
||||
cx: &mut Context<'_>, |
||||
buf: &mut [u8], |
||||
) -> Poll<Result<usize, io::Error>> { |
||||
Pin::new(&mut Pin::get_mut(self).read).poll_read(cx, buf) |
||||
} |
||||
} |
||||
|
||||
impl<T: IsA<gio::IOStream> + Unpin> AsyncWrite for IOStreamAsyncReadWrite<T> { |
||||
fn poll_write( |
||||
self: Pin<&mut Self>, |
||||
cx: &mut Context<'_>, |
||||
buf: &[u8], |
||||
) -> Poll<Result<usize, io::Error>> { |
||||
Pin::new(&mut Pin::get_mut(self).write).poll_write(cx, buf) |
||||
} |
||||
|
||||
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> { |
||||
Pin::new(&mut Pin::get_mut(self).write).poll_close(cx) |
||||
} |
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> { |
||||
Pin::new(&mut Pin::get_mut(self).write).poll_flush(cx) |
||||
} |
||||
} |
||||
|
||||
fn to_std_io_error(error: glib::Error) -> io::Error { |
||||
match error.kind::<gio::IOErrorEnum>() { |
||||
Some(io_error_enum) => io::Error::new(io_error_enum.into(), error), |
||||
None => io::Error::new(io::ErrorKind::Other, error), |
||||
} |
||||
} |
@ -0,0 +1,363 @@ |
||||
//! `tokio` integration.
|
||||
use tungstenite::handshake::client::Response; |
||||
use tungstenite::protocol::WebSocketConfig; |
||||
use tungstenite::Error; |
||||
|
||||
use tokio::net::TcpStream; |
||||
|
||||
use super::{domain, Request, WebSocketStream}; |
||||
|
||||
use futures::io::{AsyncRead, AsyncWrite}; |
||||
|
||||
#[cfg(feature = "tokio-tls")] |
||||
pub(crate) mod tokio_tls { |
||||
use real_tokio_tls::TlsConnector as AsyncTlsConnector; |
||||
use real_tokio_tls::TlsStream; |
||||
|
||||
use tungstenite::client::url_mode; |
||||
use tungstenite::stream::Mode; |
||||
use tungstenite::Error; |
||||
|
||||
use futures::io::{AsyncRead, AsyncWrite}; |
||||
|
||||
use crate::stream::Stream as StreamSwitcher; |
||||
use crate::{ |
||||
client_async_with_config, domain, Request, Response, WebSocketConfig, WebSocketStream, |
||||
}; |
||||
|
||||
use super::TokioAdapter; |
||||
|
||||
/// A stream that might be protected with TLS.
|
||||
pub type MaybeTlsStream<S> = StreamSwitcher<S, TokioAdapter<TlsStream<TokioAdapter<S>>>>; |
||||
|
||||
pub type AutoStream<S> = MaybeTlsStream<S>; |
||||
|
||||
pub type Connector = AsyncTlsConnector; |
||||
|
||||
async fn wrap_stream<S>( |
||||
socket: S, |
||||
domain: String, |
||||
connector: Option<Connector>, |
||||
mode: Mode, |
||||
) -> Result<AutoStream<S>, Error> |
||||
where |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
{ |
||||
match mode { |
||||
Mode::Plain => Ok(StreamSwitcher::Plain(socket)), |
||||
Mode::Tls => { |
||||
let stream = { |
||||
let connector = if let Some(connector) = connector { |
||||
connector |
||||
} else { |
||||
let connector = real_native_tls::TlsConnector::builder().build()?; |
||||
AsyncTlsConnector::from(connector) |
||||
}; |
||||
connector |
||||
.connect(&domain, TokioAdapter(socket)) |
||||
.await |
||||
.map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))? |
||||
}; |
||||
Ok(StreamSwitcher::Tls(TokioAdapter(stream))) |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// Creates a WebSocket handshake from a request and a stream,
|
||||
/// upgrading the stream to TLS if required and using the given
|
||||
/// connector and WebSocket configuration.
|
||||
pub async fn client_async_tls_with_connector_and_config<R, S>( |
||||
request: R, |
||||
stream: S, |
||||
connector: Option<AsyncTlsConnector>, |
||||
config: Option<WebSocketConfig>, |
||||
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
AutoStream<S>: Unpin, |
||||
{ |
||||
let request: Request = request.into(); |
||||
|
||||
let domain = domain(&request)?; |
||||
|
||||
// Make sure we check domain and mode first. URL must be valid.
|
||||
let mode = url_mode(&request.url)?; |
||||
|
||||
let stream = wrap_stream(stream, domain, connector, mode).await?; |
||||
client_async_with_config(request, stream, config).await |
||||
} |
||||
} |
||||
|
||||
#[cfg(not(any(feature = "async-tls", feature = "tokio-tls")))] |
||||
pub(crate) mod dummy_tls { |
||||
use futures::io::{AsyncRead, AsyncWrite}; |
||||
|
||||
use tungstenite::client::url_mode; |
||||
use tungstenite::stream::Mode; |
||||
use tungstenite::Error; |
||||
|
||||
use crate::{ |
||||
client_async_with_config, domain, Request, Response, WebSocketConfig, WebSocketStream, |
||||
}; |
||||
|
||||
pub type AutoStream<S> = S; |
||||
type Connector = (); |
||||
|
||||
async fn wrap_stream<S>( |
||||
socket: S, |
||||
_domain: String, |
||||
_connector: Option<()>, |
||||
mode: Mode, |
||||
) -> Result<AutoStream<S>, Error> |
||||
where |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
{ |
||||
match mode { |
||||
Mode::Plain => Ok(socket), |
||||
Mode::Tls => Err(Error::Url("TLS support not compiled in.".into())), |
||||
} |
||||
} |
||||
|
||||
pub(crate) async fn client_async_tls_with_connector_and_config<R, S>( |
||||
request: R, |
||||
stream: S, |
||||
connector: Option<Connector>, |
||||
config: Option<WebSocketConfig>, |
||||
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
AutoStream<S>: Unpin, |
||||
{ |
||||
let request: Request = request.into(); |
||||
|
||||
let domain = domain(&request)?; |
||||
|
||||
// Make sure we check domain and mode first. URL must be valid.
|
||||
let mode = url_mode(&request.url)?; |
||||
|
||||
let stream = wrap_stream(stream, domain, connector, mode).await?; |
||||
client_async_with_config(request, stream, config).await |
||||
} |
||||
} |
||||
|
||||
#[cfg(not(any(feature = "async-tls", feature = "tokio-tls")))] |
||||
use self::dummy_tls::{client_async_tls_with_connector_and_config, AutoStream}; |
||||
|
||||
#[cfg(all(feature = "async-tls", not(feature = "tokio-tls")))] |
||||
use crate::async_tls::{client_async_tls_with_connector_and_config, AutoStream}; |
||||
#[cfg(all(feature = "async-tls", not(feature = "tokio-tls")))] |
||||
type Connector = real_async_tls::TlsConnector; |
||||
|
||||
#[cfg(feature = "tokio-tls")] |
||||
use self::tokio_tls::{client_async_tls_with_connector_and_config, AutoStream, Connector}; |
||||
|
||||
#[cfg(feature = "tokio-tls")] |
||||
/// Creates a WebSocket handshake from a request and a stream,
|
||||
/// upgrading the stream to TLS if required.
|
||||
pub async fn client_async_tls<R, S>( |
||||
request: R, |
||||
stream: S, |
||||
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
AutoStream<S>: Unpin, |
||||
{ |
||||
client_async_tls_with_connector_and_config(request, stream, None, None).await |
||||
} |
||||
|
||||
#[cfg(feature = "tokio-tls")] |
||||
/// Creates a WebSocket handshake from a request and a stream,
|
||||
/// upgrading the stream to TLS if required and using the given
|
||||
/// WebSocket configuration.
|
||||
pub async fn client_async_tls_with_config<R, S>( |
||||
request: R, |
||||
stream: S, |
||||
config: Option<WebSocketConfig>, |
||||
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
AutoStream<S>: Unpin, |
||||
{ |
||||
client_async_tls_with_connector_and_config(request, stream, None, config).await |
||||
} |
||||
|
||||
#[cfg(feature = "tokio-tls")] |
||||
/// Creates a WebSocket handshake from a request and a stream,
|
||||
/// upgrading the stream to TLS if required and using the given
|
||||
/// connector.
|
||||
pub async fn client_async_tls_with_connector<R, S>( |
||||
request: R, |
||||
stream: S, |
||||
connector: Option<Connector>, |
||||
) -> Result<(WebSocketStream<AutoStream<S>>, Response), Error> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
S: 'static + AsyncRead + AsyncWrite + Unpin, |
||||
AutoStream<S>: Unpin, |
||||
{ |
||||
client_async_tls_with_connector_and_config(request, stream, connector, None).await |
||||
} |
||||
|
||||
/// Connect to a given URL.
|
||||
pub async fn connect_async<R>( |
||||
request: R, |
||||
) -> Result< |
||||
( |
||||
WebSocketStream<AutoStream<TokioAdapter<TcpStream>>>, |
||||
Response, |
||||
), |
||||
Error, |
||||
> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
{ |
||||
connect_async_with_config(request, None).await |
||||
} |
||||
|
||||
/// Connect to a given URL with a given WebSocket configuration.
|
||||
pub async fn connect_async_with_config<R>( |
||||
request: R, |
||||
config: Option<WebSocketConfig>, |
||||
) -> Result< |
||||
( |
||||
WebSocketStream<AutoStream<TokioAdapter<TcpStream>>>, |
||||
Response, |
||||
), |
||||
Error, |
||||
> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
{ |
||||
let request: Request = request.into(); |
||||
|
||||
let domain = domain(&request)?; |
||||
let port = request |
||||
.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_with_connector_and_config(request, TokioAdapter(socket), None, config).await |
||||
} |
||||
|
||||
#[cfg(any(feature = "async-tls", feature = "tokio-tls"))] |
||||
/// Connect to a given URL using the provided TLS connector.
|
||||
pub async fn connect_async_with_tls_connector<R>( |
||||
request: R, |
||||
connector: Option<Connector>, |
||||
) -> Result< |
||||
( |
||||
WebSocketStream<AutoStream<TokioAdapter<TcpStream>>>, |
||||
Response, |
||||
), |
||||
Error, |
||||
> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
{ |
||||
connect_async_with_tls_connector_and_config(request, connector, None).await |
||||
} |
||||
|
||||
#[cfg(any(feature = "async-tls", feature = "tokio-tls"))] |
||||
/// Connect to a given URL using the provided TLS connector.
|
||||
pub async fn connect_async_with_tls_connector_and_config<R>( |
||||
request: R, |
||||
connector: Option<Connector>, |
||||
config: Option<WebSocketConfig>, |
||||
) -> Result< |
||||
( |
||||
WebSocketStream<AutoStream<TokioAdapter<TcpStream>>>, |
||||
Response, |
||||
), |
||||
Error, |
||||
> |
||||
where |
||||
R: Into<Request<'static>> + Unpin, |
||||
{ |
||||
let request: Request = request.into(); |
||||
|
||||
let domain = domain(&request)?; |
||||
let port = request |
||||
.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_with_connector_and_config(request, TokioAdapter(socket), connector, config) |
||||
.await |
||||
} |
||||
|
||||
use pin_project::pin_project; |
||||
use std::pin::Pin; |
||||
use std::task::{Context, Poll}; |
||||
|
||||
/// Adapter for `tokio::io::AsyncRead` and `tokio::io::AsyncWrite` to provide
|
||||
/// the variants from the `futures` crate and the other way around.
|
||||
#[pin_project] |
||||
#[derive(Debug, Clone)] |
||||
pub struct TokioAdapter<T>(#[pin] pub T); |
||||
|
||||
impl<T: tokio::io::AsyncRead> AsyncRead for TokioAdapter<T> { |
||||
fn poll_read( |
||||
self: Pin<&mut Self>, |
||||
cx: &mut Context<'_>, |
||||
buf: &mut [u8], |
||||
) -> Poll<std::io::Result<usize>> { |
||||
self.project().0.poll_read(cx, buf) |
||||
} |
||||
} |
||||
|
||||
impl<T: tokio::io::AsyncWrite> AsyncWrite for TokioAdapter<T> { |
||||
fn poll_write( |
||||
self: Pin<&mut Self>, |
||||
cx: &mut Context<'_>, |
||||
buf: &[u8], |
||||
) -> Poll<Result<usize, std::io::Error>> { |
||||
self.project().0.poll_write(cx, buf) |
||||
} |
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), std::io::Error>> { |
||||
self.project().0.poll_flush(cx) |
||||
} |
||||
|
||||
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), std::io::Error>> { |
||||
self.project().0.poll_shutdown(cx) |
||||
} |
||||
} |
||||
|
||||
impl<T: AsyncRead> tokio::io::AsyncRead for TokioAdapter<T> { |
||||
fn poll_read( |
||||
self: Pin<&mut Self>, |
||||
cx: &mut Context<'_>, |
||||
buf: &mut [u8], |
||||
) -> Poll<std::io::Result<usize>> { |
||||
self.project().0.poll_read(cx, buf) |
||||
} |
||||
} |
||||
|
||||
impl<T: AsyncWrite> tokio::io::AsyncWrite for TokioAdapter<T> { |
||||
fn poll_write( |
||||
self: Pin<&mut Self>, |
||||
cx: &mut Context<'_>, |
||||
buf: &[u8], |
||||
) -> Poll<Result<usize, std::io::Error>> { |
||||
self.project().0.poll_write(cx, buf) |
||||
} |
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), std::io::Error>> { |
||||
self.project().0.poll_flush(cx) |
||||
} |
||||
|
||||
fn poll_shutdown( |
||||
self: Pin<&mut Self>, |
||||
cx: &mut Context<'_>, |
||||
) -> Poll<Result<(), std::io::Error>> { |
||||
self.project().0.poll_close(cx) |
||||
} |
||||
} |
Loading…
Reference in new issue