use std::{io::Cursor, sync::Arc};
use anyhow::Result;
use aws_lc_rs::{
aead::{AES_256_GCM_SIV, RandomizedNonceKey},
hmac::{HMAC_SHA512, Key},
};
use bon::Builder;
use bytes::{Buf as _, BytesMut};
use libmoshpit::{EncryptedFrame, MoshpitError};
use tokio::net::UdpSocket;
use tracing::trace;
use uuid::Uuid;
#[derive(Builder)]
#[allow(dead_code)]
pub(crate) struct UdpReader {
socket: Arc<UdpSocket>,
#[builder(default = BytesMut::with_capacity(4096))]
buffer: BytesMut,
id: Uuid,
#[builder(with = |key: [u8; 32]| -> Result<_> { RandomizedNonceKey::new(&AES_256_GCM_SIV, &key).map_err(Into::into) })]
rnk: RandomizedNonceKey,
#[builder(with = |key: [u8; 64]| { Key::new(HMAC_SHA512, &key) })]
hmac: Key,
}
impl UdpReader {
pub(crate) async fn read_encrypted_frame(&mut self) -> Result<Option<EncryptedFrame>> {
loop {
trace!("Reading frame...");
if let Some(frame) = self.parse_encrypted_frame()? {
trace!("Parsed frame");
return Ok(Some(frame));
}
trace!("Reading buffer...");
if 0 == self.socket.recv_buf(&mut self.buffer).await? {
if self.buffer.is_empty() {
return Ok(None);
}
return Err(MoshpitError::ConnectionResetByPeer.into());
}
trace!("Read {} bytes from socket", self.buffer.len());
}
}
fn parse_encrypted_frame(&mut self) -> Result<Option<EncryptedFrame>> {
let mut buf = Cursor::new(&self.buffer[..]);
buf.set_position(0);
match EncryptedFrame::parse(&mut buf, &self.hmac, &self.rnk) {
Ok(Some(frame)) => {
let len = usize::try_from(buf.position())?;
self.buffer.advance(len);
Ok(Some(frame))
}
Ok(None) => {
Ok(None)
}
Err(err) => {
eprintln!("Frame parse error: {err:?}");
Err(err)
}
}
}
}