refactor and make tcp work
This commit is contained in:
@@ -14,7 +14,6 @@ use protocol::tcp::RawTcpProtocolHandler;
|
||||
use protocol::udp::RawUdpProtocolHandler;
|
||||
use protocol::ws::WebsocketProtocolHandler;
|
||||
pub use protocol::*;
|
||||
use utils::async_peek_stream::*;
|
||||
use utils::network_interfaces::*;
|
||||
|
||||
use async_std::io;
|
||||
@@ -302,6 +301,8 @@ impl Network {
|
||||
}
|
||||
|
||||
// Handle connection-oriented protocols
|
||||
|
||||
// Try to send to the exact existing connection if one exists
|
||||
if let Some(conn) = self.connection_manager().get_connection(descriptor).await {
|
||||
// connection exists, send over it
|
||||
conn.send(data).await.map_err(logthru_net!())?;
|
||||
@@ -355,7 +356,8 @@ impl Network {
|
||||
match self
|
||||
.clone()
|
||||
.send_data_to_existing_connection(descriptor, data)
|
||||
.await?
|
||||
.await
|
||||
.map_err(logthru_net!())?
|
||||
{
|
||||
None => {
|
||||
return Ok(());
|
||||
@@ -371,7 +373,9 @@ impl Network {
|
||||
.best_dial_info()
|
||||
.ok_or_else(|| "couldn't send data, no dial info or peer address".to_owned())?;
|
||||
|
||||
self.send_data_to_dial_info(dial_info, data).await
|
||||
self.send_data_to_dial_info(dial_info, data)
|
||||
.await
|
||||
.map_err(logthru_net!())
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
@@ -1,8 +1,6 @@
|
||||
use super::*;
|
||||
use crate::intf::*;
|
||||
use crate::network_connection::*;
|
||||
use utils::clone_stream::*;
|
||||
|
||||
use async_tls::TlsAcceptor;
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
@@ -135,7 +133,7 @@ impl Network {
|
||||
let addr = match tcp_stream.peer_addr() {
|
||||
Ok(addr) => addr,
|
||||
Err(e) => {
|
||||
error!("failed to get peer address: {}", e);
|
||||
log_net!(error "failed to get peer address: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -159,6 +157,7 @@ impl Network {
|
||||
{
|
||||
// If we fail to get a packet within the connection initial timeout
|
||||
// then we punt this connection
|
||||
log_net!(warn "connection initial timeout from: {:?}", addr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -56,7 +56,7 @@ impl ProtocolNetworkConnection {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn close(&mut self) -> Result<(), String> {
|
||||
pub async fn close(&self) -> Result<(), String> {
|
||||
match self {
|
||||
Self::Dummy(d) => d.close(),
|
||||
Self::RawTcp(t) => t.close().await,
|
||||
@@ -66,7 +66,7 @@ impl ProtocolNetworkConnection {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn send(&mut self, message: Vec<u8>) -> Result<(), String> {
|
||||
pub async fn send(&self, message: Vec<u8>) -> Result<(), String> {
|
||||
match self {
|
||||
Self::Dummy(d) => d.send(message),
|
||||
Self::RawTcp(t) => t.send(message).await,
|
||||
@@ -75,7 +75,7 @@ impl ProtocolNetworkConnection {
|
||||
Self::Wss(w) => w.send(message).await,
|
||||
}
|
||||
}
|
||||
pub async fn recv(&mut self) -> Result<Vec<u8>, String> {
|
||||
pub async fn recv(&self) -> Result<Vec<u8>, String> {
|
||||
match self {
|
||||
Self::Dummy(d) => d.recv(),
|
||||
Self::RawTcp(t) => t.recv().await,
|
||||
|
@@ -1,5 +1,4 @@
|
||||
use super::*;
|
||||
use crate::intf::native::utils::async_peek_stream::*;
|
||||
use crate::intf::*;
|
||||
use crate::network_manager::MAX_MESSAGE_SIZE;
|
||||
use crate::*;
|
||||
@@ -22,37 +21,43 @@ impl RawTcpNetworkConnection {
|
||||
Self { stream }
|
||||
}
|
||||
|
||||
pub async fn close(&mut self) -> Result<(), String> {
|
||||
pub async fn close(&self) -> Result<(), String> {
|
||||
self.stream
|
||||
.clone()
|
||||
.close()
|
||||
.await
|
||||
.map_err(map_to_string)
|
||||
.map_err(logthru_net!())
|
||||
}
|
||||
|
||||
pub async fn send(&mut self, message: Vec<u8>) -> Result<(), String> {
|
||||
pub async fn send(&self, message: Vec<u8>) -> Result<(), String> {
|
||||
log_net!("sending TCP message of size {}", message.len());
|
||||
if message.len() > MAX_MESSAGE_SIZE {
|
||||
return Err("sending too large TCP message".to_owned());
|
||||
}
|
||||
let len = message.len() as u16;
|
||||
let header = [b'V', b'L', len as u8, (len >> 8) as u8];
|
||||
|
||||
self.stream
|
||||
let mut stream = self.stream.clone();
|
||||
|
||||
stream
|
||||
.write_all(&header)
|
||||
.await
|
||||
.map_err(map_to_string)
|
||||
.map_err(logthru_net!())?;
|
||||
self.stream
|
||||
stream
|
||||
.write_all(&message)
|
||||
.await
|
||||
.map_err(map_to_string)
|
||||
.map_err(logthru_net!())
|
||||
}
|
||||
|
||||
pub async fn recv(&mut self) -> Result<Vec<u8>, String> {
|
||||
pub async fn recv(&self) -> Result<Vec<u8>, String> {
|
||||
let mut header = [0u8; 4];
|
||||
|
||||
self.stream
|
||||
let mut stream = self.stream.clone();
|
||||
|
||||
stream
|
||||
.read_exact(&mut header)
|
||||
.await
|
||||
.map_err(|e| format!("TCP recv error: {}", e))?;
|
||||
@@ -65,10 +70,7 @@ impl RawTcpNetworkConnection {
|
||||
}
|
||||
|
||||
let mut out: Vec<u8> = vec![0u8; len];
|
||||
self.stream
|
||||
.read_exact(&mut out)
|
||||
.await
|
||||
.map_err(map_to_string)?;
|
||||
stream.read_exact(&mut out).await.map_err(map_to_string)?;
|
||||
Ok(out)
|
||||
}
|
||||
}
|
||||
@@ -122,6 +124,8 @@ impl RawTcpProtocolHandler {
|
||||
ProtocolNetworkConnection::RawTcp(RawTcpNetworkConnection::new(stream)),
|
||||
);
|
||||
|
||||
warn!("on_accept_async from: {}", socket_addr);
|
||||
|
||||
Ok(Some(conn))
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,4 @@
|
||||
use super::*;
|
||||
use crate::intf::native::utils::async_peek_stream::*;
|
||||
use crate::intf::*;
|
||||
use crate::network_manager::MAX_MESSAGE_SIZE;
|
||||
use crate::*;
|
||||
@@ -19,31 +18,12 @@ pub type WebsocketNetworkConnectionWSS =
|
||||
WebsocketNetworkConnection<async_tls::client::TlsStream<async_std::net::TcpStream>>;
|
||||
pub type WebsocketNetworkConnectionWS = WebsocketNetworkConnection<async_std::net::TcpStream>;
|
||||
|
||||
struct WebSocketNetworkConnectionInner<T>
|
||||
where
|
||||
T: io::Read + io::Write + Send + Unpin + 'static,
|
||||
{
|
||||
ws_stream: WebSocketStream<T>,
|
||||
}
|
||||
|
||||
pub struct WebsocketNetworkConnection<T>
|
||||
where
|
||||
T: io::Read + io::Write + Send + Unpin + 'static,
|
||||
{
|
||||
tls: bool,
|
||||
inner: Arc<AsyncMutex<WebSocketNetworkConnectionInner<T>>>,
|
||||
}
|
||||
|
||||
impl<T> Clone for WebsocketNetworkConnection<T>
|
||||
where
|
||||
T: io::Read + io::Write + Send + Unpin + 'static,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
tls: self.tls,
|
||||
inner: self.inner.clone(),
|
||||
}
|
||||
}
|
||||
ws_stream: CloneStream<WebSocketStream<T>>,
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for WebsocketNetworkConnection<T>
|
||||
@@ -62,38 +42,28 @@ where
|
||||
pub fn new(tls: bool, ws_stream: WebSocketStream<T>) -> Self {
|
||||
Self {
|
||||
tls,
|
||||
inner: Arc::new(AsyncMutex::new(WebSocketNetworkConnectionInner {
|
||||
ws_stream,
|
||||
})),
|
||||
ws_stream: CloneStream::new(ws_stream),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn close(&self) -> Result<(), String> {
|
||||
let mut inner = self.inner.lock().await;
|
||||
inner
|
||||
.ws_stream
|
||||
.close(None)
|
||||
.await
|
||||
.map_err(map_to_string)
|
||||
.map_err(logthru_net!(error "failed to close websocket"))
|
||||
self.ws_stream.clone().close().await.map_err(map_to_string)
|
||||
}
|
||||
|
||||
pub async fn send(&self, message: Vec<u8>) -> Result<(), String> {
|
||||
if message.len() > MAX_MESSAGE_SIZE {
|
||||
return Err("received too large WS message".to_owned());
|
||||
}
|
||||
let mut inner = self.inner.lock().await;
|
||||
inner
|
||||
.ws_stream
|
||||
self.ws_stream
|
||||
.clone()
|
||||
.send(Message::binary(message))
|
||||
.await
|
||||
.map_err(map_to_string)
|
||||
.map_err(logthru_net!(error "failed to send websocket message"))
|
||||
}
|
||||
pub async fn recv(&self) -> Result<Vec<u8>, String> {
|
||||
let mut inner = self.inner.lock().await;
|
||||
|
||||
let out = match inner.ws_stream.next().await {
|
||||
pub async fn recv(&self) -> Result<Vec<u8>, String> {
|
||||
let out = match self.ws_stream.clone().next().await {
|
||||
Some(Ok(Message::Binary(v))) => v,
|
||||
Some(Ok(_)) => {
|
||||
return Err("Unexpected WS message type".to_owned()).map_err(logthru_net!(error));
|
||||
|
@@ -1,171 +0,0 @@
|
||||
use crate::xx::*;
|
||||
use async_std::io::{Read, ReadExt, Result, Write};
|
||||
use core::pin::Pin;
|
||||
use core::task::{Context, Poll};
|
||||
|
||||
////////
|
||||
///
|
||||
trait SendStream: Read + Write + Send + Unpin {
|
||||
fn clone_stream(&self) -> Box<dyn SendStream>;
|
||||
}
|
||||
impl<S> SendStream for S
|
||||
where
|
||||
S: Read + Write + Send + Clone + Unpin + 'static,
|
||||
{
|
||||
fn clone_stream(&self) -> Box<dyn SendStream> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/////////
|
||||
///
|
||||
struct AsyncPeekStreamInner {
|
||||
stream: Box<dyn SendStream>,
|
||||
peekbuf: Vec<u8>,
|
||||
peekbuf_len: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AsyncPeekStream
|
||||
where
|
||||
Self: Read + Write + Send + Unpin,
|
||||
{
|
||||
inner: Arc<Mutex<AsyncPeekStreamInner>>,
|
||||
}
|
||||
|
||||
impl AsyncPeekStream {
|
||||
pub fn new<S>(stream: S) -> Self
|
||||
where
|
||||
S: Read + Write + Send + Clone + Unpin + 'static,
|
||||
{
|
||||
Self {
|
||||
inner: Arc::new(Mutex::new(AsyncPeekStreamInner {
|
||||
stream: Box::new(stream),
|
||||
peekbuf: Vec::new(),
|
||||
peekbuf_len: 0,
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn peek(&'_ self, buf: &'_ mut [u8]) -> Result<usize> {
|
||||
let (mut stream, mut peekbuf, mut peekbuf_len) = {
|
||||
let inner = self.inner.lock();
|
||||
(
|
||||
inner.stream.clone_stream(),
|
||||
inner.peekbuf.clone(),
|
||||
inner.peekbuf_len,
|
||||
)
|
||||
};
|
||||
//
|
||||
let buf_len = buf.len();
|
||||
let mut copy_len = buf_len;
|
||||
if buf_len > peekbuf_len {
|
||||
//
|
||||
peekbuf.resize(buf_len, 0u8);
|
||||
let read_len = stream
|
||||
.read(&mut peekbuf.as_mut_slice()[peekbuf_len..buf_len])
|
||||
.await?;
|
||||
peekbuf_len += read_len;
|
||||
copy_len = peekbuf_len;
|
||||
}
|
||||
buf[..copy_len].copy_from_slice(&peekbuf[..copy_len]);
|
||||
|
||||
let mut inner = self.inner.lock();
|
||||
inner.peekbuf = peekbuf;
|
||||
inner.peekbuf_len = peekbuf_len;
|
||||
Ok(copy_len)
|
||||
}
|
||||
|
||||
pub async fn peek_exact(&'_ self, buf: &'_ mut [u8]) -> Result<()> {
|
||||
let (mut stream, mut peekbuf, mut peekbuf_len) = {
|
||||
let inner = self.inner.lock();
|
||||
(
|
||||
inner.stream.clone_stream(),
|
||||
inner.peekbuf.clone(),
|
||||
inner.peekbuf_len,
|
||||
)
|
||||
};
|
||||
//
|
||||
let buf_len = buf.len();
|
||||
if buf_len > peekbuf_len {
|
||||
//
|
||||
peekbuf.resize(buf_len, 0u8);
|
||||
stream
|
||||
.read_exact(&mut peekbuf.as_mut_slice()[peekbuf_len..buf_len])
|
||||
.await?;
|
||||
peekbuf_len = buf_len;
|
||||
}
|
||||
buf.copy_from_slice(&peekbuf[..buf_len]);
|
||||
|
||||
let mut inner = self.inner.lock();
|
||||
inner.peekbuf = peekbuf;
|
||||
inner.peekbuf_len = peekbuf_len;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for AsyncPeekStream {
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<Result<usize>> {
|
||||
let mut inner = self.inner.lock();
|
||||
//
|
||||
let buflen = buf.len();
|
||||
let bufcopylen = cmp::min(buflen, inner.peekbuf_len);
|
||||
let bufreadlen = if buflen > inner.peekbuf_len {
|
||||
buflen - inner.peekbuf_len
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
if bufreadlen > 0 {
|
||||
match Pin::new(&mut inner.stream).poll_read(cx, &mut buf[bufcopylen..buflen]) {
|
||||
Poll::Ready(res) => {
|
||||
let readlen = res?;
|
||||
buf[0..bufcopylen].copy_from_slice(&inner.peekbuf[0..bufcopylen]);
|
||||
inner.peekbuf_len = 0;
|
||||
Poll::Ready(Ok(bufcopylen + readlen))
|
||||
}
|
||||
Poll::Pending => {
|
||||
if bufcopylen > 0 {
|
||||
buf[0..bufcopylen].copy_from_slice(&inner.peekbuf[0..bufcopylen]);
|
||||
inner.peekbuf_len = 0;
|
||||
Poll::Ready(Ok(bufcopylen))
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buf[0..bufcopylen].copy_from_slice(&inner.peekbuf[0..bufcopylen]);
|
||||
if bufcopylen == inner.peekbuf_len {
|
||||
inner.peekbuf_len = 0;
|
||||
} else if bufcopylen != 0 {
|
||||
// slide buffer over by bufcopylen
|
||||
let tail = inner.peekbuf.split_off(bufcopylen);
|
||||
inner.peekbuf = tail;
|
||||
inner.peekbuf_len -= bufcopylen;
|
||||
}
|
||||
Poll::Ready(Ok(bufcopylen))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for AsyncPeekStream {
|
||||
fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> {
|
||||
let mut inner = self.inner.lock();
|
||||
Pin::new(&mut inner.stream).poll_write(cx, buf)
|
||||
}
|
||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
|
||||
let mut inner = self.inner.lock();
|
||||
Pin::new(&mut inner.stream).poll_flush(cx)
|
||||
}
|
||||
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
|
||||
let mut inner = self.inner.lock();
|
||||
Pin::new(&mut inner.stream).poll_close(cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::marker::Unpin for AsyncPeekStream {}
|
@@ -1,83 +0,0 @@
|
||||
pub use async_std::channel;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Sender<T> {
|
||||
imp: channel::Sender<T>,
|
||||
}
|
||||
|
||||
impl<T> Clone for Sender<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
imp: self.imp.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Receiver<T> {
|
||||
imp: channel::Receiver<T>,
|
||||
}
|
||||
|
||||
impl<T> Clone for Receiver<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
imp: self.imp.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn channel<T>(cap: usize) -> (Sender<T>, Receiver<T>) {
|
||||
let imp = channel::bounded(cap);
|
||||
(Sender { imp: imp.0 }, Receiver { imp: imp.1 })
|
||||
}
|
||||
|
||||
pub use channel::SendError;
|
||||
pub use channel::TrySendError;
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl<T> Sender<T> {
|
||||
// NOTE: This needs a timeout or you could block a very long time
|
||||
// pub async fn send(&self, msg: T) -> Result<(), SendError<T>> {
|
||||
// self.imp.send(msg).await
|
||||
// }
|
||||
pub async fn try_send(&self, msg: T) -> Result<(), TrySendError<T>> {
|
||||
self.imp.try_send(msg)
|
||||
}
|
||||
pub fn capacity(&self) -> usize {
|
||||
self.imp.capacity().unwrap()
|
||||
}
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.imp.is_empty()
|
||||
}
|
||||
pub fn is_full(&self) -> bool {
|
||||
self.imp.is_full()
|
||||
}
|
||||
pub fn len(&self) -> usize {
|
||||
self.imp.len()
|
||||
}
|
||||
}
|
||||
|
||||
pub use channel::RecvError;
|
||||
pub use channel::TryRecvError;
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl<T> Receiver<T> {
|
||||
pub async fn recv(&self) -> Result<T, RecvError> {
|
||||
self.imp.recv().await
|
||||
}
|
||||
pub async fn try_recv(&self) -> Result<T, TryRecvError> {
|
||||
self.imp.try_recv()
|
||||
}
|
||||
pub fn capacity(&self) -> usize {
|
||||
self.imp.capacity().unwrap()
|
||||
}
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.imp.is_empty()
|
||||
}
|
||||
pub fn is_full(&self) -> bool {
|
||||
self.imp.is_full()
|
||||
}
|
||||
pub fn len(&self) -> usize {
|
||||
self.imp.len()
|
||||
}
|
||||
}
|
@@ -1,66 +0,0 @@
|
||||
use crate::xx::*;
|
||||
use async_std::io::{Read, Result, Write};
|
||||
use core::task::{Context, Poll};
|
||||
use std::pin::Pin;
|
||||
|
||||
pub struct CloneStream<T>
|
||||
where
|
||||
T: Read + Write + Send + Unpin,
|
||||
{
|
||||
inner: Arc<Mutex<T>>,
|
||||
}
|
||||
|
||||
impl<T> Clone for CloneStream<T>
|
||||
where
|
||||
T: Read + Write + Send + Unpin,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
inner: self.inner.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CloneStream<T>
|
||||
where
|
||||
T: Read + Write + Send + Unpin,
|
||||
{
|
||||
pub fn new(t: T) -> Self {
|
||||
Self {
|
||||
inner: Arc::new(Mutex::new(t)),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> Read for CloneStream<T>
|
||||
where
|
||||
T: Read + Write + Send + Unpin,
|
||||
{
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<Result<usize>> {
|
||||
let mut inner = self.inner.lock();
|
||||
Pin::new(&mut *inner).poll_read(cx, buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Write for CloneStream<T>
|
||||
where
|
||||
T: Read + Write + Send + Unpin,
|
||||
{
|
||||
fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> {
|
||||
let mut inner = self.inner.lock();
|
||||
Pin::new(&mut *inner).poll_write(cx, buf)
|
||||
}
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
|
||||
let mut inner = self.inner.lock();
|
||||
Pin::new(&mut *inner).poll_flush(cx)
|
||||
}
|
||||
|
||||
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
|
||||
let mut inner = self.inner.lock();
|
||||
Pin::new(&mut *inner).poll_close(cx)
|
||||
}
|
||||
}
|
@@ -1,8 +1,5 @@
|
||||
#[cfg(target_os = "android")]
|
||||
pub mod android;
|
||||
pub mod async_peek_stream;
|
||||
pub mod channel;
|
||||
pub mod clone_stream;
|
||||
#[cfg(target_os = "ios")]
|
||||
pub mod ios;
|
||||
pub mod network_interfaces;
|
||||
|
@@ -65,6 +65,8 @@ impl Network {
|
||||
}
|
||||
|
||||
// Handle connection-oriented protocols
|
||||
|
||||
// Try to send to the exact existing connection if one exists
|
||||
if let Some(conn) = self.connection_manager().get_connection(descriptor).await {
|
||||
// connection exists, send over it
|
||||
conn.send(data).await.map_err(logthru_net!())?;
|
||||
|
@@ -46,20 +46,20 @@ impl ProtocolNetworkConnection {
|
||||
}
|
||||
}
|
||||
}
|
||||
pub async fn close(&mut self) -> Result<(), String> {
|
||||
pub async fn close(&self) -> Result<(), String> {
|
||||
match self {
|
||||
Self::Dummy(d) => d.close(),
|
||||
Self::Ws(w) => w.close().await,
|
||||
}
|
||||
}
|
||||
pub async fn send(&mut self, message: Vec<u8>) -> Result<(), String> {
|
||||
pub async fn send(&self, message: Vec<u8>) -> Result<(), String> {
|
||||
match self {
|
||||
Self::Dummy(d) => d.send(message),
|
||||
Self::Ws(w) => w.send(message).await,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn recv(&mut self) -> Result<Vec<u8>, String> {
|
||||
pub async fn recv(&self) -> Result<Vec<u8>, String> {
|
||||
match self {
|
||||
Self::Dummy(d) => d.recv(),
|
||||
Self::Ws(w) => w.recv().await,
|
||||
|
@@ -1,154 +0,0 @@
|
||||
use crate::xx::*;
|
||||
use alloc::collections::VecDeque;
|
||||
use core::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Channel<T> {
|
||||
items: VecDeque<T>,
|
||||
cap: usize,
|
||||
eventual: Eventual,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Sender<T> {
|
||||
imp: Arc<Mutex<Channel<T>>>,
|
||||
}
|
||||
|
||||
impl<T> Clone for Sender<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
imp: self.imp.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Receiver<T> {
|
||||
imp: Arc<Mutex<Channel<T>>>,
|
||||
}
|
||||
|
||||
impl<T> Clone for Receiver<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
imp: self.imp.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn channel<T>(cap: usize) -> (Sender<T>, Receiver<T>) {
|
||||
let imp = Channel {
|
||||
items: VecDeque::with_capacity(cap),
|
||||
cap,
|
||||
eventual: Eventual::new(),
|
||||
};
|
||||
|
||||
let imparc = Arc::new(Mutex::new(imp));
|
||||
(
|
||||
Sender {
|
||||
imp: imparc.clone(),
|
||||
},
|
||||
Receiver {
|
||||
imp: imparc.clone(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum TrySendError<T> {
|
||||
Full(T),
|
||||
Disconnected(T),
|
||||
}
|
||||
|
||||
impl<T> fmt::Display for TrySendError<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
TrySendError::Full(_) => {
|
||||
write!(f, "Full")
|
||||
}
|
||||
TrySendError::Disconnected(_) => {
|
||||
write!(f, "Disconnected")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Sender<T> {
|
||||
// NOTE: This needs a timeout or you could block a very long time
|
||||
// pub async fn send(&self, msg: T) -> Result<(), SendError<T>> {
|
||||
// xxx
|
||||
// }
|
||||
|
||||
pub async fn try_send(&self, msg: T) -> Result<(), TrySendError<T>> {
|
||||
let eventual = {
|
||||
let mut inner = self.imp.lock();
|
||||
if inner.items.len() == inner.cap {
|
||||
return Err(TrySendError::Full(msg));
|
||||
}
|
||||
let empty = inner.items.is_empty();
|
||||
inner.items.push_back(msg);
|
||||
if empty {
|
||||
Some(inner.eventual.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
if let Some(e) = eventual {
|
||||
e.resolve().await;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn capacity(&self) -> usize {
|
||||
self.imp.lock().cap
|
||||
}
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.imp.lock().items.is_empty()
|
||||
}
|
||||
pub fn is_full(&self) -> bool {
|
||||
let inner = self.imp.lock();
|
||||
inner.items.len() == inner.cap
|
||||
}
|
||||
pub fn len(&self) -> usize {
|
||||
self.imp.lock().items.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct RecvError;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum TryRecvError {
|
||||
Empty,
|
||||
Disconnected,
|
||||
}
|
||||
|
||||
impl<T> Receiver<T> {
|
||||
pub async fn recv(&self) -> Result<T, RecvError> {
|
||||
let eventual = {
|
||||
let inner = self.imp.lock();
|
||||
inner.eventual.clone()
|
||||
};
|
||||
while self.is_empty() {
|
||||
eventual.instance_clone(true).await;
|
||||
}
|
||||
Ok(self.imp.lock().items.pop_front().unwrap())
|
||||
}
|
||||
pub async fn try_recv(&self) -> Result<T, TryRecvError> {
|
||||
if self.is_empty() {
|
||||
return Err(TryRecvError::Empty);
|
||||
}
|
||||
Ok(self.imp.lock().items.pop_front().unwrap())
|
||||
}
|
||||
pub fn capacity(&self) -> usize {
|
||||
self.imp.lock().cap
|
||||
}
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.imp.lock().items.is_empty()
|
||||
}
|
||||
pub fn is_full(&self) -> bool {
|
||||
let inner = self.imp.lock();
|
||||
inner.items.len() == inner.cap
|
||||
}
|
||||
pub fn len(&self) -> usize {
|
||||
self.imp.lock().items.len()
|
||||
}
|
||||
}
|
@@ -1,7 +1,5 @@
|
||||
#![cfg(target_arch = "wasm32")]
|
||||
|
||||
pub mod channel;
|
||||
|
||||
use crate::xx::*;
|
||||
use core::sync::atomic::{AtomicI8, Ordering};
|
||||
use js_sys::{global, Reflect};
|
||||
|
Reference in New Issue
Block a user