#[cfg(unix)]
use std::{collections::VecDeque, os::fd::OwnedFd};
use std::{io, mem, sync::Arc};
use super::{RegisteredIo, SocketOps};
use crate::{
Message,
conn::AuthMechanism,
connection::socket::{ReadHalf, RecvmsgResult, read_primary_header},
fdo::ConnectionCredentials,
message::header::MIN_MESSAGE_SIZE,
wire::{
Endian,
serialized::{self, Context},
},
};
#[derive(Debug)]
pub(crate) struct Reader<O> {
socket: Arc<RegisteredIo<O>>,
buffer: Vec<u8>,
start: usize,
end: usize,
#[cfg(unix)]
fds: VecDeque<Vec<OwnedFd>>,
}
impl<O> Reader<O>
where
O: SocketOps,
{
pub(crate) fn new(socket: Arc<RegisteredIo<O>>) -> Self {
Self {
socket,
buffer: vec![0; BUFFER_SIZE],
start: 0,
end: 0,
#[cfg(unix)]
fds: VecDeque::new(),
}
}
fn take_over(&mut self, bytes: &mut Vec<u8>, #[cfg(unix)] fds: &mut Vec<OwnedFd>) {
if !bytes.is_empty() {
let mut buffer = mem::take(bytes);
buffer.extend_from_slice(&self.buffer[self.start..self.end]);
self.start = 0;
self.end = buffer.len();
buffer.resize(self.end.max(BUFFER_SIZE), 0);
self.buffer = buffer;
}
#[cfg(unix)]
if !fds.is_empty() {
self.fds.push_front(mem::take(fds));
}
}
async fn fill(&mut self) -> crate::Result<()> {
if self.start > 0 {
self.buffer.copy_within(self.start..self.end, 0);
self.end -= self.start;
self.start = 0;
}
let received = self.socket.recv(&mut self.buffer[self.end..]).await;
self.end += self.received(received)?;
Ok(())
}
async fn receive_long(&mut self, len: usize) -> crate::Result<Vec<u8>> {
let mut bytes = Vec::with_capacity(len);
bytes.extend_from_slice(&self.buffer[self.start..self.end]);
self.start = 0;
self.end = 0;
let mut pos = bytes.len();
bytes.resize(len, 0);
while pos < len {
let received = self.socket.recv(&mut bytes[pos..]).await;
pos += self.received(received)?;
}
Ok(bytes)
}
fn received(&mut self, received: RecvmsgResult) -> crate::Result<usize> {
#[cfg(unix)]
let (read, fds) = received?;
#[cfg(not(unix))]
let read = received?;
if read == 0 {
return Err(
io::Error::new(io::ErrorKind::UnexpectedEof, "failed to receive message").into(),
);
}
#[cfg(unix)]
if !fds.is_empty() {
if self.fds.len() == MAX_FD_SETS {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"too many file descriptors that no message counts",
)
.into());
}
self.fds.push_back(fds);
}
Ok(read)
}
#[cfg(unix)]
fn take_fds(&mut self, bytes: &[u8]) -> crate::Result<Vec<OwnedFd>> {
if self.fds.is_empty() {
return Ok(vec![]);
}
let (_, _, fields) = crate::message::parser::parse(bytes)?;
let count = fields.unix_fds().unwrap_or(0) as usize;
let mut fds = vec![];
while fds.len() < count
&& let Some(set) = self.fds.front_mut()
{
let wanted = count - fds.len();
if set.len() > wanted {
fds.extend(set.drain(..wanted));
} else {
fds.append(set);
self.fds.pop_front();
}
}
Ok(fds)
}
}
#[async_trait::async_trait]
impl<O> ReadHalf for Reader<O>
where
O: SocketOps,
{
async fn receive_message(
&mut self,
seq: u64,
already_received_bytes: &mut Vec<u8>,
#[cfg(unix)] already_received_fds: &mut Vec<OwnedFd>,
) -> crate::Result<Message> {
self.take_over(
already_received_bytes,
#[cfg(unix)]
already_received_fds,
);
let (primary_header, bytes) = loop {
let buffered = &self.buffer[self.start..self.end];
if buffered.len() >= MIN_MESSAGE_SIZE {
let (primary_header, len) = read_primary_header(buffered)?;
if buffered.len() >= len {
let bytes = buffered[..len].to_vec();
self.start += len;
if self.start == self.end {
self.start = 0;
self.end = 0;
}
break (primary_header, bytes);
} else if len > self.buffer.len() {
break (primary_header, self.receive_long(len).await?);
}
}
self.fill().await?;
};
#[cfg(unix)]
let fds = self.take_fds(&bytes)?;
let ctxt = Context::new(Endian::from(primary_header.endian_sig()), 0);
#[cfg(unix)]
let bytes = serialized::Data::new_fds(bytes, ctxt, fds);
#[cfg(not(unix))]
let bytes = serialized::Data::new(bytes, ctxt);
Message::from_raw_parts(bytes, seq)
}
async fn recvmsg(&mut self, buf: &mut [u8]) -> RecvmsgResult {
debug_assert_eq!(self.start, self.end, "bytes read ahead would be skipped");
self.socket.recv(buf).await
}
fn can_pass_unix_fd(&self) -> bool {
self.socket.ops.can_pass_unix_fd()
}
async fn peer_credentials(&mut self) -> io::Result<ConnectionCredentials> {
self.socket
.ops
.peer_credentials(&self.socket.source, &self.socket.runtime)
.await
}
fn auth_mechanism(&self) -> AuthMechanism {
self.socket.ops.auth_mechanism()
}
}
#[cfg(unix)]
const MAX_FD_SETS: usize = 3;
const BUFFER_SIZE: usize = 4 * 1024;