borer_core/proto/
padding.rs1use anyhow::Context;
2use bytes::{BufMut, BytesMut};
3use rand::{Rng, RngCore};
4use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
5
6#[derive(Debug)]
8pub struct Padding {
9 len: u16,
10}
11
12impl Padding {
13 pub fn new(start: u16, end: u16) -> Self {
15 let mut rng = rand::rng();
16 let len = rng.random_range(start..end);
17 Self { len }
18 }
19
20 pub async fn read_from<R>(stream: &mut R) -> anyhow::Result<Self>
22 where
23 R: AsyncRead + Unpin,
24 {
25 let len = stream.read_u16().await?;
26 let mut buf = vec![0; len as usize];
27 stream.read_exact(&mut buf).await?;
28 Ok(Padding { len })
29 }
30
31 pub async fn write_to<W>(&self, w: &mut W) -> anyhow::Result<()>
33 where
34 W: AsyncWrite + Unpin,
35 {
36 let mut buf = BytesMut::with_capacity(self.serialized_len());
37 self.write_to_buf(&mut buf);
38 w.write_all(&buf)
39 .await
40 .context("padding Write buf failed")?;
41
42 Ok(())
43 }
44
45 pub fn write_to_buf<B: BufMut>(&self, buf: &mut B) {
46 let rand_buf = self.rand_buf();
47 buf.put_u16(self.len);
48 buf.put_slice(&rand_buf);
49 }
50
51 pub fn serialized_len(&self) -> usize {
52 2 + self.len as usize
53 }
54
55 pub fn rand_buf(&self) -> Vec<u8> {
56 let mut rng = rand::rng();
57 let mut buf = vec![0; self.len as usize];
58 rng.fill_bytes(&mut buf);
59 buf
60 }
61}
62
63impl Default for Padding {
64 fn default() -> Self {
65 Self::new(256, 2048)
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use std::io::Cursor;
72
73 use bytes::{Buf, BytesMut};
74
75 use super::Padding;
76
77 #[test]
78 fn serialized_len_matches_written_buffer_length() {
79 let padding = Padding::new(8, 9);
80 let mut buf = BytesMut::new();
81
82 padding.write_to_buf(&mut buf);
83
84 assert_eq!(buf.len(), padding.serialized_len());
85 assert_eq!(buf.get_u16() as usize + 2, padding.serialized_len());
86 }
87
88 #[tokio::test]
89 async fn read_from_round_trips_written_bytes() {
90 let padding = Padding::new(8, 9);
91 let mut raw = BytesMut::new();
92 padding.write_to_buf(&mut raw);
93 let expected_len = padding.serialized_len();
94
95 let mut cursor = Cursor::new(raw.to_vec());
96 let actual = Padding::read_from(&mut cursor).await.unwrap();
97
98 assert_eq!(actual.serialized_len(), expected_len);
99 }
100}