mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-07 10:14:35 +00:00
3467890270
make tunnel zero copy, for better performance. remove most of the locks in io path. introduce quic tunnel prepare for encryption
93 lines
2.4 KiB
Rust
93 lines
2.4 KiB
Rust
use std::collections::VecDeque;
|
|
use std::io::IoSlice;
|
|
|
|
use bytes::{Buf, BufMut, Bytes, BytesMut};
|
|
|
|
pub(crate) struct BufList<T> {
|
|
bufs: VecDeque<T>,
|
|
}
|
|
|
|
impl<T: Buf> BufList<T> {
|
|
pub(crate) fn new() -> BufList<T> {
|
|
BufList {
|
|
bufs: VecDeque::new(),
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub(crate) fn push(&mut self, buf: T) {
|
|
debug_assert!(buf.has_remaining());
|
|
self.bufs.push_back(buf);
|
|
}
|
|
|
|
#[inline]
|
|
pub(crate) fn bufs_cnt(&self) -> usize {
|
|
self.bufs.len()
|
|
}
|
|
}
|
|
|
|
impl<T: Buf> Buf for BufList<T> {
|
|
#[inline]
|
|
fn remaining(&self) -> usize {
|
|
self.bufs.iter().map(|buf| buf.remaining()).sum()
|
|
}
|
|
|
|
#[inline]
|
|
fn chunk(&self) -> &[u8] {
|
|
self.bufs.front().map(Buf::chunk).unwrap_or_default()
|
|
}
|
|
|
|
#[inline]
|
|
fn advance(&mut self, mut cnt: usize) {
|
|
while cnt > 0 {
|
|
{
|
|
let front = &mut self.bufs[0];
|
|
let rem = front.remaining();
|
|
if rem > cnt {
|
|
front.advance(cnt);
|
|
return;
|
|
} else {
|
|
front.advance(rem);
|
|
cnt -= rem;
|
|
}
|
|
}
|
|
self.bufs.pop_front();
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
fn chunks_vectored<'t>(&'t self, dst: &mut [IoSlice<'t>]) -> usize {
|
|
if dst.is_empty() {
|
|
return 0;
|
|
}
|
|
let mut vecs = 0;
|
|
for buf in &self.bufs {
|
|
vecs += buf.chunks_vectored(&mut dst[vecs..]);
|
|
if vecs == dst.len() {
|
|
break;
|
|
}
|
|
}
|
|
vecs
|
|
}
|
|
|
|
#[inline]
|
|
fn copy_to_bytes(&mut self, len: usize) -> Bytes {
|
|
// Our inner buffer may have an optimized version of copy_to_bytes, and if the whole
|
|
// request can be fulfilled by the front buffer, we can take advantage.
|
|
match self.bufs.front_mut() {
|
|
Some(front) if front.remaining() == len => {
|
|
let b = front.copy_to_bytes(len);
|
|
self.bufs.pop_front();
|
|
b
|
|
}
|
|
Some(front) if front.remaining() > len => front.copy_to_bytes(len),
|
|
_ => {
|
|
assert!(len <= self.remaining(), "`len` greater than remaining");
|
|
let mut bm = BytesMut::with_capacity(len);
|
|
bm.put(self.take(len));
|
|
bm.freeze()
|
|
}
|
|
}
|
|
}
|
|
}
|