1use core::future::poll_fn;
2use core::pin::Pin;
3
4use futures_io::{AsyncRead, AsyncWrite};
5
6use crate::error::{Result, RpcError};
7
8pub trait AsyncStream: AsyncRead + AsyncWrite + Send + Unpin {}
13
14impl<T> AsyncStream for T where T: AsyncRead + AsyncWrite + Send + Unpin {}
15
16pub async fn read_message<S: AsyncStream + Unpin>(
24 stream: &mut S,
25) -> Result<capnp::message::Reader<capnp::serialize::OwnedSegments>> {
26 let mut header = [0u8; 8];
27 read_exact(stream, &mut header).await?;
28 let segment_count =
29 u32::from_le_bytes(header[0..4].try_into().expect("4 bytes")).wrapping_add(1) as usize;
30 if segment_count == 0 || segment_count > 512 {
31 return Err(RpcError::Protocol(format!(
32 "invalid segment count {segment_count}"
33 )));
34 }
35
36 let mut builder = capnp::serialize::SegmentLengthsBuilder::with_capacity(segment_count);
37 let mut total_words = 0usize;
38 let first = u32::from_le_bytes(header[4..8].try_into().expect("4 bytes")) as usize;
39 total_words = total_words.saturating_add(first);
40 if total_words > MAXIMUM_TOTAL_WORDS {
41 return Err(RpcError::Protocol(format!(
42 "message too large: {total_words} words exceeds limit of {MAXIMUM_TOTAL_WORDS}"
43 )));
44 }
45 builder.try_push_segment(first)?;
46 if segment_count > 1 {
47 let header_size = (4 + 4 * segment_count + 7) & !7;
49 let mut sizes = vec![0u8; header_size - 8];
50 read_exact(stream, &mut sizes).await?;
51 for i in 1..segment_count {
52 let offset = (i - 1) * 4;
53 let length =
54 u32::from_le_bytes(sizes[offset..offset + 4].try_into().expect("4 bytes")) as usize;
55 total_words = total_words.saturating_add(length);
56 if total_words > MAXIMUM_TOTAL_WORDS {
57 return Err(RpcError::Protocol(format!(
58 "message too large: {total_words} words exceeds limit of {MAXIMUM_TOTAL_WORDS}"
59 )));
60 }
61 builder.try_push_segment(length)?;
62 }
63 }
64
65 let mut segments = builder.into_owned_segments();
66 read_exact(stream, &mut segments[..]).await?;
67 Ok(capnp::message::Reader::new(
68 segments,
69 capnp::message::ReaderOptions::new(),
70 ))
71}
72
73const MAXIMUM_TOTAL_WORDS: usize = 8 * 1024 * 1024;
76
77pub fn serialize_message(
81 message: &capnp::message::Builder<capnp::message::HeapAllocator>,
82) -> Vec<u8> {
83 capnp::serialize::write_message_to_words(message)
84}
85
86pub async fn write_raw<S: AsyncStream + Unpin>(stream: &mut S, bytes: &[u8]) -> Result<()> {
89 write_all(stream, bytes).await?;
90 Ok(())
91}
92
93async fn read_exact<S: AsyncRead + Unpin>(stream: &mut S, mut buffer: &mut [u8]) -> Result<()> {
94 while !buffer.is_empty() {
95 let n = poll_fn(|cx| Pin::new(&mut *stream).poll_read(cx, buffer)).await?;
96 if n == 0 {
97 return Err(RpcError::Eof);
98 }
99 let tmp = buffer;
100 buffer = &mut tmp[n..];
101 }
102 Ok(())
103}
104
105async fn write_all<S: AsyncWrite + Unpin>(stream: &mut S, mut buffer: &[u8]) -> Result<()> {
106 while !buffer.is_empty() {
107 let n = poll_fn(|cx| Pin::new(&mut *stream).poll_write(cx, buffer)).await?;
108 if n == 0 {
109 return Err(RpcError::Protocol("write returned zero bytes".into()));
110 }
111 buffer = &buffer[n..];
112 }
113 Ok(())
114}