Allow uncapped/growable packet sizes

This commit is contained in:
NGnius 2022-08-01 12:23:57 -04:00
parent ac03348e96
commit 424acdf694
8 changed files with 177 additions and 186 deletions

View file

@ -125,9 +125,10 @@ impl Instance {
) )
} }
}; };
let mut buffer = [0u8; socket::PACKET_BUFFER_SIZE]; //let mut buffer = [0u8; socket::PACKET_BUFFER_SIZE];
let mut buffer = String::with_capacity(socket::PACKET_BUFFER_SIZE);
let response = Self::handle_call(packet, &handlers); let response = Self::handle_call(packet, &handlers);
let len = match response.dump_base64(&mut buffer) { let _len = match response.dump_base64(&mut buffer) {
Ok(x) => x, Ok(x) => x,
Err(_) => { Err(_) => {
return warp::reply::with_status( return warp::reply::with_status(
@ -137,9 +138,8 @@ impl Instance {
) )
} }
}; };
let string: String = String::from_utf8_lossy(&buffer[..len]).into();
warp::reply::with_status( warp::reply::with_status(
warp::http::Response::builder().body(string), warp::http::Response::builder().body(buffer),
warp::http::StatusCode::from_u16(200).unwrap(), warp::http::StatusCode::from_u16(200).unwrap(),
) )
}) })
@ -165,7 +165,7 @@ impl Instance {
} }
}; };
let mut buffer = Vec::with_capacity(socket::PACKET_BUFFER_SIZE); let mut buffer = Vec::with_capacity(socket::PACKET_BUFFER_SIZE);
buffer.extend(&[0u8; socket::PACKET_BUFFER_SIZE]); //buffer.extend(&[0u8; socket::PACKET_BUFFER_SIZE]);
let response = Self::handle_call(packet, &handlers); let response = Self::handle_call(packet, &handlers);
let len = match response.dump_encrypted(&mut buffer, &key, &NONCE) { let len = match response.dump_encrypted(&mut buffer, &key, &NONCE) {
Ok(x) => x, Ok(x) => x,

View file

@ -1,3 +1,5 @@
use std::io::{Read, Write};
use crate::serdes::{DumpError, Dumpable, LoadError, Loadable, Primitive}; use crate::serdes::{DumpError, Dumpable, LoadError, Loadable, Primitive};
/// Remote call packet representing a function to call on the back-end, sent from the front-end /// Remote call packet representing a function to call on the back-end, sent from the front-end
@ -11,10 +13,10 @@ pub struct RemoteCall {
} }
impl Loadable for RemoteCall { impl Loadable for RemoteCall {
fn load(buffer: &[u8]) -> Result<(Self, usize), LoadError> { fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
let (id_num, len0) = u64::load(buffer)?; let (id_num, len0) = u64::load(buffer)?;
let (function_name, len1) = String::load(&buffer[len0..])?; let (function_name, len1) = String::load(buffer)?;
let (params, len2) = Vec::<Primitive>::load(&buffer[len0 + len1..])?; let (params, len2) = Vec::<Primitive>::load(buffer)?;
Ok(( Ok((
Self { Self {
id: id_num, id: id_num,
@ -27,10 +29,10 @@ impl Loadable for RemoteCall {
} }
impl Dumpable for RemoteCall { impl Dumpable for RemoteCall {
fn dump(&self, buffer: &mut [u8]) -> Result<usize, DumpError> { fn dump(&self, buffer: &mut dyn Write) -> Result<usize, DumpError> {
let len0 = self.id.dump(buffer)?; let len0 = self.id.dump(buffer)?;
let len1 = self.function.dump(&mut buffer[len0..])?; let len1 = self.function.dump(buffer)?;
let len2 = self.parameters.dump(&mut buffer[len0 + len1..])?; let len2 = self.parameters.dump(buffer)?;
Ok(len0 + len1 + len2) Ok(len0 + len1 + len2)
} }
} }
@ -44,9 +46,9 @@ pub struct RemoteCallResponse {
} }
impl Loadable for RemoteCallResponse { impl Loadable for RemoteCallResponse {
fn load(buffer: &[u8]) -> Result<(Self, usize), LoadError> { fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
let (id_num, len0) = u64::load(buffer)?; let (id_num, len0) = u64::load(buffer)?;
let (response_var, len1) = Vec::<Primitive>::load(&buffer[len0..])?; let (response_var, len1) = Vec::<Primitive>::load(buffer)?;
Ok(( Ok((
Self { Self {
id: id_num, id: id_num,
@ -58,9 +60,9 @@ impl Loadable for RemoteCallResponse {
} }
impl Dumpable for RemoteCallResponse { impl Dumpable for RemoteCallResponse {
fn dump(&self, buffer: &mut [u8]) -> Result<usize, DumpError> { fn dump(&self, buffer: &mut dyn Write) -> Result<usize, DumpError> {
let len0 = self.id.dump(buffer)?; let len0 = self.id.dump(buffer)?;
let len1 = self.response.dump(&mut buffer[len0..])?; let len1 = self.response.dump(buffer)?;
Ok(len0 + len1) Ok(len0 + len1)
} }
} }

View file

@ -1,88 +1,70 @@
use std::io::Write;
use super::{DumpError, Dumpable}; use super::{DumpError, Dumpable};
impl Dumpable for String { impl Dumpable for String {
fn dump(&self, buffer: &mut [u8]) -> Result<usize, DumpError> { fn dump(&self, buffer: &mut dyn Write) -> Result<usize, DumpError> {
let str_bytes = self.as_bytes(); let str_bytes = self.as_bytes();
let len_bytes = (str_bytes.len() as u32).to_le_bytes(); let len_bytes = (str_bytes.len() as u32).to_le_bytes();
let total_len = str_bytes.len() + 4; let size1 = buffer.write(&len_bytes).map_err(DumpError::Io)?;
if buffer.len() < total_len { let size2 = buffer.write(&str_bytes).map_err(DumpError::Io)?;
return Err(DumpError::TooSmallBuffer); Ok(size1 + size2)
}
(&mut buffer[..4]).copy_from_slice(&len_bytes);
(&mut buffer[4..total_len]).copy_from_slice(str_bytes);
Ok(total_len)
} }
} }
impl<T: Dumpable> Dumpable for Vec<T> { impl<T: Dumpable> Dumpable for Vec<T> {
fn dump(&self, buffer: &mut [u8]) -> Result<usize, DumpError> { fn dump(&self, buffer: &mut dyn Write) -> Result<usize, DumpError> {
let len_bytes = (self.len() as u32).to_le_bytes(); let len_bytes = (self.len() as u32).to_le_bytes();
(&mut buffer[..4]).copy_from_slice(&len_bytes); let mut total = buffer.write(&len_bytes).map_err(DumpError::Io)?;
let mut cursor = 4;
for obj in self.iter() { for obj in self.iter() {
let len = obj.dump(&mut buffer[cursor..])?; let len = obj.dump(buffer)?;
cursor += len; total += len;
} }
Ok(cursor) Ok(total)
} }
} }
impl Dumpable for bool { impl Dumpable for bool {
fn dump(&self, buffer: &mut [u8]) -> Result<usize, DumpError> { fn dump(&self, buffer: &mut dyn Write) -> Result<usize, DumpError> {
if buffer.len() < 1 { buffer.write(&[*self as u8]).map_err(DumpError::Io)
return Err(DumpError::TooSmallBuffer);
}
buffer[0] = *self as u8;
Ok(1)
} }
} }
impl Dumpable for u8 { impl Dumpable for u8 {
fn dump(&self, buffer: &mut [u8]) -> Result<usize, DumpError> { fn dump(&self, buffer: &mut dyn Write) -> Result<usize, DumpError> {
if buffer.len() < 1 { buffer.write(&[*self]).map_err(DumpError::Io)
return Err(DumpError::TooSmallBuffer);
}
buffer[0] = *self;
Ok(1)
} }
} }
impl Dumpable for i8 { /*impl Dumpable for i8 {
fn dump(&self, buffer: &mut [u8]) -> Result<usize, DumpError> { fn dump(&self, buffer: &mut dyn Write) -> Result<usize, DumpError> {
if buffer.len() < 1 { buffer.write(&self.to_le_bytes()).map_err(DumpError::Io)
return Err(DumpError::TooSmallBuffer);
}
buffer[0] = self.to_le_bytes()[0];
Ok(1)
} }
} }*/
macro_rules! int_impl { macro_rules! int_impl {
($type:ty, $size:literal) => { ($type:ty) => {
impl Dumpable for $type { impl Dumpable for $type {
fn dump(&self, buffer: &mut [u8]) -> Result<usize, DumpError> { fn dump(&self, buffer: &mut dyn Write) -> Result<usize, DumpError> {
if buffer.len() < $size { buffer.write(&self.to_le_bytes()).map_err(DumpError::Io)
return Err(DumpError::TooSmallBuffer);
}
(&mut buffer[..$size]).copy_from_slice(&self.to_le_bytes());
Ok($size)
} }
} }
}; };
} }
int_impl! {u16, 2} int_impl! {u16}
int_impl! {u32, 4} int_impl! {u32}
int_impl! {u64, 8} int_impl! {u64}
int_impl! {u128, 16} int_impl! {u128}
int_impl! {i16, 2} int_impl! {i8}
int_impl! {i32, 4} int_impl! {i16}
int_impl! {i64, 8} int_impl! {i32}
int_impl! {i128, 16} int_impl! {i64}
int_impl! {i128}
int_impl! {f32, 4} int_impl! {f32}
int_impl! {f64, 8} int_impl! {f64}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
@ -93,10 +75,11 @@ mod tests {
#[test] #[test]
fn $fn_name() { fn $fn_name() {
let data = $data; let data = $data;
let mut buffer = [0u8; 128]; let mut buffer = Vec::with_capacity(128);
let write_len = data.dump(&mut buffer).expect("Dump not ok"); let write_len = data.dump(&mut buffer).expect("Dump not ok");
assert_eq!(write_len, $expected_len, "Wrong amount written"); assert_eq!(write_len, $expected_len, "Wrong amount written");
assert_eq!(&buffer[..write_len], $expected_dump); assert_eq!(&buffer[..write_len], $expected_dump);
println!("Dumped {:?}", buffer.as_slice());
} }
}; };
} }

View file

@ -1,32 +1,36 @@
use std::io::Read;
use super::{LoadError, Loadable}; use super::{LoadError, Loadable};
impl Loadable for String { impl Loadable for String {
fn load(buffer: &[u8]) -> Result<(Self, usize), LoadError> { fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
if buffer.len() < 4 {
return Err(LoadError::TooSmallBuffer);
}
let mut u32_bytes: [u8; 4] = [u8::MAX; 4]; let mut u32_bytes: [u8; 4] = [u8::MAX; 4];
u32_bytes.copy_from_slice(&buffer[..4]); buffer.read_exact(&mut u32_bytes).map_err(LoadError::Io)?;
let str_size = u32::from_le_bytes(u32_bytes) as usize; let str_size = u32::from_le_bytes(u32_bytes) as usize;
//let mut str_buf = String::with_capacity(str_size);
let mut str_buf = Vec::with_capacity(str_size);
let mut byte_buf = [u8::MAX; 1];
for _ in 0..str_size {
buffer.read_exact(&mut byte_buf).map_err(LoadError::Io)?;
str_buf.push(byte_buf[0]);
}
//let size2 = buffer.read_to_string(&mut str_buf).map_err(LoadError::Io)?;
Ok(( Ok((
Self::from_utf8_lossy(&buffer[4..str_size + 4]).into_owned(), String::from_utf8(str_buf).map_err(|_| LoadError::InvalidData)?,
str_size + 4, str_size + 4,
)) ))
} }
} }
impl<T: Loadable> Loadable for Vec<T> { impl<T: Loadable> Loadable for Vec<T> {
fn load(buffer: &[u8]) -> Result<(Self, usize), LoadError> { fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
if buffer.len() < 4 {
return Err(LoadError::TooSmallBuffer);
}
let mut u32_bytes: [u8; 4] = [u8::MAX; 4]; let mut u32_bytes: [u8; 4] = [u8::MAX; 4];
u32_bytes.copy_from_slice(&buffer[..4]); buffer.read_exact(&mut u32_bytes).map_err(LoadError::Io)?;
let count = u32::from_le_bytes(u32_bytes) as usize; let count = u32::from_le_bytes(u32_bytes) as usize;
let mut cursor = 4; let mut cursor = 4;
let mut items = Vec::with_capacity(count); let mut items = Vec::with_capacity(count);
for _ in 0..count { for _ in 0..count {
let (obj, len) = T::load(&buffer[cursor..])?; let (obj, len) = T::load(buffer)?;
cursor += len; cursor += len;
items.push(obj); items.push(obj);
} }
@ -35,41 +39,35 @@ impl<T: Loadable> Loadable for Vec<T> {
} }
impl Loadable for bool { impl Loadable for bool {
fn load(buffer: &[u8]) -> Result<(Self, usize), LoadError> { fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
if buffer.len() < 1 { let mut byte = [u8::MAX; 1];
return Err(LoadError::TooSmallBuffer); buffer.read_exact(&mut byte).map_err(LoadError::Io)?;
} Ok((byte[0] != 0, 1))
Ok((buffer[0] != 0, 1))
} }
} }
impl Loadable for u8 { impl Loadable for u8 {
fn load(buffer: &[u8]) -> Result<(Self, usize), LoadError> { fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
if buffer.len() < 1 { let mut byte = [u8::MAX; 1];
return Err(LoadError::TooSmallBuffer); buffer.read_exact(&mut byte).map_err(LoadError::Io)?;
} Ok((byte[0], 1))
Ok((buffer[0], 1))
} }
} }
impl Loadable for i8 { impl Loadable for i8 {
fn load(buffer: &[u8]) -> Result<(Self, usize), LoadError> { fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
if buffer.len() < 1 { let mut byte = [u8::MAX; 1];
return Err(LoadError::TooSmallBuffer); buffer.read_exact(&mut byte).map_err(LoadError::Io)?;
} Ok((i8::from_le_bytes(byte), 1))
Ok((i8::from_le_bytes([buffer[0]]), 1))
} }
} }
macro_rules! int_impl { macro_rules! int_impl {
($type:ty, $size:literal) => { ($type:ty, $size:literal) => {
impl Loadable for $type { impl Loadable for $type {
fn load(buffer: &[u8]) -> Result<(Self, usize), LoadError> { fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
if buffer.len() < $size {
return Err(LoadError::TooSmallBuffer);
}
let mut bytes: [u8; $size] = [u8::MAX; $size]; let mut bytes: [u8; $size] = [u8::MAX; $size];
bytes.copy_from_slice(&buffer[..$size]); buffer.read_exact(&mut bytes).map_err(LoadError::Io)?;
let i = <$type>::from_le_bytes(bytes); let i = <$type>::from_le_bytes(bytes);
Ok((i, $size)) Ok((i, $size))
} }
@ -93,15 +91,19 @@ int_impl! {f64, 8}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use std::io::Cursor;
macro_rules! test_impl { macro_rules! test_impl {
($fn_name:ident, $data:expr, $type:ty, $expected_len:literal, $expected_load:expr) => { ($fn_name:ident, $data:expr, $type:ty, $expected_len:literal, $expected_load:expr) => {
#[test] #[test]
fn $fn_name() { fn $fn_name() {
let buffer = $data; let buffer_data = $data;
let (obj, read_len) = <$type>::load(&buffer).expect("Load not ok"); let mut buffer = Vec::with_capacity(buffer_data.len());
buffer.extend_from_slice(&buffer_data);
let (obj, read_len) = <$type>::load(&mut Cursor::new(buffer)).expect("Load not ok");
assert_eq!(read_len, $expected_len, "Wrong amount read"); assert_eq!(read_len, $expected_len, "Wrong amount read");
assert_eq!(obj, $expected_load, "Loaded value not as expected"); assert_eq!(obj, $expected_load, "Loaded value not as expected");
println!("Loaded {:?}", obj);
} }
}; };
} }

View file

@ -1,3 +1,4 @@
use std::io::{Read, Write};
use super::{DumpError, Dumpable, LoadError, Loadable}; use super::{DumpError, Dumpable, LoadError, Loadable};
/// Primitive types supported for communication between the USDPL back- and front-end. /// Primitive types supported for communication between the USDPL back- and front-end.
@ -44,22 +45,21 @@ impl Primitive {
} }
impl Loadable for Primitive { impl Loadable for Primitive {
fn load(buf: &[u8]) -> Result<(Self, usize), LoadError> { fn load(buf: &mut dyn Read) -> Result<(Self, usize), LoadError> {
if buf.len() == 0 { let mut discriminant_buf = [u8::MAX; 1];
return Err(LoadError::TooSmallBuffer); buf.read_exact(&mut discriminant_buf).map_err(LoadError::Io)?;
} let mut result: (Self, usize) = match discriminant_buf[0] {
let mut result: (Self, usize) = match buf[0] {
//0 => (None, 0), //0 => (None, 0),
1 => (Self::Empty, 0), 1 => (Self::Empty, 0),
2 => String::load(&buf[1..]).map(|(obj, len)| (Self::String(obj), len))?, 2 => String::load(buf).map(|(obj, len)| (Self::String(obj), len))?,
3 => f32::load(&buf[1..]).map(|(obj, len)| (Self::F32(obj), len))?, 3 => f32::load(buf).map(|(obj, len)| (Self::F32(obj), len))?,
4 => f64::load(&buf[1..]).map(|(obj, len)| (Self::F64(obj), len))?, 4 => f64::load(buf).map(|(obj, len)| (Self::F64(obj), len))?,
5 => u32::load(&buf[1..]).map(|(obj, len)| (Self::U32(obj), len))?, 5 => u32::load(buf).map(|(obj, len)| (Self::U32(obj), len))?,
6 => u64::load(&buf[1..]).map(|(obj, len)| (Self::U64(obj), len))?, 6 => u64::load(buf).map(|(obj, len)| (Self::U64(obj), len))?,
7 => i32::load(&buf[1..]).map(|(obj, len)| (Self::I32(obj), len))?, 7 => i32::load(buf).map(|(obj, len)| (Self::I32(obj), len))?,
8 => i64::load(&buf[1..]).map(|(obj, len)| (Self::I64(obj), len))?, 8 => i64::load(buf).map(|(obj, len)| (Self::I64(obj), len))?,
9 => bool::load(&buf[1..]).map(|(obj, len)| (Self::Bool(obj), len))?, 9 => bool::load(buf).map(|(obj, len)| (Self::Bool(obj), len))?,
10 => String::load(&buf[1..]).map(|(obj, len)| (Self::Json(obj), len))?, 10 => String::load(buf).map(|(obj, len)| (Self::Json(obj), len))?,
_ => return Err(LoadError::InvalidData), _ => return Err(LoadError::InvalidData),
}; };
result.1 += 1; result.1 += 1;
@ -68,25 +68,21 @@ impl Loadable for Primitive {
} }
impl Dumpable for Primitive { impl Dumpable for Primitive {
fn dump(&self, buf: &mut [u8]) -> Result<usize, DumpError> { fn dump(&self, buf: &mut dyn Write) -> Result<usize, DumpError> {
if buf.len() == 0 { let size1 = buf.write(&[self.discriminant()]).map_err(DumpError::Io)?;
return Err(DumpError::TooSmallBuffer); let result = match self {
}
buf[0] = self.discriminant();
let mut result = match self {
Self::Empty => Ok(0), Self::Empty => Ok(0),
Self::String(s) => s.dump(&mut buf[1..]), Self::String(s) => s.dump(buf),
Self::F32(x) => x.dump(&mut buf[1..]), Self::F32(x) => x.dump(buf),
Self::F64(x) => x.dump(&mut buf[1..]), Self::F64(x) => x.dump(buf),
Self::U32(x) => x.dump(&mut buf[1..]), Self::U32(x) => x.dump(buf),
Self::U64(x) => x.dump(&mut buf[1..]), Self::U64(x) => x.dump(buf),
Self::I32(x) => x.dump(&mut buf[1..]), Self::I32(x) => x.dump(buf),
Self::I64(x) => x.dump(&mut buf[1..]), Self::I64(x) => x.dump(buf),
Self::Bool(x) => x.dump(&mut buf[1..]), Self::Bool(x) => x.dump(buf),
Self::Json(x) => x.dump(&mut buf[1..]), Self::Json(x) => x.dump(buf),
}?; }?;
result += 1; Ok(size1 + result)
Ok(result)
} }
} }
@ -127,14 +123,15 @@ into_impl! {f64, F64}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use std::io::Cursor;
#[test] #[test]
fn string_idempotence_test() { fn string_idempotence_test() {
let data = "Test"; let data = "Test";
let primitive = Primitive::String(data.to_string()); let primitive = Primitive::String(data.to_string());
let mut buffer = [0u8; 128]; let mut buffer = Vec::with_capacity(128);
let write_len = primitive.dump(&mut buffer).expect("Dump not ok"); let write_len = primitive.dump(&mut buffer).expect("Dump not ok");
let (obj, read_len) = Primitive::load(&buffer).expect("Load not ok"); let (obj, read_len) = Primitive::load(&mut Cursor::new(buffer)).expect("Load not ok");
assert_eq!( assert_eq!(
write_len, read_len, write_len, read_len,
"Amount written and amount read do not match" "Amount written and amount read do not match"
@ -149,9 +146,9 @@ mod tests {
#[test] #[test]
fn empty_idempotence_test() { fn empty_idempotence_test() {
let primitive = Primitive::Empty; let primitive = Primitive::Empty;
let mut buffer = [0u8; 128]; let mut buffer = Vec::with_capacity(128);
let write_len = primitive.dump(&mut buffer).expect("Dump not ok"); let write_len = primitive.dump(&mut buffer).expect("Dump not ok");
let (obj, read_len) = Primitive::load(&buffer).expect("Load not ok"); let (obj, read_len) = Primitive::load(&mut Cursor::new(buffer)).expect("Load not ok");
assert_eq!( assert_eq!(
write_len, read_len, write_len, read_len,
"Amount written and amount read do not match" "Amount written and amount read do not match"

View file

@ -1,4 +1,5 @@
use base64::{decode_config_slice, encode_config_slice, Config}; use std::io::{Read, Write, Cursor};
use base64::{decode_config_buf, encode_config_buf, Config};
const B64_CONF: Config = Config::new(base64::CharacterSet::Standard, true); const B64_CONF: Config = Config::new(base64::CharacterSet::Standard, true);
@ -18,6 +19,8 @@ pub enum LoadError {
/// Encrypted data cannot be decrypted /// Encrypted data cannot be decrypted
#[cfg(feature = "encrypt")] #[cfg(feature = "encrypt")]
DecryptionError, DecryptionError,
/// Read error
Io(std::io::Error),
/// Unimplemented /// Unimplemented
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
Todo, Todo,
@ -30,6 +33,7 @@ impl std::fmt::Display for LoadError {
Self::InvalidData => write!(f, "LoadError: InvalidData"), Self::InvalidData => write!(f, "LoadError: InvalidData"),
#[cfg(feature = "encrypt")] #[cfg(feature = "encrypt")]
Self::DecryptionError => write!(f, "LoadError: DecryptionError"), Self::DecryptionError => write!(f, "LoadError: DecryptionError"),
Self::Io(err) => write!(f, "LoadError: Io({})", err),
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
Self::Todo => write!(f, "LoadError: TODO!"), Self::Todo => write!(f, "LoadError: TODO!"),
} }
@ -39,30 +43,33 @@ impl std::fmt::Display for LoadError {
/// Load an object from the buffer /// Load an object from the buffer
pub trait Loadable: Sized { pub trait Loadable: Sized {
/// Read the buffer, building the object and returning the amount of bytes read. /// Read the buffer, building the object and returning the amount of bytes read.
/// If anything is wrong with the buffer, None should be returned. /// If anything is wrong with the buffer, Err should be returned.
fn load(buffer: &[u8]) -> Result<(Self, usize), LoadError>; fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError>;
/// Load data from a base64-encoded buffer /// Load data from a base64-encoded buffer
fn load_base64(buffer: &[u8]) -> Result<(Self, usize), LoadError> { fn load_base64(buffer: &[u8]) -> Result<(Self, usize), LoadError> {
let mut buffer2 = [0u8; crate::socket::PACKET_BUFFER_SIZE]; let mut buffer2 = Vec::with_capacity(crate::socket::PACKET_BUFFER_SIZE);
let len = decode_config_slice(buffer, B64_CONF, &mut buffer2) decode_config_buf(buffer, B64_CONF, &mut buffer2)
.map_err(|_| LoadError::InvalidData)?; .map_err(|_| LoadError::InvalidData)?;
Self::load(&buffer2[..len]) let mut cursor = Cursor::new(buffer2);
Self::load(&mut cursor)
} }
/// Load data from an encrypted base64-encoded buffer /// Load data from an encrypted base64-encoded buffer
#[cfg(feature = "encrypt")] #[cfg(feature = "encrypt")]
fn load_encrypted(buffer: &[u8], key: &[u8], nonce: &[u8]) -> Result<(Self, usize), LoadError> { fn load_encrypted(buffer: &[u8], key: &[u8], nonce: &[u8]) -> Result<(Self, usize), LoadError> {
println!("encrypted buffer: {}", String::from_utf8(buffer.to_vec()).unwrap()); //println!("encrypted buffer: {}", String::from_utf8(buffer.to_vec()).unwrap());
let key = aes_gcm_siv::Key::from_slice(key); let key = aes_gcm_siv::Key::from_slice(key);
let cipher = aes_gcm_siv::Aes256GcmSiv::new(key); let cipher = aes_gcm_siv::Aes256GcmSiv::new(key);
let nonce = aes_gcm_siv::Nonce::from_slice(nonce); let nonce = aes_gcm_siv::Nonce::from_slice(nonce);
let mut decoded_buf = base64::decode_config(buffer, B64_CONF) let mut decoded_buf = Vec::with_capacity(crate::socket::PACKET_BUFFER_SIZE);
base64::decode_config_buf(buffer, B64_CONF, &mut decoded_buf)
.map_err(|_| LoadError::InvalidData)?; .map_err(|_| LoadError::InvalidData)?;
println!("Decoded buf: {:?}", decoded_buf); //println!("Decoded buf: {:?}", decoded_buf);
cipher.decrypt_in_place(nonce, ASSOCIATED_DATA, &mut decoded_buf).map_err(|_| LoadError::DecryptionError)?; cipher.decrypt_in_place(nonce, ASSOCIATED_DATA, &mut decoded_buf).map_err(|_| LoadError::DecryptionError)?;
println!("Decrypted buf: {:?}", decoded_buf); //println!("Decrypted buf: {:?}", decoded_buf);
Self::load(decoded_buf.as_slice()) let mut cursor = Cursor::new(decoded_buf);
Self::load(&mut cursor)
} }
} }
@ -76,6 +83,8 @@ pub enum DumpError {
/// Data cannot be encrypted /// Data cannot be encrypted
#[cfg(feature = "encrypt")] #[cfg(feature = "encrypt")]
EncryptionError, EncryptionError,
/// Write error
Io(std::io::Error),
/// Unimplemented /// Unimplemented
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
Todo, Todo,
@ -88,6 +97,7 @@ impl std::fmt::Display for DumpError {
Self::Unsupported => write!(f, "DumpError: Unsupported"), Self::Unsupported => write!(f, "DumpError: Unsupported"),
#[cfg(feature = "encrypt")] #[cfg(feature = "encrypt")]
Self::EncryptionError => write!(f, "DumpError: EncryptionError"), Self::EncryptionError => write!(f, "DumpError: EncryptionError"),
Self::Io(err) => write!(f, "DumpError: Io({})", err),
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
Self::Todo => write!(f, "DumpError: TODO!"), Self::Todo => write!(f, "DumpError: TODO!"),
} }
@ -98,33 +108,35 @@ impl std::fmt::Display for DumpError {
pub trait Dumpable { pub trait Dumpable {
/// Write the object to the buffer, returning the amount of bytes written. /// Write the object to the buffer, returning the amount of bytes written.
/// If anything is wrong, false should be returned. /// If anything is wrong, false should be returned.
fn dump(&self, buffer: &mut [u8]) -> Result<usize, DumpError>; fn dump(&self, buffer: &mut dyn Write) -> Result<usize, DumpError>;
/// Dump data as base64-encoded. /// Dump data as base64-encoded.
/// Useful for transmitting data as text. /// Useful for transmitting data as text.
fn dump_base64(&self, buffer: &mut [u8]) -> Result<usize, DumpError> { fn dump_base64(&self, buffer: &mut String) -> Result<usize, DumpError> {
let mut buffer2 = [0u8; crate::socket::PACKET_BUFFER_SIZE]; let mut buffer2 = Vec::with_capacity(crate::socket::PACKET_BUFFER_SIZE);
let len = self.dump(&mut buffer2)?; let len = self.dump(&mut buffer2)?;
let len = encode_config_slice(&buffer2[..len], B64_CONF, buffer); encode_config_buf(&buffer2[..len], B64_CONF, buffer);
Ok(len) Ok(len)
} }
/// Dump data as an encrypted base64-encoded buffer /// Dump data as an encrypted base64-encoded buffer
#[cfg(feature = "encrypt")] #[cfg(feature = "encrypt")]
fn dump_encrypted(&self, buffer: &mut Vec<u8>, key: &[u8], nonce: &[u8]) -> Result<usize, DumpError> { fn dump_encrypted(&self, buffer: &mut Vec<u8>, key: &[u8], nonce: &[u8]) -> Result<usize, DumpError> {
let mut buffer2 = Vec::with_capacity(buffer.capacity()); let mut buffer2 = Vec::with_capacity(crate::socket::PACKET_BUFFER_SIZE);
buffer2.extend_from_slice(buffer.as_slice());
let size = self.dump(&mut buffer2)?; let size = self.dump(&mut buffer2)?;
buffer2.truncate(size); buffer2.truncate(size);
println!("Buf: {:?}", buffer2); //println!("Buf: {:?}", buffer2);
let key = aes_gcm_siv::Key::from_slice(key); let key = aes_gcm_siv::Key::from_slice(key);
let cipher = aes_gcm_siv::Aes256GcmSiv::new(key); let cipher = aes_gcm_siv::Aes256GcmSiv::new(key);
let nonce = aes_gcm_siv::Nonce::from_slice(nonce); let nonce = aes_gcm_siv::Nonce::from_slice(nonce);
cipher.encrypt_in_place(nonce, ASSOCIATED_DATA, &mut buffer2).map_err(|_| DumpError::EncryptionError)?; cipher.encrypt_in_place(nonce, ASSOCIATED_DATA, &mut buffer2).map_err(|_| DumpError::EncryptionError)?;
println!("Encrypted slice: {:?}", &buffer2); //println!("Encrypted slice: {:?}", &buffer2);
let size = encode_config_slice(buffer2.as_slice(), B64_CONF, buffer); let mut base64_buf = String::with_capacity(crate::socket::PACKET_BUFFER_SIZE);
let string = String::from_utf8(buffer.as_slice()[..size].to_vec()).unwrap(); encode_config_buf(buffer2.as_slice(), B64_CONF, &mut base64_buf);
println!("Encoded slice: {}", string); //println!("base64 len: {}", base64_buf.as_bytes().len());
Ok(size) buffer.extend_from_slice(base64_buf.as_bytes());
//let string = String::from_utf8(buffer.as_slice().to_vec()).unwrap();
//println!("Encoded slice: {}", string);
Ok(base64_buf.len())
} }
} }

View file

@ -1,5 +1,6 @@
//! Web messaging //! Web messaging
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::io::{Read, Write};
use crate::serdes::{DumpError, Dumpable, LoadError, Loadable}; use crate::serdes::{DumpError, Dumpable, LoadError, Loadable};
use crate::{RemoteCall, RemoteCallResponse}; use crate::{RemoteCall, RemoteCallResponse};
@ -57,30 +58,29 @@ impl Packet {
} }
impl Loadable for Packet { impl Loadable for Packet {
fn load(buf: &[u8]) -> Result<(Self, usize), LoadError> { fn load(buf: &mut dyn Read) -> Result<(Self, usize), LoadError> {
if buf.len() == 0 { let mut discriminant_buf = [u8::MAX; 1];
return Err(LoadError::TooSmallBuffer); buf.read_exact(&mut discriminant_buf).map_err(LoadError::Io)?;
} let mut result: (Self, usize) = match discriminant_buf[0] {
let mut result: (Self, usize) = match buf[0] {
//0 => (None, 0), //0 => (None, 0),
1 => { 1 => {
let (obj, len) = RemoteCall::load(&buf[1..])?; let (obj, len) = RemoteCall::load(buf)?;
(Self::Call(obj), len) (Self::Call(obj), len)
} }
2 => { 2 => {
let (obj, len) = RemoteCallResponse::load(&buf[1..])?; let (obj, len) = RemoteCallResponse::load(buf)?;
(Self::CallResponse(obj), len) (Self::CallResponse(obj), len)
} }
3 => (Self::KeepAlive, 0), 3 => (Self::KeepAlive, 0),
4 => (Self::Invalid, 0), 4 => (Self::Invalid, 0),
5 => { 5 => {
let (obj, len) = String::load(&buf[1..])?; let (obj, len) = String::load(buf)?;
(Self::Message(obj), len) (Self::Message(obj), len)
} }
6 => (Self::Unsupported, 0), 6 => (Self::Unsupported, 0),
7 => return Err(LoadError::InvalidData), 7 => return Err(LoadError::InvalidData),
8 => { 8 => {
let (obj, len) = <_>::load(&buf[1..])?; let (obj, len) = <_>::load(buf)?;
(Self::Many(obj), len) (Self::Many(obj), len)
} }
_ => return Err(LoadError::InvalidData), _ => return Err(LoadError::InvalidData),
@ -91,23 +91,19 @@ impl Loadable for Packet {
} }
impl Dumpable for Packet { impl Dumpable for Packet {
fn dump(&self, buf: &mut [u8]) -> Result<usize, DumpError> { fn dump(&self, buf: &mut dyn Write) -> Result<usize, DumpError> {
if buf.len() == 0 { let size1 = buf.write(&[self.discriminant()]).map_err(DumpError::Io)?;
return Err(DumpError::TooSmallBuffer); let result = match self {
} Self::Call(c) => c.dump(buf),
buf[0] = self.discriminant(); Self::CallResponse(c) => c.dump(buf),
let mut result = match self {
Self::Call(c) => c.dump(&mut buf[1..]),
Self::CallResponse(c) => c.dump(&mut buf[1..]),
Self::KeepAlive => Ok(0), Self::KeepAlive => Ok(0),
Self::Invalid => Ok(0), Self::Invalid => Ok(0),
Self::Message(s) => s.dump(&mut buf[1..]), Self::Message(s) => s.dump(buf),
Self::Unsupported => Ok(0), Self::Unsupported => Ok(0),
Self::Bad => return Err(DumpError::Unsupported), Self::Bad => return Err(DumpError::Unsupported),
Self::Many(v) => v.dump(&mut buf[1..]), Self::Many(v) => v.dump(buf),
}?; }?;
result += 1; Ok(size1 + result)
Ok(result)
} }
} }
@ -126,7 +122,6 @@ mod tests {
parameters: Vec::new(), parameters: Vec::new(),
}); });
let mut buffer = Vec::with_capacity(PACKET_BUFFER_SIZE); let mut buffer = Vec::with_capacity(PACKET_BUFFER_SIZE);
buffer.extend_from_slice(&[0u8; PACKET_BUFFER_SIZE]);
let len = packet.dump_encrypted(&mut buffer, &key, &nonce).unwrap(); let len = packet.dump_encrypted(&mut buffer, &key, &nonce).unwrap();
println!("buffer: {}", String::from_utf8(buffer.as_slice()[..len].to_vec()).unwrap()); println!("buffer: {}", String::from_utf8(buffer.as_slice()[..len].to_vec()).unwrap());

View file

@ -80,7 +80,7 @@ pub async fn send_js(
#[cfg(feature = "encrypt")] #[cfg(feature = "encrypt")]
fn dump_to_buffer(packet: socket::Packet, key: &[u8]) -> Result<(Vec<u8>, usize), JsValue> { fn dump_to_buffer(packet: socket::Packet, key: &[u8]) -> Result<(Vec<u8>, usize), JsValue> {
let mut buffer = Vec::with_capacity(socket::PACKET_BUFFER_SIZE); let mut buffer = Vec::with_capacity(socket::PACKET_BUFFER_SIZE);
buffer.extend_from_slice(&[0u8; socket::PACKET_BUFFER_SIZE]); //buffer.extend_from_slice(&[0u8; socket::PACKET_BUFFER_SIZE]);
let len = packet let len = packet
.dump_encrypted(&mut buffer, key, &NONCE) .dump_encrypted(&mut buffer, key, &NONCE)
.map_err(super::convert::str_to_js)?; .map_err(super::convert::str_to_js)?;
@ -89,10 +89,10 @@ fn dump_to_buffer(packet: socket::Packet, key: &[u8]) -> Result<(Vec<u8>, usize)
#[cfg(not(feature = "encrypt"))] #[cfg(not(feature = "encrypt"))]
fn dump_to_buffer(packet: socket::Packet) -> Result<(Vec<u8>, usize), JsValue> { fn dump_to_buffer(packet: socket::Packet) -> Result<(Vec<u8>, usize), JsValue> {
let mut buffer = Vec::with_capacity(socket::PACKET_BUFFER_SIZE); let mut buffer = String::with_capacity(socket::PACKET_BUFFER_SIZE);
buffer.extend_from_slice(&[0u8; socket::PACKET_BUFFER_SIZE]); //buffer.extend_from_slice(&[0u8; socket::PACKET_BUFFER_SIZE]);
let len = packet let len = packet
.dump_base64(buffer.as_mut_slice()) .dump_base64(&mut buffer)
.map_err(super::convert::str_to_js)?; .map_err(super::convert::str_to_js)?;
Ok((buffer, len)) Ok((buffer.as_bytes().to_vec(), len))
} }