diff --git a/usdpl-back/src/instance.rs b/usdpl-back/src/instance.rs index 89d2ed6..9dc1641 100644 --- a/usdpl-back/src/instance.rs +++ b/usdpl-back/src/instance.rs @@ -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, diff --git a/usdpl-core/src/remote_call.rs b/usdpl-core/src/remote_call.rs index 279495d..e9dfa92 100644 --- a/usdpl-core/src/remote_call.rs +++ b/usdpl-core/src/remote_call.rs @@ -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::::load(&buffer[len0 + len1..])?; + let (function_name, len1) = String::load(buffer)?; + let (params, len2) = Vec::::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 { + fn dump(&self, buffer: &mut dyn Write) -> Result { 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::::load(&buffer[len0..])?; + let (response_var, len1) = Vec::::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 { + fn dump(&self, buffer: &mut dyn Write) -> Result { let len0 = self.id.dump(buffer)?; - let len1 = self.response.dump(&mut buffer[len0..])?; + let len1 = self.response.dump(buffer)?; Ok(len0 + len1) } } diff --git a/usdpl-core/src/serdes/dump_impl.rs b/usdpl-core/src/serdes/dump_impl.rs index b90f022..b52757f 100644 --- a/usdpl-core/src/serdes/dump_impl.rs +++ b/usdpl-core/src/serdes/dump_impl.rs @@ -1,88 +1,70 @@ +use std::io::Write; + use super::{DumpError, Dumpable}; impl Dumpable for String { - fn dump(&self, buffer: &mut [u8]) -> Result { + fn dump(&self, buffer: &mut dyn Write) -> Result { 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 Dumpable for Vec { - fn dump(&self, buffer: &mut [u8]) -> Result { + fn dump(&self, buffer: &mut dyn Write) -> Result { 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 { - if buffer.len() < 1 { - return Err(DumpError::TooSmallBuffer); - } - buffer[0] = *self as u8; - Ok(1) + fn dump(&self, buffer: &mut dyn Write) -> Result { + buffer.write(&[*self as u8]).map_err(DumpError::Io) } } impl Dumpable for u8 { - fn dump(&self, buffer: &mut [u8]) -> Result { - if buffer.len() < 1 { - return Err(DumpError::TooSmallBuffer); - } - buffer[0] = *self; - Ok(1) + fn dump(&self, buffer: &mut dyn Write) -> Result { + buffer.write(&[*self]).map_err(DumpError::Io) } } -impl Dumpable for i8 { - fn dump(&self, buffer: &mut [u8]) -> Result { - if buffer.len() < 1 { - return Err(DumpError::TooSmallBuffer); - } - buffer[0] = self.to_le_bytes()[0]; - Ok(1) +/*impl Dumpable for i8 { + fn dump(&self, buffer: &mut dyn Write) -> Result { + buffer.write(&self.to_le_bytes()).map_err(DumpError::Io) } -} +}*/ macro_rules! int_impl { - ($type:ty, $size:literal) => { + ($type:ty) => { impl Dumpable for $type { - fn dump(&self, buffer: &mut [u8]) -> Result { - 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 { + 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()); } }; } diff --git a/usdpl-core/src/serdes/load_impl.rs b/usdpl-core/src/serdes/load_impl.rs index 8ca43e8..d05537b 100644 --- a/usdpl-core/src/serdes/load_impl.rs +++ b/usdpl-core/src/serdes/load_impl.rs @@ -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 Loadable for Vec { - 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 Loadable for Vec { } 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); } }; } diff --git a/usdpl-core/src/serdes/primitive.rs b/usdpl-core/src/serdes/primitive.rs index 2e357c3..d652ea1 100644 --- a/usdpl-core/src/serdes/primitive.rs +++ b/usdpl-core/src/serdes/primitive.rs @@ -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 { - 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 { + 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" diff --git a/usdpl-core/src/serdes/traits.rs b/usdpl-core/src/serdes/traits.rs index db6967f..07bc2fd 100644 --- a/usdpl-core/src/serdes/traits.rs +++ b/usdpl-core/src/serdes/traits.rs @@ -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; + fn dump(&self, buffer: &mut dyn Write) -> Result; /// Dump data as base64-encoded. /// Useful for transmitting data as text. - fn dump_base64(&self, buffer: &mut [u8]) -> Result { - let mut buffer2 = [0u8; crate::socket::PACKET_BUFFER_SIZE]; + fn dump_base64(&self, buffer: &mut String) -> Result { + 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, key: &[u8], nonce: &[u8]) -> Result { - 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()) } } diff --git a/usdpl-core/src/socket.rs b/usdpl-core/src/socket.rs index dbe35f6..a0d19ab 100644 --- a/usdpl-core/src/socket.rs +++ b/usdpl-core/src/socket.rs @@ -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 { - 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 { + 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()); diff --git a/usdpl-front/src/connection.rs b/usdpl-front/src/connection.rs index fa9051d..4e57fd5 100644 --- a/usdpl-front/src/connection.rs +++ b/usdpl-front/src/connection.rs @@ -80,7 +80,7 @@ pub async fn send_js( #[cfg(feature = "encrypt")] fn dump_to_buffer(packet: socket::Packet, key: &[u8]) -> Result<(Vec, 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, usize) #[cfg(not(feature = "encrypt"))] fn dump_to_buffer(packet: socket::Packet) -> Result<(Vec, 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)) }