mirror of
https://mirror.suhoan.cn/https://github.com/EasyTier/EasyTier.git
synced 2025-12-14 05:37:23 +08:00
adapt tun device to zerocopy (#57)
This commit is contained in:
@@ -167,16 +167,41 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ZCPacketToBytes {
|
||||
fn into_bytes(&self, zc_packet: ZCPacket) -> Result<Bytes, TunnelError>;
|
||||
}
|
||||
|
||||
pub struct TcpZCPacketToBytes;
|
||||
impl ZCPacketToBytes for TcpZCPacketToBytes {
|
||||
fn into_bytes(&self, mut item: ZCPacket) -> Result<Bytes, TunnelError> {
|
||||
let tcp_len = PEER_MANAGER_HEADER_SIZE + item.payload_len();
|
||||
let Some(header) = item.mut_tcp_tunnel_header() else {
|
||||
return Err(TunnelError::InvalidPacket("packet too short".to_string()));
|
||||
};
|
||||
header.len.set(tcp_len.try_into().unwrap());
|
||||
|
||||
Ok(item.into_bytes(ZCPacketType::TCP))
|
||||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
pub struct FramedWriter<W> {
|
||||
pub struct FramedWriter<W, C> {
|
||||
#[pin]
|
||||
writer: W,
|
||||
sending_bufs: BufList<Bytes>,
|
||||
associate_data: Option<Box<dyn Any + Send + 'static>>,
|
||||
|
||||
converter: C,
|
||||
}
|
||||
}
|
||||
|
||||
impl<W> FramedWriter<W> {
|
||||
impl<W, C> FramedWriter<W, C> {
|
||||
fn max_buffer_count(&self) -> usize {
|
||||
64
|
||||
}
|
||||
}
|
||||
|
||||
impl<W> FramedWriter<W, TcpZCPacketToBytes> {
|
||||
pub fn new(writer: W) -> Self {
|
||||
Self::new_with_associate_data(writer, None)
|
||||
}
|
||||
@@ -188,18 +213,35 @@ impl<W> FramedWriter<W> {
|
||||
FramedWriter {
|
||||
writer,
|
||||
sending_bufs: BufList::new(),
|
||||
associate_data: associate_data,
|
||||
associate_data,
|
||||
converter: TcpZCPacketToBytes {},
|
||||
}
|
||||
}
|
||||
|
||||
fn max_buffer_count(&self) -> usize {
|
||||
64
|
||||
}
|
||||
}
|
||||
|
||||
impl<W> Sink<SinkItem> for FramedWriter<W>
|
||||
impl<W, C: ZCPacketToBytes + Send + 'static> FramedWriter<W, C> {
|
||||
pub fn new_with_converter(writer: W, converter: C) -> Self {
|
||||
Self::new_with_converter_and_associate_data(writer, converter, None)
|
||||
}
|
||||
|
||||
pub fn new_with_converter_and_associate_data(
|
||||
writer: W,
|
||||
converter: C,
|
||||
associate_data: Option<Box<dyn Any + Send + 'static>>,
|
||||
) -> Self {
|
||||
FramedWriter {
|
||||
writer,
|
||||
sending_bufs: BufList::new(),
|
||||
associate_data,
|
||||
converter,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<W, C> Sink<SinkItem> for FramedWriter<W, C>
|
||||
where
|
||||
W: AsyncWrite + Send + 'static,
|
||||
C: ZCPacketToBytes + Send + 'static,
|
||||
{
|
||||
type Error = TunnelError;
|
||||
|
||||
@@ -216,15 +258,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn start_send(self: Pin<&mut Self>, mut item: ZCPacket) -> Result<(), Self::Error> {
|
||||
let tcp_len = PEER_MANAGER_HEADER_SIZE + item.payload_len();
|
||||
let Some(header) = item.mut_tcp_tunnel_header() else {
|
||||
return Err(TunnelError::InvalidPacket("packet too short".to_string()));
|
||||
};
|
||||
header.len.set(tcp_len.try_into().unwrap());
|
||||
|
||||
let item = item.into_bytes(ZCPacketType::TCP);
|
||||
self.project().sending_bufs.push(item);
|
||||
fn start_send(self: Pin<&mut Self>, item: ZCPacket) -> Result<(), Self::Error> {
|
||||
let pinned = self.project();
|
||||
pinned.sending_bufs.push(pinned.converter.into_bytes(item)?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -52,6 +52,9 @@ pub enum TunnelError {
|
||||
|
||||
#[error("shutdown")]
|
||||
Shutdown,
|
||||
|
||||
#[error("tunnel error: {0}")]
|
||||
TunError(String),
|
||||
}
|
||||
|
||||
pub type StreamT = packet_def::ZCPacket;
|
||||
|
||||
@@ -161,12 +161,25 @@ impl ZCPacket {
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn new_with_reserved_payload(cap: usize) -> Self {
|
||||
let mut ret = Self::new_nic_packet();
|
||||
ret.inner.reserve(cap);
|
||||
let total_len = ret.packet_type.get_packet_offsets().payload_offset;
|
||||
ret.inner.resize(total_len, 0);
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn packet_type(&self) -> ZCPacketType {
|
||||
self.packet_type
|
||||
}
|
||||
|
||||
pub fn payload_offset(&self) -> usize {
|
||||
self.packet_type.get_packet_offsets().payload_offset
|
||||
}
|
||||
|
||||
pub fn mut_payload(&mut self) -> &mut [u8] {
|
||||
&mut self.inner[self.packet_type.get_packet_offsets().payload_offset..]
|
||||
let offset = self.payload_offset();
|
||||
&mut self.inner[offset..]
|
||||
}
|
||||
|
||||
pub fn mut_peer_manager_header(&mut self) -> Option<&mut PeerManagerHeader> {
|
||||
@@ -207,7 +220,7 @@ impl ZCPacket {
|
||||
|
||||
// ref versions
|
||||
pub fn payload(&self) -> &[u8] {
|
||||
&self.inner[self.packet_type.get_packet_offsets().payload_offset..]
|
||||
&self.inner[self.payload_offset()..]
|
||||
}
|
||||
|
||||
pub fn peer_manager_header(&self) -> Option<&PeerManagerHeader> {
|
||||
@@ -246,8 +259,7 @@ impl ZCPacket {
|
||||
}
|
||||
|
||||
pub fn payload_len(&self) -> usize {
|
||||
let payload_offset = self.packet_type.get_packet_offsets().payload_offset;
|
||||
self.inner.len() - payload_offset
|
||||
self.inner.len() - self.payload_offset()
|
||||
}
|
||||
|
||||
pub fn buf_len(&self) -> usize {
|
||||
@@ -307,6 +319,10 @@ impl ZCPacket {
|
||||
pub fn inner(self) -> BytesMut {
|
||||
self.inner
|
||||
}
|
||||
|
||||
pub fn mut_inner(&mut self) -> &mut BytesMut {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -176,8 +176,8 @@ impl RingSink {
|
||||
return Err(TunnelError::Shutdown);
|
||||
}
|
||||
|
||||
log::trace!("id: {}, send buffer, buf: {:?}", self.tunnel.id(), &item);
|
||||
self.tunnel.ring.push(item).unwrap();
|
||||
tracing::trace!(id=?self.tunnel.id(), ?item, "send buffer");
|
||||
let _ = self.tunnel.ring.push(item);
|
||||
self.tunnel.notify_new_item();
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user