use model::data::{Message, U16, Trame, U32};
use std::io::{Read, Write};
use model::error::{RdpResult, Error, RdpError, RdpErrorKind};
pub fn read_length(s: &mut dyn Read) -> RdpResult<u16> {
let mut byte: u8 = 0;
byte.read(s)?;
if byte & 0x80 != 0 {
byte = byte & !0x80;
let mut size = (byte as u16) << 8 ;
byte.read(s)?;
size += byte as u16;
Ok(size)
}
else {
Ok(byte as u16)
}
}
pub fn write_length(length: u16) -> RdpResult<Trame> {
if length > 0x7f {
Ok(trame![U16::BE(length | 0x8000)])
}
else {
Ok(trame![length as u8])
}
}
pub fn read_choice(s: &mut dyn Read) -> RdpResult<u8> {
let mut result : u8 = 0;
result.read(s)?;
Ok(result)
}
pub fn write_choice(choice: u8, s: &mut dyn Write) -> RdpResult<()> {
choice.write(s)?;
Ok(())
}
pub fn read_selection(s: &mut dyn Read) -> RdpResult<u8> {
let mut result : u8 = 0;
result.read(s)?;
Ok(result)
}
pub fn write_selection(selection: u8, s: &mut dyn Write) -> RdpResult<()> {
selection.write(s)?;
Ok(())
}
pub fn read_number_of_set(s: &mut dyn Read) -> RdpResult<u8> {
let mut result : u8 = 0;
result.read(s)?;
Ok(result)
}
pub fn write_number_of_set(number_of_set: u8, s: &mut dyn Write) -> RdpResult<()> {
number_of_set.write(s)?;
Ok(())
}
pub fn read_enumerates(s: &mut dyn Read) -> RdpResult<u8> {
let mut result : u8 = 0;
result.read(s)?;
Ok(result)
}
pub fn write_enumerates(enumerate: u8) -> RdpResult<u8> {
Ok(enumerate)
}
pub fn read_integer(s: &mut dyn Read) -> RdpResult<u32> {
let size = read_length(s)?;
match size {
1 => {
let mut result: u8 = 0;
result.read(s)?;
Ok(result as u32)
},
2 => {
let mut result = U16::BE(0);
result.read(s)?;
Ok(result.inner() as u32)
},
4 => {
let mut result = U32::BE(0);
result.read(s)?;
Ok(result.inner() as u32)
},
_ => Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidSize, "PER integer encoded with an invalid size")))
}
}
pub fn write_integer(integer: u32, s: &mut dyn Write) -> RdpResult<()> {
if integer < 0xFF {
write_length(1)?.write(s)?;
(integer as u8).write(s)?;
} else if integer < 0xFFFF {
write_length(2)?.write(s)?;
U16::BE(integer as u16).write(s)?;
} else {
write_length(4)?.write(s)?;
U32::BE(integer).write(s)?;
};
Ok(())
}
pub fn read_integer_16(minimum: u16, s: &mut dyn Read) -> RdpResult<u16> {
let mut result = U16::BE(0);
result.read(s)?;
Ok(result.inner() + minimum)
}
pub fn write_integer_16(integer: u16, minimum: u16, s: &mut dyn Write) -> RdpResult<()> {
U16::BE(integer - minimum).write(s)?;
Ok(())
}
pub fn read_object_identifier(oid: &[u8], s: &mut dyn Read) -> RdpResult<bool> {
if oid.len() != 6 {
return Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidSize, "Oid to check have an invalid size")));
}
let length = read_length(s)?;
if length != 5 {
return Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidSize, "Oid source have an invalid size")));
}
let mut oid_parsed = [0; 6];
let mut tmp : u8 = 0;
tmp.read(s)?;
oid_parsed[0] = tmp >> 4;
oid_parsed[1] = tmp & 0xf;
tmp.read(s)?;
oid_parsed[2] = tmp;
tmp.read(s)?;
oid_parsed[3] = tmp;
tmp.read(s)?;
oid_parsed[5] = tmp;
tmp.read(s)?;
oid_parsed[5] = tmp;
Ok(oid_parsed == oid)
}
pub fn write_object_identifier(oid: &[u8], s: &mut dyn Write) ->RdpResult<()> {
if oid.len() != 6 {
return Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidSize, "PER: oid source don't have the correct size")))
}
trame![
5 as u8,
oid[0] << 4 | oid[1] & 0xF,
oid[2],
oid[3],
oid[4],
oid[5]
].write(s)
}
pub fn read_numeric_string(minimum: usize, s: &mut dyn Read) -> RdpResult<Vec<u8>> {
let length = read_length(s)?;
let mut result = vec![0 as u8; length as usize + minimum + 1];
result.read(s)?;
Ok(result)
}
pub fn write_numeric_string(string: &[u8], minimum: usize, s: &mut dyn Write) -> RdpResult<()> {
let mut length = string.len();
if length as i64 - minimum as i64 >= 0 {
length -= minimum;
}
write_length(length as u16)?.write(s)?;
for i in 0..string.len() {
let mut c1 = string[i];
let mut c2 = if i + 1 < string.len() {
string[i+1]
} else {
0x30
};
c1 = (c1 - 0x30) % 10;
c2 = (c2 - 0x30) % 10;
((c1 << 4) | c2).write(s)?;
}
Ok(())
}
pub fn read_padding(length: usize, s: &mut dyn Read) -> RdpResult<()> {
let mut padding = vec![0; length];
s.read(&mut padding)?;
Ok(())
}
pub fn write_padding(length: usize, s: &mut dyn Write) -> RdpResult<()> {
vec![0 as u8; length].write(s)?;
Ok(())
}
pub fn read_octet_stream(octet_stream: &[u8], minimum: usize, s: &mut dyn Read) -> RdpResult<()> {
let length = read_length(s)? as usize + minimum;
if length != octet_stream.len() {
return Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidSize, "PER: source octet string have an invalid size")));
}
for i in 0..length {
let mut c: u8 = 0;
c.read(s)?;
if c != octet_stream[i] {
return Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidData, "PER: source octet string have an invalid char")));
}
}
Ok(())
}
pub fn write_octet_stream(octet_string: &[u8], minimum: usize, s: &mut dyn Write) -> RdpResult<()> {
let mut length = minimum;
if octet_string.len() as i64 - minimum as i64 >= 0 {
length = octet_string.len() - minimum;
}
write_length(length as u16)?.write(s)?;
octet_string.to_vec().write(s)?;
Ok(())
}