use tokio::io::AsyncReadExt;
use tokio::net::TcpStream;
use crate::util::allocate_vec;
const TLS_FRAME_MAX_LEN: usize = 5 + 65535;
pub struct TlsReader {
buf: Vec<u8>,
pos: usize,
end: usize,
}
impl TlsReader {
pub fn new() -> Self {
Self {
buf: allocate_vec(TLS_FRAME_MAX_LEN),
pos: 0,
end: 0,
}
}
pub async fn ensure_bytes(
&mut self,
stream: &mut TcpStream,
len: usize,
) -> std::io::Result<()> {
let needed = self.pos + len;
if needed > self.buf.len() {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"Requested data exceeds buffer size".to_string(),
));
}
while self.end < needed {
if needed - self.pos > self.buf.len() {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"Request too large for buffer",
));
}
if self.end == self.buf.len() {
if self.pos == 0 {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"Buffer full but need more data",
));
}
self.buf.copy_within(self.pos..self.end, 0);
self.end -= self.pos;
self.pos = 0;
}
loop {
match stream.read(&mut self.buf[self.end..]).await {
Ok(0) => {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"EOF while reading TLS data",
));
}
Ok(n) => {
self.end += n;
break;
}
Err(e) if e.kind() == std::io::ErrorKind::Interrupted => {
continue;
}
Err(e) => return Err(e),
}
}
}
Ok(())
}
pub fn read_u8(&mut self) -> std::io::Result<u8> {
if self.pos >= self.end {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"buffer underflow",
));
}
let val = self.buf[self.pos];
self.pos += 1;
Ok(val)
}
pub fn read_u16_be(&mut self) -> std::io::Result<u16> {
if self.pos + 2 > self.end {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"buffer underflow",
));
}
let val = u16::from_be_bytes([self.buf[self.pos], self.buf[self.pos + 1]]);
self.pos += 2;
Ok(val)
}
pub fn read_u24_be(&mut self) -> std::io::Result<u32> {
if self.pos + 3 > self.end {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"buffer underflow",
));
}
let val = u32::from_be_bytes([
0,
self.buf[self.pos],
self.buf[self.pos + 1],
self.buf[self.pos + 2],
]);
self.pos += 3;
Ok(val)
}
pub fn skip(&mut self, n: usize) -> std::io::Result<()> {
if self.pos + n > self.end {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"buffer underflow",
));
}
self.pos += n;
Ok(())
}
pub fn read_slice(&mut self, len: usize) -> std::io::Result<&[u8]> {
if self.pos + len > self.end {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"buffer underflow",
));
}
let slice = &self.buf[self.pos..self.pos + len];
self.pos += len;
Ok(slice)
}
pub fn read_str(&mut self, len: usize) -> std::io::Result<&str> {
let slice = self.read_slice(len)?;
std::str::from_utf8(slice).map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("invalid UTF-8: {}", e),
)
})
}
pub fn position(&self) -> usize {
self.pos
}
pub fn is_consumed(&self) -> bool {
self.pos >= self.end
}
pub fn into_inner(self) -> (Vec<u8>, usize, usize) {
(self.buf, self.pos, self.end)
}
}