Use tokio select for polling client socket

This commit is contained in:
Aram 🍐 2021-10-14 19:31:29 -04:00
parent 5ba111002f
commit bf489900e6
2 changed files with 60 additions and 71 deletions

View file

@ -10,7 +10,7 @@ use anyhow::Context;
use smoltcp::iface::InterfaceBuilder; use smoltcp::iface::InterfaceBuilder;
use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer}; use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
use smoltcp::wire::{IpAddress, IpCidr}; use smoltcp::wire::{IpAddress, IpCidr};
use tokio::io::Interest; use tokio::io::{AsyncReadExt, Interest};
use tokio::net::{TcpListener, TcpStream}; use tokio::net::{TcpListener, TcpStream};
use tokio::sync::mpsc::error::TryRecvError; use tokio::sync::mpsc::error::TryRecvError;
@ -158,19 +158,16 @@ async fn handle_tcp_proxy_connection(
} }
loop { loop {
let ready = socket
.ready(Interest::READABLE | Interest::WRITABLE)
.await
.with_context(|| "Failed to wait for TCP proxy socket readiness")?;
if abort.load(Ordering::Relaxed) { if abort.load(Ordering::Relaxed) {
break; break;
} }
if ready.is_readable() { tokio::select! {
let mut buffer = [0u8; MAX_PACKET]; readable_result = socket.readable() => {
match readable_result {
match socket.try_read(&mut buffer) { Ok(_) => {
let mut buffer = vec![];
match socket.try_read_buf(&mut buffer) {
Ok(size) if size > 0 => { Ok(size) if size > 0 => {
let data = &buffer[..size]; let data = &buffer[..size];
debug!( debug!(
@ -197,14 +194,20 @@ async fn handle_tcp_proxy_connection(
); );
break; break;
} }
_ => {} _ => {
break;
} }
} }
}
if ready.is_writable() { Err(e) => {
// Flush the data_to_real_client_rx channel error!("[{}] Failed to check if readable: {:?}", virtual_port, e);
match data_to_real_client_rx.try_recv() { break;
Ok(data) => match socket.try_write(&data) { }
}
}
data_recv_result = data_to_real_client_rx.recv() => {
match data_recv_result {
Some(data) => match socket.try_write(&data) {
Ok(size) => { Ok(size) => {
debug!( debug!(
"[{}] Wrote {} bytes of TCP data to real client", "[{}] Wrote {} bytes of TCP data to real client",
@ -221,22 +224,10 @@ async fn handle_tcp_proxy_connection(
); );
} }
}, },
Err(e) => match e { None => continue,
TryRecvError::Empty => {
// Nothing else to consume in the data channel.
}
TryRecvError::Disconnected => {
// Channel is broken, probably terminated.
}
},
} }
} }
if ready.is_read_closed() || ready.is_write_closed() {
break;
} }
tokio::time::sleep(Duration::from_millis(1)).await;
} }
trace!("[{}] TCP socket handler task terminated", virtual_port); trace!("[{}] TCP socket handler task terminated", virtual_port);

View file

@ -14,9 +14,7 @@ impl PortPool {
pub fn new() -> Self { pub fn new() -> Self {
let inner = lockfree::queue::Queue::default(); let inner = lockfree::queue::Queue::default();
PORT_RANGE.for_each(|p| inner.push(p) as ()); PORT_RANGE.for_each(|p| inner.push(p) as ());
Self { Self { inner }
inner,
}
} }
pub fn next(&self) -> anyhow::Result<u16> { pub fn next(&self) -> anyhow::Result<u16> {