use super::*;
pub(crate) fn priv_crypt(
send: PrivFramedSend,
enc: sss::SecretStreamEncrypt,
recv: PrivFramedRecv,
dec: sss::SecretStreamDecrypt,
) -> (PrivCryptSend, PrivCryptRecv) {
let send = PrivCryptSend::new(send, enc);
let recv = PrivCryptRecv::new(recv, dec);
(send, recv)
}
pub(crate) struct PrivCryptSend {
send: PrivFramedSend,
enc: sss::SecretStreamEncrypt,
}
impl PrivCryptSend {
pub(crate) fn new(
send: PrivFramedSend,
enc: sss::SecretStreamEncrypt,
) -> Self {
Self { send, enc }
}
pub(crate) fn send(
&mut self,
data: Box<[u8]>,
) -> impl Future<Output = LairResult<()>> + '_ + Send {
async move {
let len = data.len() + sss::ABYTES;
let cipher = sodoken::BufExtend::new_no_lock(len);
self.enc
.push_message(
data,
<Option<sodoken::BufRead>>::None,
cipher.clone(),
)
.await?;
let cipher = cipher.try_unwrap().unwrap();
self.send.send(cipher).await?;
Ok(())
}
}
pub(crate) fn shutdown(
&mut self,
) -> impl Future<Output = LairResult<()>> + '_ + Send {
async move { self.send.shutdown().await }
}
}
pub(crate) struct PrivCryptRecv(BoxStream<'static, LairResult<Box<[u8]>>>);
impl PrivCryptRecv {
pub fn new(recv: PrivFramedRecv, dec: sss::SecretStreamDecrypt) -> Self {
let recv = futures::stream::try_unfold(
(recv, dec),
|(mut recv, mut dec)| async move {
let cipher = match recv.next().await {
None => return Ok(None),
Some(cipher) => cipher?,
};
let cipher = sodoken::BufRead::from(cipher);
let msg =
sodoken::BufWrite::new_no_lock(cipher.len() - sss::ABYTES);
dec.pull(cipher, <Option<sodoken::BufRead>>::None, msg.clone())
.await?;
let msg = msg.try_unwrap().unwrap();
Ok(Some((msg, (recv, dec))))
},
);
Self(recv.boxed())
}
}
impl Stream for PrivCryptRecv {
type Item = LairResult<Box<[u8]>>;
fn poll_next(
mut self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Option<Self::Item>> {
Stream::poll_next(std::pin::Pin::new(&mut self.0), cx)
}
}