ssb_boxstream/
lib.rs

1mod bytes;
2mod duplex;
3mod msg;
4mod noncegen;
5use noncegen::*;
6mod read;
7mod write;
8
9pub use duplex::*;
10pub use read::*;
11pub use write::*;
12
13#[cfg(test)]
14mod tests {
15    use crate::bytes::AsBytes;
16    use crate::msg::*;
17    use crate::read::*;
18    use crate::write::*;
19    use crate::NonceGen;
20
21    use core::pin::Pin;
22    use core::task::Context;
23    use futures_executor::block_on;
24    use futures_io::AsyncRead;
25    use futures_task::noop_waker;
26    use futures_util::io::{AsyncReadExt, AsyncWriteExt};
27    use ssb_crypto::secretbox::{Key, Nonce};
28
29    // Test data from https://github.com/AljoschaMeyer/box-stream-c
30    const KEY: Key = Key([
31        162, 29, 153, 150, 123, 225, 10, 173, 175, 201, 160, 34, 190, 179, 158, 14, 176, 105, 232,
32        238, 97, 66, 133, 194, 250, 148, 199, 7, 34, 157, 174, 24,
33    ]);
34
35    const NONCE_BYTES: [u8; 24] = [
36        44, 140, 79, 227, 23, 153, 202, 203, 81, 40, 114, 59, 56, 167, 63, 166, 201, 9, 50, 152, 0,
37        255, 226, 147,
38    ];
39
40    const HEAD1: [u8; 34] = [
41        181, 28, 106, 117, 226, 186, 113, 206, 135, 153, 250, 54, 221, 225, 178, 211, 144, 190, 14,
42        102, 102, 246, 118, 54, 195, 34, 174, 182, 190, 45, 129, 48, 96, 193,
43    ];
44
45    const BODY1: [u8; 8] = [231, 234, 80, 195, 113, 173, 5, 158];
46
47    const HEAD2: [u8; 34] = [
48        227, 230, 249, 230, 176, 170, 49, 34, 220, 29, 156, 118, 225, 243, 7, 3, 163, 197, 125,
49        225, 240, 111, 195, 126, 240, 148, 201, 237, 158, 158, 134, 224, 246, 137,
50    ];
51    const BODY2: [u8; 8] = [22, 134, 141, 191, 19, 113, 211, 114];
52
53    const HEAD3: [u8; 34] = [
54        10, 48, 84, 111, 103, 103, 35, 162, 175, 78, 189, 58, 240, 250, 196, 226, 194, 197, 87, 73,
55        119, 174, 129, 124, 225, 30, 3, 26, 37, 221, 87, 213, 153, 123,
56    ];
57
58    #[test]
59    fn encrypt() {
60        let mut noncegen = NonceGen::with_starting_nonce(Nonce::from_slice(&NONCE_BYTES).unwrap());
61
62        let mut body = [0, 1, 2, 3, 4, 5, 6, 7];
63        let head = seal(&mut body, &KEY, &mut noncegen);
64        assert_eq!(head.as_bytes(), &HEAD1[..]);
65        assert_eq!(&body, &BODY1);
66
67        let mut body = [7, 6, 5, 4, 3, 2, 1, 0];
68        let head = seal(&mut body, &KEY, &mut noncegen);
69        assert_eq!(head.as_bytes(), &HEAD2[..]);
70        assert_eq!(&body, &BODY2);
71
72        // goodbye
73        let head = HeadPayload::goodbye().seal(&KEY, noncegen.next());
74        assert_eq!(head.as_bytes(), &HEAD3[..]);
75    }
76
77    #[test]
78    fn write_and_flush() {
79        // TODO: use a buffered writer to test that boxwriter is actually
80        //  flushing its 'inner' writer
81
82        let (rbw, mut rbr) = async_ringbuffer::ring_buffer(1024);
83        let mut boxw = BoxWriter::new(rbw, KEY.clone(), Nonce(NONCE_BYTES));
84
85        block_on(async {
86            boxw.write_all(&[0, 1, 2, 3, 4, 5, 6, 7]).await.unwrap();
87
88            let mut head = [0; 34];
89
90            // NOTE: async_ringbuffer reader.poll_read returns Pending if the buffer
91            // is empty (not Ok(0))
92            let wk = noop_waker();
93            let mut cx = Context::from_waker(&wk);
94            assert!(Pin::new(&mut rbr)
95                .poll_read(&mut cx, &mut head)
96                .is_pending());
97
98            boxw.flush().await.unwrap();
99
100            rbr.read_exact(&mut head).await.unwrap();
101            assert_eq!(&head[..], &HEAD1[..]);
102
103            let mut body = [0; 8];
104            rbr.read_exact(&mut body).await.unwrap();
105            assert_eq!(&body, &BODY1);
106        });
107    }
108
109    #[test]
110    fn twoway() {
111        let (rbw, rbr) = async_ringbuffer::ring_buffer(1024);
112        let mut boxw = BoxWriter::new(rbw, KEY.clone(), Nonce(NONCE_BYTES));
113        let mut boxr = BoxReader::new(rbr, KEY.clone(), Nonce(NONCE_BYTES));
114
115        block_on(async {
116            let body = [0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0];
117
118            boxw.write_all(&body[0..8]).await.unwrap();
119            boxw.flush().await.unwrap();
120            boxw.write_all(&body[8..]).await.unwrap();
121            boxw.flush().await.unwrap();
122
123            let mut buf = [0; 16];
124            boxr.read_exact(&mut buf).await.unwrap();
125            assert_eq!(&buf, &body);
126
127            assert!(!boxw.is_closed());
128            assert!(!boxr.is_closed());
129            boxw.close().await.unwrap();
130
131            let w = boxw.into_inner();
132            assert!(w.is_closed());
133
134            // At this point, the reader doesn't know that the underlying
135            // reader has closed.
136            assert!(!boxr.is_closed());
137
138            let n = boxr.read(&mut buf).await.unwrap();
139            assert_eq!(n, 0);
140            assert!(boxr.is_closed());
141
142            let r = boxr.into_inner();
143            assert!(r.is_closed());
144        });
145    }
146
147    #[test]
148    fn big_body() {
149        let (rbw, rbr) = async_ringbuffer::ring_buffer(16_384);
150        let mut boxw = BoxWriter::new(rbw, KEY.clone(), Nonce(NONCE_BYTES));
151        let mut boxr = BoxReader::new(rbr, KEY.clone(), Nonce(NONCE_BYTES));
152
153        block_on(async {
154            // write empty buf
155            boxw.write(&[]).await.unwrap();
156
157            let body = [123; 10_000];
158            boxw.write_all(&body).await.unwrap();
159            boxw.flush().await.unwrap();
160
161            let mut buf = [0; 10_000];
162            boxr.read_exact(&mut buf).await.unwrap();
163            assert!(buf.iter().all(|i| i == &123));
164            boxw.close().await.unwrap();
165        });
166    }
167}