Allow uncapped/growable packet sizes
This commit is contained in:
parent
ac03348e96
commit
424acdf694
8 changed files with 177 additions and 186 deletions
|
@ -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 len = match response.dump_base64(&mut buffer) {
|
||||
let _len = match response.dump_base64(&mut buffer) {
|
||||
Ok(x) => x,
|
||||
Err(_) => {
|
||||
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::http::Response::builder().body(string),
|
||||
warp::http::Response::builder().body(buffer),
|
||||
warp::http::StatusCode::from_u16(200).unwrap(),
|
||||
)
|
||||
})
|
||||
|
@ -165,7 +165,7 @@ impl Instance {
|
|||
}
|
||||
};
|
||||
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 len = match response.dump_encrypted(&mut buffer, &key, &NONCE) {
|
||||
Ok(x) => x,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::io::{Read, Write};
|
||||
|
||||
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
|
||||
|
@ -11,10 +13,10 @@ pub struct 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 (function_name, len1) = String::load(&buffer[len0..])?;
|
||||
let (params, len2) = Vec::<Primitive>::load(&buffer[len0 + len1..])?;
|
||||
let (function_name, len1) = String::load(buffer)?;
|
||||
let (params, len2) = Vec::<Primitive>::load(buffer)?;
|
||||
Ok((
|
||||
Self {
|
||||
id: id_num,
|
||||
|
@ -27,10 +29,10 @@ impl Loadable 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 len1 = self.function.dump(&mut buffer[len0..])?;
|
||||
let len2 = self.parameters.dump(&mut buffer[len0 + len1..])?;
|
||||
let len1 = self.function.dump(buffer)?;
|
||||
let len2 = self.parameters.dump(buffer)?;
|
||||
Ok(len0 + len1 + len2)
|
||||
}
|
||||
}
|
||||
|
@ -44,9 +46,9 @@ pub struct 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 (response_var, len1) = Vec::<Primitive>::load(&buffer[len0..])?;
|
||||
let (response_var, len1) = Vec::<Primitive>::load(buffer)?;
|
||||
Ok((
|
||||
Self {
|
||||
id: id_num,
|
||||
|
@ -58,9 +60,9 @@ impl Loadable 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 len1 = self.response.dump(&mut buffer[len0..])?;
|
||||
let len1 = self.response.dump(buffer)?;
|
||||
Ok(len0 + len1)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,88 +1,70 @@
|
|||
use std::io::Write;
|
||||
|
||||
use super::{DumpError, Dumpable};
|
||||
|
||||
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 len_bytes = (str_bytes.len() as u32).to_le_bytes();
|
||||
let total_len = str_bytes.len() + 4;
|
||||
if buffer.len() < total_len {
|
||||
return Err(DumpError::TooSmallBuffer);
|
||||
}
|
||||
(&mut buffer[..4]).copy_from_slice(&len_bytes);
|
||||
(&mut buffer[4..total_len]).copy_from_slice(str_bytes);
|
||||
Ok(total_len)
|
||||
let size1 = buffer.write(&len_bytes).map_err(DumpError::Io)?;
|
||||
let size2 = buffer.write(&str_bytes).map_err(DumpError::Io)?;
|
||||
Ok(size1 + size2)
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
(&mut buffer[..4]).copy_from_slice(&len_bytes);
|
||||
let mut cursor = 4;
|
||||
let mut total = buffer.write(&len_bytes).map_err(DumpError::Io)?;
|
||||
for obj in self.iter() {
|
||||
let len = obj.dump(&mut buffer[cursor..])?;
|
||||
cursor += len;
|
||||
let len = obj.dump(buffer)?;
|
||||
total += len;
|
||||
}
|
||||
Ok(cursor)
|
||||
Ok(total)
|
||||
}
|
||||
}
|
||||
|
||||
impl Dumpable for bool {
|
||||
fn dump(&self, buffer: &mut [u8]) -> Result<usize, DumpError> {
|
||||
if buffer.len() < 1 {
|
||||
return Err(DumpError::TooSmallBuffer);
|
||||
}
|
||||
buffer[0] = *self as u8;
|
||||
Ok(1)
|
||||
fn dump(&self, buffer: &mut dyn Write) -> Result<usize, DumpError> {
|
||||
buffer.write(&[*self as u8]).map_err(DumpError::Io)
|
||||
}
|
||||
}
|
||||
|
||||
impl Dumpable for u8 {
|
||||
fn dump(&self, buffer: &mut [u8]) -> Result<usize, DumpError> {
|
||||
if buffer.len() < 1 {
|
||||
return Err(DumpError::TooSmallBuffer);
|
||||
}
|
||||
buffer[0] = *self;
|
||||
Ok(1)
|
||||
fn dump(&self, buffer: &mut dyn Write) -> Result<usize, DumpError> {
|
||||
buffer.write(&[*self]).map_err(DumpError::Io)
|
||||
}
|
||||
}
|
||||
|
||||
impl Dumpable for i8 {
|
||||
fn dump(&self, buffer: &mut [u8]) -> Result<usize, DumpError> {
|
||||
if buffer.len() < 1 {
|
||||
return Err(DumpError::TooSmallBuffer);
|
||||
/*impl Dumpable for i8 {
|
||||
fn dump(&self, buffer: &mut dyn Write) -> Result<usize, DumpError> {
|
||||
buffer.write(&self.to_le_bytes()).map_err(DumpError::Io)
|
||||
}
|
||||
buffer[0] = self.to_le_bytes()[0];
|
||||
Ok(1)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
macro_rules! int_impl {
|
||||
($type:ty, $size:literal) => {
|
||||
($type:ty) => {
|
||||
impl Dumpable for $type {
|
||||
fn dump(&self, buffer: &mut [u8]) -> Result<usize, DumpError> {
|
||||
if buffer.len() < $size {
|
||||
return Err(DumpError::TooSmallBuffer);
|
||||
}
|
||||
(&mut buffer[..$size]).copy_from_slice(&self.to_le_bytes());
|
||||
Ok($size)
|
||||
fn dump(&self, buffer: &mut dyn Write) -> Result<usize, DumpError> {
|
||||
buffer.write(&self.to_le_bytes()).map_err(DumpError::Io)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
int_impl! {u16, 2}
|
||||
int_impl! {u32, 4}
|
||||
int_impl! {u64, 8}
|
||||
int_impl! {u128, 16}
|
||||
int_impl! {u16}
|
||||
int_impl! {u32}
|
||||
int_impl! {u64}
|
||||
int_impl! {u128}
|
||||
|
||||
int_impl! {i16, 2}
|
||||
int_impl! {i32, 4}
|
||||
int_impl! {i64, 8}
|
||||
int_impl! {i128, 16}
|
||||
int_impl! {i8}
|
||||
int_impl! {i16}
|
||||
int_impl! {i32}
|
||||
int_impl! {i64}
|
||||
int_impl! {i128}
|
||||
|
||||
int_impl! {f32, 4}
|
||||
int_impl! {f64, 8}
|
||||
int_impl! {f32}
|
||||
int_impl! {f64}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
@ -93,10 +75,11 @@ mod tests {
|
|||
#[test]
|
||||
fn $fn_name() {
|
||||
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");
|
||||
assert_eq!(write_len, $expected_len, "Wrong amount written");
|
||||
assert_eq!(&buffer[..write_len], $expected_dump);
|
||||
println!("Dumped {:?}", buffer.as_slice());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,32 +1,36 @@
|
|||
use std::io::Read;
|
||||
|
||||
use super::{LoadError, Loadable};
|
||||
|
||||
impl Loadable for String {
|
||||
fn load(buffer: &[u8]) -> Result<(Self, usize), LoadError> {
|
||||
if buffer.len() < 4 {
|
||||
return Err(LoadError::TooSmallBuffer);
|
||||
}
|
||||
fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
|
||||
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 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((
|
||||
Self::from_utf8_lossy(&buffer[4..str_size + 4]).into_owned(),
|
||||
String::from_utf8(str_buf).map_err(|_| LoadError::InvalidData)?,
|
||||
str_size + 4,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Loadable> Loadable for Vec<T> {
|
||||
fn load(buffer: &[u8]) -> Result<(Self, usize), LoadError> {
|
||||
if buffer.len() < 4 {
|
||||
return Err(LoadError::TooSmallBuffer);
|
||||
}
|
||||
fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
|
||||
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 mut cursor = 4;
|
||||
let mut items = Vec::with_capacity(count);
|
||||
for _ in 0..count {
|
||||
let (obj, len) = T::load(&buffer[cursor..])?;
|
||||
let (obj, len) = T::load(buffer)?;
|
||||
cursor += len;
|
||||
items.push(obj);
|
||||
}
|
||||
|
@ -35,41 +39,35 @@ impl<T: Loadable> Loadable for Vec<T> {
|
|||
}
|
||||
|
||||
impl Loadable for bool {
|
||||
fn load(buffer: &[u8]) -> Result<(Self, usize), LoadError> {
|
||||
if buffer.len() < 1 {
|
||||
return Err(LoadError::TooSmallBuffer);
|
||||
}
|
||||
Ok((buffer[0] != 0, 1))
|
||||
fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
|
||||
let mut byte = [u8::MAX; 1];
|
||||
buffer.read_exact(&mut byte).map_err(LoadError::Io)?;
|
||||
Ok((byte[0] != 0, 1))
|
||||
}
|
||||
}
|
||||
|
||||
impl Loadable for u8 {
|
||||
fn load(buffer: &[u8]) -> Result<(Self, usize), LoadError> {
|
||||
if buffer.len() < 1 {
|
||||
return Err(LoadError::TooSmallBuffer);
|
||||
}
|
||||
Ok((buffer[0], 1))
|
||||
fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
|
||||
let mut byte = [u8::MAX; 1];
|
||||
buffer.read_exact(&mut byte).map_err(LoadError::Io)?;
|
||||
Ok((byte[0], 1))
|
||||
}
|
||||
}
|
||||
|
||||
impl Loadable for i8 {
|
||||
fn load(buffer: &[u8]) -> Result<(Self, usize), LoadError> {
|
||||
if buffer.len() < 1 {
|
||||
return Err(LoadError::TooSmallBuffer);
|
||||
}
|
||||
Ok((i8::from_le_bytes([buffer[0]]), 1))
|
||||
fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
|
||||
let mut byte = [u8::MAX; 1];
|
||||
buffer.read_exact(&mut byte).map_err(LoadError::Io)?;
|
||||
Ok((i8::from_le_bytes(byte), 1))
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! int_impl {
|
||||
($type:ty, $size:literal) => {
|
||||
impl Loadable for $type {
|
||||
fn load(buffer: &[u8]) -> Result<(Self, usize), LoadError> {
|
||||
if buffer.len() < $size {
|
||||
return Err(LoadError::TooSmallBuffer);
|
||||
}
|
||||
fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError> {
|
||||
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);
|
||||
Ok((i, $size))
|
||||
}
|
||||
|
@ -93,15 +91,19 @@ int_impl! {f64, 8}
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
macro_rules! test_impl {
|
||||
($fn_name:ident, $data:expr, $type:ty, $expected_len:literal, $expected_load:expr) => {
|
||||
#[test]
|
||||
fn $fn_name() {
|
||||
let buffer = $data;
|
||||
let (obj, read_len) = <$type>::load(&buffer).expect("Load not ok");
|
||||
let buffer_data = $data;
|
||||
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!(obj, $expected_load, "Loaded value not as expected");
|
||||
println!("Loaded {:?}", obj);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::io::{Read, Write};
|
||||
use super::{DumpError, Dumpable, LoadError, Loadable};
|
||||
|
||||
/// Primitive types supported for communication between the USDPL back- and front-end.
|
||||
|
@ -44,22 +45,21 @@ impl Primitive {
|
|||
}
|
||||
|
||||
impl Loadable for Primitive {
|
||||
fn load(buf: &[u8]) -> Result<(Self, usize), LoadError> {
|
||||
if buf.len() == 0 {
|
||||
return Err(LoadError::TooSmallBuffer);
|
||||
}
|
||||
let mut result: (Self, usize) = match buf[0] {
|
||||
fn load(buf: &mut dyn Read) -> Result<(Self, usize), LoadError> {
|
||||
let mut discriminant_buf = [u8::MAX; 1];
|
||||
buf.read_exact(&mut discriminant_buf).map_err(LoadError::Io)?;
|
||||
let mut result: (Self, usize) = match discriminant_buf[0] {
|
||||
//0 => (None, 0),
|
||||
1 => (Self::Empty, 0),
|
||||
2 => String::load(&buf[1..]).map(|(obj, len)| (Self::String(obj), len))?,
|
||||
3 => f32::load(&buf[1..]).map(|(obj, len)| (Self::F32(obj), len))?,
|
||||
4 => f64::load(&buf[1..]).map(|(obj, len)| (Self::F64(obj), len))?,
|
||||
5 => u32::load(&buf[1..]).map(|(obj, len)| (Self::U32(obj), len))?,
|
||||
6 => u64::load(&buf[1..]).map(|(obj, len)| (Self::U64(obj), len))?,
|
||||
7 => i32::load(&buf[1..]).map(|(obj, len)| (Self::I32(obj), len))?,
|
||||
8 => i64::load(&buf[1..]).map(|(obj, len)| (Self::I64(obj), len))?,
|
||||
9 => bool::load(&buf[1..]).map(|(obj, len)| (Self::Bool(obj), len))?,
|
||||
10 => String::load(&buf[1..]).map(|(obj, len)| (Self::Json(obj), len))?,
|
||||
2 => String::load(buf).map(|(obj, len)| (Self::String(obj), len))?,
|
||||
3 => f32::load(buf).map(|(obj, len)| (Self::F32(obj), len))?,
|
||||
4 => f64::load(buf).map(|(obj, len)| (Self::F64(obj), len))?,
|
||||
5 => u32::load(buf).map(|(obj, len)| (Self::U32(obj), len))?,
|
||||
6 => u64::load(buf).map(|(obj, len)| (Self::U64(obj), len))?,
|
||||
7 => i32::load(buf).map(|(obj, len)| (Self::I32(obj), len))?,
|
||||
8 => i64::load(buf).map(|(obj, len)| (Self::I64(obj), len))?,
|
||||
9 => bool::load(buf).map(|(obj, len)| (Self::Bool(obj), len))?,
|
||||
10 => String::load(buf).map(|(obj, len)| (Self::Json(obj), len))?,
|
||||
_ => return Err(LoadError::InvalidData),
|
||||
};
|
||||
result.1 += 1;
|
||||
|
@ -68,25 +68,21 @@ impl Loadable for Primitive {
|
|||
}
|
||||
|
||||
impl Dumpable for Primitive {
|
||||
fn dump(&self, buf: &mut [u8]) -> Result<usize, DumpError> {
|
||||
if buf.len() == 0 {
|
||||
return Err(DumpError::TooSmallBuffer);
|
||||
}
|
||||
buf[0] = self.discriminant();
|
||||
let mut result = match self {
|
||||
fn dump(&self, buf: &mut dyn Write) -> Result<usize, DumpError> {
|
||||
let size1 = buf.write(&[self.discriminant()]).map_err(DumpError::Io)?;
|
||||
let result = match self {
|
||||
Self::Empty => Ok(0),
|
||||
Self::String(s) => s.dump(&mut buf[1..]),
|
||||
Self::F32(x) => x.dump(&mut buf[1..]),
|
||||
Self::F64(x) => x.dump(&mut buf[1..]),
|
||||
Self::U32(x) => x.dump(&mut buf[1..]),
|
||||
Self::U64(x) => x.dump(&mut buf[1..]),
|
||||
Self::I32(x) => x.dump(&mut buf[1..]),
|
||||
Self::I64(x) => x.dump(&mut buf[1..]),
|
||||
Self::Bool(x) => x.dump(&mut buf[1..]),
|
||||
Self::Json(x) => x.dump(&mut buf[1..]),
|
||||
Self::String(s) => s.dump(buf),
|
||||
Self::F32(x) => x.dump(buf),
|
||||
Self::F64(x) => x.dump(buf),
|
||||
Self::U32(x) => x.dump(buf),
|
||||
Self::U64(x) => x.dump(buf),
|
||||
Self::I32(x) => x.dump(buf),
|
||||
Self::I64(x) => x.dump(buf),
|
||||
Self::Bool(x) => x.dump(buf),
|
||||
Self::Json(x) => x.dump(buf),
|
||||
}?;
|
||||
result += 1;
|
||||
Ok(result)
|
||||
Ok(size1 + result)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,14 +123,15 @@ into_impl! {f64, F64}
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
#[test]
|
||||
fn string_idempotence_test() {
|
||||
let data = "Test";
|
||||
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 (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!(
|
||||
write_len, read_len,
|
||||
"Amount written and amount read do not match"
|
||||
|
@ -149,9 +146,9 @@ mod tests {
|
|||
#[test]
|
||||
fn empty_idempotence_test() {
|
||||
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 (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!(
|
||||
write_len, read_len,
|
||||
"Amount written and amount read do not match"
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
@ -18,6 +19,8 @@ pub enum LoadError {
|
|||
/// Encrypted data cannot be decrypted
|
||||
#[cfg(feature = "encrypt")]
|
||||
DecryptionError,
|
||||
/// Read error
|
||||
Io(std::io::Error),
|
||||
/// Unimplemented
|
||||
#[cfg(debug_assertions)]
|
||||
Todo,
|
||||
|
@ -30,6 +33,7 @@ impl std::fmt::Display for LoadError {
|
|||
Self::InvalidData => write!(f, "LoadError: InvalidData"),
|
||||
#[cfg(feature = "encrypt")]
|
||||
Self::DecryptionError => write!(f, "LoadError: DecryptionError"),
|
||||
Self::Io(err) => write!(f, "LoadError: Io({})", err),
|
||||
#[cfg(debug_assertions)]
|
||||
Self::Todo => write!(f, "LoadError: TODO!"),
|
||||
}
|
||||
|
@ -39,30 +43,33 @@ impl std::fmt::Display for LoadError {
|
|||
/// Load an object from the buffer
|
||||
pub trait Loadable: Sized {
|
||||
/// Read the buffer, building the object and returning the amount of bytes read.
|
||||
/// If anything is wrong with the buffer, None should be returned.
|
||||
fn load(buffer: &[u8]) -> Result<(Self, usize), LoadError>;
|
||||
/// If anything is wrong with the buffer, Err should be returned.
|
||||
fn load(buffer: &mut dyn Read) -> Result<(Self, usize), LoadError>;
|
||||
|
||||
/// Load data from a base64-encoded buffer
|
||||
fn load_base64(buffer: &[u8]) -> Result<(Self, usize), LoadError> {
|
||||
let mut buffer2 = [0u8; crate::socket::PACKET_BUFFER_SIZE];
|
||||
let len = decode_config_slice(buffer, B64_CONF, &mut buffer2)
|
||||
let mut buffer2 = Vec::with_capacity(crate::socket::PACKET_BUFFER_SIZE);
|
||||
decode_config_buf(buffer, B64_CONF, &mut buffer2)
|
||||
.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
|
||||
#[cfg(feature = "encrypt")]
|
||||
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 cipher = aes_gcm_siv::Aes256GcmSiv::new(key);
|
||||
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)?;
|
||||
println!("Decoded buf: {:?}", decoded_buf);
|
||||
//println!("Decoded buf: {:?}", decoded_buf);
|
||||
cipher.decrypt_in_place(nonce, ASSOCIATED_DATA, &mut decoded_buf).map_err(|_| LoadError::DecryptionError)?;
|
||||
println!("Decrypted buf: {:?}", decoded_buf);
|
||||
Self::load(decoded_buf.as_slice())
|
||||
//println!("Decrypted buf: {:?}", decoded_buf);
|
||||
let mut cursor = Cursor::new(decoded_buf);
|
||||
Self::load(&mut cursor)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,6 +83,8 @@ pub enum DumpError {
|
|||
/// Data cannot be encrypted
|
||||
#[cfg(feature = "encrypt")]
|
||||
EncryptionError,
|
||||
/// Write error
|
||||
Io(std::io::Error),
|
||||
/// Unimplemented
|
||||
#[cfg(debug_assertions)]
|
||||
Todo,
|
||||
|
@ -88,6 +97,7 @@ impl std::fmt::Display for DumpError {
|
|||
Self::Unsupported => write!(f, "DumpError: Unsupported"),
|
||||
#[cfg(feature = "encrypt")]
|
||||
Self::EncryptionError => write!(f, "DumpError: EncryptionError"),
|
||||
Self::Io(err) => write!(f, "DumpError: Io({})", err),
|
||||
#[cfg(debug_assertions)]
|
||||
Self::Todo => write!(f, "DumpError: TODO!"),
|
||||
}
|
||||
|
@ -98,33 +108,35 @@ impl std::fmt::Display for DumpError {
|
|||
pub trait Dumpable {
|
||||
/// Write the object to the buffer, returning the amount of bytes written.
|
||||
/// 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.
|
||||
/// Useful for transmitting data as text.
|
||||
fn dump_base64(&self, buffer: &mut [u8]) -> Result<usize, DumpError> {
|
||||
let mut buffer2 = [0u8; crate::socket::PACKET_BUFFER_SIZE];
|
||||
fn dump_base64(&self, buffer: &mut String) -> Result<usize, DumpError> {
|
||||
let mut buffer2 = Vec::with_capacity(crate::socket::PACKET_BUFFER_SIZE);
|
||||
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)
|
||||
}
|
||||
|
||||
/// Dump data as an encrypted base64-encoded buffer
|
||||
#[cfg(feature = "encrypt")]
|
||||
fn dump_encrypted(&self, buffer: &mut Vec<u8>, key: &[u8], nonce: &[u8]) -> Result<usize, DumpError> {
|
||||
let mut buffer2 = Vec::with_capacity(buffer.capacity());
|
||||
buffer2.extend_from_slice(buffer.as_slice());
|
||||
let mut buffer2 = Vec::with_capacity(crate::socket::PACKET_BUFFER_SIZE);
|
||||
let size = self.dump(&mut buffer2)?;
|
||||
buffer2.truncate(size);
|
||||
println!("Buf: {:?}", buffer2);
|
||||
//println!("Buf: {:?}", buffer2);
|
||||
let key = aes_gcm_siv::Key::from_slice(key);
|
||||
let cipher = aes_gcm_siv::Aes256GcmSiv::new(key);
|
||||
let nonce = aes_gcm_siv::Nonce::from_slice(nonce);
|
||||
cipher.encrypt_in_place(nonce, ASSOCIATED_DATA, &mut buffer2).map_err(|_| DumpError::EncryptionError)?;
|
||||
println!("Encrypted slice: {:?}", &buffer2);
|
||||
let size = encode_config_slice(buffer2.as_slice(), B64_CONF, buffer);
|
||||
let string = String::from_utf8(buffer.as_slice()[..size].to_vec()).unwrap();
|
||||
println!("Encoded slice: {}", string);
|
||||
Ok(size)
|
||||
//println!("Encrypted slice: {:?}", &buffer2);
|
||||
let mut base64_buf = String::with_capacity(crate::socket::PACKET_BUFFER_SIZE);
|
||||
encode_config_buf(buffer2.as_slice(), B64_CONF, &mut base64_buf);
|
||||
//println!("base64 len: {}", base64_buf.as_bytes().len());
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//! Web messaging
|
||||
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
|
||||
use std::io::{Read, Write};
|
||||
|
||||
use crate::serdes::{DumpError, Dumpable, LoadError, Loadable};
|
||||
use crate::{RemoteCall, RemoteCallResponse};
|
||||
|
@ -57,30 +58,29 @@ impl Packet {
|
|||
}
|
||||
|
||||
impl Loadable for Packet {
|
||||
fn load(buf: &[u8]) -> Result<(Self, usize), LoadError> {
|
||||
if buf.len() == 0 {
|
||||
return Err(LoadError::TooSmallBuffer);
|
||||
}
|
||||
let mut result: (Self, usize) = match buf[0] {
|
||||
fn load(buf: &mut dyn Read) -> Result<(Self, usize), LoadError> {
|
||||
let mut discriminant_buf = [u8::MAX; 1];
|
||||
buf.read_exact(&mut discriminant_buf).map_err(LoadError::Io)?;
|
||||
let mut result: (Self, usize) = match discriminant_buf[0] {
|
||||
//0 => (None, 0),
|
||||
1 => {
|
||||
let (obj, len) = RemoteCall::load(&buf[1..])?;
|
||||
let (obj, len) = RemoteCall::load(buf)?;
|
||||
(Self::Call(obj), len)
|
||||
}
|
||||
2 => {
|
||||
let (obj, len) = RemoteCallResponse::load(&buf[1..])?;
|
||||
let (obj, len) = RemoteCallResponse::load(buf)?;
|
||||
(Self::CallResponse(obj), len)
|
||||
}
|
||||
3 => (Self::KeepAlive, 0),
|
||||
4 => (Self::Invalid, 0),
|
||||
5 => {
|
||||
let (obj, len) = String::load(&buf[1..])?;
|
||||
let (obj, len) = String::load(buf)?;
|
||||
(Self::Message(obj), len)
|
||||
}
|
||||
6 => (Self::Unsupported, 0),
|
||||
7 => return Err(LoadError::InvalidData),
|
||||
8 => {
|
||||
let (obj, len) = <_>::load(&buf[1..])?;
|
||||
let (obj, len) = <_>::load(buf)?;
|
||||
(Self::Many(obj), len)
|
||||
}
|
||||
_ => return Err(LoadError::InvalidData),
|
||||
|
@ -91,23 +91,19 @@ impl Loadable for Packet {
|
|||
}
|
||||
|
||||
impl Dumpable for Packet {
|
||||
fn dump(&self, buf: &mut [u8]) -> Result<usize, DumpError> {
|
||||
if buf.len() == 0 {
|
||||
return Err(DumpError::TooSmallBuffer);
|
||||
}
|
||||
buf[0] = self.discriminant();
|
||||
let mut result = match self {
|
||||
Self::Call(c) => c.dump(&mut buf[1..]),
|
||||
Self::CallResponse(c) => c.dump(&mut buf[1..]),
|
||||
fn dump(&self, buf: &mut dyn Write) -> Result<usize, DumpError> {
|
||||
let size1 = buf.write(&[self.discriminant()]).map_err(DumpError::Io)?;
|
||||
let result = match self {
|
||||
Self::Call(c) => c.dump(buf),
|
||||
Self::CallResponse(c) => c.dump(buf),
|
||||
Self::KeepAlive => 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::Bad => return Err(DumpError::Unsupported),
|
||||
Self::Many(v) => v.dump(&mut buf[1..]),
|
||||
Self::Many(v) => v.dump(buf),
|
||||
}?;
|
||||
result += 1;
|
||||
Ok(result)
|
||||
Ok(size1 + result)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,7 +122,6 @@ mod tests {
|
|||
parameters: Vec::new(),
|
||||
});
|
||||
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();
|
||||
println!("buffer: {}", String::from_utf8(buffer.as_slice()[..len].to_vec()).unwrap());
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ pub async fn send_js(
|
|||
#[cfg(feature = "encrypt")]
|
||||
fn dump_to_buffer(packet: socket::Packet, key: &[u8]) -> Result<(Vec<u8>, usize), JsValue> {
|
||||
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
|
||||
.dump_encrypted(&mut buffer, key, &NONCE)
|
||||
.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"))]
|
||||
fn dump_to_buffer(packet: socket::Packet) -> Result<(Vec<u8>, usize), JsValue> {
|
||||
let mut buffer = Vec::with_capacity(socket::PACKET_BUFFER_SIZE);
|
||||
buffer.extend_from_slice(&[0u8; socket::PACKET_BUFFER_SIZE]);
|
||||
let mut buffer = String::with_capacity(socket::PACKET_BUFFER_SIZE);
|
||||
//buffer.extend_from_slice(&[0u8; socket::PACKET_BUFFER_SIZE]);
|
||||
let len = packet
|
||||
.dump_base64(buffer.as_mut_slice())
|
||||
.dump_base64(&mut buffer)
|
||||
.map_err(super::convert::str_to_js)?;
|
||||
Ok((buffer, len))
|
||||
Ok((buffer.as_bytes().to_vec(), len))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue