style: run cargo fmt

This commit is contained in:
Benoît CORTIER 2022-04-15 12:50:00 -04:00 committed by Benoît Cortier
parent 7264c01712
commit ad0112b47e
151 changed files with 9443 additions and 12951 deletions

View file

@ -1,18 +1,15 @@
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
use std::fmt::{self, Debug};
use std::io::{self, Write}; use std::io::{self, Write};
use bitflags::bitflags; use bitflags::bitflags;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use failure::Fail; use failure::Fail;
use std::fmt::{self, Debug};
use crate::{ use crate::utils::{Rectangle, SplitTo};
impl_from_error, use crate::{impl_from_error, PduBufferParsing, PduParsing};
utils::{Rectangle, SplitTo},
PduBufferParsing, PduParsing,
};
pub const COMPRESSED_DATA_HEADER_SIZE: usize = 8; pub const COMPRESSED_DATA_HEADER_SIZE: usize = 8;
pub const BITMAP_DATA_MAIN_DATA_SIZE: usize = 12; pub const BITMAP_DATA_MAIN_DATA_SIZE: usize = 12;
@ -57,10 +54,7 @@ impl<'a> PduBufferParsing<'a> for Bitmap<'a> {
} }
fn buffer_length(&self) -> usize { fn buffer_length(&self) -> usize {
self.rectangles self.rectangles.iter().map(|b| b.buffer_length()).sum::<usize>()
.iter()
.map(|b| b.buffer_length())
.sum::<usize>()
} }
} }
@ -234,10 +228,7 @@ pub enum BitmapError {
InvalidDataLength { actual: usize, expected: usize }, InvalidDataLength { actual: usize, expected: usize },
#[fail(display = "Compression is not supported for Bitmap data")] #[fail(display = "Compression is not supported for Bitmap data")]
NotSupportedCompression, NotSupportedCompression,
#[fail( #[fail(display = "Invalid first row size, expected: {}, but got: {}", actual, expected)]
display = "Invalid first row size, expected: {}, but got: {}",
actual, expected
)]
InvalidFirstRowSize { actual: usize, expected: usize }, InvalidFirstRowSize { actual: usize, expected: usize },
#[fail(display = "The width of the bitmap must be divisible by 4")] #[fail(display = "The width of the bitmap must be divisible by 4")]
InvalidScanWidth, InvalidScanWidth,

View file

@ -23,12 +23,11 @@ const BITMAP_BUFFER: [u8; 114] = [
0x1c, 0x00, // ScanWidth - width of the bitmap in pixels(must be divisible by 4) = 28 0x1c, 0x00, // ScanWidth - width of the bitmap in pixels(must be divisible by 4) = 28
// UncompressedSize - size in bytes of the bitmap data after it has been decompressed = 4 // UncompressedSize - size in bytes of the bitmap data after it has been decompressed = 4
0x04, 0x00, // Bitmap data 0x04, 0x00, // Bitmap data
0x21, 0x00, 0x21, 0x00, 0x01, 0x00, 0x20, 0x09, 0x84, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x12, 0x21, 0x00, 0x21, 0x00, 0x01, 0x00, 0x20, 0x09, 0x84, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x12, 0x00, 0x10, 0xd8,
0x00, 0x10, 0xd8, 0x20, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1e, 0x21, 0x20, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1e, 0x21, 0x00, 0x00, 0xa8, 0x83, 0x21, 0x00,
0x00, 0x00, 0xa8, 0x83, 0x21, 0x00, 0x55, 0xad, 0xff, 0xff, 0x45, 0x29, 0x7a, 0xce, 0xa3, 0x10, 0x55, 0xad, 0xff, 0xff, 0x45, 0x29, 0x7a, 0xce, 0xa3, 0x10, 0x0e, 0x82, 0x45, 0x29, 0x7a, 0xce, 0xd5, 0x82, 0x10,
0x0e, 0x82, 0x45, 0x29, 0x7a, 0xce, 0xd5, 0x82, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0e, 0x45, 0x29, 0x9e, 0xf7, 0xff, 0xff, 0x9e, 0xf7, 0x45, 0x29, 0x21, 0x00,
0x45, 0x29, 0x9e, 0xf7, 0xff, 0xff, 0x9e, 0xf7, 0x45, 0x29, 0x21, 0x00, 0x55, 0xad, 0x10, 0x10, 0x55, 0xad, 0x10, 0x10, 0xa8, 0xd8, 0x60, 0x12,
0xa8, 0xd8, 0x60, 0x12,
]; ];
lazy_static! { lazy_static! {
@ -70,9 +69,7 @@ fn from_buffer_bitmap_data_parsses_correctly() {
fn to_buffer_bitmap_data_serializes_correcly() { fn to_buffer_bitmap_data_serializes_correcly() {
let expected = BITMAP_BUFFER.as_ref(); let expected = BITMAP_BUFFER.as_ref();
let mut buffer = vec![0; expected.len()]; let mut buffer = vec![0; expected.len()];
BITMAP BITMAP.to_buffer_consume(&mut buffer.as_mut_slice()).unwrap();
.to_buffer_consume(&mut buffer.as_mut_slice())
.unwrap();
assert_eq!(expected, buffer.as_slice()); assert_eq!(expected, buffer.as_slice());
} }

View file

@ -10,12 +10,10 @@ use failure::Fail;
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
use super::{ use super::bitmap::{Bitmap, BitmapError};
bitmap::{Bitmap, BitmapError}, use super::surface_commands::{SurfaceCommand, SurfaceCommandsError, SURFACE_COMMAND_HEADER_SIZE};
surface_commands::{SurfaceCommand, SurfaceCommandsError, SURFACE_COMMAND_HEADER_SIZE}, use crate::utils::SplitTo;
}; use crate::{impl_from_error, per, PduBufferParsing, PduParsing};
use crate::{impl_from_error, per, utils::SplitTo, PduBufferParsing, PduParsing};
/// Implements the Fast-Path RDP message header PDU. /// Implements the Fast-Path RDP message header PDU.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -26,10 +24,7 @@ pub struct FastPathHeader {
} }
impl FastPathHeader { impl FastPathHeader {
pub fn from_buffer_with_header( pub fn from_buffer_with_header(mut stream: impl io::Read, header: u8) -> Result<Self, FastPathError> {
mut stream: impl io::Read,
header: u8,
) -> Result<Self, FastPathError> {
let flags = EncryptionFlags::from_bits_truncate(header.get_bits(6..8)); let flags = EncryptionFlags::from_bits_truncate(header.get_bits(6..8));
let (length, sizeof_length) = per::read_length(&mut stream)?; let (length, sizeof_length) = per::read_length(&mut stream)?;
@ -73,10 +68,7 @@ impl PduParsing for FastPathHeader {
// Preserve same layout for header as received // Preserve same layout for header as received
per::write_long_length(stream, (self.data_length + self.buffer_length()) as u16)?; per::write_long_length(stream, (self.data_length + self.buffer_length()) as u16)?;
} else { } else {
per::write_length( per::write_length(stream, (self.data_length + self.minimal_buffer_length()) as u16)?;
stream,
(self.data_length + self.minimal_buffer_length()) as u16,
)?;
} }
Ok(()) Ok(())
@ -105,12 +97,11 @@ impl<'a> PduBufferParsing<'a> for FastPathUpdatePdu<'a> {
let header = buffer.read_u8()?; let header = buffer.read_u8()?;
let update_code = header.get_bits(0..4); let update_code = header.get_bits(0..4);
let update_code = UpdateCode::from_u8(update_code) let update_code = UpdateCode::from_u8(update_code).ok_or(FastPathError::InvalidUpdateCode(update_code))?;
.ok_or(FastPathError::InvalidUpdateCode(update_code))?;
let fragmentation = header.get_bits(4..6); let fragmentation = header.get_bits(4..6);
let fragmentation = Fragmentation::from_u8(fragmentation) let fragmentation =
.ok_or(FastPathError::InvalidFragmentation(fragmentation))?; Fragmentation::from_u8(fragmentation).ok_or(FastPathError::InvalidFragmentation(fragmentation))?;
let compression = Compression::from_bits_truncate(header.get_bits(6..8)); let compression = Compression::from_bits_truncate(header.get_bits(6..8));
if compression.contains(Compression::COMPRESSION_USED) { if compression.contains(Compression::COMPRESSION_USED) {
@ -156,17 +147,11 @@ pub enum FastPathUpdate<'a> {
} }
impl<'a> FastPathUpdate<'a> { impl<'a> FastPathUpdate<'a> {
pub fn from_buffer_with_code( pub fn from_buffer_with_code(mut buffer: &'a [u8], code: UpdateCode) -> Result<Self, FastPathError> {
mut buffer: &'a [u8],
code: UpdateCode,
) -> Result<Self, FastPathError> {
Self::from_buffer_consume_with_code(&mut buffer, code) Self::from_buffer_consume_with_code(&mut buffer, code)
} }
pub fn from_buffer_consume_with_code( pub fn from_buffer_consume_with_code(buffer: &mut &'a [u8], code: UpdateCode) -> Result<Self, FastPathError> {
buffer: &mut &'a [u8],
code: UpdateCode,
) -> Result<Self, FastPathError> {
match code { match code {
UpdateCode::SurfaceCommands => { UpdateCode::SurfaceCommands => {
let mut commands = Vec::with_capacity(1); let mut commands = Vec::with_capacity(1);
@ -201,9 +186,7 @@ impl<'a> FastPathUpdate<'a> {
pub fn buffer_length(&self) -> usize { pub fn buffer_length(&self) -> usize {
match self { match self {
Self::SurfaceCommands(commands) => { Self::SurfaceCommands(commands) => commands.iter().map(|c| c.buffer_length()).sum::<usize>(),
commands.iter().map(|c| c.buffer_length()).sum::<usize>()
}
Self::Bitmap(bitmap) => bitmap.buffer_length(), Self::Bitmap(bitmap) => bitmap.buffer_length(),
} }
} }
@ -281,19 +264,12 @@ pub enum FastPathError {
InvalidFragmentation(u8), InvalidFragmentation(u8),
#[fail(display = "Received compressed Fast-Path package")] #[fail(display = "Received compressed Fast-Path package")]
CompressionNotSupported, CompressionNotSupported,
#[fail( #[fail(display = "Input buffer is shorter then the data length: {} < {}", actual, expected)]
display = "Input buffer is shorter then the data length: {} < {}",
actual, expected
)]
InvalidDataLength { expected: usize, actual: usize }, InvalidDataLength { expected: usize, actual: usize },
#[fail(display = "Received unsupported Fast-Path Update: {:?}", _0)] #[fail(display = "Received unsupported Fast-Path Update: {:?}", _0)]
UnsupportedFastPathUpdate(UpdateCode), UnsupportedFastPathUpdate(UpdateCode),
} }
impl_from_error!(io::Error, FastPathError, FastPathError::IOError); impl_from_error!(io::Error, FastPathError, FastPathError::IOError);
impl_from_error!( impl_from_error!(SurfaceCommandsError, FastPathError, FastPathError::SurfaceCommandsError);
SurfaceCommandsError,
FastPathError,
FastPathError::SurfaceCommandsError
);
impl_from_error!(BitmapError, FastPathError, FastPathError::BitmapError); impl_from_error!(BitmapError, FastPathError, FastPathError::BitmapError);

View file

@ -127,9 +127,7 @@ fn from_buffer_correctly_parses_fast_path_update() {
#[test] #[test]
fn from_buffer_returns_error_on_long_length_for_fast_path_update() { fn from_buffer_returns_error_on_long_length_for_fast_path_update() {
assert!( assert!(FastPathUpdatePdu::from_buffer(FAST_PATH_UPDATE_PDU_WITH_LONG_LEN_BUFFER.as_ref()).is_err());
FastPathUpdatePdu::from_buffer(FAST_PATH_UPDATE_PDU_WITH_LONG_LEN_BUFFER.as_ref()).is_err()
);
} }
#[test] #[test]
@ -145,8 +143,5 @@ fn to_buffer_correctly_serializes_fast_path_update() {
#[test] #[test]
fn buffer_length_is_correct_for_fast_path_update() { fn buffer_length_is_correct_for_fast_path_update() {
assert_eq!( assert_eq!(FAST_PATH_UPDATE_PDU_BUFFER.len(), FAST_PATH_UPDATE_PDU.buffer_length());
FAST_PATH_UPDATE_PDU_BUFFER.len(),
FAST_PATH_UPDATE_PDU.buffer_length()
);
} }

View file

@ -9,7 +9,8 @@ use failure::Fail;
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
use crate::{impl_from_error, utils::Rectangle, utils::SplitTo, PduBufferParsing, PduParsing}; use crate::utils::{Rectangle, SplitTo};
use crate::{impl_from_error, PduBufferParsing, PduParsing};
pub const SURFACE_COMMAND_HEADER_SIZE: usize = 2; pub const SURFACE_COMMAND_HEADER_SIZE: usize = 2;
@ -25,19 +26,17 @@ impl<'a> PduBufferParsing<'a> for SurfaceCommand<'a> {
fn from_buffer_consume(buffer: &mut &'a [u8]) -> Result<Self, Self::Error> { fn from_buffer_consume(buffer: &mut &'a [u8]) -> Result<Self, Self::Error> {
let cmd_type = buffer.read_u16::<LittleEndian>()?; let cmd_type = buffer.read_u16::<LittleEndian>()?;
let cmd_type = SurfaceCommandType::from_u16(cmd_type) let cmd_type =
.ok_or(SurfaceCommandsError::InvalidSurfaceCommandType(cmd_type))?; SurfaceCommandType::from_u16(cmd_type).ok_or(SurfaceCommandsError::InvalidSurfaceCommandType(cmd_type))?;
match cmd_type { match cmd_type {
SurfaceCommandType::SetSurfaceBits => Ok(Self::SetSurfaceBits( SurfaceCommandType::SetSurfaceBits => {
SurfaceBitsPdu::from_buffer_consume(buffer)?, Ok(Self::SetSurfaceBits(SurfaceBitsPdu::from_buffer_consume(buffer)?))
)), }
SurfaceCommandType::FrameMarker => Ok(Self::FrameMarker( SurfaceCommandType::FrameMarker => Ok(Self::FrameMarker(FrameMarkerPdu::from_buffer_consume(buffer)?)),
FrameMarkerPdu::from_buffer_consume(buffer)?, SurfaceCommandType::StreamSurfaceBits => {
)), Ok(Self::StreamSurfaceBits(SurfaceBitsPdu::from_buffer_consume(buffer)?))
SurfaceCommandType::StreamSurfaceBits => Ok(Self::StreamSurfaceBits( }
SurfaceBitsPdu::from_buffer_consume(buffer)?,
)),
} }
} }
@ -46,9 +45,7 @@ impl<'a> PduBufferParsing<'a> for SurfaceCommand<'a> {
buffer.write_u16::<LittleEndian>(cmd_type.to_u16().unwrap())?; buffer.write_u16::<LittleEndian>(cmd_type.to_u16().unwrap())?;
match self { match self {
Self::SetSurfaceBits(pdu) | Self::StreamSurfaceBits(pdu) => { Self::SetSurfaceBits(pdu) | Self::StreamSurfaceBits(pdu) => pdu.to_buffer_consume(buffer),
pdu.to_buffer_consume(buffer)
}
Self::FrameMarker(pdu) => pdu.to_buffer_consume(buffer), Self::FrameMarker(pdu) => pdu.to_buffer_consume(buffer),
} }
} }
@ -104,8 +101,8 @@ impl<'a> PduBufferParsing<'a> for FrameMarkerPdu {
fn from_buffer_consume(buffer: &mut &[u8]) -> Result<Self, Self::Error> { fn from_buffer_consume(buffer: &mut &[u8]) -> Result<Self, Self::Error> {
let frame_action = buffer.read_u16::<LittleEndian>()?; let frame_action = buffer.read_u16::<LittleEndian>()?;
let frame_action = FrameAction::from_u16(frame_action) let frame_action =
.ok_or(SurfaceCommandsError::InvalidFrameAction(frame_action))?; FrameAction::from_u16(frame_action).ok_or(SurfaceCommandsError::InvalidFrameAction(frame_action))?;
let frame_id = if buffer.is_empty() { let frame_id = if buffer.is_empty() {
// Sometimes Windows 10 RDP server sends not complete FrameMarker PDU (without frame ID), // Sometimes Windows 10 RDP server sends not complete FrameMarker PDU (without frame ID),
@ -116,10 +113,7 @@ impl<'a> PduBufferParsing<'a> for FrameMarkerPdu {
Some(buffer.read_u32::<LittleEndian>()?) Some(buffer.read_u32::<LittleEndian>()?)
}; };
Ok(Self { Ok(Self { frame_action, frame_id })
frame_action,
frame_id,
})
} }
fn to_buffer_consume(&self, buffer: &mut &mut [u8]) -> Result<(), Self::Error> { fn to_buffer_consume(&self, buffer: &mut &mut [u8]) -> Result<(), Self::Error> {
@ -202,12 +196,7 @@ impl<'a> PduBufferParsing<'a> for ExtendedBitmapDataPdu<'a> {
} }
fn buffer_length(&self) -> usize { fn buffer_length(&self) -> usize {
12 + self 12 + self.header.as_ref().map(PduBufferParsing::buffer_length).unwrap_or(0) + self.data.len()
.header
.as_ref()
.map(PduBufferParsing::buffer_length)
.unwrap_or(0)
+ self.data.len()
} }
} }
@ -289,15 +278,8 @@ pub enum SurfaceCommandsError {
InvalidSurfaceCommandType(u16), InvalidSurfaceCommandType(u16),
#[fail(display = "Invalid Frame Marker action: {}", _0)] #[fail(display = "Invalid Frame Marker action: {}", _0)]
InvalidFrameAction(u16), InvalidFrameAction(u16),
#[fail( #[fail(display = "Input buffer is shorter then the data length: {} < {}", actual, expected)]
display = "Input buffer is shorter then the data length: {} < {}",
actual, expected
)]
InvalidDataLength { expected: usize, actual: usize }, InvalidDataLength { expected: usize, actual: usize },
} }
impl_from_error!( impl_from_error!(io::Error, SurfaceCommandsError, SurfaceCommandsError::IOError);
io::Error,
SurfaceCommandsError,
SurfaceCommandsError::IOError
);

View file

@ -5,81 +5,68 @@ use super::*;
const FRAME_MARKER_BUFFER: [u8; 8] = [0x4, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0]; const FRAME_MARKER_BUFFER: [u8; 8] = [0x4, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0];
const SURFACE_BITS_BUFFER: [u8; 1217] = [ const SURFACE_BITS_BUFFER: [u8; 1217] = [
0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x7, 0x38, 0x4, 0x20, 0x0, 0x0, 0x3, 0x80, 0x7, 0x38, 0x4, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x7, 0x38, 0x4, 0x20, 0x0, 0x0, 0x3, 0x80, 0x7, 0x38, 0x4, 0xab, 0x4, 0x0, 0x0,
0xab, 0x4, 0x0, 0x0, 0xc4, 0xcc, 0xe, 0x0, 0x0, 0x0, 0x1, 0x0, 0x4, 0x0, 0x0, 0x0, 0x1, 0x0, 0xc4, 0xcc, 0xe, 0x0, 0x0, 0x0, 0x1, 0x0, 0x4, 0x0, 0x0, 0x0, 0x1, 0x0, 0xc6, 0xcc, 0x17, 0x0, 0x0, 0x0, 0x1, 0x0,
0xc6, 0xcc, 0x17, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x1, 0x0, 0x70, 0x7, 0xa0, 0x0, 0x10, 0x0, 0x1, 0x1, 0x0, 0x70, 0x7, 0xa0, 0x0, 0x10, 0x0, 0xc0, 0x0, 0xc1, 0xca, 0x1, 0x0, 0xc7, 0xcc, 0x7e, 0x4, 0x0, 0x0,
0xc0, 0x0, 0xc1, 0xca, 0x1, 0x0, 0xc7, 0xcc, 0x7e, 0x4, 0x0, 0x0, 0x1, 0x0, 0xc2, 0xca, 0x0, 0x1, 0x0, 0xc2, 0xca, 0x0, 0x0, 0x51, 0x50, 0x1, 0x40, 0x4, 0x0, 0x63, 0x4, 0x0, 0x0, 0x66, 0x66, 0x77, 0x88, 0x98,
0x0, 0x51, 0x50, 0x1, 0x40, 0x4, 0x0, 0x63, 0x4, 0x0, 0x0, 0x66, 0x66, 0x77, 0x88, 0x98, 0xc3, 0xc3, 0xca, 0x25, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1d, 0x0, 0x2, 0x0, 0x0, 0x1, 0xd, 0x0, 0x5, 0x0, 0x6, 0x41, 0xb8,
0xca, 0x25, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1d, 0x0, 0x2, 0x0, 0x0, 0x1, 0xd, 0x0, 0x5, 0x0, 0xbc, 0x5e, 0x7e, 0x2f, 0x3f, 0x17, 0x9f, 0x8b, 0xc3, 0xf9, 0x7c, 0xbe, 0x7e, 0x7e, 0x2f, 0x43, 0xb3, 0x85, 0x68,
0x6, 0x41, 0xb8, 0xbc, 0x5e, 0x7e, 0x2f, 0x3f, 0x17, 0x9f, 0x8b, 0xc3, 0xf9, 0x7c, 0xbe, 0x7e, 0xe4, 0x70, 0x46, 0x8e, 0x47, 0xa, 0xc8, 0xe4, 0x60, 0x46, 0x47, 0x23, 0x5, 0x64, 0x72, 0x30, 0x23, 0x23, 0x91,
0x7e, 0x2f, 0x43, 0xb3, 0x85, 0x68, 0xe4, 0x70, 0x46, 0x8e, 0x47, 0xa, 0xc8, 0xe4, 0x60, 0x46, 0x82, 0xb2, 0x39, 0x18, 0x11, 0x91, 0xc8, 0xc1, 0x59, 0x1c, 0x8c, 0x8, 0xc8, 0xe4, 0x60, 0xac, 0x8e, 0x46, 0x4,
0x47, 0x23, 0x5, 0x64, 0x72, 0x30, 0x23, 0x23, 0x91, 0x82, 0xb2, 0x39, 0x18, 0x11, 0x91, 0xc8, 0x64, 0x72, 0x30, 0x56, 0x47, 0x23, 0x2, 0x32, 0x39, 0x18, 0x0, 0xcd, 0xb0, 0x34, 0x1a, 0x1a, 0x1a, 0x34, 0xd6,
0xc1, 0x59, 0x1c, 0x8c, 0x8, 0xc8, 0xe4, 0x60, 0xac, 0x8e, 0x46, 0x4, 0x64, 0x72, 0x30, 0x56, 0xb7, 0xe7, 0xc7, 0xc7, 0x4e, 0x9d, 0x3a, 0x69, 0x0, 0x1, 0xf, 0x20, 0xc8, 0x32, 0x19, 0x18, 0x0, 0xf, 0xe6, 0x43,
0x47, 0x23, 0x2, 0x32, 0x39, 0x18, 0x0, 0xcd, 0xb0, 0x34, 0x1a, 0x1a, 0x1a, 0x34, 0xd6, 0xb7, 0xe4, 0x7c, 0x8f, 0xa7, 0xd7, 0xdf, 0xbf, 0x89, 0x32, 0x8e, 0x82, 0x13, 0xff, 0xe0, 0x84, 0x82, 0x1f, 0xfe, 0x60,
0xe7, 0xc7, 0xc7, 0x4e, 0x9d, 0x3a, 0x69, 0x0, 0x1, 0xf, 0x20, 0xc8, 0x32, 0x19, 0x18, 0x0, 0x1c, 0xa0, 0x83, 0xff, 0xcc, 0x0, 0xa2, 0x82, 0xf, 0xc6, 0x0, 0x52, 0x82, 0xf, 0xc6, 0x0, 0xa5, 0x4, 0x1f, 0xfe,
0xf, 0xe6, 0x43, 0xe4, 0x7c, 0x8f, 0xa7, 0xd7, 0xdf, 0xbf, 0x89, 0x32, 0x8e, 0x82, 0x13, 0xff, 0x60, 0x5, 0x14, 0x10, 0x7e, 0x30, 0x0, 0x18, 0xdc, 0x2e, 0x2e, 0x5c, 0xdb, 0x7f, 0x8f, 0xd3, 0xc9, 0x46, 0x0,
0xe0, 0x84, 0x82, 0x1f, 0xfe, 0x60, 0x1c, 0xa0, 0x83, 0xff, 0xcc, 0x0, 0xa2, 0x82, 0xf, 0xc6, 0x22, 0x10, 0x10, 0xa, 0x13, 0xcb, 0xcb, 0x20, 0x0, 0x7e, 0x11, 0x13, 0xa8, 0x82, 0xd8, 0x8d, 0xc4, 0xc5, 0x88,
0x0, 0x52, 0x82, 0xf, 0xc6, 0x0, 0xa5, 0x4, 0x1f, 0xfe, 0x60, 0x5, 0x14, 0x10, 0x7e, 0x30, 0x0, 0x4f, 0xf4, 0x9, 0xff, 0xff, 0xd1, 0x6, 0xf8, 0x88, 0x13, 0xe2, 0x20, 0x32, 0x65, 0xaf, 0x1e, 0x38, 0x18, 0x4c,
0x18, 0xdc, 0x2e, 0x2e, 0x5c, 0xdb, 0x7f, 0x8f, 0xd3, 0xc9, 0x46, 0x0, 0x22, 0x10, 0x10, 0xa, 0x25, 0x4a, 0xc0, 0x27, 0x80, 0x1a, 0xb, 0xdc, 0x1, 0x47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbb, 0x0,
0x13, 0xcb, 0xcb, 0x20, 0x0, 0x7e, 0x11, 0x13, 0xa8, 0x82, 0xd8, 0x8d, 0xc4, 0xc5, 0x88, 0x4f, 0xa4, 0xd, 0x1, 0x25, 0x80, 0xa8, 0x18, 0x4a, 0x40, 0x18, 0x0, 0x48, 0xa2, 0xa8, 0x0, 0x10, 0x74, 0xd6, 0x80, 0x8,
0xf4, 0x9, 0xff, 0xff, 0xd1, 0x6, 0xf8, 0x88, 0x13, 0xe2, 0x20, 0x32, 0x65, 0xaf, 0x1e, 0x38, 0xc4, 0x1b, 0x89, 0x10, 0x0, 0x28, 0xdf, 0xff, 0xf6, 0xa1, 0xc0, 0x0, 0x70, 0xde, 0x4, 0xf2, 0x0, 0x7, 0xd, 0x73,
0x18, 0x4c, 0x25, 0x4a, 0xc0, 0x27, 0x80, 0x1a, 0xb, 0xdc, 0x1, 0x47, 0xff, 0xff, 0xff, 0xff, 0xe4, 0x0, 0x0, 0x0, 0x1f, 0x10, 0x40, 0xb4, 0x4, 0x85, 0xa0, 0x48, 0xb2, 0x40, 0x0, 0x0, 0x0, 0x8, 0x6, 0x0, 0xc3,
0xff, 0xff, 0xff, 0xbb, 0x0, 0xa4, 0xd, 0x1, 0x25, 0x80, 0xa8, 0x18, 0x4a, 0x40, 0x18, 0x0, 0xca, 0x30, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1d, 0x0, 0x3, 0x0, 0x13, 0x1, 0x5, 0x0, 0x5, 0x0, 0x6, 0x49, 0xc9,
0x48, 0xa2, 0xa8, 0x0, 0x10, 0x74, 0xd6, 0x80, 0x8, 0xc4, 0x1b, 0x89, 0x10, 0x0, 0x28, 0xdf, 0x81, 0xf2, 0x39, 0x30, 0x23, 0x23, 0x91, 0x81, 0x19, 0x1c, 0x8c, 0x15, 0x91, 0xc8, 0xc0, 0x8c, 0x8e, 0x46, 0xa,
0xff, 0xf6, 0xa1, 0xc0, 0x0, 0x70, 0xde, 0x4, 0xf2, 0x0, 0x7, 0xd, 0x73, 0xe4, 0x0, 0x0, 0x0, 0xc8, 0xe4, 0x60, 0x46, 0x47, 0x23, 0x5, 0x64, 0x72, 0x30, 0x23, 0x23, 0x91, 0x82, 0xb2, 0x39, 0x18, 0x11, 0x91,
0x1f, 0x10, 0x40, 0xb4, 0x4, 0x85, 0xa0, 0x48, 0xb2, 0x40, 0x0, 0x0, 0x0, 0x8, 0x6, 0x0, 0xc3, 0xc8, 0xc1, 0x59, 0x1c, 0x8c, 0x8, 0xc8, 0xe4, 0x60, 0xac, 0x8e, 0x46, 0x4, 0x64, 0x72, 0x30, 0x56, 0x47, 0x23,
0xca, 0x30, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1d, 0x0, 0x3, 0x0, 0x13, 0x1, 0x5, 0x0, 0x5, 0x0, 0x2, 0x32, 0x39, 0x18, 0x2b, 0x23, 0x91, 0x81, 0x19, 0x1c, 0x8c, 0x15, 0x91, 0xc8, 0xc0, 0x8c, 0x8e, 0x46, 0xa,
0x6, 0x49, 0xc9, 0x81, 0xf2, 0x39, 0x30, 0x23, 0x23, 0x91, 0x81, 0x19, 0x1c, 0x8c, 0x15, 0x91, 0xc8, 0xe4, 0x60, 0x46, 0x47, 0x23, 0x5, 0x64, 0x72, 0x30, 0x23, 0x23, 0x91, 0x82, 0xb2, 0x39, 0x18, 0x11, 0x91,
0xc8, 0xc0, 0x8c, 0x8e, 0x46, 0xa, 0xc8, 0xe4, 0x60, 0x46, 0x47, 0x23, 0x5, 0x64, 0x72, 0x30, 0xc8, 0xc1, 0x59, 0x1c, 0x8c, 0x8, 0xc8, 0xe4, 0x60, 0xac, 0x8e, 0x46, 0x4, 0x64, 0x72, 0x30, 0x0, 0x4, 0x19, 0x48,
0x23, 0x23, 0x91, 0x82, 0xb2, 0x39, 0x18, 0x11, 0x91, 0xc8, 0xc1, 0x59, 0x1c, 0x8c, 0x8, 0xc8, 0x0, 0x40, 0x8, 0x7, 0xff, 0x46, 0x24, 0x1, 0x0, 0x83, 0xef, 0xa, 0x4, 0x13, 0xe8, 0x42, 0x41, 0xf, 0xff, 0x30,
0xe4, 0x60, 0xac, 0x8e, 0x46, 0x4, 0x64, 0x72, 0x30, 0x56, 0x47, 0x23, 0x2, 0x32, 0x39, 0x18, 0xe, 0x50, 0x41, 0xff, 0xe6, 0x0, 0x51, 0x41, 0x7, 0xe3, 0x0, 0x29, 0x41, 0x7, 0xe3, 0x0, 0x52, 0x82, 0xf, 0xff,
0x2b, 0x23, 0x91, 0x81, 0x19, 0x1c, 0x8c, 0x15, 0x91, 0xc8, 0xc0, 0x8c, 0x8e, 0x46, 0xa, 0xc8, 0x30, 0x2, 0x8a, 0x8, 0x3f, 0x18, 0x1, 0x4a, 0x8, 0x3f, 0x18, 0x2, 0x94, 0x10, 0x7f, 0xf9, 0x80, 0x14, 0x50, 0x41,
0xe4, 0x60, 0x46, 0x47, 0x23, 0x5, 0x64, 0x72, 0x30, 0x23, 0x23, 0x91, 0x82, 0xb2, 0x39, 0x18, 0xf8, 0xc0, 0xa, 0x50, 0x41, 0xf8, 0xc0, 0x14, 0xa0, 0x83, 0xff, 0xcc, 0x0, 0xa2, 0x82, 0xf, 0xc6, 0x0, 0x52, 0x82,
0x11, 0x91, 0xc8, 0xc1, 0x59, 0x1c, 0x8c, 0x8, 0xc8, 0xe4, 0x60, 0xac, 0x8e, 0x46, 0x4, 0x64, 0xf, 0xc6, 0x0, 0x0, 0x10, 0x7f, 0x88, 0x1, 0x46, 0xf8, 0x80, 0x53, 0x70, 0x80, 0xbb, 0x84, 0x13, 0x70, 0x84, 0x6e,
0x72, 0x30, 0x0, 0x4, 0x19, 0x48, 0x0, 0x40, 0x8, 0x7, 0xff, 0x46, 0x24, 0x1, 0x0, 0x83, 0xef, 0x10, 0x80, 0x9f, 0x10, 0x81, 0xbe, 0x21, 0x0, 0x1, 0x9, 0xff, 0xff, 0xff, 0xfd, 0x4b, 0xd, 0xb, 0xc8, 0x20, 0xf6,
0xa, 0x4, 0x13, 0xe8, 0x42, 0x41, 0xf, 0xff, 0x30, 0xe, 0x50, 0x41, 0xff, 0xe6, 0x0, 0x51, 0x1a, 0x5e, 0x4c, 0x32, 0xc3, 0x5b, 0x9e, 0x44, 0x40, 0x5, 0xd, 0x6e, 0x79, 0x11, 0x0, 0x14, 0x37, 0xf8, 0x27,
0x41, 0x7, 0xe3, 0x0, 0x29, 0x41, 0x7, 0xe3, 0x0, 0x52, 0x82, 0xf, 0xff, 0x30, 0x2, 0x8a, 0x8, 0x90, 0x0, 0x38, 0x6f, 0x2, 0x79, 0x0, 0x3, 0x86, 0xff, 0x4, 0xf2, 0x0, 0x7, 0xd, 0x73, 0xe4, 0x0, 0x0, 0x0, 0x8,
0x3f, 0x18, 0x1, 0x4a, 0x8, 0x3f, 0x18, 0x2, 0x94, 0x10, 0x7f, 0xf9, 0x80, 0x14, 0x50, 0x41, 0x6, 0x0, 0x0, 0x0, 0x8, 0x6, 0x0, 0xc3, 0xca, 0x30, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1d, 0x0, 0x4, 0x0, 0x13, 0x1,
0xf8, 0xc0, 0xa, 0x50, 0x41, 0xf8, 0xc0, 0x14, 0xa0, 0x83, 0xff, 0xcc, 0x0, 0xa2, 0x82, 0xf, 0x5, 0x0, 0x5, 0x0, 0x6, 0x49, 0xc9, 0x81, 0xf2, 0x39, 0x30, 0x23, 0x23, 0x91, 0x81, 0x19, 0x1c, 0x8c, 0x15, 0x91,
0xc6, 0x0, 0x52, 0x82, 0xf, 0xc6, 0x0, 0x0, 0x10, 0x7f, 0x88, 0x1, 0x46, 0xf8, 0x80, 0x53, 0xc8, 0xc0, 0x8c, 0x8e, 0x46, 0xa, 0xc8, 0xe4, 0x60, 0x46, 0x47, 0x23, 0x5, 0x64, 0x72, 0x30, 0x23, 0x23, 0x91,
0x70, 0x80, 0xbb, 0x84, 0x13, 0x70, 0x84, 0x6e, 0x10, 0x80, 0x9f, 0x10, 0x81, 0xbe, 0x21, 0x0, 0x82, 0xb2, 0x39, 0x18, 0x11, 0x91, 0xc8, 0xc1, 0x59, 0x1c, 0x8c, 0x8, 0xc8, 0xe4, 0x60, 0xac, 0x8e, 0x46, 0x4,
0x1, 0x9, 0xff, 0xff, 0xff, 0xfd, 0x4b, 0xd, 0xb, 0xc8, 0x20, 0xf6, 0x1a, 0x5e, 0x4c, 0x32, 0x64, 0x72, 0x30, 0x56, 0x47, 0x23, 0x2, 0x32, 0x39, 0x18, 0x2b, 0x23, 0x91, 0x81, 0x19, 0x1c, 0x8c, 0x15, 0x91,
0xc3, 0x5b, 0x9e, 0x44, 0x40, 0x5, 0xd, 0x6e, 0x79, 0x11, 0x0, 0x14, 0x37, 0xf8, 0x27, 0x90, 0xc8, 0xc0, 0x8c, 0x8e, 0x46, 0xa, 0xc8, 0xe4, 0x60, 0x46, 0x47, 0x23, 0x5, 0x64, 0x72, 0x30, 0x23, 0x23, 0x91,
0x0, 0x38, 0x6f, 0x2, 0x79, 0x0, 0x3, 0x86, 0xff, 0x4, 0xf2, 0x0, 0x7, 0xd, 0x73, 0xe4, 0x0, 0x82, 0xb2, 0x39, 0x18, 0x11, 0x91, 0xc8, 0xc1, 0x59, 0x1c, 0x8c, 0x8, 0xc8, 0xe4, 0x60, 0xac, 0x8e, 0x46, 0x4,
0x0, 0x0, 0x8, 0x6, 0x0, 0x0, 0x0, 0x8, 0x6, 0x0, 0xc3, 0xca, 0x30, 0x1, 0x0, 0x0, 0x0, 0x0, 0x64, 0x72, 0x30, 0x0, 0x4, 0x19, 0x48, 0x0, 0x40, 0x8, 0x7, 0xff, 0x46, 0x24, 0x1, 0x0, 0x83, 0xef, 0xa, 0x4,
0x0, 0x1d, 0x0, 0x4, 0x0, 0x13, 0x1, 0x5, 0x0, 0x5, 0x0, 0x6, 0x49, 0xc9, 0x81, 0xf2, 0x39, 0x13, 0xe8, 0x42, 0x41, 0xf, 0xff, 0x30, 0xe, 0x50, 0x41, 0xff, 0xe6, 0x0, 0x51, 0x41, 0x7, 0xe3, 0x0, 0x29, 0x41,
0x30, 0x23, 0x23, 0x91, 0x81, 0x19, 0x1c, 0x8c, 0x15, 0x91, 0xc8, 0xc0, 0x8c, 0x8e, 0x46, 0xa, 0x7, 0xe3, 0x0, 0x52, 0x82, 0xf, 0xff, 0x30, 0x2, 0x8a, 0x8, 0x3f, 0x18, 0x1, 0x4a, 0x8, 0x3f, 0x18, 0x2, 0x94,
0xc8, 0xe4, 0x60, 0x46, 0x47, 0x23, 0x5, 0x64, 0x72, 0x30, 0x23, 0x23, 0x91, 0x82, 0xb2, 0x39, 0x10, 0x7f, 0xf9, 0x80, 0x14, 0x50, 0x41, 0xf8, 0xc0, 0xa, 0x50, 0x41, 0xf8, 0xc0, 0x14, 0xa0, 0x83, 0xff, 0xcc,
0x18, 0x11, 0x91, 0xc8, 0xc1, 0x59, 0x1c, 0x8c, 0x8, 0xc8, 0xe4, 0x60, 0xac, 0x8e, 0x46, 0x4, 0x0, 0xa2, 0x82, 0xf, 0xc6, 0x0, 0x52, 0x82, 0xf, 0xc6, 0x0, 0x0, 0x10, 0x7f, 0x88, 0x1, 0x46, 0xf8, 0x80, 0x53,
0x64, 0x72, 0x30, 0x56, 0x47, 0x23, 0x2, 0x32, 0x39, 0x18, 0x2b, 0x23, 0x91, 0x81, 0x19, 0x1c, 0x70, 0x80, 0xbb, 0x84, 0x13, 0x70, 0x84, 0x6e, 0x10, 0x80, 0x9f, 0x10, 0x81, 0xbe, 0x21, 0x0, 0x1, 0x9, 0xff,
0x8c, 0x15, 0x91, 0xc8, 0xc0, 0x8c, 0x8e, 0x46, 0xa, 0xc8, 0xe4, 0x60, 0x46, 0x47, 0x23, 0x5, 0xff, 0xff, 0xfd, 0x4b, 0xd, 0xb, 0xc8, 0x20, 0xf6, 0x1a, 0x5e, 0x4c, 0x32, 0xc3, 0x5b, 0x9e, 0x44, 0x40, 0x5, 0xd,
0x64, 0x72, 0x30, 0x23, 0x23, 0x91, 0x82, 0xb2, 0x39, 0x18, 0x11, 0x91, 0xc8, 0xc1, 0x59, 0x1c, 0x6e, 0x79, 0x11, 0x0, 0x14, 0x37, 0xf8, 0x27, 0x90, 0x0, 0x38, 0x6f, 0x2, 0x79, 0x0, 0x3, 0x86, 0xff, 0x4, 0xf2,
0x8c, 0x8, 0xc8, 0xe4, 0x60, 0xac, 0x8e, 0x46, 0x4, 0x64, 0x72, 0x30, 0x0, 0x4, 0x19, 0x48, 0x0, 0x7, 0xd, 0x73, 0xe4, 0x0, 0x0, 0x0, 0x8, 0x6, 0x0, 0x0, 0x0, 0x8, 0x6, 0x0, 0xc3, 0xca, 0xde, 0x0, 0x0, 0x0,
0x0, 0x40, 0x8, 0x7, 0xff, 0x46, 0x24, 0x1, 0x0, 0x83, 0xef, 0xa, 0x4, 0x13, 0xe8, 0x42, 0x41, 0x0, 0x0, 0x0, 0x1d, 0x0, 0x5, 0x0, 0xc1, 0x0, 0x5, 0x0, 0x5, 0x0, 0x6, 0x49, 0xc9, 0x81, 0xf2, 0x39, 0x30, 0x23,
0xf, 0xff, 0x30, 0xe, 0x50, 0x41, 0xff, 0xe6, 0x0, 0x51, 0x41, 0x7, 0xe3, 0x0, 0x29, 0x41, 0x7, 0x23, 0x91, 0x81, 0x19, 0x1c, 0x8c, 0x15, 0x91, 0xc8, 0xc0, 0x8c, 0x8e, 0x46, 0xa, 0xc8, 0xe4, 0x60, 0x46, 0x47,
0xe3, 0x0, 0x52, 0x82, 0xf, 0xff, 0x30, 0x2, 0x8a, 0x8, 0x3f, 0x18, 0x1, 0x4a, 0x8, 0x3f, 0x18, 0x23, 0x5, 0x64, 0x72, 0x30, 0x23, 0xb, 0xc5, 0xe7, 0xe2, 0xf3, 0xf1, 0x79, 0xf8, 0xbc, 0xfc, 0x5e, 0x7e, 0x2f,
0x2, 0x94, 0x10, 0x7f, 0xf9, 0x80, 0x14, 0x50, 0x41, 0xf8, 0xc0, 0xa, 0x50, 0x41, 0xf8, 0xc0, 0x3f, 0x17, 0x9f, 0x8b, 0xcf, 0xc5, 0xe7, 0xe2, 0xf3, 0xf1, 0x78, 0xc, 0x1e, 0x81, 0xd0, 0x74, 0x3a, 0x18, 0x0,
0x14, 0xa0, 0x83, 0xff, 0xcc, 0x0, 0xa2, 0x82, 0xf, 0xc6, 0x0, 0x52, 0x82, 0xf, 0xc6, 0x0, 0x0, 0xb, 0xf5, 0x20, 0x1, 0x0, 0x20, 0x1f, 0xfd, 0x31, 0x20, 0x8, 0x4, 0x1f, 0x54, 0x28, 0x10, 0x47, 0xd0, 0x84, 0x82,
0x10, 0x7f, 0x88, 0x1, 0x46, 0xf8, 0x80, 0x53, 0x70, 0x80, 0xbb, 0x84, 0x13, 0x70, 0x84, 0x6e, 0x13, 0xe8, 0x19, 0x21, 0xf, 0xff, 0x30, 0x5, 0xa4, 0x81, 0x52, 0x7d, 0x2e, 0x97, 0x5f, 0x4b, 0xcf, 0xc5, 0xe7,
0x10, 0x80, 0x9f, 0x10, 0x81, 0xbe, 0x21, 0x0, 0x1, 0x9, 0xff, 0xff, 0xff, 0xfd, 0x4b, 0xd, 0xe2, 0xf0, 0x60, 0x40, 0x80, 0x8a, 0x1e, 0x8f, 0x4c, 0x0, 0x4, 0x4, 0x85, 0x9, 0x6f, 0xff, 0xfa, 0x1, 0x4d, 0xf1,
0xb, 0xc8, 0x20, 0xf6, 0x1a, 0x5e, 0x4c, 0x32, 0xc3, 0x5b, 0x9e, 0x44, 0x40, 0x5, 0xd, 0x6e, 0x2, 0xb7, 0xa8, 0x14, 0x84, 0x92, 0x5, 0xa6, 0x16, 0x84, 0x16, 0x8c, 0x5e, 0x1, 0x24, 0x3f, 0xff, 0x80, 0x98,
0x79, 0x11, 0x0, 0x14, 0x37, 0xf8, 0x27, 0x90, 0x0, 0x38, 0x6f, 0x2, 0x79, 0x0, 0x3, 0x86, 0xe1, 0x2, 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xb0, 0x1a, 0x21, 0xe4, 0x4, 0x35, 0x80, 0xd2,
0xff, 0x4, 0xf2, 0x0, 0x7, 0xd, 0x73, 0xe4, 0x0, 0x0, 0x0, 0x8, 0x6, 0x0, 0x0, 0x0, 0x8, 0x6, 0x3c, 0x84, 0x30, 0x3, 0x81, 0xa9, 0xa3, 0xc7, 0x80, 0xc, 0x0, 0x41, 0x24, 0x20, 0x0, 0x5, 0x12, 0xaa, 0xa0, 0x1,
0x0, 0xc3, 0xca, 0xde, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1d, 0x0, 0x5, 0x0, 0xc1, 0x0, 0x5, 0x0, 0xc4, 0xe5, 0x54, 0x0, 0x72, 0x72, 0xaa, 0x0, 0x72, 0x4b, 0x50, 0x0, 0x0, 0x8, 0x6, 0x0, 0x0, 0x0, 0x8, 0x6, 0x0,
0x5, 0x0, 0x6, 0x49, 0xc9, 0x81, 0xf2, 0x39, 0x30, 0x23, 0x23, 0x91, 0x81, 0x19, 0x1c, 0x8c, 0xc5, 0xcc, 0x8, 0x0, 0x0, 0x0, 0x1, 0x0,
0x15, 0x91, 0xc8, 0xc0, 0x8c, 0x8e, 0x46, 0xa, 0xc8, 0xe4, 0x60, 0x46, 0x47, 0x23, 0x5, 0x64,
0x72, 0x30, 0x23, 0xb, 0xc5, 0xe7, 0xe2, 0xf3, 0xf1, 0x79, 0xf8, 0xbc, 0xfc, 0x5e, 0x7e, 0x2f,
0x3f, 0x17, 0x9f, 0x8b, 0xcf, 0xc5, 0xe7, 0xe2, 0xf3, 0xf1, 0x78, 0xc, 0x1e, 0x81, 0xd0, 0x74,
0x3a, 0x18, 0x0, 0xb, 0xf5, 0x20, 0x1, 0x0, 0x20, 0x1f, 0xfd, 0x31, 0x20, 0x8, 0x4, 0x1f, 0x54,
0x28, 0x10, 0x47, 0xd0, 0x84, 0x82, 0x13, 0xe8, 0x19, 0x21, 0xf, 0xff, 0x30, 0x5, 0xa4, 0x81,
0x52, 0x7d, 0x2e, 0x97, 0x5f, 0x4b, 0xcf, 0xc5, 0xe7, 0xe2, 0xf0, 0x60, 0x40, 0x80, 0x8a, 0x1e,
0x8f, 0x4c, 0x0, 0x4, 0x4, 0x85, 0x9, 0x6f, 0xff, 0xfa, 0x1, 0x4d, 0xf1, 0x2, 0xb7, 0xa8, 0x14,
0x84, 0x92, 0x5, 0xa6, 0x16, 0x84, 0x16, 0x8c, 0x5e, 0x1, 0x24, 0x3f, 0xff, 0x80, 0x98, 0xe1,
0x2, 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xb0, 0x1a, 0x21, 0xe4, 0x4, 0x35,
0x80, 0xd2, 0x3c, 0x84, 0x30, 0x3, 0x81, 0xa9, 0xa3, 0xc7, 0x80, 0xc, 0x0, 0x41, 0x24, 0x20,
0x0, 0x5, 0x12, 0xaa, 0xa0, 0x1, 0xc4, 0xe5, 0x54, 0x0, 0x72, 0x72, 0xaa, 0x0, 0x72, 0x4b,
0x50, 0x0, 0x0, 0x8, 0x6, 0x0, 0x0, 0x0, 0x8, 0x6, 0x0, 0xc5, 0xcc, 0x8, 0x0, 0x0, 0x0, 0x1,
0x0,
]; ];
const FRAME_MARKER_PDU: SurfaceCommand<'_> = SurfaceCommand::FrameMarker(FrameMarkerPdu { const FRAME_MARKER_PDU: SurfaceCommand<'_> = SurfaceCommand::FrameMarker(FrameMarkerPdu {
@ -88,23 +75,22 @@ const FRAME_MARKER_PDU: SurfaceCommand<'_> = SurfaceCommand::FrameMarker(FrameMa
}); });
lazy_static! { lazy_static! {
static ref SURFACE_BITS_PDU: SurfaceCommand<'static> = static ref SURFACE_BITS_PDU: SurfaceCommand<'static> = SurfaceCommand::StreamSurfaceBits(SurfaceBitsPdu {
SurfaceCommand::StreamSurfaceBits(SurfaceBitsPdu { destination: Rectangle {
destination: Rectangle { left: 0,
left: 0, top: 0,
top: 0, right: 1920,
right: 1920, bottom: 1080,
bottom: 1080, },
}, extended_bitmap_data: ExtendedBitmapDataPdu {
extended_bitmap_data: ExtendedBitmapDataPdu { bpp: 32,
bpp: 32, codec_id: 3,
codec_id: 3, width: 1920,
width: 1920, height: 1080,
height: 1080, header: None,
header: None, data: &SURFACE_BITS_BUFFER[22..],
data: &SURFACE_BITS_BUFFER[22..], },
}, });
});
} }
#[test] #[test]
@ -120,9 +106,7 @@ fn to_buffer_correctly_serializes_surface_command_frame_marker() {
let expected = FRAME_MARKER_BUFFER.as_ref(); let expected = FRAME_MARKER_BUFFER.as_ref();
let mut buffer = vec![0; expected.len()]; let mut buffer = vec![0; expected.len()];
FRAME_MARKER_PDU FRAME_MARKER_PDU.to_buffer_consume(&mut buffer.as_mut_slice()).unwrap();
.to_buffer_consume(&mut buffer.as_mut_slice())
.unwrap();
assert_eq!(expected, buffer.as_slice()); assert_eq!(expected, buffer.as_slice());
} }
@ -144,9 +128,7 @@ fn to_buffer_correctly_serializes_surface_command_bits() {
let expected = SURFACE_BITS_BUFFER.as_ref(); let expected = SURFACE_BITS_BUFFER.as_ref();
let mut buffer = vec![0; expected.len()]; let mut buffer = vec![0; expected.len()];
SURFACE_BITS_PDU SURFACE_BITS_PDU.to_buffer_consume(&mut buffer.as_mut_slice()).unwrap();
.to_buffer_consume(&mut buffer.as_mut_slice())
.unwrap();
assert_eq!(expected, buffer.as_slice()); assert_eq!(expected, buffer.as_slice());
} }

View file

@ -73,8 +73,7 @@ pub fn write_sequence_tag(mut stream: impl io::Write, length: u16) -> io::Result
pub fn read_sequence_tag(mut stream: impl io::Read) -> io::Result<u16> { pub fn read_sequence_tag(mut stream: impl io::Read) -> io::Result<u16> {
let identifier = stream.read_u8()?; let identifier = stream.read_u8()?;
if identifier != Class::Universal as u8 | Pc::Construct as u8 | (TAG_MASK & Tag::Sequence as u8) if identifier != Class::Universal as u8 | Pc::Construct as u8 | (TAG_MASK & Tag::Sequence as u8) {
{
Err(io::Error::new( Err(io::Error::new(
io::ErrorKind::InvalidData, io::ErrorKind::InvalidData,
"invalid sequence tag identifier", "invalid sequence tag identifier",
@ -84,11 +83,7 @@ pub fn read_sequence_tag(mut stream: impl io::Read) -> io::Result<u16> {
} }
} }
pub fn write_application_tag( pub fn write_application_tag(mut stream: impl io::Write, tagnum: u8, length: u16) -> io::Result<usize> {
mut stream: impl io::Write,
tagnum: u8,
length: u16,
) -> io::Result<usize> {
let taglen = if tagnum > 0x1E { let taglen = if tagnum > 0x1E {
stream.write_u8(Class::Application as u8 | Pc::Construct as u8 | TAG_MASK)?; stream.write_u8(Class::Application as u8 | Pc::Construct as u8 | TAG_MASK)?;
stream.write_u8(tagnum)?; stream.write_u8(tagnum)?;
@ -142,18 +137,12 @@ pub fn read_enumerated(mut stream: impl io::Read, count: u8) -> io::Result<u8> {
let length = read_length(&mut stream)?; let length = read_length(&mut stream)?;
if length != 1 { if length != 1 {
return Err(io::Error::new( return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid enumerated len"));
io::ErrorKind::InvalidData,
"invalid enumerated len",
));
} }
let enumerated = stream.read_u8()?; let enumerated = stream.read_u8()?;
if enumerated == std::u8::MAX || enumerated + 1 > count { if enumerated == std::u8::MAX || enumerated + 1 > count {
return Err(io::Error::new( return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid enumerated value"));
io::ErrorKind::InvalidData,
"invalid enumerated value",
));
} }
Ok(enumerated) Ok(enumerated)
@ -204,10 +193,7 @@ pub fn read_integer(mut stream: impl io::Read) -> io::Result<u64> {
} else if length == 8 { } else if length == 8 {
stream.read_u64::<BigEndian>() stream.read_u64::<BigEndian>()
} else { } else {
Err(io::Error::new( Err(io::Error::new(io::ErrorKind::InvalidData, "invalid integer len"))
io::ErrorKind::InvalidData,
"invalid integer len",
))
} }
} }
@ -226,10 +212,7 @@ pub fn read_bool(mut stream: impl io::Read) -> io::Result<bool> {
let length = read_length(&mut stream)?; let length = read_length(&mut stream)?;
if length != 1 { if length != 1 {
return Err(io::Error::new( return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid integer len"));
io::ErrorKind::InvalidData,
"invalid integer len",
));
} }
Ok(stream.read_u8()? != 0) Ok(stream.read_u8()? != 0)

View file

@ -39,28 +39,20 @@ fn write_application_tag_is_correct_with_short_tag() {
#[test] #[test]
fn read_application_tag_is_correct_with_long_tag() { fn read_application_tag_is_correct_with_long_tag() {
let buf = vec![0x7F, 0x1F, 0x0F]; let buf = vec![0x7F, 0x1F, 0x0F];
assert_eq!( assert_eq!(read_application_tag(&mut buf.as_slice(), 0x1F).unwrap(), 0x0F);
read_application_tag(&mut buf.as_slice(), 0x1F).unwrap(),
0x0F
);
} }
#[test] #[test]
fn read_application_tag_is_correct_with_short_tag() { fn read_application_tag_is_correct_with_short_tag() {
let buf = vec![0x68, 0x82, 0x01, 0x00]; let buf = vec![0x68, 0x82, 0x01, 0x00];
assert_eq!( assert_eq!(read_application_tag(&mut buf.as_slice(), 0x08).unwrap(), 0x100);
read_application_tag(&mut buf.as_slice(), 0x08).unwrap(),
0x100
);
} }
#[test] #[test]
fn read_application_tag_returns_error_on_invalid_long_tag() { fn read_application_tag_returns_error_on_invalid_long_tag() {
let buf = vec![0x68, 0x1B, 0x0F]; let buf = vec![0x68, 0x1B, 0x0F];
assert_eq!( assert_eq!(
read_application_tag(&mut buf.as_slice(), 0x1F) read_application_tag(&mut buf.as_slice(), 0x1F).unwrap_err().kind(),
.unwrap_err()
.kind(),
io::ErrorKind::InvalidData io::ErrorKind::InvalidData
); );
} }
@ -69,9 +61,7 @@ fn read_application_tag_returns_error_on_invalid_long_tag() {
fn read_application_tag_returns_error_on_invalid_long_tag_value() { fn read_application_tag_returns_error_on_invalid_long_tag_value() {
let buf = vec![0x7F, 0x1B, 0x0F]; let buf = vec![0x7F, 0x1B, 0x0F];
assert_eq!( assert_eq!(
read_application_tag(&mut buf.as_slice(), 0x1F) read_application_tag(&mut buf.as_slice(), 0x1F).unwrap_err().kind(),
.unwrap_err()
.kind(),
io::ErrorKind::InvalidData io::ErrorKind::InvalidData
); );
} }
@ -80,9 +70,7 @@ fn read_application_tag_returns_error_on_invalid_long_tag_value() {
fn read_application_tag_returns_error_on_invalid_short_tag() { fn read_application_tag_returns_error_on_invalid_short_tag() {
let buf = vec![0x67, 0x0F]; let buf = vec![0x67, 0x0F];
assert_eq!( assert_eq!(
read_application_tag(&mut buf.as_slice(), 0x08) read_application_tag(&mut buf.as_slice(), 0x08).unwrap_err().kind(),
.unwrap_err()
.kind(),
io::ErrorKind::InvalidData io::ErrorKind::InvalidData
); );
} }
@ -104,9 +92,7 @@ fn read_enumerated_is_correct() {
fn read_enumerated_returns_error_on_wrong_tag() { fn read_enumerated_returns_error_on_wrong_tag() {
let buf = vec![0x0B, 0x01, 0x0F]; let buf = vec![0x0B, 0x01, 0x0F];
assert_eq!( assert_eq!(
read_enumerated(&mut buf.as_slice(), 0x10) read_enumerated(&mut buf.as_slice(), 0x10).unwrap_err().kind(),
.unwrap_err()
.kind(),
io::ErrorKind::InvalidData io::ErrorKind::InvalidData
); );
} }
@ -115,9 +101,7 @@ fn read_enumerated_returns_error_on_wrong_tag() {
fn read_enumerated_returns_error_on_invalid_len() { fn read_enumerated_returns_error_on_invalid_len() {
let buf = vec![0x0A, 0x02, 0x0F]; let buf = vec![0x0A, 0x02, 0x0F];
assert_eq!( assert_eq!(
read_enumerated(&mut buf.as_slice(), 0x10) read_enumerated(&mut buf.as_slice(), 0x10).unwrap_err().kind(),
.unwrap_err()
.kind(),
io::ErrorKind::InvalidData io::ErrorKind::InvalidData
); );
} }
@ -126,9 +110,7 @@ fn read_enumerated_returns_error_on_invalid_len() {
fn read_enumerated_returns_error_on_invalid_variant() { fn read_enumerated_returns_error_on_invalid_variant() {
let buf = vec![0x0A, 0x01, 0x0F]; let buf = vec![0x0A, 0x01, 0x0F];
assert_eq!( assert_eq!(
read_enumerated(&mut buf.as_slice(), 0x05) read_enumerated(&mut buf.as_slice(), 0x05).unwrap_err().kind(),
.unwrap_err()
.kind(),
io::ErrorKind::InvalidData io::ErrorKind::InvalidData
); );
} }
@ -194,9 +176,7 @@ fn read_octet_string_tag_is_correct() {
fn read_octet_string_tag_returns_error_on_wrong_tag() { fn read_octet_string_tag_returns_error_on_wrong_tag() {
let buf = vec![0x05, 0x0F]; let buf = vec![0x05, 0x0F];
assert_eq!( assert_eq!(
read_octet_string_tag(&mut buf.as_slice()) read_octet_string_tag(&mut buf.as_slice()).unwrap_err().kind(),
.unwrap_err()
.kind(),
io::ErrorKind::InvalidData io::ErrorKind::InvalidData
); );
} }
@ -213,10 +193,7 @@ fn write_octet_string_is_correct() {
#[test] #[test]
fn read_octet_string_is_correct() { fn read_octet_string_is_correct() {
let buf = vec![0x04, 0x03, 0x00, 0x01, 0x02]; let buf = vec![0x04, 0x03, 0x00, 0x01, 0x02];
assert_eq!( assert_eq!(read_octet_string(&mut buf.as_slice()).unwrap(), vec![0x00, 0x01, 0x02]);
read_octet_string(&mut buf.as_slice()).unwrap(),
vec![0x00, 0x01, 0x02]
);
} }
#[test] #[test]
@ -298,10 +275,7 @@ fn write_integer_is_correct_with_1_byte_integer() {
#[test] #[test]
fn read_integer_is_correct_with_8_byte_integer() { fn read_integer_is_correct_with_8_byte_integer() {
let buf = vec![0x02, 0x08, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; let buf = vec![0x02, 0x08, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
assert_eq!( assert_eq!(read_integer(&mut buf.as_slice()).unwrap(), 0x0080_0000_0000_0000);
read_integer(&mut buf.as_slice()).unwrap(),
0x0080_0000_0000_0000
);
} }
#[test] #[test]
@ -340,10 +314,7 @@ fn read_integer_returns_error_on_incorrect_len() {
#[test] #[test]
fn write_universal_tag_primitive_integer_is_correct() { fn write_universal_tag_primitive_integer_is_correct() {
let mut buf = Vec::new(); let mut buf = Vec::new();
assert_eq!( assert_eq!(write_universal_tag(&mut buf, Tag::Integer, Pc::Primitive).unwrap(), 1);
write_universal_tag(&mut buf, Tag::Integer, Pc::Primitive).unwrap(),
1
);
assert_eq!(buf, vec![0x02]); assert_eq!(buf, vec![0x02]);
} }

View file

@ -11,15 +11,6 @@ mod header_messages;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
pub use self::{
data_messages::{
ContextPdu, EntropyAlgorithm, FrameBeginPdu, FrameEndPdu, OperatingMode, Quant, RegionPdu,
RfxRectangle, Tile, TileSetPdu,
},
header_messages::{Channel, ChannelsPdu, CodecVersionsPdu, SyncPdu},
rlgr::RlgrError,
};
use std::io; use std::io;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
@ -27,6 +18,12 @@ use failure::Fail;
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
pub use self::data_messages::{
ContextPdu, EntropyAlgorithm, FrameBeginPdu, FrameEndPdu, OperatingMode, Quant, RegionPdu, RfxRectangle, Tile,
TileSetPdu,
};
pub use self::header_messages::{Channel, ChannelsPdu, CodecVersionsPdu, SyncPdu};
pub use self::rlgr::RlgrError;
use crate::{impl_from_error, PduBufferParsing, PduParsing}; use crate::{impl_from_error, PduBufferParsing, PduParsing};
const BLOCK_HEADER_SIZE: usize = 6; const BLOCK_HEADER_SIZE: usize = 6;
@ -52,9 +49,7 @@ impl<'a> PduBufferParsing<'a> for Headers {
let ty = BlockType::from_u16(ty).ok_or(RfxError::InvalidBlockType(ty))?; let ty = BlockType::from_u16(ty).ok_or(RfxError::InvalidBlockType(ty))?;
match ty { match ty {
BlockType::CodecVersions => Ok(Self::CodecVersions( BlockType::CodecVersions => Ok(Self::CodecVersions(CodecVersionsPdu::from_buffer_consume(buffer)?)),
CodecVersionsPdu::from_buffer_consume(buffer)?,
)),
BlockType::Channels => Ok(Self::Channels(ChannelsPdu::from_buffer_consume(buffer)?)), BlockType::Channels => Ok(Self::Channels(ChannelsPdu::from_buffer_consume(buffer)?)),
BlockType::Context => Ok(Self::Context(ContextPdu::from_buffer_consume(buffer)?)), BlockType::Context => Ok(Self::Context(ContextPdu::from_buffer_consume(buffer)?)),
_ => Err(RfxError::InvalidHeaderBlockType(ty)), _ => Err(RfxError::InvalidHeaderBlockType(ty)),
@ -106,10 +101,7 @@ impl BlockHeader {
Ok(Self { ty, data_length }) Ok(Self { ty, data_length })
} }
fn from_buffer_consume_with_expected_type( fn from_buffer_consume_with_expected_type(buffer: &mut &[u8], expected_type: BlockType) -> Result<Self, RfxError> {
buffer: &mut &[u8],
expected_type: BlockType,
) -> Result<Self, RfxError> {
let ty = buffer.read_u16::<LittleEndian>()?; let ty = buffer.read_u16::<LittleEndian>()?;
let ty = BlockType::from_u16(ty).ok_or(RfxError::InvalidBlockType(ty))?; let ty = BlockType::from_u16(ty).ok_or(RfxError::InvalidBlockType(ty))?;
if ty != expected_type { if ty != expected_type {
@ -152,11 +144,7 @@ impl CodecChannelHeader {
Ok(Self) Ok(Self)
} }
fn to_buffer_consume_with_type( fn to_buffer_consume_with_type(&self, buffer: &mut &mut [u8], ty: BlockType) -> Result<(), RfxError> {
&self,
buffer: &mut &mut [u8],
ty: BlockType,
) -> Result<(), RfxError> {
buffer.write_u8(CODEC_ID)?; buffer.write_u8(CODEC_ID)?;
let channel_id = match ty { let channel_id = match ty {
@ -232,14 +220,8 @@ pub enum RfxError {
display = "Got unexpected Block type: expected ({:?}) != actual({:?})", display = "Got unexpected Block type: expected ({:?}) != actual({:?})",
expected, actual expected, actual
)] )]
UnexpectedBlockType { UnexpectedBlockType { expected: BlockType, actual: BlockType },
expected: BlockType, #[fail(display = "Got unexpected Block type ({:?}) while was expected header message", _0)]
actual: BlockType,
},
#[fail(
display = "Got unexpected Block type ({:?}) while was expected header message",
_0
)]
InvalidHeaderBlockType(BlockType), InvalidHeaderBlockType(BlockType),
#[fail(display = "Got invalid block length: {}", _0)] #[fail(display = "Got invalid block length: {}", _0)]
InvalidBlockLength(usize), InvalidBlockLength(usize),
@ -267,10 +249,7 @@ pub enum RfxError {
InvalidEntropyAlgorithm(u16), InvalidEntropyAlgorithm(u16),
#[fail(display = "Got invalid quantization type: {}", _0)] #[fail(display = "Got invalid quantization type: {}", _0)]
InvalidQuantizationType(u16), InvalidQuantizationType(u16),
#[fail( #[fail(display = "Input buffer is shorter then the data length: {} < {}", actual, expected)]
display = "Input buffer is shorter then the data length: {} < {}",
actual, expected
)]
InvalidDataLength { expected: usize, actual: usize }, InvalidDataLength { expected: usize, actual: usize },
#[fail(display = "Got invalid Region LRF: {}", _0)] #[fail(display = "Got invalid Region LRF: {}", _0)]
InvalidLrf(bool), InvalidLrf(bool),

View file

@ -1,10 +1,8 @@
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
use std::{ use std::cmp::{max, min};
cmp::{max, min}, use std::io::{self, Write};
io::{self, Write},
};
const DIVISOR: f32 = (1 << 16) as f32; const DIVISOR: f32 = (1 << 16) as f32;
const ALPHA: u8 = 255; const ALPHA: u8 = 255;

File diff suppressed because it is too large Load diff

View file

@ -6,10 +6,7 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
use super::{ use super::{BlockHeader, BlockType, CodecChannelHeader, RfxError, BLOCK_HEADER_SIZE, CODEC_CHANNEL_HEADER_SIZE};
BlockHeader, BlockType, CodecChannelHeader, RfxError, BLOCK_HEADER_SIZE,
CODEC_CHANNEL_HEADER_SIZE,
};
use crate::utils::SplitTo; use crate::utils::SplitTo;
use crate::PduBufferParsing; use crate::PduBufferParsing;
@ -34,10 +31,7 @@ pub struct ContextPdu {
} }
impl ContextPdu { impl ContextPdu {
pub fn from_buffer_consume_with_header( pub fn from_buffer_consume_with_header(buffer: &mut &[u8], header: BlockHeader) -> Result<Self, RfxError> {
buffer: &mut &[u8],
header: BlockHeader,
) -> Result<Self, RfxError> {
CodecChannelHeader::from_buffer_consume_with_type(buffer, BlockType::Context)?; CodecChannelHeader::from_buffer_consume_with_type(buffer, BlockType::Context)?;
let mut buffer = buffer.split_to(header.data_length); let mut buffer = buffer.split_to(header.data_length);
@ -55,9 +49,7 @@ impl ContextPdu {
let flags = OperatingMode::from_bits_truncate(properties.get_bits(0..3)); let flags = OperatingMode::from_bits_truncate(properties.get_bits(0..3));
let color_conversion_transform = properties.get_bits(3..5); let color_conversion_transform = properties.get_bits(3..5);
if color_conversion_transform != COLOR_CONVERSION_ICT { if color_conversion_transform != COLOR_CONVERSION_ICT {
return Err(RfxError::InvalidColorConversionTransform( return Err(RfxError::InvalidColorConversionTransform(color_conversion_transform));
color_conversion_transform,
));
} }
let dwt = properties.get_bits(5..9); let dwt = properties.get_bits(5..9);
@ -87,8 +79,7 @@ impl<'a> PduBufferParsing<'a> for ContextPdu {
type Error = RfxError; type Error = RfxError;
fn from_buffer_consume(buffer: &mut &[u8]) -> Result<Self, Self::Error> { fn from_buffer_consume(buffer: &mut &[u8]) -> Result<Self, Self::Error> {
let header = let header = BlockHeader::from_buffer_consume_with_expected_type(buffer, BlockType::Context)?;
BlockHeader::from_buffer_consume_with_expected_type(buffer, BlockType::Context)?;
Self::from_buffer_consume_with_header(buffer, header) Self::from_buffer_consume_with_header(buffer, header)
} }
@ -133,8 +124,7 @@ impl<'a> PduBufferParsing<'a> for FrameBeginPdu {
type Error = RfxError; type Error = RfxError;
fn from_buffer_consume(buffer: &mut &[u8]) -> Result<Self, Self::Error> { fn from_buffer_consume(buffer: &mut &[u8]) -> Result<Self, Self::Error> {
let header = let header = BlockHeader::from_buffer_consume_with_expected_type(buffer, BlockType::FrameBegin)?;
BlockHeader::from_buffer_consume_with_expected_type(buffer, BlockType::FrameBegin)?;
CodecChannelHeader::from_buffer_consume_with_type(buffer, BlockType::FrameBegin)?; CodecChannelHeader::from_buffer_consume_with_type(buffer, BlockType::FrameBegin)?;
let mut buffer = buffer.split_to(header.data_length); let mut buffer = buffer.split_to(header.data_length);
@ -175,8 +165,7 @@ impl<'a> PduBufferParsing<'a> for FrameEndPdu {
type Error = RfxError; type Error = RfxError;
fn from_buffer_consume(buffer: &mut &[u8]) -> Result<Self, Self::Error> { fn from_buffer_consume(buffer: &mut &[u8]) -> Result<Self, Self::Error> {
let _header = let _header = BlockHeader::from_buffer_consume_with_expected_type(buffer, BlockType::FrameEnd)?;
BlockHeader::from_buffer_consume_with_expected_type(buffer, BlockType::FrameEnd)?;
CodecChannelHeader::from_buffer_consume_with_type(buffer, BlockType::FrameEnd)?; CodecChannelHeader::from_buffer_consume_with_type(buffer, BlockType::FrameEnd)?;
Ok(Self) Ok(Self)
@ -209,8 +198,7 @@ impl<'a> PduBufferParsing<'a> for RegionPdu {
type Error = RfxError; type Error = RfxError;
fn from_buffer_consume(buffer: &mut &[u8]) -> Result<Self, Self::Error> { fn from_buffer_consume(buffer: &mut &[u8]) -> Result<Self, Self::Error> {
let header = let header = BlockHeader::from_buffer_consume_with_expected_type(buffer, BlockType::Region)?;
BlockHeader::from_buffer_consume_with_expected_type(buffer, BlockType::Region)?;
CodecChannelHeader::from_buffer_consume_with_type(buffer, BlockType::Region)?; CodecChannelHeader::from_buffer_consume_with_type(buffer, BlockType::Region)?;
let mut buffer = buffer.split_to(header.data_length); let mut buffer = buffer.split_to(header.data_length);
@ -293,8 +281,7 @@ impl<'a> PduBufferParsing<'a> for TileSetPdu<'a> {
type Error = RfxError; type Error = RfxError;
fn from_buffer_consume(buffer: &mut &'a [u8]) -> Result<Self, Self::Error> { fn from_buffer_consume(buffer: &mut &'a [u8]) -> Result<Self, Self::Error> {
let header = let header = BlockHeader::from_buffer_consume_with_expected_type(buffer, BlockType::Extension)?;
BlockHeader::from_buffer_consume_with_expected_type(buffer, BlockType::Extension)?;
CodecChannelHeader::from_buffer_consume_with_type(buffer, BlockType::Extension)?; CodecChannelHeader::from_buffer_consume_with_type(buffer, BlockType::Extension)?;
let mut buffer = buffer.split_to(header.data_length); let mut buffer = buffer.split_to(header.data_length);
@ -321,9 +308,7 @@ impl<'a> PduBufferParsing<'a> for TileSetPdu<'a> {
let color_conversion_transform = properties.get_bits(4..6); let color_conversion_transform = properties.get_bits(4..6);
if color_conversion_transform != COLOR_CONVERSION_ICT { if color_conversion_transform != COLOR_CONVERSION_ICT {
return Err(RfxError::InvalidColorConversionTransform( return Err(RfxError::InvalidColorConversionTransform(color_conversion_transform));
color_conversion_transform,
));
} }
let dwt = properties.get_bits(6..10); let dwt = properties.get_bits(6..10);
@ -417,11 +402,7 @@ impl<'a> PduBufferParsing<'a> for TileSetPdu<'a> {
BLOCK_HEADER_SIZE BLOCK_HEADER_SIZE
+ CODEC_CHANNEL_HEADER_SIZE + CODEC_CHANNEL_HEADER_SIZE
+ 14 + 14
+ self + self.quants.iter().map(PduBufferParsing::buffer_length).sum::<usize>()
.quants
.iter()
.map(PduBufferParsing::buffer_length)
.sum::<usize>()
+ self.tiles.iter().map(|t| t.buffer_length()).sum::<usize>() + self.tiles.iter().map(|t| t.buffer_length()).sum::<usize>()
} }
} }
@ -443,12 +424,7 @@ impl<'a> PduBufferParsing<'a> for RfxRectangle {
let width = buffer.read_u16::<LittleEndian>()?; let width = buffer.read_u16::<LittleEndian>()?;
let height = buffer.read_u16::<LittleEndian>()?; let height = buffer.read_u16::<LittleEndian>()?;
Ok(Self { Ok(Self { x, y, width, height })
x,
y,
width,
height,
})
} }
fn to_buffer_consume(&self, buffer: &mut &mut [u8]) -> Result<(), Self::Error> { fn to_buffer_consume(&self, buffer: &mut &mut [u8]) -> Result<(), Self::Error> {

View file

@ -35,21 +35,15 @@ fn inverse_horizontal(mut buffer: &[i16], temp_buffer: &mut [i16], subband_width
h_dst[0] = (i32::from(lh[0]) - ((i32::from(hh[0]) + i32::from(hh[0]) + 1) >> 1)) as i16; h_dst[0] = (i32::from(lh[0]) - ((i32::from(hh[0]) + i32::from(hh[0]) + 1) >> 1)) as i16;
for n in 1..subband_width { for n in 1..subband_width {
let x = n * 2; let x = n * 2;
l_dst[x] = l_dst[x] = (i32::from(ll[n]) - ((i32::from(hl[n - 1]) + i32::from(hl[n]) + 1) >> 1)) as i16;
(i32::from(ll[n]) - ((i32::from(hl[n - 1]) + i32::from(hl[n]) + 1) >> 1)) as i16; h_dst[x] = (i32::from(lh[n]) - ((i32::from(hh[n - 1]) + i32::from(hh[n]) + 1) >> 1)) as i16;
h_dst[x] =
(i32::from(lh[n]) - ((i32::from(hh[n - 1]) + i32::from(hh[n]) + 1) >> 1)) as i16;
} }
// Odd coefficients // Odd coefficients
for n in 0..subband_width - 1 { for n in 0..subband_width - 1 {
let x = n * 2; let x = n * 2;
l_dst[x + 1] = (i32::from(hl[n] << 1) l_dst[x + 1] = (i32::from(hl[n] << 1) + ((i32::from(l_dst[x]) + i32::from(l_dst[x + 2])) >> 1)) as i16;
+ ((i32::from(l_dst[x]) + i32::from(l_dst[x + 2])) >> 1)) h_dst[x + 1] = (i32::from(hh[n] << 1) + ((i32::from(h_dst[x]) + i32::from(h_dst[x + 2])) >> 1)) as i16;
as i16;
h_dst[x + 1] = (i32::from(hh[n] << 1)
+ ((i32::from(h_dst[x]) + i32::from(h_dst[x + 2])) >> 1))
as i16;
} }
let n = subband_width - 1; let n = subband_width - 1;
let x = n * 2; let x = n * 2;
@ -70,9 +64,8 @@ fn inverse_vertical(mut buffer: &mut [i16], mut temp_buffer: &[i16], subband_wid
let total_width = subband_width * 2; let total_width = subband_width * 2;
for _ in 0..total_width { for _ in 0..total_width {
buffer[0] = (i32::from(temp_buffer[0]) buffer[0] =
- ((i32::from(temp_buffer[subband_width * total_width]) * 2 + 1) >> 1)) (i32::from(temp_buffer[0]) - ((i32::from(temp_buffer[subband_width * total_width]) * 2 + 1) >> 1)) as i16;
as i16;
let mut l = temp_buffer; let mut l = temp_buffer;
let mut lh = &temp_buffer[(subband_width - 1) * total_width..]; let mut lh = &temp_buffer[(subband_width - 1) * total_width..];
@ -85,19 +78,16 @@ fn inverse_vertical(mut buffer: &mut [i16], mut temp_buffer: &[i16], subband_wid
h = &h[total_width..]; h = &h[total_width..];
// Even coefficients // Even coefficients
dst[2 * total_width] = dst[2 * total_width] = (i32::from(l[0]) - ((i32::from(lh[0]) + i32::from(h[0]) + 1) >> 1)) as i16;
(i32::from(l[0]) - ((i32::from(lh[0]) + i32::from(h[0]) + 1) >> 1)) as i16;
// Odd coefficients // Odd coefficients
dst[total_width] = (i32::from(lh[0] << 1) dst[total_width] =
+ ((i32::from(dst[0]) + i32::from(dst[2 * total_width])) >> 1)) (i32::from(lh[0] << 1) + ((i32::from(dst[0]) + i32::from(dst[2 * total_width])) >> 1)) as i16;
as i16;
dst = &mut dst[2 * total_width..]; dst = &mut dst[2 * total_width..];
} }
dst[total_width] = (i32::from(lh[total_width] << 1) dst[total_width] = (i32::from(lh[total_width] << 1) + ((i32::from(dst[0]) + i32::from(dst[0])) >> 1)) as i16;
+ ((i32::from(dst[0]) + i32::from(dst[0])) >> 1)) as i16;
temp_buffer = &temp_buffer[1..]; temp_buffer = &temp_buffer[1..];
buffer = &mut buffer[1..]; buffer = &mut buffer[1..];

File diff suppressed because it is too large Load diff

View file

@ -57,10 +57,7 @@ impl<'a> PduBufferParsing<'a> for SyncPdu {
pub struct CodecVersionsPdu; pub struct CodecVersionsPdu;
impl CodecVersionsPdu { impl CodecVersionsPdu {
pub fn from_buffer_consume_with_header( pub fn from_buffer_consume_with_header(buffer: &mut &[u8], header: BlockHeader) -> Result<Self, RfxError> {
buffer: &mut &[u8],
header: BlockHeader,
) -> Result<Self, RfxError> {
let mut buffer = buffer.split_to(header.data_length); let mut buffer = buffer.split_to(header.data_length);
let codecs_number = buffer.read_u8()?; let codecs_number = buffer.read_u8()?;
@ -78,8 +75,7 @@ impl<'a> PduBufferParsing<'a> for CodecVersionsPdu {
type Error = RfxError; type Error = RfxError;
fn from_buffer_consume(buffer: &mut &[u8]) -> Result<Self, Self::Error> { fn from_buffer_consume(buffer: &mut &[u8]) -> Result<Self, Self::Error> {
let header = let header = BlockHeader::from_buffer_consume_with_expected_type(buffer, BlockType::CodecVersions)?;
BlockHeader::from_buffer_consume_with_expected_type(buffer, BlockType::CodecVersions)?;
Self::from_buffer_consume_with_header(buffer, header) Self::from_buffer_consume_with_header(buffer, header)
} }
@ -105,10 +101,7 @@ impl<'a> PduBufferParsing<'a> for CodecVersionsPdu {
pub struct ChannelsPdu(pub Vec<Channel>); pub struct ChannelsPdu(pub Vec<Channel>);
impl ChannelsPdu { impl ChannelsPdu {
pub fn from_buffer_consume_with_header( pub fn from_buffer_consume_with_header(buffer: &mut &[u8], header: BlockHeader) -> Result<Self, RfxError> {
buffer: &mut &[u8],
header: BlockHeader,
) -> Result<Self, RfxError> {
let mut buffer = buffer.split_to(header.data_length); let mut buffer = buffer.split_to(header.data_length);
let channels_number = usize::from(buffer.read_u8()?); let channels_number = usize::from(buffer.read_u8()?);
@ -132,8 +125,7 @@ impl<'a> PduBufferParsing<'a> for ChannelsPdu {
type Error = RfxError; type Error = RfxError;
fn from_buffer_consume(buffer: &mut &[u8]) -> Result<Self, Self::Error> { fn from_buffer_consume(buffer: &mut &[u8]) -> Result<Self, Self::Error> {
let header = let header = BlockHeader::from_buffer_consume_with_expected_type(buffer, BlockType::Channels)?;
BlockHeader::from_buffer_consume_with_expected_type(buffer, BlockType::Channels)?;
Self::from_buffer_consume_with_header(buffer, header) Self::from_buffer_consume_with_header(buffer, header)
} }
@ -155,13 +147,7 @@ impl<'a> PduBufferParsing<'a> for ChannelsPdu {
} }
fn buffer_length(&self) -> usize { fn buffer_length(&self) -> usize {
BLOCK_HEADER_SIZE BLOCK_HEADER_SIZE + 1 + self.0.iter().map(PduBufferParsing::buffer_length).sum::<usize>()
+ 1
+ self
.0
.iter()
.map(PduBufferParsing::buffer_length)
.sum::<usize>()
} }
} }

View file

@ -68,9 +68,7 @@ impl<'a> ImageRegion<'a> {
let dst = &mut other.data[((y + dst_point.y) * dst_step)..]; let dst = &mut other.data[((y + dst_point.y) * dst_step)..];
for x in 0..width { for x in 0..width {
let color = self let color = self.pixel_format.read_color(&src[((x + src_point.x) * src_byte)..])?;
.pixel_format
.read_color(&src[((x + src_point.x) * src_byte)..])?;
other other
.pixel_format .pixel_format
.write_color(color, &mut dst[((x + dst_point.x) * dst_byte)..])?; .write_color(color, &mut dst[((x + dst_point.x) * dst_byte)..])?;

File diff suppressed because it is too large Load diff

View file

@ -9,8 +9,7 @@ const SECOND_LEVEL_SUBBANDS_COUNT: usize = 3;
pub fn decode(buffer: &mut [i16], quant: &Quant) { pub fn decode(buffer: &mut [i16], quant: &Quant) {
let (first_level, buffer) = buffer.split_at_mut(FISRT_LEVEL_SUBBANDS_COUNT * FIRST_LEVEL_SIZE); let (first_level, buffer) = buffer.split_at_mut(FISRT_LEVEL_SUBBANDS_COUNT * FIRST_LEVEL_SIZE);
let (second_level, third_level) = let (second_level, third_level) = buffer.split_at_mut(SECOND_LEVEL_SUBBANDS_COUNT * SECOND_LEVEL_SIZE);
buffer.split_at_mut(SECOND_LEVEL_SUBBANDS_COUNT * SECOND_LEVEL_SIZE);
let decode_chunk = |a: (&mut [i16], u8)| decode_block(a.0, a.1 as i16 - 1); let decode_chunk = |a: (&mut [i16], u8)| decode_block(a.0, a.1 as i16 - 1);
@ -85,318 +84,262 @@ mod tests {
} }
const QUANTIZIED_BUFFER: [i16; 4096] = [ const QUANTIZIED_BUFFER: [i16; 4096] = [
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, -2, 4,
0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, -5, -1, 0, 0, 0, 0, 0, 0, -1, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 3, 0, 0, 0, 0, 0, 0, -1, 4, 4, -5, -1,
0, 0, 0, 0, 0, 0, 0, 1, 0, -2, 4, -5, -1, 0, 0, 0, 0, 0, 0, -1, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 5, 0, 0, 0, 0, 0, 0, 2, 1, 0, 2, -5, -4, 1, 0, 0, 0, 0, 0, 0, 1, 3, -1, 5, 0, -1, 0, 0,
0, 0, -3, 0, 3, 0, 0, 0, 0, 0, 0, -1, 4, 4, -5, -1, 0, 0, 0, 0, 0, 0, -2, 5, 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -3, 0, 0, 0, 0, 0, 3, 0, 0, 7, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 2, -1, 0, 0, 0, 0, 0,
0, 2, 1, 0, 2, -5, -4, 1, 0, 0, 0, 0, 0, 0, 1, 3, -1, 5, 0, -1, 0, 0, 0, 0, 0, -2, -2, -3, -3, 1, 5, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, -2,
0, 0, 0, 0, 0, 3, 0, 0, 7, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -9, -3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, 0, 0, 0,
-3, 1, 5, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 6, -2, -8, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0,
0, 0, 2, 0, 0, 0, -2, 0, 0, 0, 0, 0, 1, 0, -9, -3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 5, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, -1, 2, 0, 0, 1, 0, 0, -1, 0, -1, 7, 0,
0, 0, 0, 0, 0, 0, 0, -1, -1, -1, 0, 0, 0, 0, 0, 0, 6, -2, -8, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, -2, 0, 0, 0, 0, 0, 3, -1, 0, -1, 0, 1, 0, 0, 0, 1, 2, -1, 0, -5, 1, 0, 0, 0, 0,
0, 0, -1, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 5, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, -4, 0, 0, 0, 0, 0, -1, -6, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 6, 0, -1, 0, 1, 0, 0, 1, -1, 0, 0,
0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, -1, 2, 0, 0, 1, 0, 0, -1, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -5, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 1, 10, 0, 0, 0, -1, 1, 0, 0, 0, 0, -1, 1,
0, 0, 0, 0, 0, 0, 0, -3, -2, 0, 0, 0, 0, 0, 3, -1, 0, -1, 0, 1, 0, 0, 0, 1, 2, -1, 0, -5, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -5, -5, 3, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, -4, 0, 0, 0, 0, 0, -1, -6, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, -2, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 3, -1, -7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -6, 0, 0, 0, 0, 0, 0, -8,
6, 0, -1, 0, 1, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 4, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 6, -1, 0, 0, 0, 0, -1, 7, -1, 0, 0, 0,
0, 0, -1, -1, 1, 10, 0, 0, 0, -1, 1, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, -3, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 4, 1, 2, -2, -2, 0, -1, 0,
0, 0, 0, 0, 0, 1, -5, -5, 3, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, -1, -2, 0, 0, 0, 0, 1, -1, -7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6, 0, 0, 0, 0, 0, -1, -10, 3, 1, 2, 0, -2, 1, 1, 0, 0, 0,
0, 0, -1, 0, 0, 0, 0, 0, 0, 3, -1, -7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -6, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 3, -2, 0, 0, 0, 0, 0, 6, -8, -2, 0, -2, 1, 0, 0, -1, -1, -1, 1, 1, 1,
0, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 4, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 6, -1, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0, 3, 2, 0, 1, 0, 0, 1, 1, 0, 0, 1, -2, 5, -3, 2, 0, 0, 0,
0, 0, -1, 7, -1, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, -3, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, -3, 0, 1, 0, 0, 1, 1, 0, 0,
3, 1, 0, 0, 0, 0, 0, 4, 1, 2, -2, -2, 0, -1, 0, 0, 0, 0, 1, -1, -7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, -1, -1, 0, 0, 1, 0, 0, 0, 3, 0,
0, 0, 0, -6, 0, 0, 0, 0, 0, -1, -10, 3, 1, 2, 0, -2, 1, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 1, 1, -2, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 3, -2, 0, 0, 0, 0, 0, 6, -8, -2, 0, -2, 1, 0, 0, -1, -1, -1, 1, 1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0, 3, 2, 0, 1, 0, 0, 1, 1, 0, 0, 1, -2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-3, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-1, 0, 0, -3, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, -1, 1, -1, -1, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, -1, 0, 0, -1, -1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 1, 1, -2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -2, -8, 2, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, -2, 4, 4, -1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 3, -1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 3, 3, -7, -1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, -1, 0, 0, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -2, -2, 2, -1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 1, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, -5, -3, -4, -6, -6, 7, 1, 1, -1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -2, -3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, -1, 0, -2, -3, 1, 1, -8, 6, 0, -1, 1, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -2, -8, 2, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 6, -3, -1, 0, 0, 0, 0, 0, -1, 5, 2, -6, -2, 0, 0, 0, 2, 7, -6, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, -2, 4, 4, -1, 0, 0, 0, 0, 0, 0, -1, 3, -1, -1, 1, 6, 0, 0, 0, 0, 0, 0, -2, 1, 0, 0, 0, 0, 0, 0, 0, -1, 6, -1, 1, -6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1,
-1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 3, 3, -7, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -2, 0, -8, 6, 6, 4, 3, 3, 4, -1, -2, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -1, -1, 7, -8, 0, 1, -2, -4, -3, -1, 1, -3, -4, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, -3, -5, 0, 1, 0, 0, 8, -1, -7, -9, -7, -2, 6, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -2, -2, 2, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 1, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, 0, 0, -1, 1, -1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, -5, -3, -4, -6, -6, 7, 1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, -1, 0, 0, 0, 0, 0, 0, 1, 1, 3, 3, 0, 1, 1, -1, 1, 0, 0, 0, 0, 0, 0,
0, -1, -2, -3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, -1, 0, -2, -3, 1, 1, -8, 6, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, -4, -5, -8, -6, -4, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 0, 0, 6, -3, -1, 0, 0, 0, 0, 0, -1, 5, 2, -6, -2, 0, 0, 0, 2, 7, -6, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, -9, -5, 10, 2, 2, 0, -1, 2, 6, -4, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 1, 6, 0, 0, 0, 0, 0, 0, -2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 2, -1, -1, 1, 0, 0, 0, 0, 0, -1, 4, -2, -1, 1, -1, 1, -1, 0, 0, 0, 0, 0, 0,
0, -1, 6, -1, 1, -6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, -1, -2, 0, -8, 6, 6, 4, 3, 3, 4, -1, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, -1, 1, 1, 0, 1, 0, -1, 3, -1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 2, -1, -1, 7, -8, 0, 1, -2, -4, -3, -1, 1, -3, -4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, 1, 1, 1, 0, -2, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, -3, -5, 0, 1, 0, 0, 8, -1, -7, -9, -7, -2, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, -1, 0, 0, 0, 0, -1, 1, -1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, -1, 1, -1, 0, 0, 0, 0, 0, 0, 1, 1, 3, 3, 0, 1, 1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, -4, -5, -8, -6, -4, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, -9, -5, 10, 2, 2, 0, -1, 2, 6, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 2, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, -1, 4, -2, -1, 1, -1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -1, 1, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, -1, 1, 1, 0, 1, 0, -1, 3, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, 1, 1, 1, 0, -2, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -1, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 2, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, -1, 0, -5, 3, -2, 1, 0, -1, 0, 0, 0, 0, 1, -4, -1, 0, 0, 1, -5, -2, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 6, -2, -1, 0, 1, -4, 21, 6, 0, 0, -5, -1, 1, 2, 4, 4, 3, 5, 0, 0, -1, 4, -8, -11, 0, 0, -2, 8, -1, 0, 3,
-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -18, 16, 1, -1, 2, 0, -4, -4, 0, 0, -6, 1, -3, -1, 1, 14, -23, 1, 0, 1, 0, 1, -3, -1, 0, 0, 0, -5, -2, 3,
-1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 11, -8, -3, 0, 1, 0, -1, -3, 1, 0, 14, 1, 0, -1, 0, 0, -15, -2, 7, 1, -1, 1, -3, -1, -1, -2, -14, 0, 1, 0,
0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, -18, 14, -7, -1, -1, -2, 13, 1, -1, 3, -14, 1, -2, 2, -1, 11, -16, -2, 2, -1, 1, 0, -9, 0, -1, 19, 1, 1,
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 2, 8, 0, 0, 0, 0, 1, -13, 0, 0, -6, -3, -1, 0, -2, -2, 6, 13, 0, 0, 0, 1, 9, 1, 0, 0, -1, 2, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, -5, 0, 0, -1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, -2, -4, 1, 4, 4, -2, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, -4, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -1, 1, 1, -1, -3, 0, -2, -3, 0,
0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -2, -2, 0, 1, -1, 2, 0, 0, 0, 1, -1, 1, 0, 1, -8, -1, 0, 0, 1, -3, 0, 0, -1, 3, 0, 0, 1, -3,
-1, 2, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, -3, 3, -4, 0, 0, 0, 1, 0, 0, 3, -3, 3, -1, 1, 1, 0, 1, -5, 20, 0, 0, 0, -1, 2, 7, -1, 0, 3, -2, 1, 0, 4,
1, -1, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 1, -3, 2, -9, -12, -19, 10, -1, 2, 0, -1, 1, 9, -13, 0, 0, 1, -4, -13, 0, 0, 16, -7, 0, 16, -3, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -1, 2, -1, 0, 0, 0, 1, 1, 0, 0, 4, -3, -17, -14, 2, -4, -14, -1, 0, -1, 1, 0, -1, 0, 1, 1, -2, 1, 3, 17,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 15, 9, -2, 0, 2, -3, 2, 2, -2, 2, 1, -1, 1, 0, 0, -2, 5, 7, -1, 0, 1, 4, -7, -14, -7, 2, -2, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, -3, 17, 8, -1, 4, 8, -9, 6, 0, 1, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -2, -2, 2, 0, 0, 5, -1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -5, -4, -2, -6, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -7, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -4, -1, 0, 0, 0, 0, 0, 0, -1, -1, 1, -1, 0, 0, 0, 0, 2, 2, 0, 0, 0, 3, 0, 0, 1, 1, -1,
0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -4, -8, 0, 0, 0, -1, 0, 0, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, -1, -3, 3, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 1, -2, 0, 0, -1, 3, 1, 2, -1, 0, 0, 0, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, -3,
0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, -1, 0, -5, 3, -2, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 2, 0, -1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, -2, 0, 0, 2,
0, 0, 0, 1, -4, -1, 0, 0, 1, -5, -2, 1, 1, 1, 6, -2, -1, 0, 1, -4, 21, 6, 0, 0, -5, -1, 1, 2, 1, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 2, 0, 0, 1, -2, 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2, 4, 4, 3, 5, 0, 0, -1, 4, -8, -11, 0, 0, -2, 8, -1, 0, 3, 1, -18, 16, 1, -1, 2, 0, -4, 0, 0, 1, 0, 0, 0, 0, -1, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-4, 0, 0, -6, 1, -3, -1, 1, 14, -23, 1, 0, 1, 0, 1, -3, -1, 0, 0, 0, -5, -2, 3, -1, 11, -8, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -2, -2, 1, 0, -1, -2, 0, -1, 8, 6, 3, 0, -1, -6, 0, 4, 5, -13, -53, -3, -2, 0,
-3, 0, 1, 0, -1, -3, 1, 0, 14, 1, 0, -1, 0, 0, -15, -2, 7, 1, -1, 1, -3, -1, -1, -2, -14, -2, -15, -7, 25, 8, 3, 7, -25, 26, -12, 5, 20, 6, 7, -5, -13, 2, -2, 5, -54, 10, -2, 30, 3, -46, 11, -9, -1,
0, 1, 0, 0, 5, -18, 14, -7, -1, -1, -2, 13, 1, -1, 3, -14, 1, -2, 2, -1, 11, -16, -2, 2, -2, 1, -18, -2, 8, -3, 3, -5, -4, -1, -5, -2, -3, 0, 1, -10, -3, 1, -1, 1, -5, -1, -3, 3, 7, -14, -13, 10, 0,
-1, 1, 0, -9, 0, -1, 19, 1, 1, 1, 0, 2, 2, 8, 0, 0, 0, 0, 1, -13, 0, 0, -6, -3, -1, 0, -2, -1, 11, 2, 5, 2, 12, 0, -8, 24, -21, -49, -4, 10, 9, 31, -1, 5, 10, 1, 13, -57, -52, 9, 12, -6, -18, 5, 1, -3,
-2, 6, 13, 0, 0, 0, 1, 9, 1, 0, 0, -1, 2, 0, 0, 1, 0, -5, 0, 0, -1, 0, 0, 1, 1, 0, 0, 0, 0, -4, -1, 13, 21, 8, 11, 3, 7, 7, -2, -3, -1, 0, 2, -14, -19, -7, 1, -1, -1, -3, -2, 0, 0, -1, -1, -1, -7, 3, 4,
0, 0, 0, 0, 1, -2, -4, 1, 4, 4, -2, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -4, -1, 0, 0, 7, -1, -6, -14, -1, -7, 3, -12, -16, -2, 2, -1, -9, 1, 7, -21, 25, -4, -2, -23, 2, 2, 3, -4, 22, -4, 5, -4, -2,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -1, 1, 1, -1, -3, 0, -2, -3, 0, -2, 4, -7, 0, 0, 3, 2, 17, -6, 7, 5, 3, 1, -5, 0, 1, 0, 0, 6, 1, -4, 2, 0, -1, 0, -1, -15, -12, -12, -19, -23,
0, 0, 0, 0, 0, 0, -2, -2, 0, 1, -1, 2, 0, 0, 0, 1, -1, 1, 0, 1, -8, -1, 0, 0, 1, -3, 0, 0, 27, 14, 3, 37, 11, -12, -15, -16, 29, 25, 46, 103, 86, 43, 26, 11, 38, 31, 56, 86, 63, 128, 115, 27, 72, -31,
-1, 3, 0, 0, 1, -3, -3, -3, 3, -4, 0, 0, 0, 1, 0, 0, 3, -3, 3, -1, 1, 1, 0, 1, -5, 20, 0, 54, 125, 9, 97, 67, 10, 67, -34, 60, 85, 102, 107, 113, 6, 21, -10, 10, -16, 126, 108, 85, -10, 59, 52, 39, 30,
0, 0, -1, 2, 7, -1, 0, 3, -2, 1, 0, 4, -1, 0, 1, 0, 1, -3, 2, -9, -12, -19, 10, -1, 2, 0, 35, 53, 15, -3,
-1, 1, 9, -13, 0, 0, 1, -4, -13, 0, 0, 16, -7, 0, 16, -3, 1, -2, -1, 2, -1, 0, 0, 0, 1, 1,
0, 0, 4, -3, -17, -14, 2, -4, -14, -1, 0, -1, 1, 0, -1, 0, 1, 1, -2, 1, 3, 17, 13, 15, 9,
-2, 0, 2, -3, 2, 2, -2, 2, 1, -1, 1, 0, 0, -2, 5, 7, -1, 0, 1, 4, -7, -14, -7, 2, -2, 0, 0,
0, 0, 0, 0, -1, 1, 0, -3, 17, 8, -1, 4, 8, -9, 6, 0, 1, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0,
0, 0, -2, -2, 2, 0, 0, 5, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -5, -4, -2, -6, -1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-1, 0, -4, -1, 0, 0, 0, 0, 0, 0, -1, -1, 1, -1, 0, 0, 0, 0, 2, 2, 0, 0, 0, 3, 0, 0, 1, 1,
-1, 1, 0, 0, 0, 0, -4, -8, 0, 0, 0, -1, 0, 0, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1, -1, -3, 3, 0, 0, 0, -1, 1, 0, 0, 0, 0, 1, -2, 0, 0, -1, 3, 1, 2, -1, 0, 0, 0, -2, -1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 2, 0, -1, 1,
0, 0, 0, 1, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, -2, 0, 0, 2, 2, 1, -1, 0, -1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, -2, 2, 0, 0, 1, -2, 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, -1, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -2, -2, 1, 0, -1, -2, 0, -1, 8, 6, 3, 0, -1, -6,
0, 4, 5, -13, -53, -3, -2, 0, -2, -15, -7, 25, 8, 3, 7, -25, 26, -12, 5, 20, 6, 7, -5, -13,
2, -2, 5, -54, 10, -2, 30, 3, -46, 11, -9, -1, -2, 1, -18, -2, 8, -3, 3, -5, -4, -1, -5,
-2, -3, 0, 1, -10, -3, 1, -1, 1, -5, -1, -3, 3, 7, -14, -13, 10, 0, -1, 11, 2, 5, 2, 12, 0,
-8, 24, -21, -49, -4, 10, 9, 31, -1, 5, 10, 1, 13, -57, -52, 9, 12, -6, -18, 5, 1, -3, -4,
-1, 13, 21, 8, 11, 3, 7, 7, -2, -3, -1, 0, 2, -14, -19, -7, 1, -1, -1, -3, -2, 0, 0, -1,
-1, -1, -7, 3, 4, 7, -1, -6, -14, -1, -7, 3, -12, -16, -2, 2, -1, -9, 1, 7, -21, 25, -4,
-2, -23, 2, 2, 3, -4, 22, -4, 5, -4, -2, -2, 4, -7, 0, 0, 3, 2, 17, -6, 7, 5, 3, 1, -5, 0,
1, 0, 0, 6, 1, -4, 2, 0, -1, 0, -1, -15, -12, -12, -19, -23, 27, 14, 3, 37, 11, -12, -15,
-16, 29, 25, 46, 103, 86, 43, 26, 11, 38, 31, 56, 86, 63, 128, 115, 27, 72, -31, 54, 125,
9, 97, 67, 10, 67, -34, 60, 85, 102, 107, 113, 6, 21, -10, 10, -16, 126, 108, 85, -10, 59,
52, 39, 30, 35, 53, 15, -3,
]; ];
const DEQUANTIZED_BUFFER: [i16; 4096] = [ const DEQUANTIZED_BUFFER: [i16; 4096] = [
0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 256, 0, 0, 0, 0, -128, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 128, 0, 256, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 128, 0, 0, 0, 0, 0, 0, 0, 0, -384, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 256,
0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 128, 0, 0, 0, 0, 0, 0, 0, 0, -384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, -256, 512, -640, -128, 0, 0, 0, 0, 0, 0, -128, -384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
128, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 128, 0, -256, 512, -640, -128, 0, 0, 0, 0, -384, 0, 384, 0, 0, 0, 0, 0, 0, -128, 512, 512, -640, -128, 0, 0, 0, 0, 0, 0, -256, 640, 0, 0, 0, 0, 0, 0, 256,
0, 0, -128, -384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -384, 0, 384, 0, 0, 0, 0, 0, 0, -128, 512, 128, 0, 256, -640, -512, 128, 0, 0, 0, 0, 0, 0, 128, 384, -128, 640, 0, -128, 0, 0, 0, 0, 0, -256, -256, -384,
512, -640, -128, 0, 0, 0, 0, 0, 0, -256, 640, 0, 0, 0, 0, 0, 0, 256, 128, 0, 256, -640, 0, 0, 0, 0, 0, 384, 0, 0, 896, 0, -512, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, -128, 256, -128, 0, 0, 0, 0, 0, -384,
-512, 128, 0, 0, 0, 0, 0, 0, 128, 384, -128, 640, 0, -128, 0, 0, 0, 0, 0, -256, -256, -384, 128, 640, 0, 0, 0, 0, 0, 0, -128, 0, 0, 128, 896, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 256, 0,
0, 0, 0, 0, 0, 384, 0, 0, 896, 0, -512, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, -128, 256, -128, 0, 0, -256, 0, 0, 0, 0, 0, 128, 0, -1152, -384, 640, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, -384, 128, 640, 0, 0, 0, 0, 0, 0, -128, 0, 0, 128, 896, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, -128, 0, 0, 0, 0, 0, 0, 768, -256, -1024, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0,
0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, -256, 0, 0, 0, 0, 0, 128, 0, -1152, -384, 0, 0, -384, 0, 0, 0, 0, 0, 0, -128, 0, -128, 0, 640, 256, 384, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 256, 0, 0, 0, 0,
640, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, -128, 0, 0, 0, 0, 0, -128, 128, 0, 0, -128, 256, 0, 0, 128, 0, 0, -128, 0, -128, 896, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -384,
0, 0, 0, 768, -256, -1024, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 384, -128, 0, -128, 0, 128, 0, 0, 0, 128, 256, -128, 0, -640, 128, 0, 0, 0, 0, 0, 0, 0, 0,
-384, 0, 0, 0, 0, 0, 0, -128, 0, -128, 0, 640, 256, 384, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, -384, -512, 0, 0, 0, 0, 0, -128, -768, 128, 0, -128, 0, 0, 0, 0, 0, 0, 0, 768, 0, -128, 0, 128, 0, 0, 128,
256, 0, 0, 0, 0, 0, 0, -128, 128, 0, 0, -128, 256, 0, 0, 128, 0, 0, -128, 0, -128, 896, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 384, -640, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, 128, 1280, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, -384, -256, 0, 0, 0, 0, 0, 384, -128, 0, -128, 0, 128, 0, 0, 0, -128, 128, 0, 0, 0, 0, -128, 128, 0, 0, 0, 0, 0, 0, 896, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, -640, -640, 384, 0,
128, 256, -128, 0, -640, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, -384, -512, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, -128, 0, -128, 0, 0, 0, 0, 0, -128, -256, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 384, -128,
-768, 128, 0, -128, 0, 0, 0, 0, 0, 0, 0, 768, 0, -128, 0, 128, 0, 0, 128, -128, 0, 0, 0, 0, -896, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, -768, 0, 0, 0, 0, 0, 0, -1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 384, 256,
0, 0, 0, 0, 0, 0, 0, 384, -640, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, 128, 1280, 0, 0, 0, 512, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 768, -128, 0, 0, 0, 0, -128, 896, -128, 0, 0, 0, -128, -128, 0, 0, 0, 0,
-128, 128, 0, 0, 0, 0, -128, 128, 0, 0, 0, 0, 0, 0, 896, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, -384, -128, 768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 384, 128, 0, 0, 0, 0, 0, 512, 128, 256, -256, -256, 0, -128,
-640, -640, 384, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, -128, 0, 0, 0, 0, 0, -128, -256, 0, 0, 0, 0, 0, 0, 0, 128, -128, -896, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -768, 0, 0, 0, 0, 0, -128, -1280, 384, 128,
-128, 0, 0, 0, 0, 0, 0, 384, -128, -896, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, -768, 0, 0, 0, 256, 0, -256, 128, 128, 0, 0, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 384, -256, 0, 0, 0, 0, 0, 768,
0, 0, 0, -1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 384, 256, 512, 0, 0, 0, 0, 0, -128, 0, 0, 0, -1024, -256, 0, -256, 128, 0, 0, -128, -128, -128, 128, 128, 128, 768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 512, 128,
0, 768, -128, 0, 0, 0, 0, -128, 896, -128, 0, 0, 0, -128, -128, 0, 0, 0, 0, 0, -384, -128, 0, 0, 0, 0, 0, 384, 256, 0, 128, 0, 0, 128, 128, 0, 0, 128, -256, 640, -384, 256, 0, 0, 0, 0, 128, 0, 0, 0, 0,
768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 384, 128, 0, 0, 0, 0, 0, 512, 128, 256, -256, -256, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, -384, 0, 128, 0, 0, 128, 128, 0, 0, 0, 0,
-128, 0, 0, 0, 0, 128, -128, -896, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -768, 0, 0, 0, 0, 0, 0, -512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 128, -128, -128, 0, 0, 128, 0, 0, 0,
-128, -1280, 384, 128, 256, 0, -256, 128, 128, 0, 0, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, 384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 128, 128, 128, -256, 0, 128,
0, 0, 0, 384, -256, 0, 0, 0, 0, 0, 768, -1024, -256, 0, -256, 128, 0, 0, -128, -128, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, -256, 128, 128, 0, 0, 0, 0, 0,
128, 128, 128, 768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 512, 128, 0, 0, 0, 0, 0, 384, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 384, -128, 0, 0, 0, 0, 0, 0, 0, 0,
128, 0, 0, 128, 128, 0, 0, 128, -256, 640, -384, 256, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, -384, 0, 128, 0, 0, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, -512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0,
-128, -128, 0, 0, 128, 0, 0, 0, 384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, 0, 0, -128, -128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, -128, 0, 0, 0, 0,
0, 0, 0, -128, 0, 0, 0, 128, 128, 128, -256, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, -128, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, -256, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 384, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 128, 0, 0, 0, 0, 0, 0, -256, -1024, 256, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 128, 0, -256, 512, 512, -128, 0, 0, 0, 0, 0, 0, -128, 384, -128,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, -128, 384, 384, -896, -128, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 128, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 768, 384, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, -128, -128, 0, 0, -128, -128, 0, 0, 0, 128, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, -128, 0, 0, 0, 0, -128, 0, 0, 0, 128, -256, -256, 256, -128, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0,
0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, -128, 0, 128, 128, 384, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, -128,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -640, -384, -512, -768, -768, 896, 128, 128, -128, 0, 0, 0, 0, 0, 0, 0, -128, -256, -384, 0, 128, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 128, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 128, 0, 256, -128, 0, -256, -384, 128, 128, -1024, 768, 0, -128, 128, 0, 0, 0, 0, 128, 128, 0, 0,
-1024, 256, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 768, -384, -128, 0, 0, 0, 0, 0, -128, 640, 256, -768, -256, 0, 0, 0, 256, 896, -768, -128, 0, 0, 128, 0, 0, 0,
0, 0, 128, 0, -256, 512, 512, -128, 0, 0, 0, 0, 0, 0, -128, 384, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, 128, 768, 0, 0, 0, 0, 0, 0, -256, 128, 0, 0, 0, 0, 0, 0, 0, -128, 768, -128, 128,
128, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, -128, 384, 384, -896, -128, 0, 0, 0, 0, 0, 0, 0, 0, -768, 896, 0, 0, 0, 0, 0, 0, 0, 0, 128, -128, -128, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 128, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 768, 384, 0, -128, -256, 0, -1024, 768, 768, 512, 384, 384, 512, -128, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, -128, -128, 896, -1024, 0, 128, -256, -512, -384, -128, 128, -384, -512, 128, 0, 0, 0, 0, 0, 0, 0,
-1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, -256, -256, 256, -128, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 128, -384, -640, 0, 128, 0, 0, 1024, -128, -896, -1152, -896, -256, 768, 384, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 128, 128, 384, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, -128, -128, 0, 0, 0, 0, 0, 128, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, -128, -640, -384, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, -128, 128, 0, 0, 0, 0, 0, -128, 128, 0, 0, 128, -128, 0,
-512, -768, -768, 896, 128, 128, -128, 0, 0, 0, 0, 0, 0, 0, -128, -256, -384, 0, 128, 0, 0, 0, 0, 0, -128, 128, -128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 128, -128,
0, 0, 0, 0, 0, 0, 128, 0, 256, -128, 0, -256, -384, 128, 128, -1024, 768, 0, -128, 128, 0, 0, 0, 0, 0, 0, 0, 128, 128, 384, 384, 0, 128, 128, -128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 128, 128, 0, 0, 768, -384, -128, 0, 0, 0, 0, 0, -128, 640, 256, -768, -256, 0, 0, 128, 0, 0, 0, 128, 0, 0, 0, 256, 128, -512, -640, -1024, -768, -512, 128, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0,
0, 256, 896, -768, -128, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, 128, 768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 384, -1152, -640, 1280, 256, 256, 0, -128, 256, 768, -512, -128, 0, 0, 0, 0,
0, 0, 0, -256, 128, 0, 0, 0, 0, 0, 0, 0, -128, 768, -128, 128, -768, 896, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 256, -128, -128, 128, 0, 0, 0, 0, 0, -128, 512, -256,
0, 0, 128, -128, -128, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, -256, -128, 128, -128, 128, -128, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, -1024, 768, 768, 512, 384, 384, 512, -128, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, -128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 256, -128, -128, 896, -1024, 0, 128, -256, -512, -384, -128, 128, -384, -128, -128, 0, -128, 128, 128, 0, 128, 0, -128, 384, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-512, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 128, -384, -640, 0, 128, 0, 0, 0, 0, 0, 0, -128, -128, -128, 128, 128, 128, 0, -256, -384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1024, -128, -896, -1152, -896, -256, 768, 384, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 512, 256, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-128, 0, 0, 0, 0, 0, 128, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, -128, 128, 0, 0, 0, 0, 0, -128, 128, 0, 0, 128, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, -128, 128, -128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, -128, 128, -128, 0, 0, 0, 0, 0, 0, 128, 128, 384, 384, 0, 128, 128, -128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 0, 0, 256, 128, -512, -640, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-1024, -768, -512, 128, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 384, -1152, -640, 1280, 256, 256, 0, -128, 256, 768, -512, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 256, -128, -128, 128, 0, 0, 0, 0, 0, -128, 512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -512, -256, 256, 0, 0, 0, 0, 0, 0, 0, -256, -256, 0, 0, 0, 0,
-256, -128, 128, -128, 128, -128, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, -256, 256, -512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, -128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 256, -256, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0,
0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, 0, -128, 128, 128, 0, 128, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
384, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, -128, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
128, 128, 128, 0, -256, -384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, -128, 512, 256, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 256,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 256, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, -256, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, -256, 512, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, -512, -256, 256, 0, 0, 0, 0, 0, 0, 0, -256, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, -256, 0, 0, 0, 0, 0, 0, 0, 256, -256, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, -256, 256, -512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 256, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, -256, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 64, 0, 0, 64, 0, 0, 64, 0, 0, 0, 0, 0, 0, -64, 0, 0, -64, -64, 0, -320, 192, -128, 64, 0, -64, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, -256, -64, 0, 0, 64, -320, -128, 64, 64, 64, 384, -128, -64, 0, 64, -256, 1344, 384, 0, 0, -320, -64, 64,
-256, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 128, 256, 256, 192, 320, 0, 0, -64, 256, -512, -704, 0, 0, -128, 512, -64, 0, 192, 64, -1152, 1024, 64, -64,
0, 0, 0, 0, 0, 0, 0, -512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, -256, -256, 0, 0, -384, 64, -192, -64, 64, 896, -1472, 64, 0, 64, 0, 64, -192, -64, 0, 0, 0, -320,
0, 0, 0, 0, 0, 0, 0, 0, -256, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, -128, 192, -64, 704, -512, -192, 0, 64, 0, -64, -192, 64, 0, 896, 64, 0, -64, 0, 0, -960, -128, 448, 64, -64,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 64, -192, -64, -64, -128, -896, 0, 64, 0, 0, 320, -1152, 896, -448, -64, -64, -128, 832, 64, -64, 192, -896,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, -128, 128, -64, 704, -1024, -128, 128, -64, 64, 0, -576, 0, -64, 1216, 64, 64, 64, 0, 128, 128, 512, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, -832, 0, 0, -384, -192, -64, 0, -128, -128, 384, 832, 0, 0, 0, 64, 576, 64, 0, 0, -64, 128, 0, 0, 64,
256, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -320, 0, 0, -64, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 64, -128, -256, 64, 256, 256, -128, 0, 0, -64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 256, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, -256, -64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, -64, 64,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, -256, 512, 0, -256, 0, 0, 0, 0, 0, 0, 0, 64, -64, -192, 0, -128, -192, 0, 0, 0, 0, 0, 0, 0, -128, -128, 0, 64, -64, 128, 0, 0, 0, 64, -64, 64, 0, 64,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, -256, 0, 0, 0, 0, 0, 0, 0, -512, -64, 0, 0, 64, -192, 0, 0, -64, 192, 0, 0, 64, -192, -192, -192, 192, -256, 0, 0, 0, 64, 0, 0, 192, -192,
256, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, -64, 64, 64, 0, 64, -320, 1280, 0, 0, 0, -64, 128, 448, -64, 0, 192, -128, 64, 0, 256, -64, 0, 64, 0, 64,
0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -192, 128, -576, -768, -1216, 640, -64, 128, 0, -64, 64, 576, -832, 0, 0, 64, -256, -832, 0, 0, 1024, -448, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1024, -192, 64, -128, -64, 128, -64, 0, 0, 0, 64, 64, 0, 0, 256, -192, -1088, -896, 128, -256, -896, -64, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -64, 64, 0, -64, 0, 64, 64, -128, 64, 192, 1088, 832, 960, 576, -128, 0, 128, -192, 128, 128, -128, 128, 64,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -64, 64, 0, 0, -128, 320, 448, -64, 0, 64, 256, -448, -896, -448, 128, -128, 0, 0, 0, 0, 0, 0, -64, 64, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, -256, 256, 0, 0, 0, -192, 1088, 512, -64, 256, 512, -576, 384, 0, 64, 0, 0, 0, 0, 0, 0, -64, 64, 0, 0, 0, 0, 0, -128, -128, 128, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 320, -64, 0, 0, -64, 0, 0, 0, 0, 0, 0, 0, -320, -256, -128, -384, -64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -448, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, -512, -128, 0, 0, 0, 0, 0, 0, -128, -128, 128, -128,
0, 0, 64, 0, 0, 64, 0, 0, 0, 0, 0, 0, -64, 0, 0, -64, -64, 0, -320, 192, -128, 64, 0, -64, 0, 0, 0, 0, 256, 256, 0, 0, 0, 384, 0, 0, 128, 128, -128, 128, 0, 0, 0, 0, -512, -1024, 0, 0, 0, -128, 0, 0,
0, 0, 0, 0, 64, -256, -64, 0, 0, 64, -320, -128, 64, 64, 64, 384, -128, -64, 0, 64, -256, -128, -128, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, -128, -384, 384, 0, 0, 0, -128, 128, 0, 0, 0, 0, 128,
1344, 384, 0, 0, -320, -64, 64, 128, 256, 256, 192, 320, 0, 0, -64, 256, -512, -704, 0, 0, -256, 0, 0, -128, 384, 128, 256, -128, 0, 0, 0, -256, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 128, 128, 0,
-128, 512, -64, 0, 192, 64, -1152, 1024, 64, -64, 128, 0, -256, -256, 0, 0, -384, 64, -192, -384, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, -128, 256, 0, -128, 128, 0, 0, 0, 128, 128, 0, 0, 0, 0, 0, -128, 0, 0, 0,
-64, 64, 896, -1472, 64, 0, 64, 0, 64, -192, -64, 0, 0, 0, -320, -128, 192, -64, 704, -512, -128, 0, -256, 0, 0, 256, 256, 128, -128, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 256, 0, 0, 128, -256,
-192, 0, 64, 0, -64, -192, 64, 0, 896, 64, 0, -64, 0, 0, -960, -128, 448, 64, -64, 64, 128, -128, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, -128, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-192, -64, -64, -128, -896, 0, 64, 0, 0, 320, -1152, 896, -448, -64, -64, -128, 832, 64, 0, 0, 128, 128, -128, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, -64, -64, 32,
-64, 192, -896, 64, -128, 128, -64, 704, -1024, -128, 128, -64, 64, 0, -576, 0, -64, 1216, 0, -32, -64, 0, -32, 256, 192, 96, 0, -32, -192, 0, 128, 160, -416, -1696, -96, -64, 0, -64, -480, -224, 800,
64, 64, 64, 0, 128, 128, 512, 0, 0, 0, 0, 64, -832, 0, 0, -384, -192, -64, 0, -128, -128, 256, 96, 224, -800, 832, -384, 160, 640, 192, 224, -160, -416, 64, -64, 160, -1728, 320, -64, 960, 96, -1472,
384, 832, 0, 0, 0, 64, 576, 64, 0, 0, -64, 128, 0, 0, 64, 0, -320, 0, 0, -64, 0, 0, 64, 64, 352, -288, -32, -64, 32, -576, -64, 256, -96, 96, -160, -128, -32, -160, -64, -96, 0, 32, -320, -96, 32, -32,
0, 0, 0, 0, 0, 0, 0, 0, 64, -128, -256, 64, 256, 256, -128, 0, 0, -64, 0, 0, 0, 0, 0, 0, 0, 32, -160, -32, -96, 96, 224, -448, -416, 320, 0, -32, 352, 64, 160, 64, 384, 0, -256, 768, -672, -1568, -128,
0, 64, 0, -256, -64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, -64, 320, 288, 992, -32, 160, 320, 32, 416, -1824, -1664, 288, 384, -192, -576, 160, 32, -96, -128, -32, 416, 672,
64, 64, -64, -192, 0, -128, -192, 0, 0, 0, 0, 0, 0, 0, -128, -128, 0, 64, -64, 128, 0, 0, 256, 352, 96, 224, 224, -64, -96, -32, 0, 64, -448, -608, -224, 32, -32, -32, -96, -64, 0, 0, -32, -32, -32,
0, 64, -64, 64, 0, 64, -512, -64, 0, 0, 64, -192, 0, 0, -64, 192, 0, 0, 64, -192, -192, -224, 96, 128, 224, -32, -192, -448, -32, -224, 96, -384, -512, -64, 64, -32, -288, 32, 224, -672, 800, -128,
-192, 192, -256, 0, 0, 0, 64, 0, 0, 192, -192, 192, -64, 64, 64, 0, 64, -320, 1280, 0, 0, -64, -736, 64, 64, 96, -128, 704, -128, 160, -128, -64, -64, 128, -224, 0, 0, 96, 64, 544, -192, 224, 160, 96,
0, -64, 128, 448, -64, 0, 192, -128, 64, 0, 256, -64, 0, 64, 0, 64, -192, 128, -576, -768, 32, -160, 0, 32, 0, 0, 192, 32, -128, 64, 0, -32, 0, -32, -480, -384, -384, -608, -736, 864, 448, 96, 1184,
-1216, 640, -64, 128, 0, -64, 64, 576, -832, 0, 0, 64, -256, -832, 0, 0, 1024, -448, 0, 352, -384, -480, -512, 928, 800, 1472, 3296, 2752, 1376, 832, 352, 1216, 992, 1792, 2752, 2016, 4096, 3680,
1024, -192, 64, -128, -64, 128, -64, 0, 0, 0, 64, 64, 0, 0, 256, -192, -1088, -896, 128, 864, 2304, -992, 1728, 4000, 288, 3104, 2144, 320, 2144, -1088, 1920, 2720, 3264, 3424, 3616, 192, 672, -320,
-256, -896, -64, 0, -64, 64, 0, -64, 0, 64, 64, -128, 64, 192, 1088, 832, 960, 576, -128, 320, -512, 4032, 3456, 2720, -320, 1888, 1664, 1248, 960, 1120, 1696, 480, -96,
0, 128, -192, 128, 128, -128, 128, 64, -64, 64, 0, 0, -128, 320, 448, -64, 0, 64, 256,
-448, -896, -448, 128, -128, 0, 0, 0, 0, 0, 0, -64, 64, 0, -192, 1088, 512, -64, 256, 512,
-576, 384, 0, 64, 0, 0, 0, 0, 0, 0, -64, 64, 0, 0, 0, 0, 0, -128, -128, 128, 0, 0, 320,
-64, 0, 0, -64, 0, 0, 0, 0, 0, 0, 0, -320, -256, -128, -384, -64, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, -448, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0,
-512, -128, 0, 0, 0, 0, 0, 0, -128, -128, 128, -128, 0, 0, 0, 0, 256, 256, 0, 0, 0, 384, 0,
0, 128, 128, -128, 128, 0, 0, 0, 0, -512, -1024, 0, 0, 0, -128, 0, 0, -128, -128, -128, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, -128, -384, 384, 0, 0, 0, -128, 128, 0, 0, 0, 0, 128,
-256, 0, 0, -128, 384, 128, 256, -128, 0, 0, 0, -256, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128,
0, 128, 128, 0, -384, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, -128, 256, 0, -128, 128, 0, 0, 0,
128, 128, 0, 0, 0, 0, 0, -128, 0, 0, 0, -128, 0, -256, 0, 0, 256, 256, 128, -128, 0, -128,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 256, 0, 0, 128, -256, 128, -128, -128, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, -128, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128,
128, -128, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, -64,
-64, 32, 0, -32, -64, 0, -32, 256, 192, 96, 0, -32, -192, 0, 128, 160, -416, -1696, -96,
-64, 0, -64, -480, -224, 800, 256, 96, 224, -800, 832, -384, 160, 640, 192, 224, -160,
-416, 64, -64, 160, -1728, 320, -64, 960, 96, -1472, 352, -288, -32, -64, 32, -576, -64,
256, -96, 96, -160, -128, -32, -160, -64, -96, 0, 32, -320, -96, 32, -32, 32, -160, -32,
-96, 96, 224, -448, -416, 320, 0, -32, 352, 64, 160, 64, 384, 0, -256, 768, -672, -1568,
-128, 320, 288, 992, -32, 160, 320, 32, 416, -1824, -1664, 288, 384, -192, -576, 160, 32,
-96, -128, -32, 416, 672, 256, 352, 96, 224, 224, -64, -96, -32, 0, 64, -448, -608, -224,
32, -32, -32, -96, -64, 0, 0, -32, -32, -32, -224, 96, 128, 224, -32, -192, -448, -32,
-224, 96, -384, -512, -64, 64, -32, -288, 32, 224, -672, 800, -128, -64, -736, 64, 64, 96,
-128, 704, -128, 160, -128, -64, -64, 128, -224, 0, 0, 96, 64, 544, -192, 224, 160, 96, 32,
-160, 0, 32, 0, 0, 192, 32, -128, 64, 0, -32, 0, -32, -480, -384, -384, -608, -736, 864,
448, 96, 1184, 352, -384, -480, -512, 928, 800, 1472, 3296, 2752, 1376, 832, 352, 1216,
992, 1792, 2752, 2016, 4096, 3680, 864, 2304, -992, 1728, 4000, 288, 3104, 2144, 320, 2144,
-1088, 1920, 2720, 3264, 3424, 3616, 192, 672, -320, 320, -512, 4032, 3456, 2720, -320,
1888, 1664, 1248, 960, 1120, 1696, 480, -96,
]; ];
} }

View file

@ -57,13 +57,7 @@ impl Region {
if !bands.is_empty() { if !bands.is_empty() {
let next_band = bands[0]; let next_band = bands[0];
handle_rectangle_between_bands( handle_rectangle_between_bands(&rectangle, band, next_band, &mut dst, top_inter_band);
&rectangle,
band,
next_band,
&mut dst,
top_inter_band,
);
} }
} }
@ -79,23 +73,17 @@ impl Region {
pub fn intersect_rectangle(&self, rectangle: &Rectangle) -> Self { pub fn intersect_rectangle(&self, rectangle: &Rectangle) -> Self {
match self.rectangles.len() { match self.rectangles.len() {
0 => Self::new(), 0 => Self::new(),
1 => self 1 => self.extents.intersect(rectangle).map(Self::from).unwrap_or_default(),
.extents
.intersect(rectangle)
.map(Self::from)
.unwrap_or_default(),
_ => { _ => {
let rectangles = self let rectangles = self
.rectangles .rectangles
.iter() .iter()
.take_while(|r| r.top < rectangle.bottom).filter_map(|r| r.intersect(rectangle)) .take_while(|r| r.top < rectangle.bottom)
.filter_map(|r| r.intersect(rectangle))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let extents = Rectangle::union_all(rectangles.as_slice()); let extents = Rectangle::union_all(rectangles.as_slice());
let mut region = Self { let mut region = Self { rectangles, extents };
rectangles,
extents,
};
region.simplify(); region.simplify();
region region
@ -126,19 +114,14 @@ impl Region {
< self.rectangles.len() < self.rectangles.len()
{ {
let current_band = get_current_band(&self.rectangles[current_band_start..]); let current_band = get_current_band(&self.rectangles[current_band_start..]);
let next_band = let next_band = get_current_band(&self.rectangles[current_band_start + current_band.len()..]);
get_current_band(&self.rectangles[current_band_start + current_band.len()..]);
if current_band[0].bottom == next_band[0].top if current_band[0].bottom == next_band[0].top && bands_internals_equal(current_band, next_band) {
&& bands_internals_equal(current_band, next_band)
{
let first_band_len = current_band.len(); let first_band_len = current_band.len();
let second_band_len = next_band.len(); let second_band_len = next_band.len();
let second_band_bottom = next_band[0].bottom; let second_band_bottom = next_band[0].bottom;
self.rectangles.drain( self.rectangles
current_band_start + first_band_len .drain(current_band_start + first_band_len..current_band_start + first_band_len + second_band_len);
..current_band_start + first_band_len + second_band_len,
);
self.rectangles self.rectangles
.iter_mut() .iter_mut()
.skip(current_band_start) .skip(current_band_start)
@ -166,11 +149,7 @@ impl From<Rectangle> for Region {
} }
} }
fn handle_rectangle_higher_relative_to_extents( fn handle_rectangle_higher_relative_to_extents(rectangle: &Rectangle, extents: &Rectangle, dst: &mut Vec<Rectangle>) {
rectangle: &Rectangle,
extents: &Rectangle,
dst: &mut Vec<Rectangle>,
) {
if rectangle.top < extents.top { if rectangle.top < extents.top {
dst.push(Rectangle { dst.push(Rectangle {
top: rectangle.top, top: rectangle.top,
@ -181,11 +160,7 @@ fn handle_rectangle_higher_relative_to_extents(
} }
} }
fn handle_rectangle_lower_relative_to_extents( fn handle_rectangle_lower_relative_to_extents(rectangle: &Rectangle, extents: &Rectangle, dst: &mut Vec<Rectangle>) {
rectangle: &Rectangle,
extents: &Rectangle,
dst: &mut Vec<Rectangle>,
) {
if extents.bottom < rectangle.bottom { if extents.bottom < rectangle.bottom {
dst.push(Rectangle { dst.push(Rectangle {
top: max(extents.bottom, rectangle.top), top: max(extents.bottom, rectangle.top),
@ -196,11 +171,7 @@ fn handle_rectangle_lower_relative_to_extents(
} }
} }
fn handle_rectangle_that_overlaps_band( fn handle_rectangle_that_overlaps_band(rectangle: &Rectangle, band: &[Rectangle], dst: &mut Vec<Rectangle>) {
rectangle: &Rectangle,
band: &[Rectangle],
dst: &mut Vec<Rectangle>,
) {
/* rect overlaps the band: /* rect overlaps the band:
| | | | | | | |
====^=================| |==| |=========================== band ====^=================| |==| |=========================== band
@ -273,10 +244,7 @@ fn handle_rectangle_between_bands(
let band_bottom = band[0].bottom; let band_bottom = band[0].bottom;
let next_band_top = next_band[0].top; let next_band_top = next_band[0].top;
if next_band_top != band_bottom if next_band_top != band_bottom && band_bottom < rectangle.bottom && rectangle.top < next_band_top {
&& band_bottom < rectangle.bottom
&& rectangle.top < next_band_top
{
dst.push(Rectangle { dst.push(Rectangle {
top: top_inter_band, top: top_inter_band,
bottom: min(next_band_top, rectangle.bottom), bottom: min(next_band_top, rectangle.bottom),
@ -348,10 +316,7 @@ fn copy_band_with_union(
right: r.right, right: r.right,
}) })
.take_while(|r| r.right < union_rectangle.left); .take_while(|r| r.right < union_rectangle.left);
let items_before_union_rectangle_len = items_before_union_rectangle let items_before_union_rectangle_len = items_before_union_rectangle.clone().map(|_| 1).sum::<usize>();
.clone()
.map(|_| 1)
.sum::<usize>();
dst.extend(items_before_union_rectangle); dst.extend(items_before_union_rectangle);
band = &band[items_before_union_rectangle_len..]; band = &band[items_before_union_rectangle_len..];
@ -420,9 +385,7 @@ fn bands_internals_equal(first_band: &[Rectangle], second_band: &[Rectangle]) ->
} }
for (first_band_rect, second_band_rect) in first_band.iter().zip(second_band.iter()) { for (first_band_rect, second_band_rect) in first_band.iter().zip(second_band.iter()) {
if first_band_rect.left != second_band_rect.left if first_band_rect.left != second_band_rect.left || first_band_rect.right != second_band_rect.right {
|| first_band_rect.right != second_band_rect.right
{
return false; return false;
} }
} }

View file

@ -434,8 +434,7 @@ fn union_rectangle_inserts_new_rectangle_in_band_of_3_rectangles_without_merging
} }
#[test] #[test]
fn union_rectangle_inserts_new_rectangle_in_band_of_3_rectangles_with_merging_with_side_rectangles() fn union_rectangle_inserts_new_rectangle_in_band_of_3_rectangles_with_merging_with_side_rectangles() {
{
let mut region = Region { let mut region = Region {
extents: Rectangle { extents: Rectangle {
left: 2, left: 2,
@ -499,8 +498,7 @@ fn union_rectangle_inserts_new_rectangle_in_band_of_3_rectangles_with_merging_wi
} }
#[test] #[test]
fn union_rectangle_inserts_new_rectangle_in_band_of_3_rectangles_with_merging_with_side_rectangles_on_board( fn union_rectangle_inserts_new_rectangle_in_band_of_3_rectangles_with_merging_with_side_rectangles_on_board() {
) {
let mut region = Region { let mut region = Region {
extents: Rectangle { extents: Rectangle {
left: 2, left: 2,

View file

@ -1,7 +1,8 @@
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
use std::{cmp::min, io}; use std::cmp::min;
use std::io;
use bitvec::field::BitField as _; use bitvec::field::BitField as _;
use bitvec::order::Msb0; use bitvec::order::Msb0;
@ -9,7 +10,8 @@ use bitvec::slice::BitSlice;
use failure::Fail; use failure::Fail;
use super::EntropyAlgorithm; use super::EntropyAlgorithm;
use crate::{impl_from_error, utils::Bits}; use crate::impl_from_error;
use crate::utils::Bits;
const KP_MAX: u32 = 80; const KP_MAX: u32 = 80;
const LS_GR: u32 = 3; const LS_GR: u32 = 3;
@ -40,11 +42,7 @@ macro_rules! try_split_bits {
}; };
} }
pub fn decode( pub fn decode(mode: EntropyAlgorithm, tile: &[u8], mut output: &mut [i16]) -> Result<(), RlgrError> {
mode: EntropyAlgorithm,
tile: &[u8],
mut output: &mut [i16],
) -> Result<(), RlgrError> {
let mut k: u32 = 1; let mut k: u32 = 1;
let mut kr: u32 = 1; let mut kr: u32 = 1;
let mut kp: u32 = k << LS_GR; let mut kp: u32 = k << LS_GR;
@ -60,16 +58,14 @@ pub fn decode(
CompressionMode::RunLength => { CompressionMode::RunLength => {
let number_of_zeros = truncate_leading_value(&mut bits, false); let number_of_zeros = truncate_leading_value(&mut bits, false);
try_split_bits!(bits, 1); try_split_bits!(bits, 1);
let run = count_run(number_of_zeros, &mut k, &mut kp) let run = count_run(number_of_zeros, &mut k, &mut kp) + load_be_u32(try_split_bits!(bits, k as usize));
+ load_be_u32(try_split_bits!(bits, k as usize));
let sign_bit = try_split_bits!(bits, 1).load_be::<u8>(); let sign_bit = try_split_bits!(bits, 1).load_be::<u8>();
let number_of_ones = truncate_leading_value(&mut bits, true); let number_of_ones = truncate_leading_value(&mut bits, true);
try_split_bits!(bits, 1); try_split_bits!(bits, 1);
let code_remainder = load_be_u32(try_split_bits!(bits, kr as usize)) let code_remainder = load_be_u32(try_split_bits!(bits, kr as usize)) + ((number_of_ones as u32) << kr);
+ ((number_of_ones as u32) << kr);
update_parameters_according_to_number_of_ones(number_of_ones, &mut kr, &mut krp); update_parameters_according_to_number_of_ones(number_of_ones, &mut kr, &mut krp);
kp = kp.saturating_sub(DN_GR); kp = kp.saturating_sub(DN_GR);
@ -86,8 +82,7 @@ pub fn decode(
let number_of_ones = truncate_leading_value(&mut bits, true); let number_of_ones = truncate_leading_value(&mut bits, true);
try_split_bits!(bits, 1); try_split_bits!(bits, 1);
let code_remainder = load_be_u32(try_split_bits!(bits, kr as usize)) let code_remainder = load_be_u32(try_split_bits!(bits, kr as usize)) + ((number_of_ones as u32) << kr);
+ ((number_of_ones as u32) << kr);
update_parameters_according_to_number_of_ones(number_of_ones, &mut kr, &mut krp); update_parameters_according_to_number_of_ones(number_of_ones, &mut kr, &mut krp);
@ -209,11 +204,7 @@ fn compute_n_index(code_remainder: u32) -> usize {
32 - leading_zeros 32 - leading_zeros
} }
fn update_parameters_according_to_number_of_ones( fn update_parameters_according_to_number_of_ones(number_of_ones: usize, kr: &mut u32, krp: &mut u32) {
number_of_ones: usize,
kr: &mut u32,
krp: &mut u32,
) {
if number_of_ones == 0 { if number_of_ones == 0 {
*krp = (*krp).saturating_sub(2); *krp = (*krp).saturating_sub(2);
*kr = *krp >> LS_GR; *kr = *krp >> LS_GR;

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,7 @@
use lazy_static::lazy_static; use lazy_static::lazy_static;
use super::{data_messages::*, header_messages::*}; use super::data_messages::*;
use super::header_messages::*;
use crate::PduBufferParsing; use crate::PduBufferParsing;
const SYNC_PDU_BUFFER: [u8; 12] = [ const SYNC_PDU_BUFFER: [u8; 12] = [
@ -233,14 +234,8 @@ const FRAME_END_PDU: FrameEndPdu = FrameEndPdu;
lazy_static! { lazy_static! {
static ref CHANNELS_PDU: ChannelsPdu = ChannelsPdu(vec![ static ref CHANNELS_PDU: ChannelsPdu = ChannelsPdu(vec![
Channel { Channel { width: 64, height: 64 },
width: 64, Channel { width: 32, height: 32 }
height: 64,
},
Channel {
width: 32,
height: 32,
}
]); ]);
static ref REGION_PDU: RegionPdu = RegionPdu { static ref REGION_PDU: RegionPdu = RegionPdu {
rectangles: vec![ rectangles: vec![
@ -321,10 +316,7 @@ fn from_buffer_for_pdu_with_codec_channel_header_returns_error_on_small_buffer()
#[test] #[test]
fn from_buffer_correctly_parses_sync_pdu() { fn from_buffer_correctly_parses_sync_pdu() {
assert_eq!( assert_eq!(SYNC_PDU, SyncPdu::from_buffer(SYNC_PDU_BUFFER.as_ref()).unwrap());
SYNC_PDU,
SyncPdu::from_buffer(SYNC_PDU_BUFFER.as_ref()).unwrap()
);
} }
#[test] #[test]
@ -332,9 +324,7 @@ fn to_buffer_correctly_serializes_sync_pdu() {
let expected = SYNC_PDU_BUFFER.as_ref(); let expected = SYNC_PDU_BUFFER.as_ref();
let mut buffer = vec![0; expected.len()]; let mut buffer = vec![0; expected.len()];
SYNC_PDU SYNC_PDU.to_buffer_consume(&mut buffer.as_mut_slice()).unwrap();
.to_buffer_consume(&mut buffer.as_mut_slice())
.unwrap();
assert_eq!(expected, buffer.as_slice()); assert_eq!(expected, buffer.as_slice());
} }
@ -364,10 +354,7 @@ fn to_buffer_correctly_serializes_codec_versions_pdu() {
#[test] #[test]
fn buffer_length_is_correct_for_codec_versions_pdu() { fn buffer_length_is_correct_for_codec_versions_pdu() {
assert_eq!( assert_eq!(CODEC_VERSIONS_PDU_BUFFER.len(), CODEC_VERSIONS_PDU.buffer_length());
CODEC_VERSIONS_PDU_BUFFER.len(),
CODEC_VERSIONS_PDU.buffer_length()
);
} }
#[test] #[test]
@ -383,17 +370,13 @@ fn to_buffer_correctly_serializes_channels_pdu() {
let expected = CHANNELS_PDU_BUFFER.as_ref(); let expected = CHANNELS_PDU_BUFFER.as_ref();
let mut buffer = vec![0; expected.len()]; let mut buffer = vec![0; expected.len()];
CHANNELS_PDU CHANNELS_PDU.to_buffer_consume(&mut buffer.as_mut_slice()).unwrap();
.to_buffer_consume(&mut buffer.as_mut_slice())
.unwrap();
assert_eq!(expected, buffer.as_slice()); assert_eq!(expected, buffer.as_slice());
} }
#[test] #[test]
fn from_buffer_returns_error_on_invalid_data_length_for_channels_pdu() { fn from_buffer_returns_error_on_invalid_data_length_for_channels_pdu() {
assert!( assert!(ChannelsPdu::from_buffer(CHANNELS_PDU_BUFFER_WITH_INVALID_DATA_LENGTH.as_ref()).is_err());
ChannelsPdu::from_buffer(CHANNELS_PDU_BUFFER_WITH_INVALID_DATA_LENGTH.as_ref()).is_err()
);
} }
#[test] #[test]
@ -424,9 +407,7 @@ fn to_buffer_correctly_serializes_context_pdu() {
let expected = CONTEXT_PDU_BUFFER.as_ref(); let expected = CONTEXT_PDU_BUFFER.as_ref();
let mut buffer = vec![0; expected.len()]; let mut buffer = vec![0; expected.len()];
CONTEXT_PDU CONTEXT_PDU.to_buffer_consume(&mut buffer.as_mut_slice()).unwrap();
.to_buffer_consume(&mut buffer.as_mut_slice())
.unwrap();
assert_eq!(expected, buffer.as_slice()); assert_eq!(expected, buffer.as_slice());
} }
@ -448,18 +429,13 @@ fn to_buffer_correctly_serializes_frame_begin_pdu() {
let expected = FRAME_BEGIN_PDU_BUFFER.as_ref(); let expected = FRAME_BEGIN_PDU_BUFFER.as_ref();
let mut buffer = vec![0; expected.len()]; let mut buffer = vec![0; expected.len()];
FRAME_BEGIN_PDU FRAME_BEGIN_PDU.to_buffer_consume(&mut buffer.as_mut_slice()).unwrap();
.to_buffer_consume(&mut buffer.as_mut_slice())
.unwrap();
assert_eq!(expected, buffer.as_slice()); assert_eq!(expected, buffer.as_slice());
} }
#[test] #[test]
fn buffer_length_is_correct_for_frame_begin_pdu() { fn buffer_length_is_correct_for_frame_begin_pdu() {
assert_eq!( assert_eq!(FRAME_BEGIN_PDU_BUFFER.len(), FRAME_BEGIN_PDU.buffer_length());
FRAME_BEGIN_PDU_BUFFER.len(),
FRAME_BEGIN_PDU.buffer_length()
);
} }
#[test] #[test]
@ -475,9 +451,7 @@ fn to_buffer_correctly_serializes_frame_end_pdu() {
let expected = FRAME_END_PDU_BUFFER.as_ref(); let expected = FRAME_END_PDU_BUFFER.as_ref();
let mut buffer = vec![0; expected.len()]; let mut buffer = vec![0; expected.len()];
FRAME_END_PDU FRAME_END_PDU.to_buffer_consume(&mut buffer.as_mut_slice()).unwrap();
.to_buffer_consume(&mut buffer.as_mut_slice())
.unwrap();
assert_eq!(expected, buffer.as_slice()); assert_eq!(expected, buffer.as_slice());
} }
@ -488,10 +462,7 @@ fn buffer_length_is_correct_for_frame_end_pdu() {
#[test] #[test]
fn from_buffer_correctly_parses_region_pdu() { fn from_buffer_correctly_parses_region_pdu() {
assert_eq!( assert_eq!(*REGION_PDU, RegionPdu::from_buffer(REGION_PDU_BUFFER.as_ref()).unwrap());
*REGION_PDU,
RegionPdu::from_buffer(REGION_PDU_BUFFER.as_ref()).unwrap()
);
} }
#[test] #[test]
@ -499,9 +470,7 @@ fn to_buffer_correctly_serializes_region_pdu() {
let expected = REGION_PDU_BUFFER.as_ref(); let expected = REGION_PDU_BUFFER.as_ref();
let mut buffer = vec![0; expected.len()]; let mut buffer = vec![0; expected.len()];
REGION_PDU REGION_PDU.to_buffer_consume(&mut buffer.as_mut_slice()).unwrap();
.to_buffer_consume(&mut buffer.as_mut_slice())
.unwrap();
assert_eq!(expected, buffer.as_slice()); assert_eq!(expected, buffer.as_slice());
} }
@ -512,18 +481,12 @@ fn buffer_length_is_correct_for_region_pdu() {
#[test] #[test]
fn from_buffer_returns_error_on_invalid_number_of_quants_for_tile_set_pdu() { fn from_buffer_returns_error_on_invalid_number_of_quants_for_tile_set_pdu() {
assert!(TileSetPdu::from_buffer_consume( assert!(TileSetPdu::from_buffer_consume(&mut TILESET_PDU_BUFFER_WITH_INVALID_NUMBER_OF_QUANTS.as_ref()).is_err());
&mut TILESET_PDU_BUFFER_WITH_INVALID_NUMBER_OF_QUANTS.as_ref()
)
.is_err());
} }
#[test] #[test]
fn from_buffer_returns_error_on_invalid_tiles_data_size_for_tile_set_pdu() { fn from_buffer_returns_error_on_invalid_tiles_data_size_for_tile_set_pdu() {
assert!(TileSetPdu::from_buffer_consume( assert!(TileSetPdu::from_buffer_consume(&mut TILESET_PDU_BUFFER_WITH_INVALID_TILES_DATA_SIZE.as_ref()).is_err());
&mut TILESET_PDU_BUFFER_WITH_INVALID_TILES_DATA_SIZE.as_ref()
)
.is_err());
} }
#[test] #[test]
@ -539,9 +502,7 @@ fn to_buffer_correctly_serializes_tile_set_pdu() {
let expected = TILESET_PDU_BUFFER.as_ref(); let expected = TILESET_PDU_BUFFER.as_ref();
let mut buffer = vec![0; expected.len()]; let mut buffer = vec![0; expected.len()];
TILESET_PDU TILESET_PDU.to_buffer_consume(&mut buffer.as_mut_slice()).unwrap();
.to_buffer_consume(&mut buffer.as_mut_slice())
.unwrap();
assert_eq!(expected, buffer.as_slice()); assert_eq!(expected, buffer.as_slice());
} }

View file

@ -11,39 +11,6 @@ mod multi_transport_channel_data;
mod network_data; mod network_data;
mod security_data; mod security_data;
pub use self::{
cluster_data::{ClientClusterData, ClusterDataError, RedirectionFlags, RedirectionVersion},
conference_create::{ConferenceCreateRequest, ConferenceCreateResponse},
core_data::{
client::{
ClientColorDepth, ClientCoreData, ClientCoreOptionalData, ClientEarlyCapabilityFlags,
ColorDepth, ConnectionType, HighColorDepth, KeyboardType, SecureAccessSequence,
SupportedColorDepths, IME_FILE_NAME_SIZE,
},
server::{ServerCoreData, ServerCoreOptionalData, ServerEarlyCapabilityFlags},
CoreDataError, RdpVersion,
},
message_channel_data::{ClientMessageChannelData, ServerMessageChannelData},
monitor_data::{
ClientMonitorData, Monitor, MonitorDataError, MonitorFlags, MONITOR_COUNT_SIZE,
MONITOR_FLAGS_SIZE, MONITOR_SIZE,
},
monitor_extended_data::{
ClientMonitorExtendedData, ExtendedMonitorInfo, MonitorExtendedDataError,
MonitorOrientation,
},
multi_transport_channel_data::{
MultiTransportChannelData, MultiTransportChannelDataError, MultiTransportFlags,
},
network_data::{
Channel, ChannelOptions, ClientNetworkData, NetworkDataError, ServerNetworkData,
},
security_data::{
ClientSecurityData, EncryptionLevel, EncryptionMethod, SecurityDataError,
ServerSecurityData,
},
};
use std::io; use std::io;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
@ -51,6 +18,28 @@ use failure::Fail;
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
pub use self::cluster_data::{ClientClusterData, ClusterDataError, RedirectionFlags, RedirectionVersion};
pub use self::conference_create::{ConferenceCreateRequest, ConferenceCreateResponse};
pub use self::core_data::client::{
ClientColorDepth, ClientCoreData, ClientCoreOptionalData, ClientEarlyCapabilityFlags, ColorDepth, ConnectionType,
HighColorDepth, KeyboardType, SecureAccessSequence, SupportedColorDepths, IME_FILE_NAME_SIZE,
};
pub use self::core_data::server::{ServerCoreData, ServerCoreOptionalData, ServerEarlyCapabilityFlags};
pub use self::core_data::{CoreDataError, RdpVersion};
pub use self::message_channel_data::{ClientMessageChannelData, ServerMessageChannelData};
pub use self::monitor_data::{
ClientMonitorData, Monitor, MonitorDataError, MonitorFlags, MONITOR_COUNT_SIZE, MONITOR_FLAGS_SIZE, MONITOR_SIZE,
};
pub use self::monitor_extended_data::{
ClientMonitorExtendedData, ExtendedMonitorInfo, MonitorExtendedDataError, MonitorOrientation,
};
pub use self::multi_transport_channel_data::{
MultiTransportChannelData, MultiTransportChannelDataError, MultiTransportFlags,
};
pub use self::network_data::{Channel, ChannelOptions, ClientNetworkData, NetworkDataError, ServerNetworkData};
pub use self::security_data::{
ClientSecurityData, EncryptionLevel, EncryptionMethod, SecurityDataError, ServerSecurityData,
};
use crate::{impl_from_error, PduParsing}; use crate::{impl_from_error, PduParsing};
macro_rules! user_header_try { macro_rules! user_header_try {
@ -103,34 +92,21 @@ impl PduParsing for ClientGccBlocks {
let mut monitor_extended = None; let mut monitor_extended = None;
loop { loop {
let user_header = let user_header = user_header_try!(UserDataHeader::<ClientGccType>::from_buffer(&mut buffer));
user_header_try!(UserDataHeader::<ClientGccType>::from_buffer(&mut buffer));
match user_header.block_type { match user_header.block_type {
ClientGccType::CoreData => { ClientGccType::CoreData => core = Some(ClientCoreData::from_buffer(user_header.block_data.as_slice())?),
core = Some(ClientCoreData::from_buffer(
user_header.block_data.as_slice(),
)?)
}
ClientGccType::SecurityData => { ClientGccType::SecurityData => {
security = Some(ClientSecurityData::from_buffer( security = Some(ClientSecurityData::from_buffer(user_header.block_data.as_slice())?)
user_header.block_data.as_slice(),
)?)
} }
ClientGccType::NetworkData => { ClientGccType::NetworkData => {
network = Some(ClientNetworkData::from_buffer( network = Some(ClientNetworkData::from_buffer(user_header.block_data.as_slice())?)
user_header.block_data.as_slice(),
)?)
} }
ClientGccType::ClusterData => { ClientGccType::ClusterData => {
cluster = Some(ClientClusterData::from_buffer( cluster = Some(ClientClusterData::from_buffer(user_header.block_data.as_slice())?)
user_header.block_data.as_slice(),
)?)
} }
ClientGccType::MonitorData => { ClientGccType::MonitorData => {
monitor = Some(ClientMonitorData::from_buffer( monitor = Some(ClientMonitorData::from_buffer(user_header.block_data.as_slice())?)
user_header.block_data.as_slice(),
)?)
} }
ClientGccType::MessageChannelData => { ClientGccType::MessageChannelData => {
message_channel = Some(ClientMessageChannelData::from_buffer( message_channel = Some(ClientMessageChannelData::from_buffer(
@ -151,12 +127,8 @@ impl PduParsing for ClientGccBlocks {
} }
Ok(Self { Ok(Self {
core: core.ok_or(GccError::RequiredClientDataBlockIsAbsent( core: core.ok_or(GccError::RequiredClientDataBlockIsAbsent(ClientGccType::CoreData))?,
ClientGccType::CoreData, security: security.ok_or(GccError::RequiredClientDataBlockIsAbsent(ClientGccType::SecurityData))?,
))?,
security: security.ok_or(GccError::RequiredClientDataBlockIsAbsent(
ClientGccType::SecurityData,
))?,
network, network,
cluster, cluster,
monitor, monitor,
@ -167,33 +139,25 @@ impl PduParsing for ClientGccBlocks {
} }
fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> {
UserDataHeader::from_gcc_block(ClientGccType::CoreData, &self.core)? UserDataHeader::from_gcc_block(ClientGccType::CoreData, &self.core)?.to_buffer(&mut buffer)?;
.to_buffer(&mut buffer)?; UserDataHeader::from_gcc_block(ClientGccType::SecurityData, &self.security)?.to_buffer(&mut buffer)?;
UserDataHeader::from_gcc_block(ClientGccType::SecurityData, &self.security)?
.to_buffer(&mut buffer)?;
if let Some(ref network) = self.network { if let Some(ref network) = self.network {
UserDataHeader::from_gcc_block(ClientGccType::NetworkData, network)? UserDataHeader::from_gcc_block(ClientGccType::NetworkData, network)?.to_buffer(&mut buffer)?;
.to_buffer(&mut buffer)?;
} }
if let Some(ref cluster) = self.cluster { if let Some(ref cluster) = self.cluster {
UserDataHeader::from_gcc_block(ClientGccType::ClusterData, cluster)? UserDataHeader::from_gcc_block(ClientGccType::ClusterData, cluster)?.to_buffer(&mut buffer)?;
.to_buffer(&mut buffer)?;
} }
if let Some(ref monitor) = self.monitor { if let Some(ref monitor) = self.monitor {
UserDataHeader::from_gcc_block(ClientGccType::MonitorData, monitor)? UserDataHeader::from_gcc_block(ClientGccType::MonitorData, monitor)?.to_buffer(&mut buffer)?;
.to_buffer(&mut buffer)?;
} }
if let Some(ref message_channel) = self.message_channel { if let Some(ref message_channel) = self.message_channel {
UserDataHeader::from_gcc_block(ClientGccType::MessageChannelData, message_channel)? UserDataHeader::from_gcc_block(ClientGccType::MessageChannelData, message_channel)?
.to_buffer(&mut buffer)?; .to_buffer(&mut buffer)?;
} }
if let Some(ref multi_transport_channel) = self.multi_transport_channel { if let Some(ref multi_transport_channel) = self.multi_transport_channel {
UserDataHeader::from_gcc_block( UserDataHeader::from_gcc_block(ClientGccType::MultiTransportChannelData, multi_transport_channel)?
ClientGccType::MultiTransportChannelData, .to_buffer(&mut buffer)?;
multi_transport_channel,
)?
.to_buffer(&mut buffer)?;
} }
if let Some(ref monitor_extended) = self.monitor_extended { if let Some(ref monitor_extended) = self.monitor_extended {
UserDataHeader::from_gcc_block(ClientGccType::MonitorExtendedData, monitor_extended)? UserDataHeader::from_gcc_block(ClientGccType::MonitorExtendedData, monitor_extended)?
@ -204,8 +168,7 @@ impl PduParsing for ClientGccBlocks {
} }
fn buffer_length(&self) -> usize { fn buffer_length(&self) -> usize {
let mut size = let mut size = self.core.buffer_length() + self.security.buffer_length() + USER_DATA_HEADER_SIZE * 2;
self.core.buffer_length() + self.security.buffer_length() + USER_DATA_HEADER_SIZE * 2;
if let Some(ref network) = self.network { if let Some(ref network) = self.network {
size += network.buffer_length() + USER_DATA_HEADER_SIZE; size += network.buffer_length() + USER_DATA_HEADER_SIZE;
@ -259,24 +222,15 @@ impl PduParsing for ServerGccBlocks {
let mut multi_transport_channel = None; let mut multi_transport_channel = None;
loop { loop {
let user_header = let user_header = user_header_try!(UserDataHeader::<ServerGccType>::from_buffer(&mut buffer));
user_header_try!(UserDataHeader::<ServerGccType>::from_buffer(&mut buffer));
match user_header.block_type { match user_header.block_type {
ServerGccType::CoreData => { ServerGccType::CoreData => core = Some(ServerCoreData::from_buffer(user_header.block_data.as_slice())?),
core = Some(ServerCoreData::from_buffer(
user_header.block_data.as_slice(),
)?)
}
ServerGccType::NetworkData => { ServerGccType::NetworkData => {
network = Some(ServerNetworkData::from_buffer( network = Some(ServerNetworkData::from_buffer(user_header.block_data.as_slice())?)
user_header.block_data.as_slice(),
)?)
} }
ServerGccType::SecurityData => { ServerGccType::SecurityData => {
security = Some(ServerSecurityData::from_buffer( security = Some(ServerSecurityData::from_buffer(user_header.block_data.as_slice())?)
user_header.block_data.as_slice(),
)?)
} }
ServerGccType::MessageChannelData => { ServerGccType::MessageChannelData => {
message_channel = Some(ServerMessageChannelData::from_buffer( message_channel = Some(ServerMessageChannelData::from_buffer(
@ -292,38 +246,26 @@ impl PduParsing for ServerGccBlocks {
} }
Ok(Self { Ok(Self {
core: core.ok_or(GccError::RequiredServerDataBlockIsAbsent( core: core.ok_or(GccError::RequiredServerDataBlockIsAbsent(ServerGccType::CoreData))?,
ServerGccType::CoreData, network: network.ok_or(GccError::RequiredServerDataBlockIsAbsent(ServerGccType::NetworkData))?,
))?, security: security.ok_or(GccError::RequiredServerDataBlockIsAbsent(ServerGccType::SecurityData))?,
network: network.ok_or(GccError::RequiredServerDataBlockIsAbsent(
ServerGccType::NetworkData,
))?,
security: security.ok_or(GccError::RequiredServerDataBlockIsAbsent(
ServerGccType::SecurityData,
))?,
message_channel, message_channel,
multi_transport_channel, multi_transport_channel,
}) })
} }
fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> {
UserDataHeader::from_gcc_block(ServerGccType::CoreData, &self.core)? UserDataHeader::from_gcc_block(ServerGccType::CoreData, &self.core)?.to_buffer(&mut buffer)?;
.to_buffer(&mut buffer)?; UserDataHeader::from_gcc_block(ServerGccType::NetworkData, &self.network)?.to_buffer(&mut buffer)?;
UserDataHeader::from_gcc_block(ServerGccType::NetworkData, &self.network)? UserDataHeader::from_gcc_block(ServerGccType::SecurityData, &self.security)?.to_buffer(&mut buffer)?;
.to_buffer(&mut buffer)?;
UserDataHeader::from_gcc_block(ServerGccType::SecurityData, &self.security)?
.to_buffer(&mut buffer)?;
if let Some(ref message_channel) = self.message_channel { if let Some(ref message_channel) = self.message_channel {
UserDataHeader::from_gcc_block(ServerGccType::MessageChannelData, message_channel)? UserDataHeader::from_gcc_block(ServerGccType::MessageChannelData, message_channel)?
.to_buffer(&mut buffer)?; .to_buffer(&mut buffer)?;
} }
if let Some(ref multi_transport_channel) = self.multi_transport_channel { if let Some(ref multi_transport_channel) = self.multi_transport_channel {
UserDataHeader::from_gcc_block( UserDataHeader::from_gcc_block(ServerGccType::MultiTransportChannelData, multi_transport_channel)?
ServerGccType::MultiTransportChannelData, .to_buffer(&mut buffer)?;
multi_transport_channel,
)?
.to_buffer(&mut buffer)?;
} }
Ok(()) Ok(())
@ -383,10 +325,7 @@ impl<T: FromPrimitive + ToPrimitive> UserDataHeader<T> {
let mut block_data = Vec::with_capacity(gcc_block.buffer_length()); let mut block_data = Vec::with_capacity(gcc_block.buffer_length());
gcc_block.to_buffer(&mut block_data)?; gcc_block.to_buffer(&mut block_data)?;
Ok(Self { Ok(Self { block_type, block_data })
block_type,
block_data,
})
} }
fn block_length(&self) -> usize { fn block_length(&self) -> usize {
@ -398,8 +337,7 @@ impl<T: FromPrimitive + ToPrimitive> PduParsing for UserDataHeader<T> {
type Error = GccError; type Error = GccError;
fn from_buffer(mut buffer: impl io::Read) -> Result<Self, Self::Error> { fn from_buffer(mut buffer: impl io::Read) -> Result<Self, Self::Error> {
let block_type = let block_type = T::from_u16(buffer.read_u16::<LittleEndian>()?).ok_or(GccError::InvalidGccType)?;
T::from_u16(buffer.read_u16::<LittleEndian>()?).ok_or(GccError::InvalidGccType)?;
let block_length = buffer.read_u16::<LittleEndian>()?; let block_length = buffer.read_u16::<LittleEndian>()?;
if block_length <= USER_DATA_HEADER_SIZE as u16 { if block_length <= USER_DATA_HEADER_SIZE as u16 {
@ -412,10 +350,7 @@ impl<T: FromPrimitive + ToPrimitive> PduParsing for UserDataHeader<T> {
let mut block_data = vec![0; block_length as usize - USER_DATA_HEADER_SIZE]; let mut block_data = vec![0; block_length as usize - USER_DATA_HEADER_SIZE];
buffer.read_exact(&mut block_data)?; buffer.read_exact(&mut block_data)?;
Ok(Self { Ok(Self { block_type, block_data })
block_type,
block_data,
})
} }
fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> {
@ -455,15 +390,9 @@ pub enum GccError {
InvalidConferenceCreateRequest(String), InvalidConferenceCreateRequest(String),
#[fail(display = "Invalid Conference create response: {}", _0)] #[fail(display = "Invalid Conference create response: {}", _0)]
InvalidConferenceCreateResponse(String), InvalidConferenceCreateResponse(String),
#[fail( #[fail(display = "A server did not send the required GCC data block: {:?}", _0)]
display = "A server did not send the required GCC data block: {:?}",
_0
)]
RequiredClientDataBlockIsAbsent(ClientGccType), RequiredClientDataBlockIsAbsent(ClientGccType),
#[fail( #[fail(display = "A client did not send the required GCC data block: {:?}", _0)]
display = "A client did not send the required GCC data block: {:?}",
_0
)]
RequiredServerDataBlockIsAbsent(ServerGccType), RequiredServerDataBlockIsAbsent(ServerGccType),
} }
@ -478,8 +407,4 @@ impl_from_error!(
GccError, GccError,
GccError::MultiTransportChannelError GccError::MultiTransportChannelError
); );
impl_from_error!( impl_from_error!(MonitorExtendedDataError, GccError, GccError::MonitorExtendedError);
MonitorExtendedDataError,
GccError,
GccError::MonitorExtendedError
);

View file

@ -32,10 +32,9 @@ impl PduParsing for ClientClusterData {
let flags = RedirectionFlags::from_bits(flags_with_version & !REDIRECTION_VERSION_MASK) let flags = RedirectionFlags::from_bits(flags_with_version & !REDIRECTION_VERSION_MASK)
.ok_or(ClusterDataError::InvalidRedirectionFlags)?; .ok_or(ClusterDataError::InvalidRedirectionFlags)?;
let redirection_version = RedirectionVersion::from_u8( let redirection_version =
((flags_with_version & REDIRECTION_VERSION_MASK) >> 2) as u8, RedirectionVersion::from_u8(((flags_with_version & REDIRECTION_VERSION_MASK) >> 2) as u8)
) .ok_or(ClusterDataError::InvalidRedirectionFlags)?;
.ok_or(ClusterDataError::InvalidRedirectionFlags)?;
Ok(Self { Ok(Self {
flags, flags,
@ -45,8 +44,7 @@ impl PduParsing for ClientClusterData {
} }
fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> {
let flags_with_version = let flags_with_version = self.flags.bits() | (self.redirection_version.to_u32().unwrap() << 2);
self.flags.bits() | (self.redirection_version.to_u32().unwrap() << 2);
buffer.write_u32::<LittleEndian>(flags_with_version)?; buffer.write_u32::<LittleEndian>(flags_with_version)?;
buffer.write_u32::<LittleEndian>(self.redirected_session_id)?; buffer.write_u32::<LittleEndian>(self.redirected_session_id)?;

View file

@ -16,10 +16,7 @@ lazy_static! {
fn from_buffer_correctly_parses_client_cluster_data() { fn from_buffer_correctly_parses_client_cluster_data() {
let buffer = CLUSTER_DATA_BUFFER.as_ref(); let buffer = CLUSTER_DATA_BUFFER.as_ref();
assert_eq!( assert_eq!(*CLUSTER_DATA, ClientClusterData::from_buffer(buffer).unwrap());
*CLUSTER_DATA,
ClientClusterData::from_buffer(buffer).unwrap()
);
} }
#[test] #[test]

View file

@ -210,10 +210,7 @@ impl PduParsing for ConferenceCreateResponse {
let (_gcc_blocks_buffer_length, _) = per::read_length(&mut stream)?; let (_gcc_blocks_buffer_length, _) = per::read_length(&mut stream)?;
let gcc_blocks = ServerGccBlocks::from_buffer(&mut stream)?; let gcc_blocks = ServerGccBlocks::from_buffer(&mut stream)?;
Ok(Self { Ok(Self { user_id, gcc_blocks })
user_id,
gcc_blocks,
})
} }
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {

View file

@ -4,23 +4,22 @@ use super::*;
use crate::gcc; use crate::gcc;
const CONFERENCE_CREATE_REQUEST_PREFIX_BUFFER: [u8; 23] = [ const CONFERENCE_CREATE_REQUEST_PREFIX_BUFFER: [u8; 23] = [
0x00, 0x05, 0x00, 0x14, 0x7c, 0x00, 0x01, 0x81, 0x28, 0x00, 0x08, 0x00, 0x10, 0x00, 0x01, 0xc0, 0x00, 0x05, 0x00, 0x14, 0x7c, 0x00, 0x01, 0x81, 0x28, 0x00, 0x08, 0x00, 0x10, 0x00, 0x01, 0xc0, 0x00, 0x44, 0x75,
0x00, 0x44, 0x75, 0x63, 0x61, 0x81, 0x1c, 0x63, 0x61, 0x81, 0x1c,
]; ];
const CONFERENCE_CREATE_RESPONSE_PREFIX_BUFFER: [u8; 24] = [ const CONFERENCE_CREATE_RESPONSE_PREFIX_BUFFER: [u8; 24] = [
0x00, 0x05, 0x00, 0x14, 0x7c, 0x00, 0x01, 0x81, 0x15, 0x14, 0x76, 0x0a, 0x01, 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x14, 0x7c, 0x00, 0x01, 0x81, 0x15, 0x14, 0x76, 0x0a, 0x01, 0x01, 0x00, 0x01, 0xc0, 0x00, 0x4d,
0xc0, 0x00, 0x4d, 0x63, 0x44, 0x6e, 0x81, 0x08, 0x63, 0x44, 0x6e, 0x81, 0x08,
]; ];
lazy_static! { lazy_static! {
pub static ref CONFERENCE_CREATE_REQUEST: ConferenceCreateRequest = ConferenceCreateRequest { pub static ref CONFERENCE_CREATE_REQUEST: ConferenceCreateRequest = ConferenceCreateRequest {
gcc_blocks: gcc::test::CLIENT_GCC_WITH_CLUSTER_OPTIONAL_FIELD.clone(), gcc_blocks: gcc::test::CLIENT_GCC_WITH_CLUSTER_OPTIONAL_FIELD.clone(),
}; };
pub static ref CONFERENCE_CREATE_RESPONSE: ConferenceCreateResponse = pub static ref CONFERENCE_CREATE_RESPONSE: ConferenceCreateResponse = ConferenceCreateResponse {
ConferenceCreateResponse { user_id: 0x79f3,
user_id: 0x79f3, gcc_blocks: gcc::test::SERVER_GCC_WITHOUT_OPTIONAL_FIELDS.clone(),
gcc_blocks: gcc::test::SERVER_GCC_WITHOUT_OPTIONAL_FIELDS.clone(), };
};
pub static ref CONFERENCE_CREATE_REQUEST_BUFFER: Vec<u8> = { pub static ref CONFERENCE_CREATE_REQUEST_BUFFER: Vec<u8> = {
let mut buffer = CONFERENCE_CREATE_REQUEST_PREFIX_BUFFER.to_vec(); let mut buffer = CONFERENCE_CREATE_REQUEST_PREFIX_BUFFER.to_vec();
buffer.extend(gcc::test::CLIENT_GCC_WITH_CLUSTER_OPTIONAL_FIELD_BUFFER.as_slice()); buffer.extend(gcc::test::CLIENT_GCC_WITH_CLUSTER_OPTIONAL_FIELD_BUFFER.as_slice());

View file

@ -61,8 +61,7 @@ impl ClientCoreData {
pub fn client_color_depth(&self) -> ClientColorDepth { pub fn client_color_depth(&self) -> ClientColorDepth {
if let Some(high_color_depth) = self.optional_data.high_color_depth { if let Some(high_color_depth) = self.optional_data.high_color_depth {
if let Some(early_capability_flags) = self.optional_data.early_capability_flags { if let Some(early_capability_flags) = self.optional_data.early_capability_flags {
if early_capability_flags.contains(ClientEarlyCapabilityFlags::WANT_32_BPP_SESSION) if early_capability_flags.contains(ClientEarlyCapabilityFlags::WANT_32_BPP_SESSION) {
{
ClientColorDepth::Bpp32 ClientColorDepth::Bpp32
} else { } else {
From::from(high_color_depth) From::from(high_color_depth)
@ -82,15 +81,13 @@ impl PduParsing for ClientCoreData {
type Error = CoreDataError; type Error = CoreDataError;
fn from_buffer(mut buffer: impl io::Read) -> Result<Self, Self::Error> { fn from_buffer(mut buffer: impl io::Read) -> Result<Self, Self::Error> {
let version = RdpVersion::from_u32(buffer.read_u32::<LittleEndian>()?) let version = RdpVersion::from_u32(buffer.read_u32::<LittleEndian>()?).unwrap_or(RdpVersion::VUnknown);
.unwrap_or(RdpVersion::VUnknown);
let desktop_width = buffer.read_u16::<LittleEndian>()?; let desktop_width = buffer.read_u16::<LittleEndian>()?;
let desktop_height = buffer.read_u16::<LittleEndian>()?; let desktop_height = buffer.read_u16::<LittleEndian>()?;
let color_depth = ColorDepth::from_u16(buffer.read_u16::<LittleEndian>()?) let color_depth =
.ok_or(CoreDataError::InvalidColorDepth)?; ColorDepth::from_u16(buffer.read_u16::<LittleEndian>()?).ok_or(CoreDataError::InvalidColorDepth)?;
let sec_access_sequence = let sec_access_sequence = SecureAccessSequence::from_u16(buffer.read_u16::<LittleEndian>()?)
SecureAccessSequence::from_u16(buffer.read_u16::<LittleEndian>()?) .ok_or(CoreDataError::InvalidSecureAccessSequence)?;
.ok_or(CoreDataError::InvalidSecureAccessSequence)?;
let keyboard_layout = buffer.read_u32::<LittleEndian>()?; let keyboard_layout = buffer.read_u32::<LittleEndian>()?;
let client_build = buffer.read_u32::<LittleEndian>()?; let client_build = buffer.read_u32::<LittleEndian>()?;
@ -100,8 +97,8 @@ impl PduParsing for ClientCoreData {
.trim_end_matches('\u{0}') .trim_end_matches('\u{0}')
.into(); .into();
let keyboard_type = KeyboardType::from_u32(buffer.read_u32::<LittleEndian>()?) let keyboard_type =
.ok_or(CoreDataError::InvalidKeyboardType)?; KeyboardType::from_u32(buffer.read_u32::<LittleEndian>()?).ok_or(CoreDataError::InvalidKeyboardType)?;
let keyboard_subtype = buffer.read_u32::<LittleEndian>()?; let keyboard_subtype = buffer.read_u32::<LittleEndian>()?;
let keyboard_functional_keys_count = buffer.read_u32::<LittleEndian>()?; let keyboard_functional_keys_count = buffer.read_u32::<LittleEndian>()?;
@ -196,44 +193,26 @@ impl PduParsing for ClientCoreOptionalData {
let mut optional_data = Self::default(); let mut optional_data = Self::default();
optional_data.post_beta_color_depth = Some( optional_data.post_beta_color_depth = Some(
ColorDepth::from_u16(try_read_optional!( ColorDepth::from_u16(try_read_optional!(buffer.read_u16::<LittleEndian>(), optional_data))
buffer.read_u16::<LittleEndian>(), .ok_or(CoreDataError::InvalidPostBetaColorDepth)?,
optional_data
))
.ok_or(CoreDataError::InvalidPostBetaColorDepth)?,
); );
optional_data.client_product_id = Some(try_read_optional!( optional_data.client_product_id = Some(try_read_optional!(buffer.read_u16::<LittleEndian>(), optional_data));
buffer.read_u16::<LittleEndian>(), optional_data.serial_number = Some(try_read_optional!(buffer.read_u32::<LittleEndian>(), optional_data));
optional_data
));
optional_data.serial_number = Some(try_read_optional!(
buffer.read_u32::<LittleEndian>(),
optional_data
));
optional_data.high_color_depth = Some( optional_data.high_color_depth = Some(
HighColorDepth::from_u16(try_read_optional!( HighColorDepth::from_u16(try_read_optional!(buffer.read_u16::<LittleEndian>(), optional_data))
buffer.read_u16::<LittleEndian>(), .ok_or(CoreDataError::InvalidHighColorDepth)?,
optional_data
))
.ok_or(CoreDataError::InvalidHighColorDepth)?,
); );
optional_data.supported_color_depths = Some( optional_data.supported_color_depths = Some(
SupportedColorDepths::from_bits(try_read_optional!( SupportedColorDepths::from_bits(try_read_optional!(buffer.read_u16::<LittleEndian>(), optional_data))
buffer.read_u16::<LittleEndian>(), .ok_or(CoreDataError::InvalidSupportedColorDepths)?,
optional_data
))
.ok_or(CoreDataError::InvalidSupportedColorDepths)?,
); );
optional_data.early_capability_flags = Some( optional_data.early_capability_flags = Some(
ClientEarlyCapabilityFlags::from_bits(try_read_optional!( ClientEarlyCapabilityFlags::from_bits(try_read_optional!(buffer.read_u16::<LittleEndian>(), optional_data))
buffer.read_u16::<LittleEndian>(), .ok_or(CoreDataError::InvalidEarlyCapabilityFlags)?,
optional_data
))
.ok_or(CoreDataError::InvalidEarlyCapabilityFlags)?,
); );
let mut dig_product_id_buffer = [0; DIG_PRODUCT_ID_SIZE]; let mut dig_product_id_buffer = [0; DIG_PRODUCT_ID_SIZE];
@ -252,28 +231,17 @@ impl PduParsing for ClientCoreOptionalData {
try_read_optional!(buffer.read_u8(), optional_data); // pad1octet try_read_optional!(buffer.read_u8(), optional_data); // pad1octet
optional_data.server_selected_protocol = Some( optional_data.server_selected_protocol = Some(
nego::SecurityProtocol::from_bits(try_read_optional!( nego::SecurityProtocol::from_bits(try_read_optional!(buffer.read_u32::<LittleEndian>(), optional_data))
buffer.read_u32::<LittleEndian>(), .ok_or(CoreDataError::InvalidServerSecurityProtocol)?,
optional_data
))
.ok_or(CoreDataError::InvalidServerSecurityProtocol)?,
); );
optional_data.desktop_physical_width = Some(try_read_optional!( optional_data.desktop_physical_width =
buffer.read_u32::<LittleEndian>(), Some(try_read_optional!(buffer.read_u32::<LittleEndian>(), optional_data));
optional_data
));
// physical height must be present, if the physical width is present // physical height must be present, if the physical width is present
optional_data.desktop_physical_height = Some(buffer.read_u32::<LittleEndian>()?); optional_data.desktop_physical_height = Some(buffer.read_u32::<LittleEndian>()?);
optional_data.desktop_orientation = Some(try_read_optional!( optional_data.desktop_orientation = Some(try_read_optional!(buffer.read_u16::<LittleEndian>(), optional_data));
buffer.read_u16::<LittleEndian>(), optional_data.desktop_scale_factor = Some(try_read_optional!(buffer.read_u32::<LittleEndian>(), optional_data));
optional_data
));
optional_data.desktop_scale_factor = Some(try_read_optional!(
buffer.read_u32::<LittleEndian>(),
optional_data
));
// device scale factor must be present, if the desktop scale factor is present // device scale factor must be present, if the desktop scale factor is present
optional_data.device_scale_factor = Some(buffer.read_u32::<LittleEndian>()?); optional_data.device_scale_factor = Some(buffer.read_u32::<LittleEndian>()?);
@ -292,19 +260,15 @@ impl PduParsing for ClientCoreOptionalData {
.write_u32::<LittleEndian>(*value)); .write_u32::<LittleEndian>(*value));
try_write_optional!(self.high_color_depth, |value: &HighColorDepth| buffer try_write_optional!(self.high_color_depth, |value: &HighColorDepth| buffer
.write_u16::<LittleEndian>(value.to_u16().unwrap()));
try_write_optional!(self.supported_color_depths, |value: &SupportedColorDepths| buffer
.write_u16::<LittleEndian>( .write_u16::<LittleEndian>(
value.to_u16().unwrap() value.bits()
)); ));
try_write_optional!( try_write_optional!(self.early_capability_flags, |value: &ClientEarlyCapabilityFlags| buffer
self.supported_color_depths, .write_u16::<LittleEndian>(value.bits()));
|value: &SupportedColorDepths| buffer.write_u16::<LittleEndian>(value.bits())
);
try_write_optional!(
self.early_capability_flags,
|value: &ClientEarlyCapabilityFlags| buffer.write_u16::<LittleEndian>(value.bits())
);
try_write_optional!(self.dig_product_id, |value: &str| { try_write_optional!(self.dig_product_id, |value: &str| {
let mut dig_product_id_buffer = utils::string_to_utf16(value); let mut dig_product_id_buffer = utils::string_to_utf16(value);
@ -319,20 +283,15 @@ impl PduParsing for ClientCoreOptionalData {
buffer.write_u8(0)?; // pad1octet buffer.write_u8(0)?; // pad1octet
try_write_optional!( try_write_optional!(self.server_selected_protocol, |value: &nego::SecurityProtocol| {
self.server_selected_protocol, buffer.write_u32::<LittleEndian>(value.bits())
|value: &nego::SecurityProtocol| { buffer.write_u32::<LittleEndian>(value.bits()) } });
);
try_write_optional!(self.desktop_physical_width, |value: &u32| buffer try_write_optional!(self.desktop_physical_width, |value: &u32| buffer
.write_u32::<LittleEndian>( .write_u32::<LittleEndian>(*value));
*value
));
try_write_optional!(self.desktop_physical_height, |value: &u32| buffer try_write_optional!(self.desktop_physical_height, |value: &u32| buffer
.write_u32::<LittleEndian>( .write_u32::<LittleEndian>(*value));
*value
));
try_write_optional!(self.desktop_orientation, |value: &u16| buffer try_write_optional!(self.desktop_orientation, |value: &u16| buffer
.write_u16::<LittleEndian>(*value)); .write_u16::<LittleEndian>(*value));

View file

@ -1,9 +1,8 @@
use lazy_static::lazy_static; use lazy_static::lazy_static;
use crate::{ use crate::gcc::core_data::client::*;
gcc::core_data::{client::*, *}, use crate::gcc::core_data::*;
nego, use crate::nego;
};
const CLIENT_CORE_DATA_BUFFER: [u8; 128] = [ const CLIENT_CORE_DATA_BUFFER: [u8; 128] = [
0x04, 0x00, 0x08, 0x00, // version 0x04, 0x00, 0x08, 0x00, // version
@ -13,17 +12,15 @@ const CLIENT_CORE_DATA_BUFFER: [u8; 128] = [
0x03, 0xaa, // sas sequence 0x03, 0xaa, // sas sequence
0x09, 0x04, 0x00, 0x00, // keyboard layout 0x09, 0x04, 0x00, 0x00, // keyboard layout
0xce, 0x0e, 0x00, 0x00, // client build 0xce, 0x0e, 0x00, 0x00, // client build
0x45, 0x00, 0x4c, 0x00, 0x54, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x53, 0x00, 0x2d, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4c, 0x00, 0x54, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x53, 0x00, 0x2d, 0x00, 0x44, 0x00, 0x45, 0x00, 0x56,
0x45, 0x00, 0x56, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // client name
0x00, // client name
0x04, 0x00, 0x00, 0x00, // keyboard type 0x04, 0x00, 0x00, 0x00, // keyboard type
0x00, 0x00, 0x00, 0x00, // keyboard subtype 0x00, 0x00, 0x00, 0x00, // keyboard subtype
0x0c, 0x00, 0x00, 0x00, // keyboard function key 0x0c, 0x00, 0x00, 0x00, // keyboard function key
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ime file name
0x00, // ime file name
]; ];
const CLIENT_OPTIONAL_CORE_DATA_TO_HIGH_COLOR_DEPTH_BUFFER: [u8; 8] = [ const CLIENT_OPTIONAL_CORE_DATA_TO_HIGH_COLOR_DEPTH_BUFFER: [u8; 8] = [
0x01, 0xca, // post beta color depth 0x01, 0xca, // post beta color depth
@ -37,18 +34,16 @@ const CLIENT_OPTIONAL_CORE_DATA_FROM_HIGH_COLOR_DEPTH_TO_SERVER_SELECTED_PROTOCO
0x18, 0x00, // high color depth 0x18, 0x00, // high color depth
0x07, 0x00, // supported color depths 0x07, 0x00, // supported color depths
0x01, 0x00, // early capability flags 0x01, 0x00, // early capability flags
0x36, 0x00, 0x39, 0x00, 0x37, 0x00, 0x31, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x37, 0x00, 0x38, 0x00, 0x36, 0x00, 0x39, 0x00, 0x37, 0x00, 0x31, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x37, 0x00, 0x38, 0x00, 0x33, 0x00, 0x2d,
0x33, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x37, 0x00, 0x39, 0x00, 0x37, 0x00, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x37, 0x00, 0x39, 0x00, 0x37, 0x00, 0x34, 0x00, 0x2d, 0x00, 0x34, 0x00,
0x34, 0x00, 0x2d, 0x00, 0x34, 0x00, 0x32, 0x00, 0x37, 0x00, 0x31, 0x00, 0x34, 0x00, 0x00, 0x00, 0x32, 0x00, 0x37, 0x00, 0x31, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // client dig product id
0x00, // client dig product id
0x00, // connection type 0x00, // connection type
0x00, // padding 0x00, // padding
0x00, 0x00, 0x00, 0x00, // server selected protocol 0x00, 0x00, 0x00, 0x00, // server selected protocol
]; ];
const CLIENT_OPTIONAL_CORE_DATA_FROM_DESKTOP_PHYSICAL_WIDTH_TO_DEVICE_SCALE_FACTOR_BUFFER: [u8; const CLIENT_OPTIONAL_CORE_DATA_FROM_DESKTOP_PHYSICAL_WIDTH_TO_DEVICE_SCALE_FACTOR_BUFFER: [u8; 18] = [
18] = [
0x88, 0x13, 0x00, 0x00, // desktop physical width 0x88, 0x13, 0x00, 0x00, // desktop physical width
0xb8, 0x0b, 0x00, 0x00, //desktop physical height 0xb8, 0x0b, 0x00, 0x00, //desktop physical height
0x5a, 0x00, // desktop orientation 0x5a, 0x00, // desktop orientation
@ -84,11 +79,9 @@ lazy_static! {
pub static ref CLIENT_OPTIONAL_CORE_DATA_TO_SERVER_SELECTED_PROTOCOL: ClientCoreData = { pub static ref CLIENT_OPTIONAL_CORE_DATA_TO_SERVER_SELECTED_PROTOCOL: ClientCoreData = {
let mut data = CLIENT_OPTIONAL_CORE_DATA_TO_HIGH_COLOR_DEPTH.clone(); let mut data = CLIENT_OPTIONAL_CORE_DATA_TO_HIGH_COLOR_DEPTH.clone();
data.optional_data.high_color_depth = Some(HighColorDepth::Bpp24); data.optional_data.high_color_depth = Some(HighColorDepth::Bpp24);
data.optional_data.supported_color_depths = Some( data.optional_data.supported_color_depths =
SupportedColorDepths::BPP24 | SupportedColorDepths::BPP16 | SupportedColorDepths::BPP15, Some(SupportedColorDepths::BPP24 | SupportedColorDepths::BPP16 | SupportedColorDepths::BPP15);
); data.optional_data.early_capability_flags = Some(ClientEarlyCapabilityFlags::SUPPORT_ERR_INFO_PDU);
data.optional_data.early_capability_flags =
Some(ClientEarlyCapabilityFlags::SUPPORT_ERR_INFO_PDU);
data.optional_data.dig_product_id = Some(String::from("69712-783-0357974-42714")); data.optional_data.dig_product_id = Some(String::from("69712-783-0357974-42714"));
data.optional_data.connection_type = Some(ConnectionType::NotUsed); data.optional_data.connection_type = Some(ConnectionType::NotUsed);
data.optional_data.server_selected_protocol = Some(nego::SecurityProtocol::RDP); data.optional_data.server_selected_protocol = Some(nego::SecurityProtocol::RDP);
@ -107,8 +100,7 @@ lazy_static! {
}; };
pub static ref CLIENT_CORE_DATA_WITH_ALL_OPTIONAL_FIELDS_WITH_WANT_32_BPP_EARLY_FLAG: ClientCoreData = { pub static ref CLIENT_CORE_DATA_WITH_ALL_OPTIONAL_FIELDS_WITH_WANT_32_BPP_EARLY_FLAG: ClientCoreData = {
let mut data = CLIENT_CORE_DATA_WITH_ALL_OPTIONAL_FIELDS.clone(); let mut data = CLIENT_CORE_DATA_WITH_ALL_OPTIONAL_FIELDS.clone();
data.optional_data.early_capability_flags = data.optional_data.early_capability_flags = Some(ClientEarlyCapabilityFlags::WANT_32_BPP_SESSION);
Some(ClientEarlyCapabilityFlags::WANT_32_BPP_SESSION);
data data
}; };
@ -120,39 +112,28 @@ lazy_static! {
}; };
pub static ref CLIENT_OPTIONAL_CORE_DATA_TO_SERVER_SELECTED_PROTOCOL_BUFFER: Vec<u8> = { pub static ref CLIENT_OPTIONAL_CORE_DATA_TO_SERVER_SELECTED_PROTOCOL_BUFFER: Vec<u8> = {
let mut buffer = CLIENT_OPTIONAL_CORE_DATA_TO_HIGH_COLOR_DEPTH_BUFFER_BUFFER.to_vec(); let mut buffer = CLIENT_OPTIONAL_CORE_DATA_TO_HIGH_COLOR_DEPTH_BUFFER_BUFFER.to_vec();
buffer.extend( buffer.extend(CLIENT_OPTIONAL_CORE_DATA_FROM_HIGH_COLOR_DEPTH_TO_SERVER_SELECTED_PROTOCOL_BUFFER.as_ref());
CLIENT_OPTIONAL_CORE_DATA_FROM_HIGH_COLOR_DEPTH_TO_SERVER_SELECTED_PROTOCOL_BUFFER
.as_ref(),
);
buffer buffer
}; };
pub static ref CLIENT_OPTIONAL_CORE_DATA_WITH_ALL_OPTIONAL_FIELDS_BUFFER: Vec<u8> = { pub static ref CLIENT_OPTIONAL_CORE_DATA_WITH_ALL_OPTIONAL_FIELDS_BUFFER: Vec<u8> = {
let mut buffer = CLIENT_OPTIONAL_CORE_DATA_TO_SERVER_SELECTED_PROTOCOL_BUFFER.to_vec(); let mut buffer = CLIENT_OPTIONAL_CORE_DATA_TO_SERVER_SELECTED_PROTOCOL_BUFFER.to_vec();
buffer.extend( buffer.extend(CLIENT_OPTIONAL_CORE_DATA_FROM_DESKTOP_PHYSICAL_WIDTH_TO_DEVICE_SCALE_FACTOR_BUFFER.as_ref());
CLIENT_OPTIONAL_CORE_DATA_FROM_DESKTOP_PHYSICAL_WIDTH_TO_DEVICE_SCALE_FACTOR_BUFFER
.as_ref(),
);
buffer buffer
}; };
pub static ref CLIENT_CORE_DATA_WITH_ALL_OPTIONAL_FIELDS_WITH_WANT_32_BPP_EARLY_FLAG_BUFFER: Vec<u8> = { pub static ref CLIENT_CORE_DATA_WITH_ALL_OPTIONAL_FIELDS_WITH_WANT_32_BPP_EARLY_FLAG_BUFFER: Vec<u8> = {
let early_capability_flags = ClientEarlyCapabilityFlags::WANT_32_BPP_SESSION let early_capability_flags = ClientEarlyCapabilityFlags::WANT_32_BPP_SESSION.bits().to_le_bytes();
.bits()
.to_le_bytes();
let mut from_high_color_to_server_protocol = let mut from_high_color_to_server_protocol =
CLIENT_OPTIONAL_CORE_DATA_FROM_HIGH_COLOR_DEPTH_TO_SERVER_SELECTED_PROTOCOL_BUFFER; CLIENT_OPTIONAL_CORE_DATA_FROM_HIGH_COLOR_DEPTH_TO_SERVER_SELECTED_PROTOCOL_BUFFER;
from_high_color_to_server_protocol[EARLY_CAPABILITY_FLAGS_START from_high_color_to_server_protocol
..EARLY_CAPABILITY_FLAGS_START + EARLY_CAPABILITY_FLAGS_LENGTH] [EARLY_CAPABILITY_FLAGS_START..EARLY_CAPABILITY_FLAGS_START + EARLY_CAPABILITY_FLAGS_LENGTH]
.clone_from_slice(early_capability_flags.as_ref()); .clone_from_slice(early_capability_flags.as_ref());
let mut buffer = CLIENT_OPTIONAL_CORE_DATA_TO_HIGH_COLOR_DEPTH_BUFFER_BUFFER.to_vec(); let mut buffer = CLIENT_OPTIONAL_CORE_DATA_TO_HIGH_COLOR_DEPTH_BUFFER_BUFFER.to_vec();
buffer.extend(from_high_color_to_server_protocol.as_ref()); buffer.extend(from_high_color_to_server_protocol.as_ref());
buffer.extend( buffer.extend(CLIENT_OPTIONAL_CORE_DATA_FROM_DESKTOP_PHYSICAL_WIDTH_TO_DEVICE_SCALE_FACTOR_BUFFER.as_ref());
CLIENT_OPTIONAL_CORE_DATA_FROM_DESKTOP_PHYSICAL_WIDTH_TO_DEVICE_SCALE_FACTOR_BUFFER
.as_ref(),
);
buffer buffer
}; };
@ -277,18 +258,15 @@ fn client_color_depth_is_high_color_depth_if_want_32_bpp_flag_is_absent() {
let buffer = CLIENT_OPTIONAL_CORE_DATA_WITH_ALL_OPTIONAL_FIELDS_BUFFER.clone(); let buffer = CLIENT_OPTIONAL_CORE_DATA_WITH_ALL_OPTIONAL_FIELDS_BUFFER.clone();
let core_data = ClientCoreData::from_buffer(buffer.as_slice()).unwrap(); let core_data = ClientCoreData::from_buffer(buffer.as_slice()).unwrap();
let expected_client_color_depth: ClientColorDepth = let expected_client_color_depth: ClientColorDepth = From::from(core_data.optional_data.high_color_depth.unwrap());
From::from(core_data.optional_data.high_color_depth.unwrap());
assert_eq!(expected_client_color_depth, core_data.client_color_depth()); assert_eq!(expected_client_color_depth, core_data.client_color_depth());
} }
#[test] #[test]
fn client_color_depth_is_32_bpp_if_want_32_bpp_flag_is_set() { fn client_color_depth_is_32_bpp_if_want_32_bpp_flag_is_set() {
let buffer = let buffer = CLIENT_CORE_DATA_WITH_ALL_OPTIONAL_FIELDS_WITH_WANT_32_BPP_EARLY_FLAG_BUFFER.clone();
CLIENT_CORE_DATA_WITH_ALL_OPTIONAL_FIELDS_WITH_WANT_32_BPP_EARLY_FLAG_BUFFER.clone(); let expected_core_data = CLIENT_CORE_DATA_WITH_ALL_OPTIONAL_FIELDS_WITH_WANT_32_BPP_EARLY_FLAG.clone();
let expected_core_data =
CLIENT_CORE_DATA_WITH_ALL_OPTIONAL_FIELDS_WITH_WANT_32_BPP_EARLY_FLAG.clone();
let expected_client_color_depth = ClientColorDepth::Bpp32; let expected_client_color_depth = ClientColorDepth::Bpp32;
let core_data = ClientCoreData::from_buffer(buffer.as_slice()).unwrap(); let core_data = ClientCoreData::from_buffer(buffer.as_slice()).unwrap();

View file

@ -23,14 +23,10 @@ impl PduParsing for ServerCoreData {
type Error = CoreDataError; type Error = CoreDataError;
fn from_buffer(mut buffer: impl io::Read) -> Result<Self, Self::Error> { fn from_buffer(mut buffer: impl io::Read) -> Result<Self, Self::Error> {
let version = RdpVersion::from_u32(buffer.read_u32::<LittleEndian>()?) let version = RdpVersion::from_u32(buffer.read_u32::<LittleEndian>()?).unwrap_or(RdpVersion::VUnknown);
.unwrap_or(RdpVersion::VUnknown);
let optional_data = ServerCoreOptionalData::from_buffer(&mut buffer)?; let optional_data = ServerCoreOptionalData::from_buffer(&mut buffer)?;
Ok(Self { Ok(Self { version, optional_data })
version,
optional_data,
})
} }
fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> {
@ -56,34 +52,25 @@ impl PduParsing for ServerCoreOptionalData {
let mut optional_data = Self::default(); let mut optional_data = Self::default();
optional_data.client_requested_protocols = Some( optional_data.client_requested_protocols = Some(
nego::SecurityProtocol::from_bits(try_read_optional!( nego::SecurityProtocol::from_bits(try_read_optional!(buffer.read_u32::<LittleEndian>(), optional_data))
buffer.read_u32::<LittleEndian>(), .ok_or(CoreDataError::InvalidServerSecurityProtocol)?,
optional_data
))
.ok_or(CoreDataError::InvalidServerSecurityProtocol)?,
); );
optional_data.early_capability_flags = Some( optional_data.early_capability_flags = Some(
ServerEarlyCapabilityFlags::from_bits(try_read_optional!( ServerEarlyCapabilityFlags::from_bits(try_read_optional!(buffer.read_u32::<LittleEndian>(), optional_data))
buffer.read_u32::<LittleEndian>(), .ok_or(CoreDataError::InvalidEarlyCapabilityFlags)?,
optional_data
))
.ok_or(CoreDataError::InvalidEarlyCapabilityFlags)?,
); );
Ok(optional_data) Ok(optional_data)
} }
fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> {
try_write_optional!( try_write_optional!(self.client_requested_protocols, |value: &nego::SecurityProtocol| {
self.client_requested_protocols, buffer.write_u32::<LittleEndian>(value.bits())
|value: &nego::SecurityProtocol| { buffer.write_u32::<LittleEndian>(value.bits()) } });
);
try_write_optional!( try_write_optional!(self.early_capability_flags, |value: &ServerEarlyCapabilityFlags| buffer
self.early_capability_flags, .write_u32::<LittleEndian>(value.bits()));
|value: &ServerEarlyCapabilityFlags| buffer.write_u32::<LittleEndian>(value.bits())
);
Ok(()) Ok(())
} }

View file

@ -1,9 +1,8 @@
use lazy_static::lazy_static; use lazy_static::lazy_static;
use crate::{ use crate::gcc::core_data::server::*;
gcc::core_data::{server::*, *}, use crate::gcc::core_data::*;
nego, use crate::nego;
};
const SERVER_CORE_DATA_BUFFER: [u8; 4] = [ const SERVER_CORE_DATA_BUFFER: [u8; 4] = [
0x04, 0x00, 0x08, 0x00, // version 0x04, 0x00, 0x08, 0x00, // version
@ -55,10 +54,7 @@ lazy_static! {
fn from_buffer_correctly_parses_server_core_data_without_optional_fields() { fn from_buffer_correctly_parses_server_core_data_without_optional_fields() {
let buffer = SERVER_CORE_DATA_BUFFER.as_ref(); let buffer = SERVER_CORE_DATA_BUFFER.as_ref();
assert_eq!( assert_eq!(*SERVER_CORE_DATA, ServerCoreData::from_buffer(buffer).unwrap());
*SERVER_CORE_DATA,
ServerCoreData::from_buffer(buffer).unwrap()
);
} }
#[test] #[test]

View file

@ -43,9 +43,7 @@ impl PduParsing for ServerMessageChannelData {
fn from_buffer(mut buffer: impl io::Read) -> Result<Self, Self::Error> { fn from_buffer(mut buffer: impl io::Read) -> Result<Self, Self::Error> {
let mcs_message_channel_id = buffer.read_u16::<LittleEndian>()?; let mcs_message_channel_id = buffer.read_u16::<LittleEndian>()?;
Ok(Self { Ok(Self { mcs_message_channel_id })
mcs_message_channel_id,
})
} }
fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> {
buffer.write_u16::<LittleEndian>(self.mcs_message_channel_id)?; buffer.write_u16::<LittleEndian>(self.mcs_message_channel_id)?;

View file

@ -71,8 +71,8 @@ impl PduParsing for Monitor {
let top = buffer.read_i32::<LittleEndian>()?; let top = buffer.read_i32::<LittleEndian>()?;
let right = buffer.read_i32::<LittleEndian>()?; let right = buffer.read_i32::<LittleEndian>()?;
let bottom = buffer.read_i32::<LittleEndian>()?; let bottom = buffer.read_i32::<LittleEndian>()?;
let flags = MonitorFlags::from_bits(buffer.read_u32::<LittleEndian>()?) let flags =
.ok_or(MonitorDataError::InvalidMonitorFlags)?; MonitorFlags::from_bits(buffer.read_u32::<LittleEndian>()?).ok_or(MonitorDataError::InvalidMonitorFlags)?;
Ok(Self { Ok(Self {
left, left,

View file

@ -2,18 +2,15 @@ use lazy_static::lazy_static;
use super::*; use super::*;
pub const MONITOR_DATA_WITHOUT_MONITORS_BUFFER: [u8; 8] = pub const MONITOR_DATA_WITHOUT_MONITORS_BUFFER: [u8; 8] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
pub const MONITOR_DATA_WITH_MONITORS_BUFFER: [u8; 48] = [ pub const MONITOR_DATA_WITH_MONITORS_BUFFER: [u8; 48] = [
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x07, 0x00,
0x7f, 0x07, 0x00, 0x00, 0x37, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xff, 0xff, 0x00, 0x37, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
lazy_static! { lazy_static! {
pub static ref MONITOR_DATA_WITHOUT_MONITORS: ClientMonitorData = ClientMonitorData { pub static ref MONITOR_DATA_WITHOUT_MONITORS: ClientMonitorData = ClientMonitorData { monitors: Vec::new() };
monitors: Vec::new()
};
pub static ref MONITOR_DATA_WITH_MONITORS: ClientMonitorData = ClientMonitorData { pub static ref MONITOR_DATA_WITH_MONITORS: ClientMonitorData = ClientMonitorData {
monitors: vec![ monitors: vec![
Monitor { Monitor {

View file

@ -45,9 +45,7 @@ impl PduParsing for ClientMonitorExtendedData {
extended_monitors_info.push(ExtendedMonitorInfo::from_buffer(&mut buffer)?); extended_monitors_info.push(ExtendedMonitorInfo::from_buffer(&mut buffer)?);
} }
Ok(Self { Ok(Self { extended_monitors_info })
extended_monitors_info,
})
} }
fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> {
buffer.write_u32::<LittleEndian>(0)?; // flags buffer.write_u32::<LittleEndian>(0)?; // flags
@ -131,8 +129,4 @@ pub enum MonitorExtendedDataError {
InvalidMonitorCount, InvalidMonitorCount,
} }
impl_from_error!( impl_from_error!(io::Error, MonitorExtendedDataError, MonitorExtendedDataError::IOError);
io::Error,
MonitorExtendedDataError,
MonitorExtendedDataError::IOError
);

View file

@ -2,40 +2,36 @@ use lazy_static::lazy_static;
use super::*; use super::*;
pub const MONITOR_DATA_WITHOUT_MONITORS_BUFFER: [u8; 12] = [ pub const MONITOR_DATA_WITHOUT_MONITORS_BUFFER: [u8; 12] =
0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, [0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
];
pub const MONITOR_DATA_WITH_MONITORS_BUFFER: [u8; 52] = [ pub const MONITOR_DATA_WITH_MONITORS_BUFFER: [u8; 52] = [
0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
]; ];
lazy_static! { lazy_static! {
pub static ref MONITOR_DATA_WITHOUT_MONITORS: ClientMonitorExtendedData = pub static ref MONITOR_DATA_WITHOUT_MONITORS: ClientMonitorExtendedData = ClientMonitorExtendedData {
ClientMonitorExtendedData { extended_monitors_info: Vec::new()
extended_monitors_info: Vec::new() };
}; pub static ref MONITOR_DATA_WITH_MONITORS: ClientMonitorExtendedData = ClientMonitorExtendedData {
pub static ref MONITOR_DATA_WITH_MONITORS: ClientMonitorExtendedData = extended_monitors_info: vec![
ClientMonitorExtendedData { ExtendedMonitorInfo {
extended_monitors_info: vec![ physical_width: 0,
ExtendedMonitorInfo { physical_height: 0,
physical_width: 0, orientation: MonitorOrientation::Landscape,
physical_height: 0, desktop_scale_factor: 0,
orientation: MonitorOrientation::Landscape, device_scale_factor: 0,
desktop_scale_factor: 0, },
device_scale_factor: 0, ExtendedMonitorInfo {
}, physical_width: 0,
ExtendedMonitorInfo { physical_height: 0,
physical_width: 0, orientation: MonitorOrientation::Landscape,
physical_height: 0, desktop_scale_factor: 0,
orientation: MonitorOrientation::Landscape, device_scale_factor: 0,
desktop_scale_factor: 0, }
device_scale_factor: 0, ]
} };
]
};
} }
#[test] #[test]

View file

@ -5,12 +5,11 @@ use super::*;
pub const SERVER_GCC_MULTI_TRANSPORT_CHANNEL_BLOCK_BUFFER: [u8; 4] = [0x01, 0x03, 0x00, 0x00]; pub const SERVER_GCC_MULTI_TRANSPORT_CHANNEL_BLOCK_BUFFER: [u8; 4] = [0x01, 0x03, 0x00, 0x00];
lazy_static! { lazy_static! {
pub static ref SERVER_GCC_MULTI_TRANSPORT_CHANNEL_BLOCK: MultiTransportChannelData = pub static ref SERVER_GCC_MULTI_TRANSPORT_CHANNEL_BLOCK: MultiTransportChannelData = MultiTransportChannelData {
MultiTransportChannelData { flags: MultiTransportFlags::TRANSPORT_TYPE_UDP_FECR
flags: MultiTransportFlags::TRANSPORT_TYPE_UDP_FECR | MultiTransportFlags::TRANSPORT_TYPE_UDP_PREFERRED
| MultiTransportFlags::TRANSPORT_TYPE_UDP_PREFERRED | MultiTransportFlags::SOFT_SYNC_TCP_TO_UDP,
| MultiTransportFlags::SOFT_SYNC_TCP_TO_UDP, };
};
} }
#[test] #[test]

View file

@ -1,10 +1,8 @@
#[cfg(test)] #[cfg(test)]
pub mod test; pub mod test;
use std::{ use std::io::{self, Write};
io::{self, Write}, use std::str;
str,
};
use bitflags::bitflags; use bitflags::bitflags;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
@ -120,10 +118,7 @@ impl PduParsing for ServerNetworkData {
fn buffer_length(&self) -> usize { fn buffer_length(&self) -> usize {
let padding_size = if self.write_padding() { 2 } else { 0 }; let padding_size = if self.write_padding() { 2 } else { 0 };
SERVER_IO_CHANNEL_SIZE SERVER_IO_CHANNEL_SIZE + SERVER_CHANNEL_COUNT_SIZE + self.channel_ids.len() * SERVER_CHANNEL_SIZE + padding_size
+ SERVER_CHANNEL_COUNT_SIZE
+ self.channel_ids.len() * SERVER_CHANNEL_SIZE
+ padding_size
} }
} }
@ -194,8 +189,4 @@ pub enum NetworkDataError {
} }
impl_from_error!(io::Error, NetworkDataError, NetworkDataError::IOError); impl_from_error!(io::Error, NetworkDataError, NetworkDataError::IOError);
impl_from_error!( impl_from_error!(str::Utf8Error, NetworkDataError, NetworkDataError::Utf8Error);
str::Utf8Error,
NetworkDataError,
NetworkDataError::Utf8Error
);

View file

@ -51,9 +51,7 @@ lazy_static! {
io_channel: 1003, io_channel: 1003,
channel_ids: vec![1004, 1005, 1006], channel_ids: vec![1004, 1005, 1006],
}; };
static ref CLIENT_NETOWORK_DATA_WITHOUT_CHANNELS: ClientNetworkData = ClientNetworkData { static ref CLIENT_NETOWORK_DATA_WITHOUT_CHANNELS: ClientNetworkData = ClientNetworkData { channels: Vec::new() };
channels: Vec::new()
};
static ref SERVER_NETOWORK_DATA_WITHOUT_CHANNELS_ID: ServerNetworkData = ServerNetworkData { static ref SERVER_NETOWORK_DATA_WITHOUT_CHANNELS_ID: ServerNetworkData = ServerNetworkData {
io_channel: 1003, io_channel: 1003,
channel_ids: Vec::new(), channel_ids: Vec::new(),

View file

@ -90,31 +90,29 @@ impl PduParsing for ServerSecurityData {
let encryption_level = EncryptionLevel::from_u32(buffer.read_u32::<LittleEndian>()?) let encryption_level = EncryptionLevel::from_u32(buffer.read_u32::<LittleEndian>()?)
.ok_or(SecurityDataError::InvalidEncryptionLevel)?; .ok_or(SecurityDataError::InvalidEncryptionLevel)?;
let (server_random, server_cert) = let (server_random, server_cert) = if encryption_method.is_empty() && encryption_level == EncryptionLevel::None
if encryption_method.is_empty() && encryption_level == EncryptionLevel::None { {
(None, Vec::new()) (None, Vec::new())
} else { } else {
let server_random_len = buffer.read_u32::<LittleEndian>()?; let server_random_len = buffer.read_u32::<LittleEndian>()?;
if server_random_len != SERVER_RANDOM_LEN as u32 { if server_random_len != SERVER_RANDOM_LEN as u32 {
return Err(SecurityDataError::InvalidServerRandomLen(server_random_len)); return Err(SecurityDataError::InvalidServerRandomLen(server_random_len));
} }
let server_cert_len = buffer.read_u32::<LittleEndian>()?; let server_cert_len = buffer.read_u32::<LittleEndian>()?;
if server_cert_len > MAX_SERVER_CERT_LEN { if server_cert_len > MAX_SERVER_CERT_LEN {
return Err(SecurityDataError::InvalidServerCertificateLen( return Err(SecurityDataError::InvalidServerCertificateLen(server_cert_len));
server_cert_len, }
));
}
let mut server_random = [0; SERVER_RANDOM_LEN]; let mut server_random = [0; SERVER_RANDOM_LEN];
buffer.read_exact(&mut server_random)?; buffer.read_exact(&mut server_random)?;
let mut server_cert = vec![0; server_cert_len as usize]; let mut server_cert = vec![0; server_cert_len as usize];
buffer.read_exact(&mut server_cert)?; buffer.read_exact(&mut server_cert)?;
(Some(server_random), server_cert) (Some(server_random), server_cert)
}; };
Ok(Self { Ok(Self {
encryption_method, encryption_method,

View file

@ -16,22 +16,20 @@ const SERVER_SECURITY_DATA_WITH_OPTIONAL_FIELDS_PREFIX_BUFFER: [u8; 8] = [
0x02, 0x00, 0x00, 0x00, // encryption level 0x02, 0x00, 0x00, 0x00, // encryption level
]; ];
const SERVER_RANDOM_BUFFER: [u8; 32] = [ const SERVER_RANDOM_BUFFER: [u8; 32] = [
0x10, 0x11, 0x77, 0x20, 0x30, 0x61, 0x0a, 0x12, 0xe4, 0x34, 0xa1, 0x1e, 0xf2, 0xc3, 0x9f, 0x31, 0x10, 0x11, 0x77, 0x20, 0x30, 0x61, 0x0a, 0x12, 0xe4, 0x34, 0xa1, 0x1e, 0xf2, 0xc3, 0x9f, 0x31, 0x7d, 0xa4, 0x5f,
0x7d, 0xa4, 0x5f, 0x01, 0x89, 0x34, 0x96, 0xe0, 0xff, 0x11, 0x08, 0x69, 0x7f, 0x1a, 0xc3, 0xd2, 0x01, 0x89, 0x34, 0x96, 0xe0, 0xff, 0x11, 0x08, 0x69, 0x7f, 0x1a, 0xc3, 0xd2,
]; ];
const SERVER_CERT_BUFFER: [u8; 184] = [ const SERVER_CERT_BUFFER: [u8; 184] = [
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x5c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x5c, 0x00, 0x52, 0x53, 0x41,
0x52, 0x53, 0x41, 0x31, 0x48, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x31, 0x48, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0xcb, 0x81,
0x01, 0x00, 0x01, 0x00, 0xcb, 0x81, 0xfe, 0xba, 0x6d, 0x61, 0xc3, 0x55, 0x05, 0xd5, 0x5f, 0x2e, 0xfe, 0xba, 0x6d, 0x61, 0xc3, 0x55, 0x05, 0xd5, 0x5f, 0x2e, 0x87, 0xf8, 0x71, 0x94, 0xd6, 0xf1, 0xa5, 0xcb, 0xf1,
0x87, 0xf8, 0x71, 0x94, 0xd6, 0xf1, 0xa5, 0xcb, 0xf1, 0x5f, 0x0c, 0x3d, 0xf8, 0x70, 0x02, 0x96, 0x5f, 0x0c, 0x3d, 0xf8, 0x70, 0x02, 0x96, 0xc4, 0xfb, 0x9b, 0xc8, 0x3c, 0x2d, 0x55, 0xae, 0xe8, 0xff, 0x32, 0x75,
0xc4, 0xfb, 0x9b, 0xc8, 0x3c, 0x2d, 0x55, 0xae, 0xe8, 0xff, 0x32, 0x75, 0xea, 0x68, 0x79, 0xe5, 0xea, 0x68, 0x79, 0xe5, 0xa2, 0x01, 0xfd, 0x31, 0xa0, 0xb1, 0x1f, 0x55, 0xa6, 0x1f, 0xc1, 0xf6, 0xd1, 0x83, 0x88,
0xa2, 0x01, 0xfd, 0x31, 0xa0, 0xb1, 0x1f, 0x55, 0xa6, 0x1f, 0xc1, 0xf6, 0xd1, 0x83, 0x88, 0x63, 0x63, 0x26, 0x56, 0x12, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x48, 0x00, 0xe9, 0xe1,
0x26, 0x56, 0x12, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x48, 0x00, 0xd6, 0x28, 0x46, 0x8b, 0x4e, 0xf5, 0x0a, 0xdf, 0xfd, 0xee, 0x21, 0x99, 0xac, 0xb4, 0xe1, 0x8f, 0x5f, 0x81, 0x57,
0xe9, 0xe1, 0xd6, 0x28, 0x46, 0x8b, 0x4e, 0xf5, 0x0a, 0xdf, 0xfd, 0xee, 0x21, 0x99, 0xac, 0xb4, 0x82, 0xef, 0x9d, 0x96, 0x52, 0x63, 0x27, 0x18, 0x29, 0xdb, 0xb3, 0x4a, 0xfd, 0x9a, 0xda, 0x42, 0xad, 0xb5, 0x69,
0xe1, 0x8f, 0x5f, 0x81, 0x57, 0x82, 0xef, 0x9d, 0x96, 0x52, 0x63, 0x27, 0x18, 0x29, 0xdb, 0xb3, 0x21, 0x89, 0x0e, 0x1d, 0xc0, 0x4c, 0x1a, 0xa8, 0xaa, 0x71, 0x3e, 0x0f, 0x54, 0xb9, 0x9a, 0xe4, 0x99, 0x68, 0x3f,
0x4a, 0xfd, 0x9a, 0xda, 0x42, 0xad, 0xb5, 0x69, 0x21, 0x89, 0x0e, 0x1d, 0xc0, 0x4c, 0x1a, 0xa8, 0x6c, 0xd6, 0x76, 0x84, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xaa, 0x71, 0x3e, 0x0f, 0x54, 0xb9, 0x9a, 0xe4, 0x99, 0x68, 0x3f, 0x6c, 0xd6, 0x76, 0x84, 0x61,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
lazy_static! { lazy_static! {
@ -42,20 +40,18 @@ lazy_static! {
| EncryptionMethod::FIPS, | EncryptionMethod::FIPS,
ext_encryption_methods: 0, ext_encryption_methods: 0,
}; };
pub static ref SERVER_SECURITY_DATA_WITHOUT_OPTIONAL_FIELDS: ServerSecurityData = pub static ref SERVER_SECURITY_DATA_WITHOUT_OPTIONAL_FIELDS: ServerSecurityData = ServerSecurityData {
ServerSecurityData { encryption_method: EncryptionMethod::empty(),
encryption_method: EncryptionMethod::empty(), encryption_level: EncryptionLevel::None,
encryption_level: EncryptionLevel::None, server_random: None,
server_random: None, server_cert: Vec::new(),
server_cert: Vec::new(), };
}; pub static ref SERVER_SECURITY_DATA_WITH_OPTIONAL_FIELDS: ServerSecurityData = ServerSecurityData {
pub static ref SERVER_SECURITY_DATA_WITH_OPTIONAL_FIELDS: ServerSecurityData = encryption_method: EncryptionMethod::BIT_128,
ServerSecurityData { encryption_level: EncryptionLevel::ClientCompatible,
encryption_method: EncryptionMethod::BIT_128, server_random: Some(SERVER_RANDOM_BUFFER),
encryption_level: EncryptionLevel::ClientCompatible, server_cert: SERVER_CERT_BUFFER.to_vec(),
server_random: Some(SERVER_RANDOM_BUFFER), };
server_cert: SERVER_CERT_BUFFER.to_vec(),
};
pub static ref SERVER_SECURITY_DATA_WITH_MISMATCH_OF_REQUIRED_AND_OPTIONAL_FIELDS: ServerSecurityData = pub static ref SERVER_SECURITY_DATA_WITH_MISMATCH_OF_REQUIRED_AND_OPTIONAL_FIELDS: ServerSecurityData =
ServerSecurityData { ServerSecurityData {
encryption_method: EncryptionMethod::empty(), encryption_method: EncryptionMethod::empty(),
@ -99,10 +95,7 @@ lazy_static! {
fn from_buffer_correctly_parses_client_security_data() { fn from_buffer_correctly_parses_client_security_data() {
let buffer = CLIENT_SECURITY_DATA_BUFFER.as_ref(); let buffer = CLIENT_SECURITY_DATA_BUFFER.as_ref();
assert_eq!( assert_eq!(*CLIENT_SECURITY_DATA, ClientSecurityData::from_buffer(buffer).unwrap());
*CLIENT_SECURITY_DATA,
ClientSecurityData::from_buffer(buffer).unwrap()
);
} }
#[test] #[test]
@ -152,10 +145,7 @@ fn from_buffer_server_security_data_fails_with_invalid_server_random_length() {
match ServerSecurityData::from_buffer(buffer.as_slice()) { match ServerSecurityData::from_buffer(buffer.as_slice()) {
Err(SecurityDataError::InvalidServerRandomLen(_)) => (), Err(SecurityDataError::InvalidServerRandomLen(_)) => (),
res => panic!( res => panic!("Expected the invalid server random length error, got: {:?}", res),
"Expected the invalid server random length error, got: {:?}",
res
),
}; };
} }

View file

@ -3,8 +3,8 @@ use num_traits::{FromPrimitive, ToPrimitive};
use super::*; use super::*;
use crate::gcc::{ use crate::gcc::{
cluster_data, core_data, message_channel_data, monitor_data, monitor_extended_data, cluster_data, core_data, message_channel_data, monitor_data, monitor_extended_data, multi_transport_channel_data,
multi_transport_channel_data, network_data, security_data, network_data, security_data,
}; };
const USER_HEADER_LEN: usize = 4; const USER_HEADER_LEN: usize = 4;
@ -64,8 +64,7 @@ lazy_static! {
buffer buffer
}; };
pub static ref CLIENT_GCC_WITHOUT_OPTIONAL_FIELDS: ClientGccBlocks = ClientGccBlocks { pub static ref CLIENT_GCC_WITHOUT_OPTIONAL_FIELDS: ClientGccBlocks = ClientGccBlocks {
core: core_data::client::test::CLIENT_OPTIONAL_CORE_DATA_TO_SERVER_SELECTED_PROTOCOL core: core_data::client::test::CLIENT_OPTIONAL_CORE_DATA_TO_SERVER_SELECTED_PROTOCOL.clone(),
.clone(),
security: security_data::test::CLIENT_SECURITY_DATA.clone(), security: security_data::test::CLIENT_SECURITY_DATA.clone(),
network: Some(network_data::test::CLIENT_NETOWORK_DATA_WITH_CHANNELS.clone()), network: Some(network_data::test::CLIENT_NETOWORK_DATA_WITH_CHANNELS.clone()),
cluster: None, cluster: None,
@ -83,8 +82,7 @@ lazy_static! {
pub static ref CLIENT_GCC_WITH_ALL_OPTIONAL_FIELDS: ClientGccBlocks = { pub static ref CLIENT_GCC_WITH_ALL_OPTIONAL_FIELDS: ClientGccBlocks = {
let mut data = CLIENT_GCC_WITH_CLUSTER_OPTIONAL_FIELD.clone(); let mut data = CLIENT_GCC_WITH_CLUSTER_OPTIONAL_FIELD.clone();
data.monitor = Some(monitor_data::test::MONITOR_DATA_WITH_MONITORS.clone()); data.monitor = Some(monitor_data::test::MONITOR_DATA_WITH_MONITORS.clone());
data.monitor_extended = data.monitor_extended = Some(monitor_extended_data::test::MONITOR_DATA_WITH_MONITORS.clone());
Some(monitor_extended_data::test::MONITOR_DATA_WITH_MONITORS.clone());
data data
}; };
@ -98,16 +96,14 @@ lazy_static! {
pub static ref SERVER_GCC_WITH_OPTIONAL_FIELDS: ServerGccBlocks = { pub static ref SERVER_GCC_WITH_OPTIONAL_FIELDS: ServerGccBlocks = {
let mut data = SERVER_GCC_WITHOUT_OPTIONAL_FIELDS.clone(); let mut data = SERVER_GCC_WITHOUT_OPTIONAL_FIELDS.clone();
data.message_channel = Some(message_channel_data::test::SERVER_GCC_MESSAGE_CHANNEL_BLOCK); data.message_channel = Some(message_channel_data::test::SERVER_GCC_MESSAGE_CHANNEL_BLOCK);
data.multi_transport_channel = Some( data.multi_transport_channel =
multi_transport_channel_data::test::SERVER_GCC_MULTI_TRANSPORT_CHANNEL_BLOCK.clone(), Some(multi_transport_channel_data::test::SERVER_GCC_MULTI_TRANSPORT_CHANNEL_BLOCK.clone());
);
data data
}; };
pub static ref CLIENT_GCC_CORE_BLOCK_BUFFER: Vec<u8> = make_gcc_block_buffer( pub static ref CLIENT_GCC_CORE_BLOCK_BUFFER: Vec<u8> = make_gcc_block_buffer(
ClientGccType::CoreData, ClientGccType::CoreData,
core_data::client::test::CLIENT_OPTIONAL_CORE_DATA_TO_SERVER_SELECTED_PROTOCOL_BUFFER core_data::client::test::CLIENT_OPTIONAL_CORE_DATA_TO_SERVER_SELECTED_PROTOCOL_BUFFER.as_ref(),
.as_ref(),
); );
pub static ref CLIENT_GCC_SECURITY_BLOCK_BUFFER: Vec<u8> = make_gcc_block_buffer( pub static ref CLIENT_GCC_SECURITY_BLOCK_BUFFER: Vec<u8> = make_gcc_block_buffer(
ClientGccType::SecurityData, ClientGccType::SecurityData,
@ -147,19 +143,14 @@ lazy_static! {
); );
pub static ref SERVER_GCC_MULTI_TRANSPORT_CHANNEL_BLOCK_BUFFER: Vec<u8> = make_gcc_block_buffer( pub static ref SERVER_GCC_MULTI_TRANSPORT_CHANNEL_BLOCK_BUFFER: Vec<u8> = make_gcc_block_buffer(
ServerGccType::MultiTransportChannelData, ServerGccType::MultiTransportChannelData,
multi_transport_channel_data::test::SERVER_GCC_MULTI_TRANSPORT_CHANNEL_BLOCK_BUFFER multi_transport_channel_data::test::SERVER_GCC_MULTI_TRANSPORT_CHANNEL_BLOCK_BUFFER.as_ref(),
.as_ref(),
); );
} }
fn make_gcc_block_buffer<T: FromPrimitive + ToPrimitive>(data_type: T, buffer: &[u8]) -> Vec<u8> { fn make_gcc_block_buffer<T: FromPrimitive + ToPrimitive>(data_type: T, buffer: &[u8]) -> Vec<u8> {
let mut result = Vec::new(); let mut result = Vec::new();
result.extend(data_type.to_u16().unwrap().to_le_bytes().as_ref()); result.extend(data_type.to_u16().unwrap().to_le_bytes().as_ref());
result.extend( result.extend(((buffer.len() + USER_HEADER_LEN) as u16).to_le_bytes().as_ref());
((buffer.len() + USER_HEADER_LEN) as u16)
.to_le_bytes()
.as_ref(),
);
result.extend(buffer.as_ref()); result.extend(buffer.as_ref());
result result

View file

@ -7,11 +7,6 @@ mod tests;
pub mod unicode; pub mod unicode;
pub mod unused; pub mod unused;
pub use self::{
mouse::MousePdu, mouse_x::MouseXPdu, scan_code::ScanCodePdu, sync::SyncPdu,
unicode::UnicodePdu, unused::UnusedPdu,
};
use std::io; use std::io;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
@ -19,6 +14,12 @@ use failure::Fail;
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
pub use self::mouse::MousePdu;
pub use self::mouse_x::MouseXPdu;
pub use self::scan_code::ScanCodePdu;
pub use self::sync::SyncPdu;
pub use self::unicode::UnicodePdu;
pub use self::unused::UnusedPdu;
use crate::{impl_from_error, PduParsing}; use crate::{impl_from_error, PduParsing};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -70,8 +71,8 @@ impl PduParsing for InputEvent {
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> { fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
let _event_time = stream.read_u32::<LittleEndian>()?; // ignored by a server let _event_time = stream.read_u32::<LittleEndian>()?; // ignored by a server
let event_type = stream.read_u16::<LittleEndian>()?; let event_type = stream.read_u16::<LittleEndian>()?;
let event_type = InputEventType::from_u16(event_type) let event_type =
.ok_or(InputEventError::InvalidInputEventType(event_type))?; InputEventType::from_u16(event_type).ok_or(InputEventError::InvalidInputEventType(event_type))?;
match event_type { match event_type {
InputEventType::Sync => Ok(Self::Sync(SyncPdu::from_buffer(&mut stream)?)), InputEventType::Sync => Ok(Self::Sync(SyncPdu::from_buffer(&mut stream)?)),

View file

@ -51,8 +51,7 @@ impl PduParsing for MousePdu {
} else { } else {
WheelEvents::empty() WheelEvents::empty()
}; };
let number_of_wheel_rotations = let number_of_wheel_rotations = self.number_of_wheel_rotations as u16 & !WHEEL_ROTATION_MASK;
self.number_of_wheel_rotations as u16 & !WHEEL_ROTATION_MASK;
let flags = self.wheel_events.bits() let flags = self.wheel_events.bits()
| self.movement_events.bits() | self.movement_events.bits()

View file

@ -20,10 +20,7 @@ impl PduParsing for UnicodePdu {
let unicode_code = stream.read_u16::<LittleEndian>()?; let unicode_code = stream.read_u16::<LittleEndian>()?;
let _padding = stream.read_u16::<LittleEndian>()?; let _padding = stream.read_u16::<LittleEndian>()?;
Ok(Self { Ok(Self { flags, unicode_code })
flags,
unicode_code,
})
} }
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {

View file

@ -12,19 +12,17 @@ mod preconnection;
mod utils; mod utils;
mod x224; mod x224;
pub use crate::{ pub use crate::basic_output::{bitmap, fast_path, surface_commands};
basic_output::{bitmap, fast_path, surface_commands}, pub use crate::mcs::{ConnectInitial, ConnectResponse, McsError, McsPdu, SendDataContext};
mcs::{ConnectInitial, ConnectResponse, McsError, McsPdu, SendDataContext}, pub use crate::nego::*;
nego::*, pub use crate::preconnection::{PreconnectionPdu, PreconnectionPduError};
preconnection::{PreconnectionPdu, PreconnectionPduError}, pub use crate::rdp::vc::dvc;
rdp::{ pub use crate::rdp::{
vc::dvc, CapabilitySet, ClientConfirmActive, ClientInfoPdu, ControlAction, DemandActive, CapabilitySet, ClientConfirmActive, ClientInfoPdu, ControlAction, DemandActive, ServerDemandActive,
ServerDemandActive, ShareControlHeader, ShareControlPdu, ShareDataHeader, ShareDataPdu, ShareControlHeader, ShareControlPdu, ShareDataHeader, ShareDataPdu, VirtualChannel,
VirtualChannel,
},
utils::Rectangle,
x224::*,
}; };
pub use crate::utils::Rectangle;
pub use crate::x224::*;
pub trait PduParsing { pub trait PduParsing {
type Error; type Error;
@ -65,13 +63,11 @@ impl PduParsing for RdpPdu {
let action = Action::from_u8(action).ok_or(RdpError::InvalidActionCode(action))?; let action = Action::from_u8(action).ok_or(RdpError::InvalidActionCode(action))?;
match action { match action {
Action::X224 => Ok(Self::X224(x224::Data::from_buffer_with_version( Action::X224 => Ok(Self::X224(x224::Data::from_buffer_with_version(&mut stream, header)?)),
Action::FastPath => Ok(Self::FastPath(fast_path::FastPathHeader::from_buffer_with_header(
&mut stream, &mut stream,
header, header,
)?)), )?)),
Action::FastPath => Ok(Self::FastPath(
fast_path::FastPathHeader::from_buffer_with_header(&mut stream, header)?,
)),
} }
} }

View file

@ -2,8 +2,6 @@ mod connect_initial;
#[cfg(test)] #[cfg(test)]
mod test; mod test;
pub use self::connect_initial::{ConnectInitial, ConnectResponse, DomainParameters};
use std::io; use std::io;
use byteorder::{ReadBytesExt, WriteBytesExt}; use byteorder::{ReadBytesExt, WriteBytesExt};
@ -11,7 +9,9 @@ use failure::Fail;
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
use crate::{gcc::GccError, impl_from_error, per, PduParsing}; pub use self::connect_initial::{ConnectInitial, ConnectResponse, DomainParameters};
use crate::gcc::GccError;
use crate::{impl_from_error, per, PduParsing};
pub const RESULT_ENUM_LENGTH: u8 = 16; pub const RESULT_ENUM_LENGTH: u8 = 16;
@ -54,28 +54,26 @@ impl PduParsing for McsPdu {
let mcs_pdu = DomainMcsPdu::from_u8(choice >> 2).ok_or(McsError::InvalidDomainMcsPdu)?; let mcs_pdu = DomainMcsPdu::from_u8(choice >> 2).ok_or(McsError::InvalidDomainMcsPdu)?;
match mcs_pdu { match mcs_pdu {
DomainMcsPdu::ErectDomainRequest => Ok(McsPdu::ErectDomainRequest( DomainMcsPdu::ErectDomainRequest => {
ErectDomainPdu::from_buffer(&mut stream)?, Ok(McsPdu::ErectDomainRequest(ErectDomainPdu::from_buffer(&mut stream)?))
)), }
DomainMcsPdu::AttachUserRequest => Ok(McsPdu::AttachUserRequest), DomainMcsPdu::AttachUserRequest => Ok(McsPdu::AttachUserRequest),
DomainMcsPdu::AttachUserConfirm => Ok(McsPdu::AttachUserConfirm( DomainMcsPdu::AttachUserConfirm => Ok(McsPdu::AttachUserConfirm(AttachUserConfirmPdu::from_buffer(
AttachUserConfirmPdu::from_buffer(&mut stream)?, &mut stream,
)), )?)),
DomainMcsPdu::ChannelJoinRequest => Ok(McsPdu::ChannelJoinRequest( DomainMcsPdu::ChannelJoinRequest => Ok(McsPdu::ChannelJoinRequest(ChannelJoinRequestPdu::from_buffer(
ChannelJoinRequestPdu::from_buffer(&mut stream)?, &mut stream,
)), )?)),
DomainMcsPdu::ChannelJoinConfirm => Ok(McsPdu::ChannelJoinConfirm( DomainMcsPdu::ChannelJoinConfirm => Ok(McsPdu::ChannelJoinConfirm(ChannelJoinConfirmPdu::from_buffer(
ChannelJoinConfirmPdu::from_buffer(&mut stream)?, &mut stream,
)), )?)),
DomainMcsPdu::DisconnectProviderUltimatum => Ok(McsPdu::DisconnectProviderUltimatum( DomainMcsPdu::DisconnectProviderUltimatum => Ok(McsPdu::DisconnectProviderUltimatum(
DisconnectUltimatumReason::from_choice(&mut stream, choice)?, DisconnectUltimatumReason::from_choice(&mut stream, choice)?,
)), )),
DomainMcsPdu::SendDataRequest => Ok(McsPdu::SendDataRequest( DomainMcsPdu::SendDataRequest => Ok(McsPdu::SendDataRequest(SendDataContext::from_buffer(&mut stream)?)),
SendDataContext::from_buffer(&mut stream)?, DomainMcsPdu::SendDataIndication => {
)), Ok(McsPdu::SendDataIndication(SendDataContext::from_buffer(&mut stream)?))
DomainMcsPdu::SendDataIndication => Ok(McsPdu::SendDataIndication( }
SendDataContext::from_buffer(&mut stream)?,
)),
} }
} }
@ -92,25 +90,14 @@ impl PduParsing for McsPdu {
McsPdu::SendDataRequest(_) => (DomainMcsPdu::SendDataRequest, 0), McsPdu::SendDataRequest(_) => (DomainMcsPdu::SendDataRequest, 0),
McsPdu::SendDataIndication(_) => (DomainMcsPdu::SendDataIndication, 0), McsPdu::SendDataIndication(_) => (DomainMcsPdu::SendDataIndication, 0),
}; };
per::write_choice( per::write_choice(&mut stream, (domain_mcs_pdu.to_u8().unwrap() << 2) | options)?;
&mut stream,
(domain_mcs_pdu.to_u8().unwrap() << 2) | options,
)?;
match self { match self {
McsPdu::ErectDomainRequest(erect_domain_request) => { McsPdu::ErectDomainRequest(erect_domain_request) => erect_domain_request.to_buffer(&mut stream)?,
erect_domain_request.to_buffer(&mut stream)?
}
McsPdu::AttachUserRequest => (), McsPdu::AttachUserRequest => (),
McsPdu::AttachUserConfirm(attach_user_confirm_pdu) => { McsPdu::AttachUserConfirm(attach_user_confirm_pdu) => attach_user_confirm_pdu.to_buffer(&mut stream)?,
attach_user_confirm_pdu.to_buffer(&mut stream)? McsPdu::ChannelJoinRequest(channel_join_request_pdu) => channel_join_request_pdu.to_buffer(&mut stream)?,
} McsPdu::ChannelJoinConfirm(channel_join_confirm_pdu) => channel_join_confirm_pdu.to_buffer(&mut stream)?,
McsPdu::ChannelJoinRequest(channel_join_request_pdu) => {
channel_join_request_pdu.to_buffer(&mut stream)?
}
McsPdu::ChannelJoinConfirm(channel_join_confirm_pdu) => {
channel_join_confirm_pdu.to_buffer(&mut stream)?
}
McsPdu::DisconnectProviderUltimatum(reason) => reason.to_buffer(&mut stream)?, McsPdu::DisconnectProviderUltimatum(reason) => reason.to_buffer(&mut stream)?,
McsPdu::SendDataRequest(send_data) => send_data.to_buffer(&mut stream)?, McsPdu::SendDataRequest(send_data) => send_data.to_buffer(&mut stream)?,
McsPdu::SendDataIndication(send_data) => send_data.to_buffer(&mut stream)?, McsPdu::SendDataIndication(send_data) => send_data.to_buffer(&mut stream)?,
@ -121,19 +108,11 @@ impl PduParsing for McsPdu {
fn buffer_length(&self) -> usize { fn buffer_length(&self) -> usize {
let pdu_length = match self { let pdu_length = match self {
McsPdu::ErectDomainRequest(erect_domain_request) => { McsPdu::ErectDomainRequest(erect_domain_request) => erect_domain_request.buffer_length(),
erect_domain_request.buffer_length()
}
McsPdu::AttachUserRequest => 0, McsPdu::AttachUserRequest => 0,
McsPdu::AttachUserConfirm(attach_user_confirm_pdu) => { McsPdu::AttachUserConfirm(attach_user_confirm_pdu) => attach_user_confirm_pdu.buffer_length(),
attach_user_confirm_pdu.buffer_length() McsPdu::ChannelJoinRequest(channel_join_request_pdu) => channel_join_request_pdu.buffer_length(),
} McsPdu::ChannelJoinConfirm(channel_join_confirm_pdu) => channel_join_confirm_pdu.buffer_length(),
McsPdu::ChannelJoinRequest(channel_join_request_pdu) => {
channel_join_request_pdu.buffer_length()
}
McsPdu::ChannelJoinConfirm(channel_join_confirm_pdu) => {
channel_join_confirm_pdu.buffer_length()
}
McsPdu::DisconnectProviderUltimatum(reason) => reason.buffer_length(), McsPdu::DisconnectProviderUltimatum(reason) => reason.buffer_length(),
McsPdu::SendDataRequest(send_data) => send_data.buffer_length(), McsPdu::SendDataRequest(send_data) => send_data.buffer_length(),
McsPdu::SendDataIndication(send_data) => send_data.buffer_length(), McsPdu::SendDataIndication(send_data) => send_data.buffer_length(),
@ -335,14 +314,12 @@ impl DisconnectUltimatumReason {
fn from_choice(mut stream: impl io::Read, choice: u8) -> Result<Self, McsError> { fn from_choice(mut stream: impl io::Read, choice: u8) -> Result<Self, McsError> {
let b = per::read_choice(&mut stream)?; let b = per::read_choice(&mut stream)?;
Self::from_u8(((choice & 0x01) << 1) | (b >> 7)) Self::from_u8(((choice & 0x01) << 1) | (b >> 7)).ok_or(McsError::InvalidDisconnectProviderUltimatum)
.ok_or(McsError::InvalidDisconnectProviderUltimatum)
} }
fn to_buffer(self, mut stream: impl io::Write) -> Result<(), McsError> { fn to_buffer(self, mut stream: impl io::Write) -> Result<(), McsError> {
let enumerated = match self { let enumerated = match self {
DisconnectUltimatumReason::UserRequested DisconnectUltimatumReason::UserRequested | DisconnectUltimatumReason::ProviderInitiated => 0x80,
| DisconnectUltimatumReason::ProviderInitiated => 0x80,
_ => 0x40, _ => 0x40,
}; };
per::write_enum(&mut stream, enumerated)?; per::write_enum(&mut stream, enumerated)?;
@ -382,9 +359,6 @@ impl_from_error!(GccError, McsError, McsError::GccError);
impl From<McsError> for io::Error { impl From<McsError> for io::Error {
fn from(e: McsError) -> io::Error { fn from(e: McsError) -> io::Error {
io::Error::new( io::Error::new(io::ErrorKind::Other, format!("MCS Connection Sequence error: {}", e))
io::ErrorKind::Other,
format!("MCS Connection Sequence error: {}", e),
)
} }
} }

View file

@ -4,14 +4,9 @@ mod test;
use std::io; use std::io;
use super::{McsError, RESULT_ENUM_LENGTH}; use super::{McsError, RESULT_ENUM_LENGTH};
use crate::{ use crate::gcc::conference_create::{ConferenceCreateRequest, ConferenceCreateResponse};
ber, use crate::gcc::{Channel, ClientGccBlocks};
gcc::{ use crate::{ber, PduParsing};
conference_create::{ConferenceCreateRequest, ConferenceCreateResponse},
Channel, ClientGccBlocks,
},
PduParsing,
};
const MCS_TYPE_CONNECT_INITIAL: u8 = 0x65; const MCS_TYPE_CONNECT_INITIAL: u8 = 0x65;
const MCS_TYPE_CONNECT_RESPONSE: u8 = 0x66; const MCS_TYPE_CONNECT_RESPONSE: u8 = 0x66;
@ -81,21 +76,14 @@ impl PduParsing for ConnectInitial {
} }
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), McsError> { fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), McsError> {
ber::write_application_tag( ber::write_application_tag(&mut stream, MCS_TYPE_CONNECT_INITIAL, self.fields_buffer_ber_length())?;
&mut stream,
MCS_TYPE_CONNECT_INITIAL,
self.fields_buffer_ber_length(),
)?;
ber::write_octet_string(&mut stream, self.calling_domain_selector.as_ref())?; ber::write_octet_string(&mut stream, self.calling_domain_selector.as_ref())?;
ber::write_octet_string(&mut stream, self.called_domain_selector.as_ref())?; ber::write_octet_string(&mut stream, self.called_domain_selector.as_ref())?;
ber::write_bool(&mut stream, self.upward_flag)?; ber::write_bool(&mut stream, self.upward_flag)?;
self.target_parameters.to_buffer(&mut stream)?; self.target_parameters.to_buffer(&mut stream)?;
self.min_parameters.to_buffer(&mut stream)?; self.min_parameters.to_buffer(&mut stream)?;
self.max_parameters.to_buffer(&mut stream)?; self.max_parameters.to_buffer(&mut stream)?;
ber::write_octet_string_tag( ber::write_octet_string_tag(&mut stream, self.conference_create_request.buffer_length() as u16)?;
&mut stream,
self.conference_create_request.buffer_length() as u16,
)?;
self.conference_create_request.to_buffer(&mut stream)?; self.conference_create_request.to_buffer(&mut stream)?;
Ok(()) Ok(())
@ -104,8 +92,7 @@ impl PduParsing for ConnectInitial {
fn buffer_length(&self) -> usize { fn buffer_length(&self) -> usize {
let fields_buffer_ber_length = self.fields_buffer_ber_length(); let fields_buffer_ber_length = self.fields_buffer_ber_length();
(fields_buffer_ber_length (fields_buffer_ber_length + ber::sizeof_application_tag(MCS_TYPE_CONNECT_INITIAL, fields_buffer_ber_length))
+ ber::sizeof_application_tag(MCS_TYPE_CONNECT_INITIAL, fields_buffer_ber_length))
as usize as usize
} }
} }
@ -122,9 +109,7 @@ impl ConnectResponse {
self.conference_create_response.gcc_blocks.channel_ids() self.conference_create_response.gcc_blocks.channel_ids()
} }
pub fn global_channel_id(&self) -> u16 { pub fn global_channel_id(&self) -> u16 {
self.conference_create_response self.conference_create_response.gcc_blocks.global_channel_id()
.gcc_blocks
.global_channel_id()
} }
fn fields_buffer_ber_length(&self) -> u16 { fn fields_buffer_ber_length(&self) -> u16 {
@ -154,18 +139,11 @@ impl PduParsing for ConnectResponse {
} }
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), McsError> { fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), McsError> {
ber::write_application_tag( ber::write_application_tag(&mut stream, MCS_TYPE_CONNECT_RESPONSE, self.fields_buffer_ber_length())?;
&mut stream,
MCS_TYPE_CONNECT_RESPONSE,
self.fields_buffer_ber_length(),
)?;
ber::write_enumerated(&mut stream, 0)?; ber::write_enumerated(&mut stream, 0)?;
ber::write_integer(&mut stream, self.called_connect_id)?; ber::write_integer(&mut stream, self.called_connect_id)?;
self.domain_parameters.to_buffer(&mut stream)?; self.domain_parameters.to_buffer(&mut stream)?;
ber::write_octet_string_tag( ber::write_octet_string_tag(&mut stream, self.conference_create_response.buffer_length() as u16)?;
&mut stream,
self.conference_create_response.buffer_length() as u16,
)?;
self.conference_create_response.to_buffer(&mut stream)?; self.conference_create_response.to_buffer(&mut stream)?;
Ok(()) Ok(())
@ -174,8 +152,7 @@ impl PduParsing for ConnectResponse {
fn buffer_length(&self) -> usize { fn buffer_length(&self) -> usize {
let fields_buffer_ber_length = self.fields_buffer_ber_length(); let fields_buffer_ber_length = self.fields_buffer_ber_length();
(fields_buffer_ber_length (fields_buffer_ber_length + ber::sizeof_application_tag(MCS_TYPE_CONNECT_RESPONSE, fields_buffer_ber_length))
+ ber::sizeof_application_tag(MCS_TYPE_CONNECT_RESPONSE, fields_buffer_ber_length))
as usize as usize
} }
} }

View file

@ -5,20 +5,19 @@ use crate::gcc::conference_create;
const CONNECT_INITIAL_PREFIX_BUFFER_LEN: usize = 107; const CONNECT_INITIAL_PREFIX_BUFFER_LEN: usize = 107;
const CONNECT_INITIAL_PREFIX_BUFFER: [u8; CONNECT_INITIAL_PREFIX_BUFFER_LEN] = [ const CONNECT_INITIAL_PREFIX_BUFFER: [u8; CONNECT_INITIAL_PREFIX_BUFFER_LEN] = [
0x7f, 0x65, 0x82, 0x01, 0x99, 0x04, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0xff, 0x30, 0x1a, 0x7f, 0x65, 0x82, 0x01, 0x99, 0x04, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0xff, 0x30, 0x1a, 0x02, 0x01, 0x22,
0x02, 0x01, 0x22, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x02, 0x03, 0x00, 0xff,
0x01, 0x01, 0x02, 0x03, 0x00, 0xff, 0xff, 0x02, 0x01, 0x02, 0x30, 0x19, 0x02, 0x01, 0x01, 0x02, 0xff, 0x02, 0x01, 0x02, 0x30, 0x19, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02,
0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x20, 0x02, 0x01, 0x02, 0x30, 0x20, 0x02, 0x03, 0x00, 0xff, 0xff,
0x04, 0x20, 0x02, 0x01, 0x02, 0x30, 0x20, 0x02, 0x03, 0x00, 0xff, 0xff, 0x02, 0x03, 0x00, 0xfc, 0x02, 0x03, 0x00, 0xfc, 0x17, 0x02, 0x03, 0x00, 0xff, 0xff, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x02, 0x01, 0x01,
0x17, 0x02, 0x03, 0x00, 0xff, 0xff, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x03, 0x00, 0xff, 0xff, 0x02, 0x01, 0x02, 0x04, 0x82, 0x01, 0x33,
0x03, 0x00, 0xff, 0xff, 0x02, 0x01, 0x02, 0x04, 0x82, 0x01, 0x33,
]; ];
const CONNECT_RESPONSE_PREFIX_BUFFER_LEN: usize = 43; const CONNECT_RESPONSE_PREFIX_BUFFER_LEN: usize = 43;
const CONNECT_RESPONSE_PREFIX_BUFFER: [u8; CONNECT_RESPONSE_PREFIX_BUFFER_LEN] = [ const CONNECT_RESPONSE_PREFIX_BUFFER: [u8; CONNECT_RESPONSE_PREFIX_BUFFER_LEN] = [
0x7f, 0x66, 0x82, 0x01, 0x46, 0x0a, 0x01, 0x00, 0x02, 0x01, 0x00, 0x30, 0x1a, 0x02, 0x01, 0x22, 0x7f, 0x66, 0x82, 0x01, 0x46, 0x0a, 0x01, 0x00, 0x02, 0x01, 0x00, 0x30, 0x1a, 0x02, 0x01, 0x22, 0x02, 0x01, 0x03,
0x02, 0x01, 0x03, 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x02, 0x03, 0x00, 0xff, 0xf8, 0x02, 0x01,
0x03, 0x00, 0xff, 0xf8, 0x02, 0x01, 0x02, 0x04, 0x82, 0x01, 0x20, 0x02, 0x04, 0x82, 0x01, 0x20,
]; ];
lazy_static! { lazy_static! {

View file

@ -10,20 +10,17 @@ const ATTACH_USER_REQUEST_PDU_BUFFER_LEN: usize = 1;
const ATTACH_USER_REQUEST_PDU_BUFFER: [u8; ATTACH_USER_REQUEST_PDU_BUFFER_LEN] = [0x28]; const ATTACH_USER_REQUEST_PDU_BUFFER: [u8; ATTACH_USER_REQUEST_PDU_BUFFER_LEN] = [0x28];
const ATTACH_USER_CONFIRM_PDU_BUFFER_LEN: usize = 4; const ATTACH_USER_CONFIRM_PDU_BUFFER_LEN: usize = 4;
const ATTACH_USER_CONFIRM_PDU_BUFFER: [u8; ATTACH_USER_CONFIRM_PDU_BUFFER_LEN] = const ATTACH_USER_CONFIRM_PDU_BUFFER: [u8; ATTACH_USER_CONFIRM_PDU_BUFFER_LEN] = [0x2e, 0x00, 0x00, 0x06];
[0x2e, 0x00, 0x00, 0x06];
const CHANNEL_JOIN_REQUEST_PDU_BUFFER_LEN: usize = 5; const CHANNEL_JOIN_REQUEST_PDU_BUFFER_LEN: usize = 5;
const CHANNEL_JOIN_REQUEST_PDU_BUFFER: [u8; CHANNEL_JOIN_REQUEST_PDU_BUFFER_LEN] = const CHANNEL_JOIN_REQUEST_PDU_BUFFER: [u8; CHANNEL_JOIN_REQUEST_PDU_BUFFER_LEN] = [0x38, 0x00, 0x06, 0x03, 0xef];
[0x38, 0x00, 0x06, 0x03, 0xef];
const CHANNEL_JOIN_CONFIRM_PDU_BUFFER_LEN: usize = 8; const CHANNEL_JOIN_CONFIRM_PDU_BUFFER_LEN: usize = 8;
const CHANNEL_JOIN_CONFIRM_PDU_BUFFER: [u8; CHANNEL_JOIN_CONFIRM_PDU_BUFFER_LEN] = const CHANNEL_JOIN_CONFIRM_PDU_BUFFER: [u8; CHANNEL_JOIN_CONFIRM_PDU_BUFFER_LEN] =
[0x3e, 0x00, 0x00, 0x06, 0x03, 0xef, 0x03, 0xef]; [0x3e, 0x00, 0x00, 0x06, 0x03, 0xef, 0x03, 0xef];
const DISCONNECT_PROVIDER_ULTIMATUM_PDU_BUFFER_LEN: usize = 2; const DISCONNECT_PROVIDER_ULTIMATUM_PDU_BUFFER_LEN: usize = 2;
const DISCONNECT_PROVIDER_ULTIMATUM_PDU_BUFFER: [u8; DISCONNECT_PROVIDER_ULTIMATUM_PDU_BUFFER_LEN] = const DISCONNECT_PROVIDER_ULTIMATUM_PDU_BUFFER: [u8; DISCONNECT_PROVIDER_ULTIMATUM_PDU_BUFFER_LEN] = [0x21, 0x80];
[0x21, 0x80];
const SEND_DATA_REQUEST_PDU_BUFFER_PREFIX_LEN: usize = 8; const SEND_DATA_REQUEST_PDU_BUFFER_PREFIX_LEN: usize = 8;
const SEND_DATA_REQUEST_PDU_BUFFER_PREFIX: [u8; SEND_DATA_REQUEST_PDU_BUFFER_PREFIX_LEN] = const SEND_DATA_REQUEST_PDU_BUFFER_PREFIX: [u8; SEND_DATA_REQUEST_PDU_BUFFER_PREFIX_LEN] =
@ -82,9 +79,7 @@ lazy_static! {
#[test] #[test]
fn from_buffer_returns_error_with_invalid_domain_mcs_pdu() { fn from_buffer_returns_error_with_invalid_domain_mcs_pdu() {
let buf = vec![ let buf = vec![0x48, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x03, 0xEB, 0x70, 0x14];
0x48, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x03, 0xEB, 0x70, 0x14,
];
match McsPdu::from_buffer(&mut buf.as_slice()) { match McsPdu::from_buffer(&mut buf.as_slice()) {
Err(McsError::InvalidDomainMcsPdu) => (), Err(McsError::InvalidDomainMcsPdu) => (),
@ -124,10 +119,7 @@ fn buffer_length_is_correct_for_erect_domain_request() {
fn from_buffer_correct_parses_attach_user_request() { fn from_buffer_correct_parses_attach_user_request() {
let buf = ATTACH_USER_REQUEST_PDU_BUFFER; let buf = ATTACH_USER_REQUEST_PDU_BUFFER;
assert_eq!( assert_eq!(ATTACH_USER_REQUEST_PDU, McsPdu::from_buffer(buf.as_ref()).unwrap());
ATTACH_USER_REQUEST_PDU,
McsPdu::from_buffer(buf.as_ref()).unwrap()
);
} }
#[test] #[test]
@ -155,10 +147,7 @@ fn buffer_length_is_correct_for_attach_user_request() {
fn from_buffer_correct_parses_attach_user_confirm() { fn from_buffer_correct_parses_attach_user_confirm() {
let buf = ATTACH_USER_CONFIRM_PDU_BUFFER; let buf = ATTACH_USER_CONFIRM_PDU_BUFFER;
assert_eq!( assert_eq!(ATTACH_USER_CONFIRM_PDU, McsPdu::from_buffer(buf.as_ref()).unwrap());
ATTACH_USER_CONFIRM_PDU,
McsPdu::from_buffer(buf.as_ref()).unwrap()
);
} }
#[test] #[test]
@ -186,10 +175,7 @@ fn buffer_length_is_correct_for_attach_user_confirm() {
fn from_buffer_correct_parses_channel_join_request() { fn from_buffer_correct_parses_channel_join_request() {
let buf = CHANNEL_JOIN_REQUEST_PDU_BUFFER; let buf = CHANNEL_JOIN_REQUEST_PDU_BUFFER;
assert_eq!( assert_eq!(CHANNEL_JOIN_REQUEST_PDU, McsPdu::from_buffer(buf.as_ref()).unwrap());
CHANNEL_JOIN_REQUEST_PDU,
McsPdu::from_buffer(buf.as_ref()).unwrap()
);
} }
#[test] #[test]
@ -217,10 +203,7 @@ fn buffer_length_is_correct_for_channel_join_request() {
fn from_buffer_correct_parses_channel_join_confirm() { fn from_buffer_correct_parses_channel_join_confirm() {
let buf = CHANNEL_JOIN_CONFIRM_PDU_BUFFER; let buf = CHANNEL_JOIN_CONFIRM_PDU_BUFFER;
assert_eq!( assert_eq!(CHANNEL_JOIN_CONFIRM_PDU, McsPdu::from_buffer(buf.as_ref()).unwrap());
CHANNEL_JOIN_CONFIRM_PDU,
McsPdu::from_buffer(buf.as_ref()).unwrap()
);
} }
#[test] #[test]

View file

@ -1,7 +1,8 @@
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
use std::io::{self, prelude::*}; use std::io::prelude::*;
use std::io::{self};
use bitflags::bitflags; use bitflags::bitflags;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
@ -9,11 +10,8 @@ use failure::Fail;
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
use crate::{ use crate::x224::{TpktHeader, X224TPDUType, TPDU_REQUEST_LENGTH, TPKT_HEADER_LENGTH};
impl_from_error, use crate::{impl_from_error, PduParsing};
x224::{TpktHeader, X224TPDUType, TPDU_REQUEST_LENGTH, TPKT_HEADER_LENGTH},
PduParsing,
};
const COOKIE_PREFIX: &str = "Cookie: mstshash="; const COOKIE_PREFIX: &str = "Cookie: mstshash=";
const ROUTING_TOKEN_PREFIX: &str = "Cookie: msts="; const ROUTING_TOKEN_PREFIX: &str = "Cookie: msts=";
@ -203,9 +201,7 @@ impl PduParsing for Request {
match &self.nego_data { match &self.nego_data {
Some(NegoData::Cookie(s)) => writeln!(&mut stream, "{}{}\r", COOKIE_PREFIX, s)?, Some(NegoData::Cookie(s)) => writeln!(&mut stream, "{}{}\r", COOKIE_PREFIX, s)?,
Some(NegoData::RoutingToken(s)) => { Some(NegoData::RoutingToken(s)) => writeln!(&mut stream, "{}{}\r", ROUTING_TOKEN_PREFIX, s)?,
writeln!(&mut stream, "{}{}\r", ROUTING_TOKEN_PREFIX, s)?
}
None => (), None => (),
} }
@ -223,9 +219,7 @@ impl PduParsing for Request {
TPDU_REQUEST_LENGTH TPDU_REQUEST_LENGTH
+ match &self.nego_data { + match &self.nego_data {
Some(NegoData::Cookie(s)) => s.len() + COOKIE_PREFIX.len() + CR_LF_SEQ_LENGTH, Some(NegoData::Cookie(s)) => s.len() + COOKIE_PREFIX.len() + CR_LF_SEQ_LENGTH,
Some(NegoData::RoutingToken(s)) => { Some(NegoData::RoutingToken(s)) => s.len() + ROUTING_TOKEN_PREFIX.len() + CR_LF_SEQ_LENGTH,
s.len() + ROUTING_TOKEN_PREFIX.len() + CR_LF_SEQ_LENGTH
}
None => 0, None => 0,
} }
+ if self.protocol.bits() > SecurityProtocol::RDP.bits() { + if self.protocol.bits() > SecurityProtocol::RDP.bits() {
@ -278,8 +272,7 @@ impl PduParsing for Response {
match neg_resp { match neg_resp {
Message::Response => { Message::Response => {
let protocol = let protocol = SecurityProtocol::from_bits_truncate(stream.read_u32::<LittleEndian>()?);
SecurityProtocol::from_bits_truncate(stream.read_u32::<LittleEndian>()?);
Ok(Self { Ok(Self {
response: Some(ResponseData::Response { flags, protocol }), response: Some(ResponseData::Response { flags, protocol }),
@ -288,13 +281,12 @@ impl PduParsing for Response {
}) })
} }
Message::Failure => { Message::Failure => {
let error = let error = FailureCode::from_u32(stream.read_u32::<LittleEndian>()?).ok_or_else(|| {
FailureCode::from_u32(stream.read_u32::<LittleEndian>()?).ok_or_else(|| { NegotiationError::IOError(io::Error::new(
NegotiationError::IOError(io::Error::new( io::ErrorKind::InvalidData,
io::ErrorKind::InvalidData, "invalid negotiation failure code",
"invalid negotiation failure code", ))
)) })?;
})?;
Err(NegotiationError::ResponseFailure(error)) Err(NegotiationError::ResponseFailure(error))
} }
@ -350,10 +342,7 @@ fn read_nego_data(stream: &[u8]) -> Option<(NegoData, usize)> {
} }
} }
fn read_string_with_cr_lf( fn read_string_with_cr_lf(mut stream: impl io::BufRead, start: &str) -> io::Result<(String, usize)> {
mut stream: impl io::BufRead,
start: &str,
) -> io::Result<(String, usize)> {
let mut read_start = String::new(); let mut read_start = String::new();
stream stream
.by_ref() .by_ref()
@ -392,10 +381,7 @@ fn read_string_with_cr_lf(
} }
} }
fn read_and_check_class( fn read_and_check_class(mut stream: impl io::Read, required_class: u8) -> Result<(), NegotiationError> {
mut stream: impl io::Read,
required_class: u8,
) -> Result<(), NegotiationError> {
let class = stream.read_u8()?; let class = stream.read_u8()?;
if class != required_class { if class != required_class {

View file

@ -14,10 +14,7 @@ fn rdp_negotiation_data_is_written_to_request_if_nla_security() {
request.to_buffer(&mut buffer).unwrap(); request.to_buffer(&mut buffer).unwrap();
assert_eq!( assert_eq!(buffer[buffer.len() - usize::from(RDP_NEG_DATA_LENGTH)..], expected);
buffer[buffer.len() - usize::from(RDP_NEG_DATA_LENGTH)..],
expected
);
} }
#[test] #[test]
@ -177,8 +174,7 @@ fn negotiation_failure_in_response_results_in_error() {
]; ];
match Response::from_buffer(buffer.as_ref()) { match Response::from_buffer(buffer.as_ref()) {
Err(NegotiationError::ResponseFailure(e)) Err(NegotiationError::ResponseFailure(e)) if e == FailureCode::SSLWithUserAuthRequiredByServer => {}
if e == FailureCode::SSLWithUserAuthRequiredByServer => {}
Err(e) => panic!("wrong error type: {}", e), Err(e) => panic!("wrong error type: {}", e),
_ => panic!("error expected"), _ => panic!("error expected"),
} }
@ -187,8 +183,8 @@ fn negotiation_failure_in_response_results_in_error() {
#[test] #[test]
fn cookie_in_request_is_parsed_correctly() { fn cookie_in_request_is_parsed_correctly() {
let request = [ let request = [
0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x68, 0x61, 0x73, 0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x68, 0x61, 0x73, 0x68, 0x3D, 0x55,
0x68, 0x3D, 0x55, 0x73, 0x65, 0x72, 0x0D, 0x0A, 0xFF, 0xFF, 0x73, 0x65, 0x72, 0x0D, 0x0A, 0xFF, 0xFF,
]; ];
let (nego_data, _read_len) = read_nego_data(request.as_ref()).unwrap(); let (nego_data, _read_len) = read_nego_data(request.as_ref()).unwrap();
@ -202,9 +198,9 @@ fn cookie_in_request_is_parsed_correctly() {
#[test] #[test]
fn routing_token_in_request_is_parsed_correctly() { fn routing_token_in_request_is_parsed_correctly() {
let request = [ let request = [
0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x3D, 0x33, 0x36, 0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x3D, 0x33, 0x36, 0x34, 0x30, 0x32,
0x34, 0x30, 0x32, 0x30, 0x35, 0x32, 0x32, 0x38, 0x2E, 0x31, 0x35, 0x36, 0x32, 0x39, 0x2E, 0x30, 0x35, 0x32, 0x32, 0x38, 0x2E, 0x31, 0x35, 0x36, 0x32, 0x39, 0x2E, 0x30, 0x30, 0x30, 0x30, 0x0D, 0x0A,
0x30, 0x30, 0x30, 0x30, 0x0D, 0x0A, 0xFF, 0xFF, 0xFF, 0xFF,
]; ];
let (nego_data, _read_len) = read_nego_data(request.as_ref()).unwrap(); let (nego_data, _read_len) = read_nego_data(request.as_ref()).unwrap();
@ -218,8 +214,8 @@ fn routing_token_in_request_is_parsed_correctly() {
#[test] #[test]
fn read_string_with_cr_lf_on_non_value_results_in_error() { fn read_string_with_cr_lf_on_non_value_results_in_error() {
let request = [ let request = [
0x6e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x0F, 0x42, 0x73, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x0F, 0x42, 0x73, 0x65, 0x72, 0x0D,
0x65, 0x72, 0x0D, 0x0A, 0xFF, 0xFF, 0x0A, 0xFF, 0xFF,
]; ];
match read_string_with_cr_lf(&mut request.as_ref(), COOKIE_PREFIX) { match read_string_with_cr_lf(&mut request.as_ref(), COOKIE_PREFIX) {
@ -232,8 +228,8 @@ fn read_string_with_cr_lf_on_non_value_results_in_error() {
#[test] #[test]
fn read_string_with_cr_lf_on_unterminated_message_results_in_error() { fn read_string_with_cr_lf_on_unterminated_message_results_in_error() {
let request = [ let request = [
0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x68, 0x61, 0x73, 0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x68, 0x61, 0x73, 0x68, 0x3D, 0x55,
0x68, 0x3D, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x72,
]; ];
match read_string_with_cr_lf(&mut request.as_ref(), COOKIE_PREFIX) { match read_string_with_cr_lf(&mut request.as_ref(), COOKIE_PREFIX) {
@ -246,8 +242,7 @@ fn read_string_with_cr_lf_on_unterminated_message_results_in_error() {
#[test] #[test]
fn read_string_with_cr_lf_on_unterminated_with_cr_message() { fn read_string_with_cr_lf_on_unterminated_with_cr_message() {
let request = [ let request = [
0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x68, 0x61, 0x73, 0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x68, 0x61, 0x73, 0x68, 0x3D, 0x0a,
0x68, 0x3D, 0x0a,
]; ];
match read_string_with_cr_lf(&mut request.as_ref(), COOKIE_PREFIX) { match read_string_with_cr_lf(&mut request.as_ref(), COOKIE_PREFIX) {
@ -259,8 +254,8 @@ fn read_string_with_cr_lf_on_unterminated_with_cr_message() {
#[test] #[test]
fn negotiation_request_with_negotiation_data_is_parsed_correctly() { fn negotiation_request_with_negotiation_data_is_parsed_correctly() {
let expected_flags = RequestFlags::RESTRICTED_ADMIN_MODE_REQUIRED let expected_flags =
| RequestFlags::REDIRECTED_AUTHENTICATION_MODE_REQUIRED; RequestFlags::RESTRICTED_ADMIN_MODE_REQUIRED | RequestFlags::REDIRECTED_AUTHENTICATION_MODE_REQUIRED;
#[rustfmt::skip] #[rustfmt::skip]
let buffer = [ let buffer = [
@ -295,8 +290,8 @@ fn negotiation_request_with_negotiation_data_is_parsed_correctly() {
#[test] #[test]
fn negotiation_request_without_variable_fields_is_parsed_correctly() { fn negotiation_request_without_variable_fields_is_parsed_correctly() {
let expected_flags = RequestFlags::RESTRICTED_ADMIN_MODE_REQUIRED let expected_flags =
| RequestFlags::REDIRECTED_AUTHENTICATION_MODE_REQUIRED; RequestFlags::RESTRICTED_ADMIN_MODE_REQUIRED | RequestFlags::REDIRECTED_AUTHENTICATION_MODE_REQUIRED;
#[rustfmt::skip] #[rustfmt::skip]
let buffer = [ let buffer = [
@ -625,8 +620,7 @@ fn read_and_check_tpdu_header_reads_correct_data_correctly() {
0x00, // class 0x00, // class
]; ];
crate::x224::read_and_check_tpdu_header(buffer.as_ref(), X224TPDUType::ConnectionConfirm) crate::x224::read_and_check_tpdu_header(buffer.as_ref(), X224TPDUType::ConnectionConfirm).unwrap();
.unwrap();
} }
#[test] #[test]
@ -657,8 +651,8 @@ fn invalid_class_is_handeled_correctly() {
#[test] #[test]
fn parse_negotiation_request_correctly_handles_invalid_slice_length() { fn parse_negotiation_request_correctly_handles_invalid_slice_length() {
let request = [ let request = [
0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x68, 0x61, 0x73, 0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x68, 0x61, 0x73, 0x68, 0x3D,
0x68, 0x3D, 0x0a, // failing cookie 0x0a, // failing cookie
]; ];
match Request::from_buffer(request.as_ref()) { match Request::from_buffer(request.as_ref()) {

View file

@ -162,10 +162,7 @@ pub fn read_enum(mut stream: impl io::Read, count: u8) -> io::Result<u8> {
if u16::from(enumerated) + 1 > u16::from(count) { if u16::from(enumerated) + 1 > u16::from(count) {
Err(io::Error::new( Err(io::Error::new(
io::ErrorKind::InvalidData, io::ErrorKind::InvalidData,
format!( format!("Enumerated value ({}) does not fall within expected range", enumerated),
"Enumerated value ({}) does not fall within expected range",
enumerated
),
)) ))
} else { } else {
Ok(enumerated) Ok(enumerated)
@ -199,10 +196,7 @@ pub fn read_object_id(mut stream: impl io::Read) -> io::Result<[u8; OBJECT_ID_LE
Ok(read_object_ids) Ok(read_object_ids)
} }
pub fn write_object_id( pub fn write_object_id(mut stream: impl io::Write, object_ids: [u8; OBJECT_ID_LEN]) -> io::Result<usize> {
mut stream: impl io::Write,
object_ids: [u8; OBJECT_ID_LEN],
) -> io::Result<usize> {
let size = write_length(&mut stream, OBJECT_ID_LEN as u16 - 1)?; let size = write_length(&mut stream, OBJECT_ID_LEN as u16 - 1)?;
let first_two_tuples = object_ids[0] * 40 + object_ids[1]; let first_two_tuples = object_ids[0] * 40 + object_ids[1];
@ -224,11 +218,7 @@ pub fn read_octet_string(mut stream: impl io::Read, min: usize) -> io::Result<Ve
Ok(read_octet_string) Ok(read_octet_string)
} }
pub fn write_octet_string( pub fn write_octet_string(mut stream: impl io::Write, octet_string: &[u8], min: usize) -> io::Result<usize> {
mut stream: impl io::Write,
octet_string: &[u8],
min: usize,
) -> io::Result<usize> {
let length = if octet_string.len() >= min { let length = if octet_string.len() >= min {
octet_string.len() - min octet_string.len() - min
} else { } else {
@ -252,16 +242,8 @@ pub fn read_numeric_string(mut stream: impl io::Read, min: u16) -> io::Result<()
Ok(()) Ok(())
} }
pub fn write_numeric_string( pub fn write_numeric_string(mut stream: impl io::Write, num_str: &[u8], min: usize) -> io::Result<usize> {
mut stream: impl io::Write, let length = if num_str.len() >= min { num_str.len() - min } else { min };
num_str: &[u8],
min: usize,
) -> io::Result<usize> {
let length = if num_str.len() >= min {
num_str.len() - min
} else {
min
};
let mut size = write_length(&mut stream, length as u16)?; let mut size = write_length(&mut stream, length as u16)?;

View file

@ -220,10 +220,7 @@ fn write_numeric_string_is_correct() {
#[test] #[test]
fn read_octet_string_returns_ok() { fn read_octet_string_returns_ok() {
let buf = [0x00, 0x44, 0x75, 0x63, 0x61]; let buf = [0x00, 0x44, 0x75, 0x63, 0x61];
assert_eq!( assert_eq!(b"Duca".as_ref(), read_octet_string(buf.as_ref(), 4).unwrap().as_slice());
b"Duca".as_ref(),
read_octet_string(buf.as_ref(), 4).unwrap().as_slice()
);
} }
#[test] #[test]

View file

@ -5,11 +5,8 @@ use failure::Fail;
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
use crate::{ use crate::utils::{self, SplitTo};
impl_from_error, use crate::{impl_from_error, PduBufferParsing};
utils::{self, SplitTo},
PduBufferParsing,
};
const PRECONNECTION_PDU_V1_SIZE: usize = 16; const PRECONNECTION_PDU_V1_SIZE: usize = 16;
@ -41,8 +38,7 @@ impl PduBufferParsing<'_> for PreconnectionPdu {
buffer.read_u32::<LittleEndian>()?; // flags buffer.read_u32::<LittleEndian>()?; // flags
let version = buffer.read_u32::<LittleEndian>()?; let version = buffer.read_u32::<LittleEndian>()?;
let version = let version = Version::from_u32(version).ok_or(PreconnectionPduError::UnexpectedVersion(version))?;
Version::from_u32(version).ok_or(PreconnectionPduError::UnexpectedVersion(version))?;
let id = buffer.read_u32::<LittleEndian>()?; let id = buffer.read_u32::<LittleEndian>()?;
@ -74,11 +70,7 @@ impl PduBufferParsing<'_> for PreconnectionPdu {
} }
}; };
Ok(Self { Ok(Self { id, cch_pcb, payload })
id,
cch_pcb,
payload,
})
} }
fn to_buffer_consume(&self, buffer: &mut &mut [u8]) -> Result<(), Self::Error> { fn to_buffer_consume(&self, buffer: &mut &mut [u8]) -> Result<(), Self::Error> {
@ -91,11 +83,7 @@ impl PduBufferParsing<'_> for PreconnectionPdu {
if let Some(ref payload) = self.payload { if let Some(ref payload) = self.payload {
buffer.write_u16::<LittleEndian>(payload.len() as u16 + 1)?; // + null terminator buffer.write_u16::<LittleEndian>(payload.len() as u16 + 1)?; // + null terminator
utils::write_string_with_null_terminator( utils::write_string_with_null_terminator(buffer, payload.as_str(), utils::CharacterSet::Unicode)?;
buffer,
payload.as_str(),
utils::CharacterSet::Unicode,
)?;
} }
Ok(()) Ok(())
@ -143,11 +131,7 @@ pub enum PreconnectionPduError {
UnexpectedVersion(u32), UnexpectedVersion(u32),
} }
impl_from_error!( impl_from_error!(io::Error, PreconnectionPduError, PreconnectionPduError::IoError);
io::Error,
PreconnectionPduError,
PreconnectionPduError::IoError
);
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
@ -208,18 +192,12 @@ mod tests {
#[test] #[test]
fn from_buffer_for_preconnection_pdu_returns_error_on_empty_size() { fn from_buffer_for_preconnection_pdu_returns_error_on_empty_size() {
assert!( assert!(PreconnectionPdu::from_buffer(PRECONNECTION_PDU_V1_EMPTY_SIZE_BUFFER.as_ref()).is_err());
PreconnectionPdu::from_buffer(PRECONNECTION_PDU_V1_EMPTY_SIZE_BUFFER.as_ref()).is_err()
);
} }
#[test] #[test]
fn from_buffer_for_preconnection_pdu_returns_error_on_data_length_greater_then_available_data() fn from_buffer_for_preconnection_pdu_returns_error_on_data_length_greater_then_available_data() {
{ assert!(PreconnectionPdu::from_buffer(PRECONNECTION_PDU_V1_LARGE_DATA_LENGTH_BUFFER.as_ref()).is_err());
assert!(PreconnectionPdu::from_buffer(
PRECONNECTION_PDU_V1_LARGE_DATA_LENGTH_BUFFER.as_ref()
)
.is_err());
} }
#[test] #[test]
@ -243,19 +221,12 @@ mod tests {
#[test] #[test]
fn buffer_length_is_correct_for_preconnection_pdu_v1() { fn buffer_length_is_correct_for_preconnection_pdu_v1() {
assert_eq!( assert_eq!(PRECONNECTION_PDU_V1_BUFFER.len(), PRECONNECTION_PDU_V1.buffer_length());
PRECONNECTION_PDU_V1_BUFFER.len(),
PRECONNECTION_PDU_V1.buffer_length()
);
} }
#[test] #[test]
fn from_buffer_for_preconnection_pdu_v2_returns_error_on_payload_size_greater_then_available_data( fn from_buffer_for_preconnection_pdu_v2_returns_error_on_payload_size_greater_then_available_data() {
) { assert!(PreconnectionPdu::from_buffer(PRECONNECTION_PDU_V2_LARGE_PAYLOAD_SIZE_BUFFER.as_ref()).is_err());
assert!(PreconnectionPdu::from_buffer(
PRECONNECTION_PDU_V2_LARGE_PAYLOAD_SIZE_BUFFER.as_ref()
)
.is_err());
} }
#[test] #[test]
@ -279,9 +250,6 @@ mod tests {
#[test] #[test]
fn buffer_length_is_correct_for_preconnection_pdu_v2() { fn buffer_length_is_correct_for_preconnection_pdu_v2() {
assert_eq!( assert_eq!(PRECONNECTION_PDU_V2_BUFFER.len(), PRECONNECTION_PDU_V2.buffer_length());
PRECONNECTION_PDU_V2_BUFFER.len(),
PRECONNECTION_PDU_V2.buffer_length()
);
} }
} }

View file

@ -11,39 +11,32 @@ mod finalization_messages;
mod headers; mod headers;
mod server_error_info; mod server_error_info;
pub use self::{
capability_sets::{
CapabilitySet, CapabilitySetsError, ClientConfirmActive, DemandActive, ServerDemandActive,
VirtualChannel, SERVER_CHANNEL_ID,
},
client_info::{
AddressFamily, ClientInfo, ClientInfoFlags, CompressionType, Credentials, DayOfWeek,
DayOfWeekOccurrence, ExtendedClientInfo, ExtendedClientOptionalInfo, Month,
PerformanceFlags, SystemTime, TimezoneInfo,
},
finalization_messages::{
ControlAction, ControlPdu, FontPdu, MonitorLayoutPdu, SequenceFlags, SynchronizePdu,
},
headers::{
BasicSecurityHeader, BasicSecurityHeaderFlags, CompressionFlags, ShareControlHeader,
ShareControlPdu, ShareControlPduType, ShareDataHeader, ShareDataPdu, ShareDataPduType,
StreamPriority, BASIC_SECURITY_HEADER_SIZE,
},
server_error_info::{
ErrorInfo, ProtocolIndependentCode, ProtocolIndependentConnectionBrokerCode,
ProtocolIndependentLicensingCode, RdpSpecificCode, ServerSetErrorInfoError,
ServerSetErrorInfoPdu,
},
};
use std::io; use std::io;
use failure::Fail; use failure::Fail;
use self::{ pub use self::capability_sets::{
client_info::ClientInfoError, finalization_messages::FinalizationMessagesError, CapabilitySet, CapabilitySetsError, ClientConfirmActive, DemandActive, ServerDemandActive, VirtualChannel,
server_license::ServerLicenseError, SERVER_CHANNEL_ID,
}; };
use self::client_info::ClientInfoError;
pub use self::client_info::{
AddressFamily, ClientInfo, ClientInfoFlags, CompressionType, Credentials, DayOfWeek, DayOfWeekOccurrence,
ExtendedClientInfo, ExtendedClientOptionalInfo, Month, PerformanceFlags, SystemTime, TimezoneInfo,
};
use self::finalization_messages::FinalizationMessagesError;
pub use self::finalization_messages::{
ControlAction, ControlPdu, FontPdu, MonitorLayoutPdu, SequenceFlags, SynchronizePdu,
};
pub use self::headers::{
BasicSecurityHeader, BasicSecurityHeaderFlags, CompressionFlags, ShareControlHeader, ShareControlPdu,
ShareControlPduType, ShareDataHeader, ShareDataPdu, ShareDataPduType, StreamPriority, BASIC_SECURITY_HEADER_SIZE,
};
pub use self::server_error_info::{
ErrorInfo, ProtocolIndependentCode, ProtocolIndependentConnectionBrokerCode, ProtocolIndependentLicensingCode,
RdpSpecificCode, ServerSetErrorInfoError, ServerSetErrorInfoPdu,
};
use self::server_license::ServerLicenseError;
use crate::{impl_from_error, PduParsing}; use crate::{impl_from_error, PduParsing};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -57,10 +50,7 @@ impl PduParsing for ClientInfoPdu {
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> { fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
let security_header = BasicSecurityHeader::from_buffer(&mut stream)?; let security_header = BasicSecurityHeader::from_buffer(&mut stream)?;
if security_header if security_header.flags.contains(BasicSecurityHeaderFlags::INFO_PKT) {
.flags
.contains(BasicSecurityHeaderFlags::INFO_PKT)
{
let client_info = ClientInfo::from_buffer(&mut stream)?; let client_info = ClientInfo::from_buffer(&mut stream)?;
Ok(Self { Ok(Self {
@ -120,27 +110,12 @@ impl_from_error!(io::Error, RdpError, RdpError::IOError);
impl_from_error!(ClientInfoError, RdpError, RdpError::ClientInfoError); impl_from_error!(ClientInfoError, RdpError, RdpError::ClientInfoError);
impl_from_error!(ServerLicenseError, RdpError, RdpError::ServerLicenseError); impl_from_error!(ServerLicenseError, RdpError, RdpError::ServerLicenseError);
impl_from_error!(CapabilitySetsError, RdpError, RdpError::CapabilitySetsError); impl_from_error!(CapabilitySetsError, RdpError, RdpError::CapabilitySetsError);
impl_from_error!( impl_from_error!(FinalizationMessagesError, RdpError, RdpError::FinalizationMessagesError);
FinalizationMessagesError, impl_from_error!(session_info::SessionError, RdpError, RdpError::SaveSessionInfoError);
RdpError, impl_from_error!(ServerSetErrorInfoError, RdpError, RdpError::ServerSetErrorInfoError);
RdpError::FinalizationMessagesError
);
impl_from_error!(
session_info::SessionError,
RdpError,
RdpError::SaveSessionInfoError
);
impl_from_error!(
ServerSetErrorInfoError,
RdpError,
RdpError::ServerSetErrorInfoError
);
impl From<RdpError> for io::Error { impl From<RdpError> for io::Error {
fn from(e: RdpError) -> io::Error { fn from(e: RdpError) -> io::Error {
io::Error::new( io::Error::new(io::ErrorKind::Other, format!("RDP Connection Sequence error: {}", e))
io::ErrorKind::Other,
format!("RDP Connection Sequence error: {}", e),
)
} }
} }

View file

@ -20,35 +20,32 @@ mod virtual_channel;
use std::io; use std::io;
pub use self::{
bitmap::{Bitmap, BitmapDrawingFlags},
bitmap_cache::{
BitmapCache, BitmapCacheRev2, CacheEntry, CacheFlags, CellInfo, BITMAP_CACHE_ENTRIES_NUM,
},
bitmap_codecs::{
BitmapCodecs, CaptureFlags, Codec, CodecProperty, EntropyBits, Guid, NsCodec,
RemoteFxContainer, RfxCaps, RfxCapset, RfxClientCapsContainer, RfxICap, RfxICapFlags,
},
brush::{Brush, SupportLevel},
frame_acknowledge::FrameAcknowledge,
general::{General, GeneralExtraFlags, MajorPlatformType, MinorPlatformType},
glyph_cache::{CacheDefinition, GlyphCache, GlyphSupportLevel, GLYPH_CACHE_NUM},
input::{Input, InputFlags},
large_pointer::{LargePointer, LargePointerSupportFlags},
multifragment_update::MultifragmentUpdate,
offscreen_bitmap_cache::OffscreenBitmapCache,
order::{Order, OrderFlags, OrderSupportExFlags, OrderSupportIndex},
pointer::Pointer,
sound::{Sound, SoundFlags},
surface_commands::{CmdFlags, SurfaceCommands},
virtual_channel::{VirtualChannel, VirtualChannelFlags},
};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use failure::Fail; use failure::Fail;
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
pub use self::bitmap::{Bitmap, BitmapDrawingFlags};
pub use self::bitmap_cache::{
BitmapCache, BitmapCacheRev2, CacheEntry, CacheFlags, CellInfo, BITMAP_CACHE_ENTRIES_NUM,
};
pub use self::bitmap_codecs::{
BitmapCodecs, CaptureFlags, Codec, CodecProperty, EntropyBits, Guid, NsCodec, RemoteFxContainer, RfxCaps,
RfxCapset, RfxClientCapsContainer, RfxICap, RfxICapFlags,
};
pub use self::brush::{Brush, SupportLevel};
pub use self::frame_acknowledge::FrameAcknowledge;
pub use self::general::{General, GeneralExtraFlags, MajorPlatformType, MinorPlatformType};
pub use self::glyph_cache::{CacheDefinition, GlyphCache, GlyphSupportLevel, GLYPH_CACHE_NUM};
pub use self::input::{Input, InputFlags};
pub use self::large_pointer::{LargePointer, LargePointerSupportFlags};
pub use self::multifragment_update::MultifragmentUpdate;
pub use self::offscreen_bitmap_cache::OffscreenBitmapCache;
pub use self::order::{Order, OrderFlags, OrderSupportExFlags, OrderSupportIndex};
pub use self::pointer::Pointer;
pub use self::sound::{Sound, SoundFlags};
pub use self::surface_commands::{CmdFlags, SurfaceCommands};
pub use self::virtual_channel::{VirtualChannel, VirtualChannelFlags};
use crate::{impl_from_error, PduParsing}; use crate::{impl_from_error, PduParsing};
pub const SERVER_CHANNEL_ID: u16 = 0x03ea; pub const SERVER_CHANNEL_ID: u16 = 0x03ea;
@ -167,9 +164,7 @@ impl PduParsing for DemandActive {
+ NUMBER_CAPABILITIES_FIELD_SIZE + NUMBER_CAPABILITIES_FIELD_SIZE
+ PADDING_SIZE; + PADDING_SIZE;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>((self.source_descriptor.len() + NULL_TERMINATOR.as_bytes().len()) as u16)?;
(self.source_descriptor.len() + NULL_TERMINATOR.as_bytes().len()) as u16,
)?;
stream.write_u16::<LittleEndian>(combined_length as u16)?; stream.write_u16::<LittleEndian>(combined_length as u16)?;
stream.write_all(self.source_descriptor.as_ref())?; stream.write_all(self.source_descriptor.as_ref())?;
stream.write_all(NULL_TERMINATOR.as_bytes())?; stream.write_all(NULL_TERMINATOR.as_bytes())?;
@ -239,8 +234,8 @@ impl PduParsing for CapabilitySet {
type Error = CapabilitySetsError; type Error = CapabilitySetsError;
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> { fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
let capability_set_type = CapabilitySetType::from_u16(stream.read_u16::<LittleEndian>()?) let capability_set_type =
.ok_or(CapabilitySetsError::InvalidType)?; CapabilitySetType::from_u16(stream.read_u16::<LittleEndian>()?).ok_or(CapabilitySetsError::InvalidType)?;
let length = stream.read_u16::<LittleEndian>()? as usize; let length = stream.read_u16::<LittleEndian>()? as usize;
@ -248,8 +243,7 @@ impl PduParsing for CapabilitySet {
return Err(CapabilitySetsError::InvalidLength); return Err(CapabilitySetsError::InvalidLength);
} }
let buffer_length = let buffer_length = length - CAPABILITY_SET_TYPE_FIELD_SIZE - CAPABILITY_SET_LENGTH_FIELD_SIZE;
length - CAPABILITY_SET_TYPE_FIELD_SIZE - CAPABILITY_SET_LENGTH_FIELD_SIZE;
let mut capability_set_buffer = vec![0; buffer_length]; let mut capability_set_buffer = vec![0; buffer_length];
stream.read_exact(capability_set_buffer.as_mut())?; stream.read_exact(capability_set_buffer.as_mut())?;
@ -263,12 +257,12 @@ impl PduParsing for CapabilitySet {
CapabilitySetType::Order => Ok(CapabilitySet::Order(Order::from_buffer( CapabilitySetType::Order => Ok(CapabilitySet::Order(Order::from_buffer(
&mut capability_set_buffer.as_slice(), &mut capability_set_buffer.as_slice(),
)?)), )?)),
CapabilitySetType::BitmapCache => Ok(CapabilitySet::BitmapCache( CapabilitySetType::BitmapCache => Ok(CapabilitySet::BitmapCache(BitmapCache::from_buffer(
BitmapCache::from_buffer(&mut capability_set_buffer.as_slice())?, &mut capability_set_buffer.as_slice(),
)), )?)),
CapabilitySetType::BitmapCacheRev2 => Ok(CapabilitySet::BitmapCacheRev2( CapabilitySetType::BitmapCacheRev2 => Ok(CapabilitySet::BitmapCacheRev2(BitmapCacheRev2::from_buffer(
BitmapCacheRev2::from_buffer(&mut capability_set_buffer.as_slice())?, &mut capability_set_buffer.as_slice(),
)), )?)),
CapabilitySetType::Pointer => Ok(CapabilitySet::Pointer(Pointer::from_buffer( CapabilitySetType::Pointer => Ok(CapabilitySet::Pointer(Pointer::from_buffer(
&mut capability_set_buffer.as_slice(), &mut capability_set_buffer.as_slice(),
)?)), )?)),
@ -281,50 +275,44 @@ impl PduParsing for CapabilitySet {
CapabilitySetType::Brush => Ok(CapabilitySet::Brush(Brush::from_buffer( CapabilitySetType::Brush => Ok(CapabilitySet::Brush(Brush::from_buffer(
&mut capability_set_buffer.as_slice(), &mut capability_set_buffer.as_slice(),
)?)), )?)),
CapabilitySetType::GlyphCache => Ok(CapabilitySet::GlyphCache( CapabilitySetType::GlyphCache => Ok(CapabilitySet::GlyphCache(GlyphCache::from_buffer(
GlyphCache::from_buffer(&mut capability_set_buffer.as_slice())?, &mut capability_set_buffer.as_slice(),
)), )?)),
CapabilitySetType::OffscreenBitmapCache => Ok(CapabilitySet::OffscreenBitmapCache( CapabilitySetType::OffscreenBitmapCache => Ok(CapabilitySet::OffscreenBitmapCache(
OffscreenBitmapCache::from_buffer(&mut capability_set_buffer.as_slice())?, OffscreenBitmapCache::from_buffer(&mut capability_set_buffer.as_slice())?,
)), )),
CapabilitySetType::VirtualChannel => Ok(CapabilitySet::VirtualChannel( CapabilitySetType::VirtualChannel => Ok(CapabilitySet::VirtualChannel(VirtualChannel::from_buffer(
VirtualChannel::from_buffer(&mut capability_set_buffer.as_slice())?, &mut capability_set_buffer.as_slice(),
)), )?)),
CapabilitySetType::SurfaceCommands => Ok(CapabilitySet::SurfaceCommands( CapabilitySetType::SurfaceCommands => Ok(CapabilitySet::SurfaceCommands(SurfaceCommands::from_buffer(
SurfaceCommands::from_buffer(&mut capability_set_buffer.as_slice())?, &mut capability_set_buffer.as_slice(),
)), )?)),
CapabilitySetType::BitmapCodecs => Ok(CapabilitySet::BitmapCodecs( CapabilitySetType::BitmapCodecs => Ok(CapabilitySet::BitmapCodecs(BitmapCodecs::from_buffer(
BitmapCodecs::from_buffer(&mut capability_set_buffer.as_slice())?, &mut capability_set_buffer.as_slice(),
)), )?)),
CapabilitySetType::Control => Ok(CapabilitySet::Control(capability_set_buffer)), CapabilitySetType::Control => Ok(CapabilitySet::Control(capability_set_buffer)),
CapabilitySetType::WindowActivation => { CapabilitySetType::WindowActivation => Ok(CapabilitySet::WindowActivation(capability_set_buffer)),
Ok(CapabilitySet::WindowActivation(capability_set_buffer))
}
CapabilitySetType::Share => Ok(CapabilitySet::Share(capability_set_buffer)), CapabilitySetType::Share => Ok(CapabilitySet::Share(capability_set_buffer)),
CapabilitySetType::Font => Ok(CapabilitySet::Font(capability_set_buffer)), CapabilitySetType::Font => Ok(CapabilitySet::Font(capability_set_buffer)),
CapabilitySetType::BitmapCacheHostSupport => { CapabilitySetType::BitmapCacheHostSupport => {
Ok(CapabilitySet::BitmapCacheHostSupport(capability_set_buffer)) Ok(CapabilitySet::BitmapCacheHostSupport(capability_set_buffer))
} }
CapabilitySetType::DesktopComposition => { CapabilitySetType::DesktopComposition => Ok(CapabilitySet::DesktopComposition(capability_set_buffer)),
Ok(CapabilitySet::DesktopComposition(capability_set_buffer))
}
CapabilitySetType::MultiFragmentUpdate => Ok(CapabilitySet::MultiFragmentUpdate( CapabilitySetType::MultiFragmentUpdate => Ok(CapabilitySet::MultiFragmentUpdate(
MultifragmentUpdate::from_buffer(&mut capability_set_buffer.as_slice())?, MultifragmentUpdate::from_buffer(&mut capability_set_buffer.as_slice())?,
)), )),
CapabilitySetType::LargePointer => Ok(CapabilitySet::LargePointer( CapabilitySetType::LargePointer => Ok(CapabilitySet::LargePointer(LargePointer::from_buffer(
LargePointer::from_buffer(&mut capability_set_buffer.as_slice())?, &mut capability_set_buffer.as_slice(),
)), )?)),
CapabilitySetType::ColorCache => Ok(CapabilitySet::ColorCache(capability_set_buffer)), CapabilitySetType::ColorCache => Ok(CapabilitySet::ColorCache(capability_set_buffer)),
CapabilitySetType::DrawNineGridCache => { CapabilitySetType::DrawNineGridCache => Ok(CapabilitySet::DrawNineGridCache(capability_set_buffer)),
Ok(CapabilitySet::DrawNineGridCache(capability_set_buffer))
}
CapabilitySetType::DrawGdiPlus => Ok(CapabilitySet::DrawGdiPlus(capability_set_buffer)), CapabilitySetType::DrawGdiPlus => Ok(CapabilitySet::DrawGdiPlus(capability_set_buffer)),
CapabilitySetType::Rail => Ok(CapabilitySet::Rail(capability_set_buffer)), CapabilitySetType::Rail => Ok(CapabilitySet::Rail(capability_set_buffer)),
CapabilitySetType::WindowList => Ok(CapabilitySet::WindowList(capability_set_buffer)), CapabilitySetType::WindowList => Ok(CapabilitySet::WindowList(capability_set_buffer)),
CapabilitySetType::FrameAcknowledge => Ok(CapabilitySet::FrameAcknowledge( CapabilitySetType::FrameAcknowledge => Ok(CapabilitySet::FrameAcknowledge(FrameAcknowledge::from_buffer(
FrameAcknowledge::from_buffer(&mut capability_set_buffer.as_slice())?, &mut capability_set_buffer.as_slice(),
)), )?)),
} }
} }
@ -333,190 +321,134 @@ impl PduParsing for CapabilitySet {
CapabilitySet::General(capset) => { CapabilitySet::General(capset) => {
stream.write_u16::<LittleEndian>(CapabilitySetType::General.to_u16().unwrap())?; stream.write_u16::<LittleEndian>(CapabilitySetType::General.to_u16().unwrap())?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
(capset.buffer_length() (capset.buffer_length() + CAPABILITY_SET_TYPE_FIELD_SIZE + CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
+ CAPABILITY_SET_TYPE_FIELD_SIZE
+ CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?; )?;
capset.to_buffer(&mut stream)?; capset.to_buffer(&mut stream)?;
} }
CapabilitySet::Bitmap(capset) => { CapabilitySet::Bitmap(capset) => {
stream.write_u16::<LittleEndian>(CapabilitySetType::Bitmap.to_u16().unwrap())?; stream.write_u16::<LittleEndian>(CapabilitySetType::Bitmap.to_u16().unwrap())?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
(capset.buffer_length() (capset.buffer_length() + CAPABILITY_SET_TYPE_FIELD_SIZE + CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
+ CAPABILITY_SET_TYPE_FIELD_SIZE
+ CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?; )?;
capset.to_buffer(&mut stream)?; capset.to_buffer(&mut stream)?;
} }
CapabilitySet::Order(capset) => { CapabilitySet::Order(capset) => {
stream.write_u16::<LittleEndian>(CapabilitySetType::Order.to_u16().unwrap())?; stream.write_u16::<LittleEndian>(CapabilitySetType::Order.to_u16().unwrap())?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
(capset.buffer_length() (capset.buffer_length() + CAPABILITY_SET_TYPE_FIELD_SIZE + CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
+ CAPABILITY_SET_TYPE_FIELD_SIZE
+ CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?; )?;
capset.to_buffer(&mut stream)?; capset.to_buffer(&mut stream)?;
} }
CapabilitySet::BitmapCache(capset) => { CapabilitySet::BitmapCache(capset) => {
stream stream.write_u16::<LittleEndian>(CapabilitySetType::BitmapCache.to_u16().unwrap())?;
.write_u16::<LittleEndian>(CapabilitySetType::BitmapCache.to_u16().unwrap())?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
(capset.buffer_length() (capset.buffer_length() + CAPABILITY_SET_TYPE_FIELD_SIZE + CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
+ CAPABILITY_SET_TYPE_FIELD_SIZE
+ CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?; )?;
capset.to_buffer(&mut stream)?; capset.to_buffer(&mut stream)?;
} }
CapabilitySet::BitmapCacheRev2(capset) => { CapabilitySet::BitmapCacheRev2(capset) => {
stream.write_u16::<LittleEndian>(CapabilitySetType::BitmapCacheRev2.to_u16().unwrap())?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
CapabilitySetType::BitmapCacheRev2.to_u16().unwrap(), (capset.buffer_length() + CAPABILITY_SET_TYPE_FIELD_SIZE + CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?;
stream.write_u16::<LittleEndian>(
(capset.buffer_length()
+ CAPABILITY_SET_TYPE_FIELD_SIZE
+ CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?; )?;
capset.to_buffer(&mut stream)?; capset.to_buffer(&mut stream)?;
} }
CapabilitySet::Pointer(capset) => { CapabilitySet::Pointer(capset) => {
stream.write_u16::<LittleEndian>(CapabilitySetType::Pointer.to_u16().unwrap())?; stream.write_u16::<LittleEndian>(CapabilitySetType::Pointer.to_u16().unwrap())?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
(capset.buffer_length() (capset.buffer_length() + CAPABILITY_SET_TYPE_FIELD_SIZE + CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
+ CAPABILITY_SET_TYPE_FIELD_SIZE
+ CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?; )?;
capset.to_buffer(&mut stream)?; capset.to_buffer(&mut stream)?;
} }
CapabilitySet::Sound(capset) => { CapabilitySet::Sound(capset) => {
stream.write_u16::<LittleEndian>(CapabilitySetType::Sound.to_u16().unwrap())?; stream.write_u16::<LittleEndian>(CapabilitySetType::Sound.to_u16().unwrap())?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
(capset.buffer_length() (capset.buffer_length() + CAPABILITY_SET_TYPE_FIELD_SIZE + CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
+ CAPABILITY_SET_TYPE_FIELD_SIZE
+ CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?; )?;
capset.to_buffer(&mut stream)?; capset.to_buffer(&mut stream)?;
} }
CapabilitySet::Input(capset) => { CapabilitySet::Input(capset) => {
stream.write_u16::<LittleEndian>(CapabilitySetType::Input.to_u16().unwrap())?; stream.write_u16::<LittleEndian>(CapabilitySetType::Input.to_u16().unwrap())?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
(capset.buffer_length() (capset.buffer_length() + CAPABILITY_SET_TYPE_FIELD_SIZE + CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
+ CAPABILITY_SET_TYPE_FIELD_SIZE
+ CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?; )?;
capset.to_buffer(&mut stream)?; capset.to_buffer(&mut stream)?;
} }
CapabilitySet::Brush(capset) => { CapabilitySet::Brush(capset) => {
stream.write_u16::<LittleEndian>(CapabilitySetType::Brush.to_u16().unwrap())?; stream.write_u16::<LittleEndian>(CapabilitySetType::Brush.to_u16().unwrap())?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
(capset.buffer_length() (capset.buffer_length() + CAPABILITY_SET_TYPE_FIELD_SIZE + CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
+ CAPABILITY_SET_TYPE_FIELD_SIZE
+ CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?; )?;
capset.to_buffer(&mut stream)?; capset.to_buffer(&mut stream)?;
} }
CapabilitySet::GlyphCache(capset) => { CapabilitySet::GlyphCache(capset) => {
stream stream.write_u16::<LittleEndian>(CapabilitySetType::GlyphCache.to_u16().unwrap())?;
.write_u16::<LittleEndian>(CapabilitySetType::GlyphCache.to_u16().unwrap())?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
(capset.buffer_length() (capset.buffer_length() + CAPABILITY_SET_TYPE_FIELD_SIZE + CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
+ CAPABILITY_SET_TYPE_FIELD_SIZE
+ CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?; )?;
capset.to_buffer(&mut stream)?; capset.to_buffer(&mut stream)?;
} }
CapabilitySet::OffscreenBitmapCache(capset) => { CapabilitySet::OffscreenBitmapCache(capset) => {
stream.write_u16::<LittleEndian>(CapabilitySetType::OffscreenBitmapCache.to_u16().unwrap())?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
CapabilitySetType::OffscreenBitmapCache.to_u16().unwrap(), (capset.buffer_length() + CAPABILITY_SET_TYPE_FIELD_SIZE + CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?;
stream.write_u16::<LittleEndian>(
(capset.buffer_length()
+ CAPABILITY_SET_TYPE_FIELD_SIZE
+ CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?; )?;
capset.to_buffer(&mut stream)?; capset.to_buffer(&mut stream)?;
} }
CapabilitySet::VirtualChannel(capset) => { CapabilitySet::VirtualChannel(capset) => {
stream.write_u16::<LittleEndian>(CapabilitySetType::VirtualChannel.to_u16().unwrap())?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
CapabilitySetType::VirtualChannel.to_u16().unwrap(), (capset.buffer_length() + CAPABILITY_SET_TYPE_FIELD_SIZE + CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?;
stream.write_u16::<LittleEndian>(
(capset.buffer_length()
+ CAPABILITY_SET_TYPE_FIELD_SIZE
+ CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?; )?;
capset.to_buffer(&mut stream)?; capset.to_buffer(&mut stream)?;
} }
CapabilitySet::SurfaceCommands(capset) => { CapabilitySet::SurfaceCommands(capset) => {
stream.write_u16::<LittleEndian>(CapabilitySetType::SurfaceCommands.to_u16().unwrap())?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
CapabilitySetType::SurfaceCommands.to_u16().unwrap(), (capset.buffer_length() + CAPABILITY_SET_TYPE_FIELD_SIZE + CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?;
stream.write_u16::<LittleEndian>(
(capset.buffer_length()
+ CAPABILITY_SET_TYPE_FIELD_SIZE
+ CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?; )?;
capset.to_buffer(&mut stream)?; capset.to_buffer(&mut stream)?;
} }
CapabilitySet::BitmapCodecs(capset) => { CapabilitySet::BitmapCodecs(capset) => {
stream stream.write_u16::<LittleEndian>(CapabilitySetType::BitmapCodecs.to_u16().unwrap())?;
.write_u16::<LittleEndian>(CapabilitySetType::BitmapCodecs.to_u16().unwrap())?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
(capset.buffer_length() (capset.buffer_length() + CAPABILITY_SET_TYPE_FIELD_SIZE + CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
+ CAPABILITY_SET_TYPE_FIELD_SIZE
+ CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?; )?;
capset.to_buffer(&mut stream)?; capset.to_buffer(&mut stream)?;
} }
CapabilitySet::MultiFragmentUpdate(capset) => { CapabilitySet::MultiFragmentUpdate(capset) => {
stream.write_u16::<LittleEndian>(CapabilitySetType::MultiFragmentUpdate.to_u16().unwrap())?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
CapabilitySetType::MultiFragmentUpdate.to_u16().unwrap(), (capset.buffer_length() + CAPABILITY_SET_TYPE_FIELD_SIZE + CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?;
stream.write_u16::<LittleEndian>(
(capset.buffer_length()
+ CAPABILITY_SET_TYPE_FIELD_SIZE
+ CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?; )?;
capset.to_buffer(&mut stream)?; capset.to_buffer(&mut stream)?;
} }
CapabilitySet::LargePointer(capset) => { CapabilitySet::LargePointer(capset) => {
stream stream.write_u16::<LittleEndian>(CapabilitySetType::LargePointer.to_u16().unwrap())?;
.write_u16::<LittleEndian>(CapabilitySetType::LargePointer.to_u16().unwrap())?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
(capset.buffer_length() (capset.buffer_length() + CAPABILITY_SET_TYPE_FIELD_SIZE + CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
+ CAPABILITY_SET_TYPE_FIELD_SIZE
+ CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?; )?;
capset.to_buffer(&mut stream)?; capset.to_buffer(&mut stream)?;
} }
CapabilitySet::FrameAcknowledge(capset) => { CapabilitySet::FrameAcknowledge(capset) => {
stream.write_u16::<LittleEndian>(CapabilitySetType::FrameAcknowledge.to_u16().unwrap())?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
CapabilitySetType::FrameAcknowledge.to_u16().unwrap(), (capset.buffer_length() + CAPABILITY_SET_TYPE_FIELD_SIZE + CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?;
stream.write_u16::<LittleEndian>(
(capset.buffer_length()
+ CAPABILITY_SET_TYPE_FIELD_SIZE
+ CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?; )?;
capset.to_buffer(&mut stream)?; capset.to_buffer(&mut stream)?;
} }
_ => { _ => {
let (capability_set_type, capability_set_buffer) = match self { let (capability_set_type, capability_set_buffer) = match self {
CapabilitySet::Control(buffer) => (CapabilitySetType::Control, buffer), CapabilitySet::Control(buffer) => (CapabilitySetType::Control, buffer),
CapabilitySet::WindowActivation(buffer) => { CapabilitySet::WindowActivation(buffer) => (CapabilitySetType::WindowActivation, buffer),
(CapabilitySetType::WindowActivation, buffer)
}
CapabilitySet::Share(buffer) => (CapabilitySetType::Share, buffer), CapabilitySet::Share(buffer) => (CapabilitySetType::Share, buffer),
CapabilitySet::Font(buffer) => (CapabilitySetType::Font, buffer), CapabilitySet::Font(buffer) => (CapabilitySetType::Font, buffer),
CapabilitySet::BitmapCacheHostSupport(buffer) => { CapabilitySet::BitmapCacheHostSupport(buffer) => {
(CapabilitySetType::BitmapCacheHostSupport, buffer) (CapabilitySetType::BitmapCacheHostSupport, buffer)
} }
CapabilitySet::DesktopComposition(buffer) => { CapabilitySet::DesktopComposition(buffer) => (CapabilitySetType::DesktopComposition, buffer),
(CapabilitySetType::DesktopComposition, buffer)
}
CapabilitySet::ColorCache(buffer) => (CapabilitySetType::ColorCache, buffer), CapabilitySet::ColorCache(buffer) => (CapabilitySetType::ColorCache, buffer),
CapabilitySet::DrawNineGridCache(buffer) => { CapabilitySet::DrawNineGridCache(buffer) => (CapabilitySetType::DrawNineGridCache, buffer),
(CapabilitySetType::DrawNineGridCache, buffer)
}
CapabilitySet::DrawGdiPlus(buffer) => (CapabilitySetType::DrawGdiPlus, buffer), CapabilitySet::DrawGdiPlus(buffer) => (CapabilitySetType::DrawGdiPlus, buffer),
CapabilitySet::Rail(buffer) => (CapabilitySetType::Rail, buffer), CapabilitySet::Rail(buffer) => (CapabilitySetType::Rail, buffer),
CapabilitySet::WindowList(buffer) => (CapabilitySetType::WindowList, buffer), CapabilitySet::WindowList(buffer) => (CapabilitySetType::WindowList, buffer),
@ -525,9 +457,8 @@ impl PduParsing for CapabilitySet {
stream.write_u16::<LittleEndian>(capability_set_type.to_u16().unwrap())?; stream.write_u16::<LittleEndian>(capability_set_type.to_u16().unwrap())?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
(capability_set_buffer.len() (capability_set_buffer.len() + CAPABILITY_SET_TYPE_FIELD_SIZE + CAPABILITY_SET_LENGTH_FIELD_SIZE)
+ CAPABILITY_SET_TYPE_FIELD_SIZE as u16,
+ CAPABILITY_SET_LENGTH_FIELD_SIZE) as u16,
)?; )?;
stream.write_all(capability_set_buffer)?; stream.write_all(capability_set_buffer)?;
} }

View file

@ -6,7 +6,8 @@ use std::io;
use bitflags::bitflags; use bitflags::bitflags;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use crate::{rdp::CapabilitySetsError, PduParsing}; use crate::rdp::CapabilitySetsError;
use crate::PduParsing;
const BITMAP_LENGTH: usize = 24; const BITMAP_LENGTH: usize = 24;

View file

@ -6,7 +6,8 @@ use std::io;
use bitflags::bitflags; use bitflags::bitflags;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use crate::{rdp::CapabilitySetsError, PduParsing}; use crate::rdp::CapabilitySetsError;
use crate::PduParsing;
pub const BITMAP_CACHE_ENTRIES_NUM: usize = 3; pub const BITMAP_CACHE_ENTRIES_NUM: usize = 3;
@ -74,10 +75,7 @@ impl PduParsing for CacheEntry {
let entries = buffer.read_u16::<LittleEndian>()?; let entries = buffer.read_u16::<LittleEndian>()?;
let max_cell_size = buffer.read_u16::<LittleEndian>()?; let max_cell_size = buffer.read_u16::<LittleEndian>()?;
Ok(CacheEntry { Ok(CacheEntry { entries, max_cell_size })
entries,
max_cell_size,
})
} }
fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> {

View file

@ -52,8 +52,7 @@ lazy_static! {
], ],
}; };
pub static ref BITMAP_CACHE_REV2: BitmapCacheRev2 = BitmapCacheRev2 { pub static ref BITMAP_CACHE_REV2: BitmapCacheRev2 = BitmapCacheRev2 {
cache_flags: CacheFlags::PERSISTENT_KEYS_EXPECTED_FLAG cache_flags: CacheFlags::PERSISTENT_KEYS_EXPECTED_FLAG | CacheFlags::ALLOW_CACHE_WAITING_LIST_FLAG,
| CacheFlags::ALLOW_CACHE_WAITING_LIST_FLAG,
num_cell_caches: 3, num_cell_caches: 3,
cache_cell_info: [ cache_cell_info: [
CellInfo { CellInfo {
@ -112,10 +111,7 @@ fn buffer_length_is_correct_for_bitmap_cache_capset() {
fn from_buffer_correctly_parses_bitmap_cache_rev2_capset() { fn from_buffer_correctly_parses_bitmap_cache_rev2_capset() {
let buffer = BITMAP_CACHE_REV2_BUFFER.as_ref(); let buffer = BITMAP_CACHE_REV2_BUFFER.as_ref();
assert_eq!( assert_eq!(*BITMAP_CACHE_REV2, BitmapCacheRev2::from_buffer(buffer).unwrap());
*BITMAP_CACHE_REV2,
BitmapCacheRev2::from_buffer(buffer).unwrap()
);
} }
#[test] #[test]
@ -128,18 +124,12 @@ fn to_buffer_correctly_serializes_bitmap_cache_rev2_capset() {
#[test] #[test]
fn buffer_length_is_correct_for_bitmap_cache_rev2_capset() { fn buffer_length_is_correct_for_bitmap_cache_rev2_capset() {
assert_eq!( assert_eq!(BITMAP_CACHE_REV2_BUFFER.len(), BITMAP_CACHE_REV2.buffer_length());
BITMAP_CACHE_REV2_BUFFER.len(),
BITMAP_CACHE_REV2.buffer_length()
);
} }
#[test] #[test]
fn from_buffer_correctly_parses_cell_info() { fn from_buffer_correctly_parses_cell_info() {
assert_eq!( assert_eq!(*CELL_INFO, CellInfo::from_buffer(CELL_INFO_BUFFER.as_ref()).unwrap());
*CELL_INFO,
CellInfo::from_buffer(CELL_INFO_BUFFER.as_ref()).unwrap()
);
} }
#[test] #[test]

View file

@ -8,7 +8,8 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
use crate::{rdp::CapabilitySetsError, PduParsing}; use crate::rdp::CapabilitySetsError;
use crate::PduParsing;
const RFX_ICAP_VERSION: u16 = 0x0100; const RFX_ICAP_VERSION: u16 = 0x0100;
const RFX_ICAP_TILE_SIZE: u16 = 0x40; const RFX_ICAP_TILE_SIZE: u16 = 0x40;
@ -138,9 +139,7 @@ impl PduParsing for Codec {
buffer.read_exact(&mut property_buffer)?; buffer.read_exact(&mut property_buffer)?;
match guid { match guid {
GUID_NSCODEC => { GUID_NSCODEC => CodecProperty::NsCodec(NsCodec::from_buffer(&mut property_buffer.as_slice())?),
CodecProperty::NsCodec(NsCodec::from_buffer(&mut property_buffer.as_slice())?)
}
GUID_REMOTEFX | GUID_IMAGE_REMOTEFX => { GUID_REMOTEFX | GUID_IMAGE_REMOTEFX => {
let property = if property_buffer[0] == 0 { let property = if property_buffer[0] == 0 {
RemoteFxContainer::ServerContainer(codec_properties_len) RemoteFxContainer::ServerContainer(codec_properties_len)
@ -417,9 +416,7 @@ impl PduParsing for RfxCapset {
fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> {
buffer.write_u16::<LittleEndian>(RFX_CAPSET_BLOCK_TYPE)?; buffer.write_u16::<LittleEndian>(RFX_CAPSET_BLOCK_TYPE)?;
buffer.write_u32::<LittleEndian>( buffer.write_u32::<LittleEndian>((RFX_CAPSET_STATIC_DATA_LENGTH + self.0.len() * RFX_ICAP_LENGTH) as u32)?;
(RFX_CAPSET_STATIC_DATA_LENGTH + self.0.len() * RFX_ICAP_LENGTH) as u32,
)?;
buffer.write_u8(1)?; // codec id buffer.write_u8(1)?; // codec id
buffer.write_u16::<LittleEndian>(RFX_CAPSET_TYPE)?; buffer.write_u16::<LittleEndian>(RFX_CAPSET_TYPE)?;
buffer.write_u16::<LittleEndian>(self.0.len() as u16)?; buffer.write_u16::<LittleEndian>(self.0.len() as u16)?;
@ -469,13 +466,10 @@ impl PduParsing for RfxICap {
return Err(CapabilitySetsError::InvalidRfxICapTransformBits); return Err(CapabilitySetsError::InvalidRfxICapTransformBits);
} }
let entropy_bits = EntropyBits::from_u8(buffer.read_u8()?) let entropy_bits =
.ok_or(CapabilitySetsError::InvalidRfxICapEntropyBits)?; EntropyBits::from_u8(buffer.read_u8()?).ok_or(CapabilitySetsError::InvalidRfxICapEntropyBits)?;
Ok(RfxICap { Ok(RfxICap { flags, entropy_bits })
flags,
entropy_bits,
})
} }
fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> {

View file

@ -94,8 +94,7 @@ const NSCODEC_BUFFER: [u8; 3] = [
]; ];
const CODEC_BUFFER: [u8; 68] = [ const CODEC_BUFFER: [u8; 68] = [
0x12, 0x2f, 0x77, 0x76, 0x72, 0xbd, 0x63, 0x44, 0xAF, 0xB3, 0xB7, 0x3C, 0x9C, 0x6F, 0x78, 0x12, 0x2f, 0x77, 0x76, 0x72, 0xbd, 0x63, 0x44, 0xAF, 0xB3, 0xB7, 0x3C, 0x9C, 0x6F, 0x78, 0x86, // guid
0x86, // guid
0x03, // codec id 0x03, // codec id
0x31, 0x00, // codec properties len 0x31, 0x00, // codec properties len
0x31, 0x00, 0x00, 0x00, // length 0x31, 0x00, 0x00, 0x00, // length
@ -284,10 +283,7 @@ fn buffer_length_is_correct_for_guid() {
#[test] #[test]
fn from_buffer_correctly_parses_rfx_icap() { fn from_buffer_correctly_parses_rfx_icap() {
assert_eq!( assert_eq!(*RFX_ICAP, RfxICap::from_buffer(RFX_ICAP_BUFFER.as_ref()).unwrap());
*RFX_ICAP,
RfxICap::from_buffer(RFX_ICAP_BUFFER.as_ref()).unwrap()
);
} }
#[test] #[test]
@ -306,10 +302,7 @@ fn buffer_length_is_correct_for_rfx_icap() {
#[test] #[test]
fn from_buffer_correctly_parses_rfx_capset() { fn from_buffer_correctly_parses_rfx_capset() {
assert_eq!( assert_eq!(*RFX_CAPSET, RfxCapset::from_buffer(RFX_CAPSET_BUFFER.as_ref()).unwrap());
*RFX_CAPSET,
RfxCapset::from_buffer(RFX_CAPSET_BUFFER.as_ref()).unwrap()
);
} }
#[test] #[test]
@ -328,10 +321,7 @@ fn buffer_length_is_correct_for_rfx_capset() {
#[test] #[test]
fn from_buffer_correctly_parses_rfx_caps() { fn from_buffer_correctly_parses_rfx_caps() {
assert_eq!( assert_eq!(*RFX_CAPS, RfxCaps::from_buffer(RFX_CAPS_BUFFER.as_ref()).unwrap());
*RFX_CAPS,
RfxCaps::from_buffer(RFX_CAPS_BUFFER.as_ref()).unwrap()
);
} }
#[test] #[test]
@ -375,10 +365,7 @@ fn buffer_length_is_correct_for_rfx_client_caps_container() {
#[test] #[test]
fn from_buffer_correctly_parses_nscodec() { fn from_buffer_correctly_parses_nscodec() {
assert_eq!( assert_eq!(*NSCODEC, NsCodec::from_buffer(NSCODEC_BUFFER.as_ref()).unwrap());
*NSCODEC,
NsCodec::from_buffer(NSCODEC_BUFFER.as_ref()).unwrap()
);
} }
#[test] #[test]
@ -461,8 +448,7 @@ fn buffer_length_is_correct_for_bitmap_codec() {
#[test] #[test]
fn codec_with_invalid_property_length_handles_correctly() { fn codec_with_invalid_property_length_handles_correctly() {
let codec_buffer: [u8; 68] = [ let codec_buffer: [u8; 68] = [
0x12, 0x2f, 0x77, 0x76, 0x72, 0xbd, 0x63, 0x44, 0xAF, 0xB3, 0xB7, 0x3C, 0x9C, 0x6F, 0x78, 0x12, 0x2f, 0x77, 0x76, 0x72, 0xbd, 0x63, 0x44, 0xAF, 0xB3, 0xB7, 0x3C, 0x9C, 0x6F, 0x78, 0x86, // guid
0x86, // guid
0x03, // codec id 0x03, // codec id
0x00, 0x00, // codec properties len 0x00, 0x00, // codec properties len
0x31, 0x00, 0x00, 0x00, // length 0x31, 0x00, 0x00, 0x00, // length
@ -501,8 +487,8 @@ fn codec_with_invalid_property_length_handles_correctly() {
#[test] #[test]
fn codec_with_empty_property_length_and_ignore_guid_handles_correctly() { fn codec_with_empty_property_length_and_ignore_guid_handles_correctly() {
let codec_buffer: [u8; 19] = [ let codec_buffer: [u8; 19] = [
0xa6, 0x51, 0x43, 0x9c, 0x35, 0x35, 0xae, 0x42, 0x91, 0x0c, 0xcd, 0xfc, 0xe5, 0x76, 0x0b, 0xa6, 0x51, 0x43, 0x9c, 0x35, 0x35, 0xae, 0x42, 0x91, 0x0c, 0xcd, 0xfc, 0xe5, 0x76, 0x0b, 0x58,
0x58, 0x00, // codec id 0x00, // codec id
0x00, 0x00, // codec properties len 0x00, 0x00, // codec properties len
]; ];
@ -517,8 +503,8 @@ fn codec_with_empty_property_length_and_ignore_guid_handles_correctly() {
#[test] #[test]
fn codec_with_property_length_and_ignore_guid_handled_correctly() { fn codec_with_property_length_and_ignore_guid_handled_correctly() {
let codec_buffer = vec![ let codec_buffer = vec![
0xa6u8, 0x51, 0x43, 0x9c, 0x35, 0x35, 0xae, 0x42, 0x91, 0x0c, 0xcd, 0xfc, 0xe5, 0x76, 0x0b, 0xa6u8, 0x51, 0x43, 0x9c, 0x35, 0x35, 0xae, 0x42, 0x91, 0x0c, 0xcd, 0xfc, 0xe5, 0x76, 0x0b, 0x58,
0x58, 0x00, // codec id 0x00, // codec id
0x0f, 0x00, // codec properties len 0x0f, 0x00, // codec properties len
0xa6, 0x51, 0x43, 0x9c, 0x35, 0x35, 0xae, 0x42, 0x91, 0x0c, 0xcd, 0xfc, 0xe5, 0x76, 0x0b, 0xa6, 0x51, 0x43, 0x9c, 0x35, 0x35, 0xae, 0x42, 0x91, 0x0c, 0xcd, 0xfc, 0xe5, 0x76, 0x0b,
]; ];
@ -537,8 +523,7 @@ fn codec_with_property_length_and_ignore_guid_handled_correctly() {
#[test] #[test]
fn ns_codec_with_too_high_color_loss_level_handled_correctly() { fn ns_codec_with_too_high_color_loss_level_handled_correctly() {
let codec_buffer = vec![ let codec_buffer = vec![
0xb9, 0x1b, 0x8d, 0xca, 0x0f, 0x00, 0x4f, 0x15, 0x58, 0x9F, 0xAE, 0x2D, 0x1A, 0x87, 0xE2, 0xb9, 0x1b, 0x8d, 0xca, 0x0f, 0x00, 0x4f, 0x15, 0x58, 0x9F, 0xAE, 0x2D, 0x1A, 0x87, 0xE2, 0xd6, // guid
0xd6, // guid
0x00, // codec id 0x00, // codec id
0x03, 0x00, // codec properties len 0x03, 0x00, // codec properties len
0x01, // allow dynamic fidelity 0x01, // allow dynamic fidelity
@ -555,17 +540,13 @@ fn ns_codec_with_too_high_color_loss_level_handled_correctly() {
}), }),
}; };
assert_eq!( assert_eq!(codec, Codec::from_buffer(&mut codec_buffer.as_slice()).unwrap());
codec,
Codec::from_buffer(&mut codec_buffer.as_slice()).unwrap()
);
} }
#[test] #[test]
fn ns_codec_with_too_low_color_loss_level_handled_correctly() { fn ns_codec_with_too_low_color_loss_level_handled_correctly() {
let codec_buffer = vec![ let codec_buffer = vec![
0xb9, 0x1b, 0x8d, 0xca, 0x0f, 0x00, 0x4f, 0x15, 0x58, 0x9F, 0xAE, 0x2D, 0x1A, 0x87, 0xE2, 0xb9, 0x1b, 0x8d, 0xca, 0x0f, 0x00, 0x4f, 0x15, 0x58, 0x9F, 0xAE, 0x2D, 0x1A, 0x87, 0xE2, 0xd6, // guid
0xd6, // guid
0x00, // codec id 0x00, // codec id
0x03, 0x00, // codec properties len 0x03, 0x00, // codec properties len
0x01, // allow dynamic fidelity 0x01, // allow dynamic fidelity
@ -582,8 +563,5 @@ fn ns_codec_with_too_low_color_loss_level_handled_correctly() {
}), }),
}; };
assert_eq!( assert_eq!(codec, Codec::from_buffer(&mut codec_buffer.as_slice()).unwrap());
codec,
Codec::from_buffer(&mut codec_buffer.as_slice()).unwrap()
);
} }

View file

@ -7,7 +7,8 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
use crate::{rdp::CapabilitySetsError, PduParsing}; use crate::rdp::CapabilitySetsError;
use crate::PduParsing;
const BRUSH_LENGTH: usize = 4; const BRUSH_LENGTH: usize = 4;

View file

@ -2,7 +2,8 @@ use std::io;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use crate::{rdp::CapabilitySetsError, PduParsing}; use crate::rdp::CapabilitySetsError;
use crate::PduParsing;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct FrameAcknowledge { pub struct FrameAcknowledge {

View file

@ -8,7 +8,8 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
use crate::{rdp::CapabilitySetsError, PduParsing}; use crate::rdp::CapabilitySetsError;
use crate::PduParsing;
const GENERAL_LENGTH: usize = 20; const GENERAL_LENGTH: usize = 20;
const PROTOCOL_VER: u16 = 0x0200; const PROTOCOL_VER: u16 = 0x0200;

View file

@ -7,7 +7,8 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
use crate::{rdp::CapabilitySetsError, PduParsing}; use crate::rdp::CapabilitySetsError;
use crate::PduParsing;
pub const GLYPH_CACHE_NUM: usize = 10; pub const GLYPH_CACHE_NUM: usize = 10;
@ -35,10 +36,7 @@ impl PduParsing for CacheDefinition {
let entries = buffer.read_u16::<LittleEndian>()?; let entries = buffer.read_u16::<LittleEndian>()?;
let max_cell_size = buffer.read_u16::<LittleEndian>()?; let max_cell_size = buffer.read_u16::<LittleEndian>()?;
Ok(CacheDefinition { Ok(CacheDefinition { entries, max_cell_size })
entries,
max_cell_size,
})
} }
fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> {

View file

@ -3,9 +3,9 @@ use lazy_static::lazy_static;
use super::*; use super::*;
const GLYPH_CACHE_BUFFER: [u8; 48] = [ const GLYPH_CACHE_BUFFER: [u8; 48] = [
0xfe, 0x00, 0x04, 0x00, 0xfe, 0x00, 0x04, 0x00, 0xfe, 0x00, 0x08, 0x00, 0xfe, 0x00, 0x08, 0x00, 0xfe, 0x00, 0x04, 0x00, 0xfe, 0x00, 0x04, 0x00, 0xfe, 0x00, 0x08, 0x00, 0xfe, 0x00, 0x08, 0x00, 0xfe, 0x00, 0x10,
0xfe, 0x00, 0x10, 0x00, 0xfe, 0x00, 0x20, 0x00, 0xfe, 0x00, 0x40, 0x00, 0xfe, 0x00, 0x80, 0x00, 0x00, 0xfe, 0x00, 0x20, 0x00, 0xfe, 0x00, 0x40, 0x00, 0xfe, 0x00, 0x80, 0x00, 0xfe, 0x00, 0x00, 0x01, 0x40, 0x00,
0xfe, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, // GlyphCache 0x00, 0x08, // GlyphCache
0x00, 0x01, 0x00, 0x01, // FragCache 0x00, 0x01, 0x00, 0x01, // FragCache
0x03, 0x00, // GlyphSupportLevel 0x03, 0x00, // GlyphSupportLevel
0x00, 0x00, // pad2octets 0x00, 0x00, // pad2octets
@ -110,8 +110,5 @@ fn to_buffer_correctly_serializes_cache_definition() {
#[test] #[test]
fn buffer_length_is_correct_for_cache_definition() { fn buffer_length_is_correct_for_cache_definition() {
assert_eq!( assert_eq!(CACHE_DEFINITION_BUFFER.len(), CACHE_DEFINITION.buffer_length());
CACHE_DEFINITION_BUFFER.len(),
CACHE_DEFINITION.buffer_length()
);
} }

View file

@ -7,11 +7,9 @@ use bitflags::bitflags;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
use crate::{ use crate::gcc::{KeyboardType, IME_FILE_NAME_SIZE};
gcc::{KeyboardType, IME_FILE_NAME_SIZE}, use crate::rdp::CapabilitySetsError;
rdp::CapabilitySetsError, use crate::{utils, PduParsing};
utils, PduParsing,
};
const INPUT_LENGTH: usize = 84; const INPUT_LENGTH: usize = 84;
@ -82,8 +80,7 @@ impl PduParsing for Input {
buffer.write_u32::<LittleEndian>(self.keyboard_subtype)?; buffer.write_u32::<LittleEndian>(self.keyboard_subtype)?;
buffer.write_u32::<LittleEndian>(self.keyboard_function_key)?; buffer.write_u32::<LittleEndian>(self.keyboard_function_key)?;
let mut keyboard_ime_file_name_buffer = let mut keyboard_ime_file_name_buffer = utils::string_to_utf16(self.keyboard_ime_filename.as_ref());
utils::string_to_utf16(self.keyboard_ime_filename.as_ref());
keyboard_ime_file_name_buffer.resize(IME_FILE_NAME_SIZE - 2, 0); keyboard_ime_file_name_buffer.resize(IME_FILE_NAME_SIZE - 2, 0);
buffer.write_all(keyboard_ime_file_name_buffer.as_ref())?; buffer.write_all(keyboard_ime_file_name_buffer.as_ref())?;
buffer.write_u16::<LittleEndian>(0)?; // ime file name null terminator buffer.write_u16::<LittleEndian>(0)?; // ime file name null terminator

View file

@ -9,11 +9,10 @@ const INPUT_BUFFER: [u8; 84] = [
0x04, 0x00, 0x00, 0x00, // keyboardType 0x04, 0x00, 0x00, 0x00, // keyboardType
0x00, 0x00, 0x00, 0x00, // keyboardSubType 0x00, 0x00, 0x00, 0x00, // keyboardSubType
0x0c, 0x00, 0x00, 0x00, // keyboardFunctionKey 0x0c, 0x00, 0x00, 0x00, // keyboardFunctionKey
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // imeFileName
0x00, // imeFileName
]; ];
lazy_static! { lazy_static! {

View file

@ -3,7 +3,8 @@ use std::io;
use bitflags::bitflags; use bitflags::bitflags;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use crate::{rdp::CapabilitySetsError, PduParsing}; use crate::rdp::CapabilitySetsError;
use crate::PduParsing;
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct LargePointer { pub struct LargePointer {
@ -14,8 +15,7 @@ impl PduParsing for LargePointer {
type Error = CapabilitySetsError; type Error = CapabilitySetsError;
fn from_buffer(mut buffer: impl io::Read) -> Result<Self, Self::Error> { fn from_buffer(mut buffer: impl io::Read) -> Result<Self, Self::Error> {
let flags = let flags = LargePointerSupportFlags::from_bits_truncate(buffer.read_u16::<LittleEndian>()?);
LargePointerSupportFlags::from_bits_truncate(buffer.read_u16::<LittleEndian>()?);
Ok(Self { flags }) Ok(Self { flags })
} }
@ -66,9 +66,6 @@ mod test {
#[test] #[test]
fn buffer_length_is_correct_for_large_pointer() { fn buffer_length_is_correct_for_large_pointer() {
assert_eq!( assert_eq!(LARGE_POINTER_PDU_BUFFER.len(), LARGE_POINTER_PDU.buffer_length());
LARGE_POINTER_PDU_BUFFER.len(),
LARGE_POINTER_PDU.buffer_length()
);
} }
} }

View file

@ -2,7 +2,8 @@ use std::io;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use crate::{rdp::CapabilitySetsError, PduParsing}; use crate::rdp::CapabilitySetsError;
use crate::PduParsing;
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct MultifragmentUpdate { pub struct MultifragmentUpdate {

View file

@ -5,7 +5,8 @@ use std::io;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use crate::{rdp::CapabilitySetsError, PduParsing}; use crate::rdp::CapabilitySetsError;
use crate::PduParsing;
const OFFSCREEN_BITMAP_CACHE_LENGTH: usize = 8; const OFFSCREEN_BITMAP_CACHE_LENGTH: usize = 8;

View file

@ -6,7 +6,8 @@ use std::io;
use bitflags::bitflags; use bitflags::bitflags;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use crate::{rdp::CapabilitySetsError, PduParsing}; use crate::rdp::CapabilitySetsError;
use crate::PduParsing;
const ORDER_LENGTH: usize = 84; const ORDER_LENGTH: usize = 84;
const ORD_LEVEL_1_ORDERS: u16 = 1; const ORD_LEVEL_1_ORDERS: u16 = 1;
@ -108,8 +109,7 @@ impl PduParsing for Order {
let _text_flags = buffer.read_u16::<LittleEndian>()?; let _text_flags = buffer.read_u16::<LittleEndian>()?;
let order_support_ex_flags = let order_support_ex_flags = OrderSupportExFlags::from_bits_truncate(buffer.read_u16::<LittleEndian>()?);
OrderSupportExFlags::from_bits_truncate(buffer.read_u16::<LittleEndian>()?);
let _padding = buffer.read_u32::<LittleEndian>()?; let _padding = buffer.read_u32::<LittleEndian>()?;
let desktop_save_size = buffer.read_u32::<LittleEndian>()?; let desktop_save_size = buffer.read_u32::<LittleEndian>()?;

View file

@ -3,17 +3,16 @@ use lazy_static::lazy_static;
use super::*; use super::*;
const ORDER_BUFFER: [u8; 84] = [ const ORDER_BUFFER: [u8; 84] = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, // pad4octetsA 0x00, // pad4octetsA
0x01, 0x00, // desktopSaveXGranularity 0x01, 0x00, // desktopSaveXGranularity
0x14, 0x00, // desktopSaveYGranularity 0x14, 0x00, // desktopSaveYGranularity
0x00, 0x00, // pad2octetsA 0x00, 0x00, // pad2octetsA
0x01, 0x00, // maximumOrderLevel 0x01, 0x00, // maximumOrderLevel
0x00, 0x00, // numberFonts 0x00, 0x00, // numberFonts
0x22, 0x00, // orderFlags 0x22, 0x00, // orderFlags
0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, // orderSupport
0x00, // orderSupport
0x00, 0x00, // textFlags 0x00, 0x00, // textFlags
0x02, 0x00, // orderSupportExFlags 0x02, 0x00, // orderSupportExFlags
0x00, 0x00, 0x00, 0x00, // pad4octetsB 0x00, 0x00, 0x00, 0x00, // pad4octetsB

View file

@ -5,7 +5,8 @@ use std::io;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use crate::{rdp::CapabilitySetsError, PduParsing}; use crate::rdp::CapabilitySetsError;
use crate::PduParsing;
const POINTER_LENGTH: usize = 6; const POINTER_LENGTH: usize = 6;

View file

@ -6,7 +6,8 @@ use std::io;
use bitflags::bitflags; use bitflags::bitflags;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use crate::{rdp::CapabilitySetsError, PduParsing}; use crate::rdp::CapabilitySetsError;
use crate::PduParsing;
const SOUND_LENGTH: usize = 4; const SOUND_LENGTH: usize = 4;

View file

@ -6,7 +6,8 @@ use std::io;
use bitflags::bitflags; use bitflags::bitflags;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use crate::{rdp::CapabilitySetsError, PduParsing}; use crate::rdp::CapabilitySetsError;
use crate::PduParsing;
const SURFACE_COMMANDS_LENGTH: usize = 8; const SURFACE_COMMANDS_LENGTH: usize = 8;

View file

@ -32,8 +32,5 @@ fn to_buffer_correctly_serializes_surface_commands_capset() {
#[test] #[test]
fn buffer_length_is_correct_for_surface_commands_capset() { fn buffer_length_is_correct_for_surface_commands_capset() {
assert_eq!( assert_eq!(SURFACE_COMMANDS_BUFFER.len(), SURFACE_COMMANDS.buffer_length());
SURFACE_COMMANDS_BUFFER.len(),
SURFACE_COMMANDS.buffer_length()
);
} }

View file

@ -9,35 +9,30 @@ pub const SERVER_DEMAND_ACTIVE_BUFFER: [u8; 357] = [
0x0d, 0x00, // capabilities count 0x0d, 0x00, // capabilities count
0x00, 0x00, // padding 0x00, 0x00, // padding
0x09, 0x00, 0x08, 0x00, 0xea, 0x03, 0xdc, 0xe2, // Share capability set, 0x09, 0x00, 0x08, 0x00, 0xea, 0x03, 0xdc, 0xe2, // Share capability set,
0x01, 0x00, 0x18, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x04, 0x01, 0x00, 0x18, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, // General capability set 0x00, 0x00, 0x00, 0x01, 0x01, // General capability set
0x14, 0x00, 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x14, 0x00, 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x00, // VirtualChannel capability set
0x00, // VirtualChannel capability set 0x16, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xf6, 0x13, 0xf3, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x16, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xf6, 0x13, 0xf3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x9c, 0xf6, 0x13, 0xf3, 0x61, 0xa6, 0x82, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x9c, 0xf6, 0x13, 0xf3, 0x61, 0xa6, 0x82, 0x80, 0x91, 0xbf, // DrawGdiPlus capability set
0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x91, 0xbf, // DrawGdiPlus capability set
0x0e, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, // Font capability set 0x0e, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, // Font capability set
0x02, 0x00, 0x1c, 0x00, 0x18, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x02, 0x00, 0x1c, 0x00, 0x18, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x00, 0x01,
0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // Bitmap capability set
0x00, // Bitmap capability set 0x03, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x00, 0x00, 0x22, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x40, 0x42, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Order capability set
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Order capability set
0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, // ColorCache capability set 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, // ColorCache capability set
0x12, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, // BitmapCache capability set 0x12, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, // BitmapCache capability set
0x08, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x19, 0x00, 0x19, 0x00, // Pointer capability set 0x08, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x19, 0x00, 0x19, 0x00, // Pointer capability set
0x0d, 0x00, 0x58, 0x00, 0x35, 0x00, 0x00, 0x00, 0xa1, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x58, 0x00, 0x35, 0x00, 0x00, 0x00, 0xa1, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf6, 0x13,
0x0c, 0xf6, 0x13, 0xf3, 0x93, 0x5a, 0x37, 0xf3, 0x00, 0x90, 0x30, 0xe1, 0x34, 0x1c, 0x38, 0xf3, 0xf3, 0x93, 0x5a, 0x37, 0xf3, 0x00, 0x90, 0x30, 0xe1, 0x34, 0x1c, 0x38, 0xf3, 0x40, 0xf6, 0x13, 0xf3, 0x04, 0x00,
0x40, 0xf6, 0x13, 0xf3, 0x04, 0x00, 0x00, 0x00, 0x4c, 0x54, 0xdc, 0xe2, 0x08, 0x50, 0xdc, 0xe2, 0x00, 0x00, 0x4c, 0x54, 0xdc, 0xe2, 0x08, 0x50, 0xdc, 0xe2, 0x01, 0x00, 0x00, 0x00, 0x08, 0x50, 0xdc, 0xe2, 0x00,
0x01, 0x00, 0x00, 0x00, 0x08, 0x50, 0xdc, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x38, 0xf6, 0x13, 0xf3, 0x00, 0x00, 0x00, 0x38, 0xf6, 0x13, 0xf3, 0x2e, 0x05, 0x38, 0xf3, 0x08, 0x50, 0xdc, 0xe2, 0x2c, 0xf6, 0x13, 0xf3,
0x2e, 0x05, 0x38, 0xf3, 0x08, 0x50, 0xdc, 0xe2, 0x2c, 0xf6, 0x13, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x00, // Input capability set
0x08, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x00, // Input capability set
0x17, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // Rail capability set 0x17, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // Rail capability set
0x18, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // WindowList capability set
0x00, // WindowList capability set
0x00, 0x00, 0x00, 0x00, // session id 0x00, 0x00, 0x00, 0x00, // session id
]; ];
pub const CLIENT_DEMAND_ACTIVE_WITH_INCOMPLETE_CAPABILITY_SET_BUFFER: [u8; 501] = [ pub const CLIENT_DEMAND_ACTIVE_WITH_INCOMPLETE_CAPABILITY_SET_BUFFER: [u8; 501] = [
@ -47,41 +42,36 @@ pub const CLIENT_DEMAND_ACTIVE_WITH_INCOMPLETE_CAPABILITY_SET_BUFFER: [u8; 501]
0x4d, 0x53, 0x54, 0x53, 0x43, 0x0, // source descriptor 0x4d, 0x53, 0x54, 0x53, 0x43, 0x0, // source descriptor
0x14, 0x0, // capability sets count 0x14, 0x0, // capability sets count
0x0, 0x0, // padding 0x0, 0x0, // padding
0x1, 0x0, 0x18, 0x0, 0x1, 0x0, 0x3, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x1d, 0x4, 0x0, 0x0, 0x1, 0x0, 0x18, 0x0, 0x1, 0x0, 0x3, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x1d, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // general capability set 0x0, 0x0, // general capability set
0x2, 0x0, 0x1c, 0x0, 0x20, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x20, 0x3, 0x58, 0x2, 0x0, 0x0, 0x2, 0x0, 0x1c, 0x0, 0x20, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x20, 0x3, 0x58, 0x2, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0,
0x1, 0x0, 0x1, 0x0, 0x0, 0xa, 0x1, 0x0, 0x0, 0x0, // bitmap 0x0, 0xa, 0x1, 0x0, 0x0, 0x0, // bitmap
0x3, 0x0, 0x58, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x58, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x14, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x1, 0x0, 0x1, 0x0, 0x14, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1, 0x1,
0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
0x1, 0x1, 0x1, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x84, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe4, 0x4, 0x0, 0x0, // order
0x0, 0x0, 0x84, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe4, 0x4, 0x0, 0x0, // order 0x4, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x4, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x78, 0x0, 0x0, 0x4, 0x78, 0x0, 0x0, 0x10, 0x51, 0x1, 0x0, 0x40, // bitmap cache
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x78, 0x0, 0x0, 0x4, 0x78, 0x0, 0x0, 0x10, 0x51,
0x1, 0x0, 0x40, // bitmap cache
0xa, 0x0, 0x8, 0x0, 0x6, 0x0, 0x0, 0x0, // color cache 0xa, 0x0, 0x8, 0x0, 0x6, 0x0, 0x0, 0x0, // color cache
0x7, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // window activation 0x7, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // window activation
0x5, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x2, 0x0, // control 0x5, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x2, 0x0, // control
0x8, 0x0, 0xa, 0x0, 0x1, 0x0, 0x14, 0x0, 0x15, 0x0, // pointer 0x8, 0x0, 0xa, 0x0, 0x1, 0x0, 0x14, 0x0, 0x15, 0x0, // pointer
0x9, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, // share 0x9, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, // share
0xd, 0x0, 0x58, 0x0, 0x91, 0x0, 0x0, 0x0, 0x9, 0x4, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0x0, 0x58, 0x0, 0x91, 0x0, 0x0, 0x0, 0x9, 0x4, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x0,
0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // input
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // input
0xc, 0x0, 0x8, 0x0, 0x1, 0x0, 0x0, 0x0, // sound 0xc, 0x0, 0x8, 0x0, 0x1, 0x0, 0x0, 0x0, // sound
0xe, 0x0, 0x8, 0x0, 0x1, 0x0, 0x0, 0x0, // font 0xe, 0x0, 0x8, 0x0, 0x1, 0x0, 0x0, 0x0, // font
0x10, 0x0, 0x34, 0x0, 0xfe, 0x0, 0x4, 0x0, 0xfe, 0x0, 0x4, 0x0, 0xfe, 0x0, 0x8, 0x0, 0xfe, 0x0, 0x10, 0x0, 0x34, 0x0, 0xfe, 0x0, 0x4, 0x0, 0xfe, 0x0, 0x4, 0x0, 0xfe, 0x0, 0x8, 0x0, 0xfe, 0x0, 0x8, 0x0, 0xfe,
0x8, 0x0, 0xfe, 0x0, 0x10, 0x0, 0xfe, 0x0, 0x20, 0x0, 0xfe, 0x0, 0x40, 0x0, 0xfe, 0x0, 0x80, 0x0, 0x10, 0x0, 0xfe, 0x0, 0x20, 0x0, 0xfe, 0x0, 0x40, 0x0, 0xfe, 0x0, 0x80, 0x0, 0xfe, 0x0, 0x0, 0x1, 0x40, 0x0,
0x0, 0xfe, 0x0, 0x0, 0x1, 0x40, 0x0, 0x0, 0x8, 0x0, 0x1, 0x0, 0x1, 0x3, 0x0, 0x0, 0x0, 0x8, 0x0, 0x1, 0x0, 0x1, 0x3, 0x0, 0x0, 0x0, // glyph cache
0x0, // glyph cache
0xf, 0x0, 0x8, 0x0, 0x1, 0x0, 0x0, 0x0, // brush 0xf, 0x0, 0x8, 0x0, 0x1, 0x0, 0x0, 0x0, // brush
0x11, 0x0, 0xc, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x64, 0x0, // offscreen bitmap cache 0x11, 0x0, 0xc, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x64, 0x0, // offscreen bitmap cache
0x14, 0x0, 0x8, 0x0, 0x1, 0x0, 0x0, 0x0, // virtual channel 0x14, 0x0, 0x8, 0x0, 0x1, 0x0, 0x0, 0x0, // virtual channel
0x15, 0x0, 0xc, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x1, // draw nine grid cache 0x15, 0x0, 0xc, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x1, // draw nine grid cache
0x16, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // draw GDI plus
0x0, 0x0, 0x0, // draw GDI plus
0x1a, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, // multi fragment update 0x1a, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, // multi fragment update
0x18, 0x0, 0xb, 0x0, 0x1, 0x0, 0x0, 0x0, 0x3, 0xc, 0x0, // window list 0x18, 0x0, 0xb, 0x0, 0x1, 0x0, 0x0, 0x0, 0x3, 0xc, 0x0, // window list
]; ];
@ -92,165 +82,144 @@ pub const CLIENT_DEMAND_ACTIVE_BUFFER: [u8; 486] = [
0x4d, 0x53, 0x54, 0x53, 0x43, 0x00, // source descriptor 0x4d, 0x53, 0x54, 0x53, 0x43, 0x00, // source descriptor
0x12, 0x00, // capabilities count 0x12, 0x00, // capabilities count
0x00, 0x00, // padding 0x00, 0x00, // padding
0x01, 0x00, 0x18, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x04, 0x01, 0x00, 0x18, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // general capability set 0x00, 0x00, 0x00, 0x00, 0x00, // general capability set
0x02, 0x00, 0x1c, 0x00, 0x18, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x02, 0x00, 0x1c, 0x00, 0x18, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x00, 0x01,
0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // bitmap capability set
0x00, // bitmap capability set 0x03, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x00, 0x00, 0x2a, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x84, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // order capability set
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x03, 0x00, 0x13, 0x00, 0x28, 0x00, 0x03, 0x00, 0x00, 0x03, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xfb, 0x09, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // order capability set 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x13, 0x00, 0x28, 0x00, 0x03, 0x00, 0x00, 0x03, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, // bitmap cache rev 2 capability set
0xfb, 0x09, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // bitmap cache rev 2 capability set
0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, // color cache 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, // color cache
0x07, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // window activation capability set
0x00, // window activation capability set 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, // control capability set
0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02,
0x00, // control capability set
0x08, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x14, 0x00, 0x15, 0x00, // pointer capability set 0x08, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x14, 0x00, 0x15, 0x00, // pointer capability set
0x09, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // share capability set 0x09, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // share capability set
0x0d, 0x00, 0x58, 0x00, 0x15, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x58, 0x00, 0x15, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // input capability set
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // input capability set
0x0c, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, // sound capability set 0x0c, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, // sound capability set
0x0e, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, // font capability set 0x0e, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, // font capability set
0x10, 0x00, 0x34, 0x00, 0xfe, 0x00, 0x04, 0x00, 0xfe, 0x00, 0x04, 0x00, 0xfe, 0x00, 0x08, 0x00, 0x10, 0x00, 0x34, 0x00, 0xfe, 0x00, 0x04, 0x00, 0xfe, 0x00, 0x04, 0x00, 0xfe, 0x00, 0x08, 0x00, 0xfe, 0x00, 0x08,
0xfe, 0x00, 0x08, 0x00, 0xfe, 0x00, 0x10, 0x00, 0xfe, 0x00, 0x20, 0x00, 0xfe, 0x00, 0x40, 0x00, 0x00, 0xfe, 0x00, 0x10, 0x00, 0xfe, 0x00, 0x20, 0x00, 0xfe, 0x00, 0x40, 0x00, 0xfe, 0x00, 0x80, 0x00, 0xfe, 0x00,
0xfe, 0x00, 0x80, 0x00, 0xfe, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x03, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, // glyph cache capability set 0x00, // glyph cache capability set
0x0f, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, // brush capability set 0x0f, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, // brush capability set
0x11, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x64, 0x11, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x64,
0x00, // offscreen bitmap cache capability set 0x00, // offscreen bitmap cache capability set
0x14, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x14, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x00, // virtual channel capability set
0x00, // virtual channel capability set 0x15, 0x00, 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, // draw nine grid cache capability set
0x15, 0x00, 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x16, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, // draw nine grid cache capability set 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x16, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // draw gdi plus capability set
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // draw gdi plus capability set
]; ];
const SERVER_SHARE_CAPABILITY_SET: [u8; 4] = [0xea, 0x03, 0xdc, 0xe2]; const SERVER_SHARE_CAPABILITY_SET: [u8; 4] = [0xea, 0x03, 0xdc, 0xe2];
const SERVER_GENERAL_CAPABILITY_SET: [u8; 20] = [ const SERVER_GENERAL_CAPABILITY_SET: [u8; 20] = [
0x01, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x01, 0x01, 0x01,
]; ];
const SERVER_VIRTUAL_CHANNEL_CAPABILITY_SET: [u8; 8] = const SERVER_VIRTUAL_CHANNEL_CAPABILITY_SET: [u8; 8] = [0x02, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x00];
[0x02, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x00];
const SERVER_DRAW_GDI_PLUS_CAPABILITY_SET: [u8; 36] = [ const SERVER_DRAW_GDI_PLUS_CAPABILITY_SET: [u8; 36] = [
0x00, 0x00, 0x00, 0x00, 0x70, 0xf6, 0x13, 0xf3, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xf6, 0x13, 0xf3, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x9c, 0xf6, 0x13, 0xf3, 0x61, 0xa6, 0x82, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0xf6, 0x13, 0xf3, 0x61, 0xa6, 0x82, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x91, 0xbf,
0x00, 0x50, 0x91, 0xbf,
]; ];
const SERVER_FONT_CAPABILITY_SET: [u8; 4] = [0x00, 0x01, 0x00, 0x00]; const SERVER_FONT_CAPABILITY_SET: [u8; 4] = [0x00, 0x01, 0x00, 0x00];
const SERVER_BITMAP_CAPABILITY_SET: [u8; 24] = [ const SERVER_BITMAP_CAPABILITY_SET: [u8; 24] = [
0x18, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
]; ];
const SERVER_ORDER_CAPABILITY_SET: [u8; 84] = [ const SERVER_ORDER_CAPABILITY_SET: [u8; 84] = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
]; ];
const SERVER_COLOR_CACHE_CAPABILITY_SET: [u8; 4] = [0x06, 0x00, 0x00, 0x00]; const SERVER_COLOR_CACHE_CAPABILITY_SET: [u8; 4] = [0x06, 0x00, 0x00, 0x00];
const SERVER_BITMAP_CACHE_HOST_SUPPORT_CAPABILITY_SET: [u8; 4] = [0x01, 0x00, 0x00, 0x00]; const SERVER_BITMAP_CACHE_HOST_SUPPORT_CAPABILITY_SET: [u8; 4] = [0x01, 0x00, 0x00, 0x00];
const SERVER_POINTER_CAPABILITY_SET: [u8; 6] = [0x01, 0x00, 0x19, 0x00, 0x19, 0x00]; const SERVER_POINTER_CAPABILITY_SET: [u8; 6] = [0x01, 0x00, 0x19, 0x00, 0x19, 0x00];
const SERVER_INPUT_CAPABILITY_SET: [u8; 84] = [ const SERVER_INPUT_CAPABILITY_SET: [u8; 84] = [
0x35, 0x00, 0x00, 0x00, 0xa1, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf6, 0x13, 0xf3, 0x35, 0x00, 0x00, 0x00, 0xa1, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf6, 0x13, 0xf3, 0x93, 0x5a, 0x37,
0x93, 0x5a, 0x37, 0xf3, 0x00, 0x90, 0x30, 0xe1, 0x34, 0x1c, 0x38, 0xf3, 0x40, 0xf6, 0x13, 0xf3, 0xf3, 0x00, 0x90, 0x30, 0xe1, 0x34, 0x1c, 0x38, 0xf3, 0x40, 0xf6, 0x13, 0xf3, 0x04, 0x00, 0x00, 0x00, 0x4c, 0x54,
0x04, 0x00, 0x00, 0x00, 0x4c, 0x54, 0xdc, 0xe2, 0x08, 0x50, 0xdc, 0xe2, 0x01, 0x00, 0x00, 0x00, 0xdc, 0xe2, 0x08, 0x50, 0xdc, 0xe2, 0x01, 0x00, 0x00, 0x00, 0x08, 0x50, 0xdc, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x38,
0x08, 0x50, 0xdc, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x38, 0xf6, 0x13, 0xf3, 0x2e, 0x05, 0x38, 0xf3, 0xf6, 0x13, 0xf3, 0x2e, 0x05, 0x38, 0xf3, 0x08, 0x50, 0xdc, 0xe2, 0x2c, 0xf6, 0x13, 0xf3, 0x00, 0x00, 0x00, 0x00,
0x08, 0x50, 0xdc, 0xe2, 0x2c, 0xf6, 0x13, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00,
]; ];
const SERVER_RAIL_CAPABILITY_SET: [u8; 4] = [0x00, 0x00, 0x00, 0x00]; const SERVER_RAIL_CAPABILITY_SET: [u8; 4] = [0x00, 0x00, 0x00, 0x00];
const SERVER_WINDOW_LIST_CAPABILITY_SET: [u8; 7] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; const SERVER_WINDOW_LIST_CAPABILITY_SET: [u8; 7] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
const CLIENT_GENERAL_CAPABILITY_SET: [u8; 20] = [ const CLIENT_GENERAL_CAPABILITY_SET: [u8; 20] = [
0x01, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
const CLIENT_BITMAP_CAPABILITY_SET: [u8; 24] = [ const CLIENT_BITMAP_CAPABILITY_SET: [u8; 24] = [
0x18, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
]; ];
const CLIENT_BITMAP_CAPABILITY_SET_32_BIT: [u8; 24] = [ const CLIENT_BITMAP_CAPABILITY_SET_32_BIT: [u8; 24] = [
0x20, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x20, 0x3, 0x58, 0x2, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x20, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x20, 0x3, 0x58, 0x2, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0xa, 0x1, 0x0,
0x0, 0xa, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
]; ];
const CLIENT_ORDER_CAPABILITY_SET: [u8; 84] = [ const CLIENT_ORDER_CAPABILITY_SET: [u8; 84] = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
]; ];
const CLIENT_ORDER_CAPABILITY_SET_ANSI_CODE_PAGE: [u8; 84] = [ const CLIENT_ORDER_CAPABILITY_SET_ANSI_CODE_PAGE: [u8; 84] = [
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x14,
0x0, 0x1, 0x0, 0x14, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x1, 0x0, 0x0,
0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x84, 0x3, 0x0, 0x0, 0x0, 0x0, 0x84, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe4, 0x4, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0xe4, 0x4, 0x0, 0x0,
]; ];
const CLIENT_BITMAP_CACHE_REV_2_CAPABILITY_SET: [u8; 36] = [ const CLIENT_BITMAP_CACHE_REV_2_CAPABILITY_SET: [u8; 36] = [
0x03, 0x00, 0x00, 0x03, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xfb, 0x09, 0x00, 0x80, 0x03, 0x00, 0x00, 0x03, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xfb, 0x09, 0x00, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
]; ];
const CLIENT_BITMAP_CACHE_REV_1_CAPABILITY_SET: [u8; 36] = [ const CLIENT_BITMAP_CACHE_REV_1_CAPABILITY_SET: [u8; 36] = [
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x78, 0x0, 0x0, 0x4, 0x78, 0x0, 0x0, 0x10, 0x51, 0x1, 0x0, 0x40, 0x0, 0x78, 0x0, 0x0, 0x4, 0x78, 0x0, 0x0, 0x10, 0x51, 0x1, 0x0, 0x40,
]; ];
const CLIENT_COLOR_CACHE_CAPABILITY_SET: [u8; 4] = [0x06, 0x00, 0x00, 0x00]; const CLIENT_COLOR_CACHE_CAPABILITY_SET: [u8; 4] = [0x06, 0x00, 0x00, 0x00];
const CLIENT_WINDOW_ACTIVATION_CAPABILITY_SET: [u8; 8] = const CLIENT_WINDOW_ACTIVATION_CAPABILITY_SET: [u8; 8] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
const CLIENT_CONTROL_CAPABILITY_SET: [u8; 8] = [0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00]; const CLIENT_CONTROL_CAPABILITY_SET: [u8; 8] = [0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00];
const CLIENT_POINTER_CAPABILITY_SET: [u8; 6] = [0x01, 0x00, 0x14, 0x00, 0x15, 0x00]; const CLIENT_POINTER_CAPABILITY_SET: [u8; 6] = [0x01, 0x00, 0x14, 0x00, 0x15, 0x00];
const CLIENT_SHARE_CAPABILITY_SET: [u8; 4] = [0x00, 0x00, 0x00, 0x00]; const CLIENT_SHARE_CAPABILITY_SET: [u8; 4] = [0x00, 0x00, 0x00, 0x00];
const CLIENT_INPUT_CAPABILITY_SET: [u8; 84] = [ const CLIENT_INPUT_CAPABILITY_SET: [u8; 84] = [
0x15, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
]; ];
const CLIENT_INPUT_CAPABILITY_SET_UNICODE: [u8; 84] = [ const CLIENT_INPUT_CAPABILITY_SET_UNICODE: [u8; 84] = [
0x91, 0x0, 0x20, 0x0, 0x9, 0x4, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x0, 0x91, 0x0, 0x20, 0x0, 0x9, 0x4, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
]; ];
const CLIENT_SOUND_CAPABILITY_SET: [u8; 4] = [0x01, 0x00, 0x00, 0x00]; const CLIENT_SOUND_CAPABILITY_SET: [u8; 4] = [0x01, 0x00, 0x00, 0x00];
const CLIENT_FONT_CAPABILITY_SET: [u8; 4] = [0x01, 0x00, 0x00, 0x00]; const CLIENT_FONT_CAPABILITY_SET: [u8; 4] = [0x01, 0x00, 0x00, 0x00];
const CLIENT_GLYPH_CACHE_CAPABILITY_SET: [u8; 48] = [ const CLIENT_GLYPH_CACHE_CAPABILITY_SET: [u8; 48] = [
0xfe, 0x00, 0x04, 0x00, 0xfe, 0x00, 0x04, 0x00, 0xfe, 0x00, 0x08, 0x00, 0xfe, 0x00, 0x08, 0x00, 0xfe, 0x00, 0x04, 0x00, 0xfe, 0x00, 0x04, 0x00, 0xfe, 0x00, 0x08, 0x00, 0xfe, 0x00, 0x08, 0x00, 0xfe, 0x00, 0x10,
0xfe, 0x00, 0x10, 0x00, 0xfe, 0x00, 0x20, 0x00, 0xfe, 0x00, 0x40, 0x00, 0xfe, 0x00, 0x80, 0x00, 0x00, 0xfe, 0x00, 0x20, 0x00, 0xfe, 0x00, 0x40, 0x00, 0xfe, 0x00, 0x80, 0x00, 0xfe, 0x00, 0x00, 0x01, 0x40, 0x00,
0xfe, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00,
]; ];
const CLIENT_BRUSH_CAPABILITY_SET: [u8; 4] = [0x01, 0x00, 0x00, 0x00]; const CLIENT_BRUSH_CAPABILITY_SET: [u8; 4] = [0x01, 0x00, 0x00, 0x00];
const CLIENT_OFFSCREEN_BITMAP_CAPABILITY_SET: [u8; 8] = const CLIENT_OFFSCREEN_BITMAP_CAPABILITY_SET: [u8; 8] = [0x01, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x64, 0x00];
[0x01, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x64, 0x00];
const CLIENT_VIRTUAL_CHANNEL_CAPABILITY_SET_INCOMPLETE: [u8; 4] = [0x1, 0x0, 0x0, 0x0]; const CLIENT_VIRTUAL_CHANNEL_CAPABILITY_SET_INCOMPLETE: [u8; 4] = [0x1, 0x0, 0x0, 0x0];
const CLIENT_VIRTUAL_CHANNEL_CAPABILITY_SET: [u8; 8] = const CLIENT_VIRTUAL_CHANNEL_CAPABILITY_SET: [u8; 8] = [0x01, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x00];
[0x01, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x00]; const CLIENT_DRAW_NINE_GRID_CACHE_CAPABILITY_SET: [u8; 8] = [0x02, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01];
const CLIENT_DRAW_NINE_GRID_CACHE_CAPABILITY_SET: [u8; 8] =
[0x02, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01];
const CLIENT_DRAW_GDI_PLUS_CAPABILITY_SET: [u8; 36] = [ const CLIENT_DRAW_GDI_PLUS_CAPABILITY_SET: [u8; 36] = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
]; ];
const CLIENT_MULTI_FRAGMENT_UPDATE_CAPABILITY_SET: [u8; 4] = [0x0, 0x0, 0x0, 0x0]; const CLIENT_MULTI_FRAGMENT_UPDATE_CAPABILITY_SET: [u8; 4] = [0x0, 0x0, 0x0, 0x0];
const CLIENT_WINDOW_LIST_CAPABILITY_SET: [u8; 7] = [0x1, 0x0, 0x0, 0x0, 0x3, 0xc, 0x0]; const CLIENT_WINDOW_LIST_CAPABILITY_SET: [u8; 7] = [0x1, 0x0, 0x0, 0x0, 0x3, 0xc, 0x0];
@ -261,156 +230,87 @@ lazy_static! {
source_descriptor: String::from("RDP"), source_descriptor: String::from("RDP"),
capability_sets: vec![ capability_sets: vec![
CapabilitySet::Share(SERVER_SHARE_CAPABILITY_SET.to_vec()), CapabilitySet::Share(SERVER_SHARE_CAPABILITY_SET.to_vec()),
CapabilitySet::General( CapabilitySet::General(General::from_buffer(SERVER_GENERAL_CAPABILITY_SET.as_ref()).unwrap()),
General::from_buffer(SERVER_GENERAL_CAPABILITY_SET.as_ref()).unwrap()
),
CapabilitySet::VirtualChannel( CapabilitySet::VirtualChannel(
VirtualChannel::from_buffer(SERVER_VIRTUAL_CHANNEL_CAPABILITY_SET.as_ref()) VirtualChannel::from_buffer(SERVER_VIRTUAL_CHANNEL_CAPABILITY_SET.as_ref()).unwrap()
.unwrap()
), ),
CapabilitySet::DrawGdiPlus(SERVER_DRAW_GDI_PLUS_CAPABILITY_SET.to_vec()), CapabilitySet::DrawGdiPlus(SERVER_DRAW_GDI_PLUS_CAPABILITY_SET.to_vec()),
CapabilitySet::Font(SERVER_FONT_CAPABILITY_SET.to_vec()), CapabilitySet::Font(SERVER_FONT_CAPABILITY_SET.to_vec()),
CapabilitySet::Bitmap( CapabilitySet::Bitmap(Bitmap::from_buffer(SERVER_BITMAP_CAPABILITY_SET.as_ref()).unwrap()),
Bitmap::from_buffer(SERVER_BITMAP_CAPABILITY_SET.as_ref()).unwrap() CapabilitySet::Order(Order::from_buffer(SERVER_ORDER_CAPABILITY_SET.as_ref()).unwrap()),
),
CapabilitySet::Order(
Order::from_buffer(SERVER_ORDER_CAPABILITY_SET.as_ref()).unwrap()
),
CapabilitySet::ColorCache(SERVER_COLOR_CACHE_CAPABILITY_SET.to_vec()), CapabilitySet::ColorCache(SERVER_COLOR_CACHE_CAPABILITY_SET.to_vec()),
CapabilitySet::BitmapCacheHostSupport( CapabilitySet::BitmapCacheHostSupport(SERVER_BITMAP_CACHE_HOST_SUPPORT_CAPABILITY_SET.to_vec()),
SERVER_BITMAP_CACHE_HOST_SUPPORT_CAPABILITY_SET.to_vec() CapabilitySet::Pointer(Pointer::from_buffer(SERVER_POINTER_CAPABILITY_SET.as_ref()).unwrap()),
), CapabilitySet::Input(Input::from_buffer(SERVER_INPUT_CAPABILITY_SET.as_ref()).unwrap()),
CapabilitySet::Pointer(
Pointer::from_buffer(SERVER_POINTER_CAPABILITY_SET.as_ref()).unwrap()
),
CapabilitySet::Input(
Input::from_buffer(SERVER_INPUT_CAPABILITY_SET.as_ref()).unwrap()
),
CapabilitySet::Rail(SERVER_RAIL_CAPABILITY_SET.to_vec()), CapabilitySet::Rail(SERVER_RAIL_CAPABILITY_SET.to_vec()),
CapabilitySet::WindowList(SERVER_WINDOW_LIST_CAPABILITY_SET.to_vec()), CapabilitySet::WindowList(SERVER_WINDOW_LIST_CAPABILITY_SET.to_vec()),
], ],
} }
}; };
pub static ref CLIENT_DEMAND_ACTIVE_WITH_INCOMPLETE_CAPABILITY_SET: ClientConfirmActive = pub static ref CLIENT_DEMAND_ACTIVE_WITH_INCOMPLETE_CAPABILITY_SET: ClientConfirmActive = ClientConfirmActive {
ClientConfirmActive { originator_id: SERVER_CHANNEL_ID,
originator_id: SERVER_CHANNEL_ID, pdu: DemandActive {
pdu: DemandActive { source_descriptor: String::from("MSTSC"),
source_descriptor: String::from("MSTSC"), capability_sets: vec![
capability_sets: vec![ CapabilitySet::General(General::from_buffer(CLIENT_GENERAL_CAPABILITY_SET.as_ref()).unwrap()),
CapabilitySet::General( CapabilitySet::Bitmap(Bitmap::from_buffer(CLIENT_BITMAP_CAPABILITY_SET_32_BIT.as_ref()).unwrap()),
General::from_buffer(CLIENT_GENERAL_CAPABILITY_SET.as_ref()).unwrap() CapabilitySet::Order(Order::from_buffer(CLIENT_ORDER_CAPABILITY_SET_ANSI_CODE_PAGE.as_ref()).unwrap()),
), CapabilitySet::BitmapCache(
CapabilitySet::Bitmap( BitmapCache::from_buffer(CLIENT_BITMAP_CACHE_REV_1_CAPABILITY_SET.as_ref()).unwrap()
Bitmap::from_buffer(CLIENT_BITMAP_CAPABILITY_SET_32_BIT.as_ref()).unwrap() ),
), CapabilitySet::ColorCache(CLIENT_COLOR_CACHE_CAPABILITY_SET.to_vec()),
CapabilitySet::Order( CapabilitySet::WindowActivation(CLIENT_WINDOW_ACTIVATION_CAPABILITY_SET.to_vec()),
Order::from_buffer(CLIENT_ORDER_CAPABILITY_SET_ANSI_CODE_PAGE.as_ref()) CapabilitySet::Control(CLIENT_CONTROL_CAPABILITY_SET.to_vec()),
.unwrap() CapabilitySet::Pointer(Pointer::from_buffer(CLIENT_POINTER_CAPABILITY_SET.as_ref()).unwrap()),
), CapabilitySet::Share(CLIENT_SHARE_CAPABILITY_SET.to_vec()),
CapabilitySet::BitmapCache( CapabilitySet::Input(Input::from_buffer(CLIENT_INPUT_CAPABILITY_SET_UNICODE.as_ref()).unwrap()),
BitmapCache::from_buffer(CLIENT_BITMAP_CACHE_REV_1_CAPABILITY_SET.as_ref()) CapabilitySet::Sound(Sound::from_buffer(CLIENT_SOUND_CAPABILITY_SET.as_ref()).unwrap()),
.unwrap() CapabilitySet::Font(CLIENT_FONT_CAPABILITY_SET.to_vec()),
), CapabilitySet::GlyphCache(GlyphCache::from_buffer(CLIENT_GLYPH_CACHE_CAPABILITY_SET.as_ref()).unwrap()),
CapabilitySet::ColorCache(CLIENT_COLOR_CACHE_CAPABILITY_SET.to_vec()), CapabilitySet::Brush(Brush::from_buffer(CLIENT_BRUSH_CAPABILITY_SET.as_ref()).unwrap()),
CapabilitySet::WindowActivation( CapabilitySet::OffscreenBitmapCache(
CLIENT_WINDOW_ACTIVATION_CAPABILITY_SET.to_vec() OffscreenBitmapCache::from_buffer(CLIENT_OFFSCREEN_BITMAP_CAPABILITY_SET.as_ref()).unwrap()
), ),
CapabilitySet::Control(CLIENT_CONTROL_CAPABILITY_SET.to_vec()), CapabilitySet::VirtualChannel(
CapabilitySet::Pointer( VirtualChannel::from_buffer(CLIENT_VIRTUAL_CHANNEL_CAPABILITY_SET_INCOMPLETE.as_ref()).unwrap()
Pointer::from_buffer(CLIENT_POINTER_CAPABILITY_SET.as_ref()).unwrap() ),
), CapabilitySet::DrawNineGridCache(CLIENT_DRAW_NINE_GRID_CACHE_CAPABILITY_SET.to_vec()),
CapabilitySet::Share(CLIENT_SHARE_CAPABILITY_SET.to_vec()), CapabilitySet::DrawGdiPlus(CLIENT_DRAW_GDI_PLUS_CAPABILITY_SET.to_vec()),
CapabilitySet::Input( CapabilitySet::MultiFragmentUpdate(
Input::from_buffer(CLIENT_INPUT_CAPABILITY_SET_UNICODE.as_ref()).unwrap() MultifragmentUpdate::from_buffer(CLIENT_MULTI_FRAGMENT_UPDATE_CAPABILITY_SET.as_ref()).unwrap()
), ),
CapabilitySet::Sound( CapabilitySet::WindowList(CLIENT_WINDOW_LIST_CAPABILITY_SET.to_vec()),
Sound::from_buffer(CLIENT_SOUND_CAPABILITY_SET.as_ref()).unwrap() ],
), }
CapabilitySet::Font(CLIENT_FONT_CAPABILITY_SET.to_vec()), };
CapabilitySet::GlyphCache(
GlyphCache::from_buffer(CLIENT_GLYPH_CACHE_CAPABILITY_SET.as_ref())
.unwrap()
),
CapabilitySet::Brush(
Brush::from_buffer(CLIENT_BRUSH_CAPABILITY_SET.as_ref()).unwrap()
),
CapabilitySet::OffscreenBitmapCache(
OffscreenBitmapCache::from_buffer(
CLIENT_OFFSCREEN_BITMAP_CAPABILITY_SET.as_ref()
)
.unwrap()
),
CapabilitySet::VirtualChannel(
VirtualChannel::from_buffer(
CLIENT_VIRTUAL_CHANNEL_CAPABILITY_SET_INCOMPLETE.as_ref()
)
.unwrap()
),
CapabilitySet::DrawNineGridCache(
CLIENT_DRAW_NINE_GRID_CACHE_CAPABILITY_SET.to_vec()
),
CapabilitySet::DrawGdiPlus(CLIENT_DRAW_GDI_PLUS_CAPABILITY_SET.to_vec()),
CapabilitySet::MultiFragmentUpdate(
MultifragmentUpdate::from_buffer(
CLIENT_MULTI_FRAGMENT_UPDATE_CAPABILITY_SET.as_ref()
)
.unwrap()
),
CapabilitySet::WindowList(CLIENT_WINDOW_LIST_CAPABILITY_SET.to_vec()),
],
}
};
pub static ref CLIENT_DEMAND_ACTIVE: ClientConfirmActive = ClientConfirmActive { pub static ref CLIENT_DEMAND_ACTIVE: ClientConfirmActive = ClientConfirmActive {
originator_id: SERVER_CHANNEL_ID, originator_id: SERVER_CHANNEL_ID,
pdu: DemandActive { pdu: DemandActive {
source_descriptor: String::from("MSTSC"), source_descriptor: String::from("MSTSC"),
capability_sets: vec![ capability_sets: vec![
CapabilitySet::General( CapabilitySet::General(General::from_buffer(CLIENT_GENERAL_CAPABILITY_SET.as_ref()).unwrap()),
General::from_buffer(CLIENT_GENERAL_CAPABILITY_SET.as_ref()).unwrap() CapabilitySet::Bitmap(Bitmap::from_buffer(CLIENT_BITMAP_CAPABILITY_SET.as_ref()).unwrap()),
), CapabilitySet::Order(Order::from_buffer(CLIENT_ORDER_CAPABILITY_SET.as_ref()).unwrap()),
CapabilitySet::Bitmap(
Bitmap::from_buffer(CLIENT_BITMAP_CAPABILITY_SET.as_ref()).unwrap()
),
CapabilitySet::Order(
Order::from_buffer(CLIENT_ORDER_CAPABILITY_SET.as_ref()).unwrap()
),
CapabilitySet::BitmapCacheRev2( CapabilitySet::BitmapCacheRev2(
BitmapCacheRev2::from_buffer(CLIENT_BITMAP_CACHE_REV_2_CAPABILITY_SET.as_ref()) BitmapCacheRev2::from_buffer(CLIENT_BITMAP_CACHE_REV_2_CAPABILITY_SET.as_ref()).unwrap()
.unwrap()
), ),
CapabilitySet::ColorCache(CLIENT_COLOR_CACHE_CAPABILITY_SET.to_vec()), CapabilitySet::ColorCache(CLIENT_COLOR_CACHE_CAPABILITY_SET.to_vec()),
CapabilitySet::WindowActivation(CLIENT_WINDOW_ACTIVATION_CAPABILITY_SET.to_vec()), CapabilitySet::WindowActivation(CLIENT_WINDOW_ACTIVATION_CAPABILITY_SET.to_vec()),
CapabilitySet::Control(CLIENT_CONTROL_CAPABILITY_SET.to_vec()), CapabilitySet::Control(CLIENT_CONTROL_CAPABILITY_SET.to_vec()),
CapabilitySet::Pointer( CapabilitySet::Pointer(Pointer::from_buffer(CLIENT_POINTER_CAPABILITY_SET.as_ref()).unwrap()),
Pointer::from_buffer(CLIENT_POINTER_CAPABILITY_SET.as_ref()).unwrap()
),
CapabilitySet::Share(CLIENT_SHARE_CAPABILITY_SET.to_vec()), CapabilitySet::Share(CLIENT_SHARE_CAPABILITY_SET.to_vec()),
CapabilitySet::Input( CapabilitySet::Input(Input::from_buffer(CLIENT_INPUT_CAPABILITY_SET.as_ref()).unwrap()),
Input::from_buffer(CLIENT_INPUT_CAPABILITY_SET.as_ref()).unwrap() CapabilitySet::Sound(Sound::from_buffer(CLIENT_SOUND_CAPABILITY_SET.as_ref()).unwrap()),
),
CapabilitySet::Sound(
Sound::from_buffer(CLIENT_SOUND_CAPABILITY_SET.as_ref()).unwrap()
),
CapabilitySet::Font(CLIENT_FONT_CAPABILITY_SET.to_vec()), CapabilitySet::Font(CLIENT_FONT_CAPABILITY_SET.to_vec()),
CapabilitySet::GlyphCache( CapabilitySet::GlyphCache(GlyphCache::from_buffer(CLIENT_GLYPH_CACHE_CAPABILITY_SET.as_ref()).unwrap()),
GlyphCache::from_buffer(CLIENT_GLYPH_CACHE_CAPABILITY_SET.as_ref()).unwrap() CapabilitySet::Brush(Brush::from_buffer(CLIENT_BRUSH_CAPABILITY_SET.as_ref()).unwrap()),
),
CapabilitySet::Brush(
Brush::from_buffer(CLIENT_BRUSH_CAPABILITY_SET.as_ref()).unwrap()
),
CapabilitySet::OffscreenBitmapCache( CapabilitySet::OffscreenBitmapCache(
OffscreenBitmapCache::from_buffer( OffscreenBitmapCache::from_buffer(CLIENT_OFFSCREEN_BITMAP_CAPABILITY_SET.as_ref()).unwrap()
CLIENT_OFFSCREEN_BITMAP_CAPABILITY_SET.as_ref()
)
.unwrap()
), ),
CapabilitySet::VirtualChannel( CapabilitySet::VirtualChannel(
VirtualChannel::from_buffer(CLIENT_VIRTUAL_CHANNEL_CAPABILITY_SET.as_ref()) VirtualChannel::from_buffer(CLIENT_VIRTUAL_CHANNEL_CAPABILITY_SET.as_ref()).unwrap()
.unwrap()
),
CapabilitySet::DrawNineGridCache(
CLIENT_DRAW_NINE_GRID_CACHE_CAPABILITY_SET.to_vec()
), ),
CapabilitySet::DrawNineGridCache(CLIENT_DRAW_NINE_GRID_CACHE_CAPABILITY_SET.to_vec()),
CapabilitySet::DrawGdiPlus(CLIENT_DRAW_GDI_PLUS_CAPABILITY_SET.to_vec()), CapabilitySet::DrawGdiPlus(CLIENT_DRAW_GDI_PLUS_CAPABILITY_SET.to_vec()),
], ],
} }
@ -421,10 +321,7 @@ lazy_static! {
fn from_buffer_correctly_parses_server_demand_active() { fn from_buffer_correctly_parses_server_demand_active() {
let buffer = SERVER_DEMAND_ACTIVE_BUFFER.as_ref(); let buffer = SERVER_DEMAND_ACTIVE_BUFFER.as_ref();
assert_eq!( assert_eq!(*SERVER_DEMAND_ACTIVE, ServerDemandActive::from_buffer(buffer).unwrap());
*SERVER_DEMAND_ACTIVE,
ServerDemandActive::from_buffer(buffer).unwrap()
);
} }
#[test] #[test]
@ -441,10 +338,7 @@ fn from_buffer_correctly_parses_client_demand_active_with_incomplete_capability_
fn from_buffer_correctly_parses_client_demand_active() { fn from_buffer_correctly_parses_client_demand_active() {
let buffer = CLIENT_DEMAND_ACTIVE_BUFFER.as_ref(); let buffer = CLIENT_DEMAND_ACTIVE_BUFFER.as_ref();
assert_eq!( assert_eq!(*CLIENT_DEMAND_ACTIVE, ClientConfirmActive::from_buffer(buffer).unwrap());
*CLIENT_DEMAND_ACTIVE,
ClientConfirmActive::from_buffer(buffer).unwrap()
);
} }
#[test] #[test]

View file

@ -6,7 +6,8 @@ use std::io;
use bitflags::bitflags; use bitflags::bitflags;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use crate::{rdp::CapabilitySetsError, try_read_optional, try_write_optional, PduParsing}; use crate::rdp::CapabilitySetsError;
use crate::{try_read_optional, try_write_optional, PduParsing};
const FLAGS_FIELD_SIZE: usize = 4; const FLAGS_FIELD_SIZE: usize = 4;
const CHUNK_SIZE_FIELD_SIZE: usize = 4; const CHUNK_SIZE_FIELD_SIZE: usize = 4;

View file

@ -66,8 +66,5 @@ fn buffer_length_is_correct_for_virtual_channel_incomplete_capset() {
#[test] #[test]
fn buffer_length_is_correct_for_virtual_channel_capset() { fn buffer_length_is_correct_for_virtual_channel_capset() {
assert_eq!( assert_eq!(VIRTUAL_CHANNEL_BUFFER.len(), VIRTUAL_CHANNEL.buffer_length());
VIRTUAL_CHANNEL_BUFFER.len(),
VIRTUAL_CHANNEL.buffer_length()
);
} }

View file

@ -9,9 +9,8 @@ use failure::Fail;
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
use crate::{ use crate::utils::CharacterSet;
impl_from_error, try_read_optional, try_write_optional, utils, utils::CharacterSet, PduParsing, use crate::{impl_from_error, try_read_optional, try_write_optional, utils, PduParsing};
};
const RECONNECT_COOKIE_LEN: usize = 28; const RECONNECT_COOKIE_LEN: usize = 28;
const TIMEZONE_INFO_NAME_LEN: usize = 64; const TIMEZONE_INFO_NAME_LEN: usize = 64;
@ -52,13 +51,11 @@ impl PduParsing for ClientInfo {
let code_page = stream.read_u32::<LittleEndian>()?; let code_page = stream.read_u32::<LittleEndian>()?;
let flags_with_compression_type = stream.read_u32::<LittleEndian>()?; let flags_with_compression_type = stream.read_u32::<LittleEndian>()?;
let flags = let flags = ClientInfoFlags::from_bits(flags_with_compression_type & !COMPRESSION_TYPE_MASK)
ClientInfoFlags::from_bits(flags_with_compression_type & !COMPRESSION_TYPE_MASK) .ok_or(ClientInfoError::InvalidClientInfoFlags)?;
let compression_type =
CompressionType::from_u8(((flags_with_compression_type & COMPRESSION_TYPE_MASK) >> 9) as u8)
.ok_or(ClientInfoError::InvalidClientInfoFlags)?; .ok_or(ClientInfoError::InvalidClientInfoFlags)?;
let compression_type = CompressionType::from_u8(
((flags_with_compression_type & COMPRESSION_TYPE_MASK) >> 9) as u8,
)
.ok_or(ClientInfoError::InvalidClientInfoFlags)?;
let character_set = if flags.contains(ClientInfoFlags::UNICODE) { let character_set = if flags.contains(ClientInfoFlags::UNICODE) {
CharacterSet::Unicode CharacterSet::Unicode
} else { } else {
@ -76,19 +73,14 @@ impl PduParsing for ClientInfo {
let username = utils::read_string(&mut stream, user_name_size, character_set, true)?; let username = utils::read_string(&mut stream, user_name_size, character_set, true)?;
let password = utils::read_string(&mut stream, password_size, character_set, true)?; let password = utils::read_string(&mut stream, password_size, character_set, true)?;
let domain = if domain.is_empty() { let domain = if domain.is_empty() { None } else { Some(domain) };
None
} else {
Some(domain)
};
let credentials = Credentials { let credentials = Credentials {
username, username,
password, password,
domain, domain,
}; };
let alternate_shell = let alternate_shell = utils::read_string(&mut stream, alternate_shell_size, character_set, true)?;
utils::read_string(&mut stream, alternate_shell_size, character_set, true)?;
let work_dir = utils::read_string(&mut stream, work_dir_size, character_set, true)?; let work_dir = utils::read_string(&mut stream, work_dir_size, character_set, true)?;
let extra_info = ExtendedClientInfo::from_buffer(&mut stream, character_set)?; let extra_info = ExtendedClientInfo::from_buffer(&mut stream, character_set)?;
@ -113,45 +105,21 @@ impl PduParsing for ClientInfo {
stream.write_u32::<LittleEndian>(self.code_page)?; stream.write_u32::<LittleEndian>(self.code_page)?;
let flags_with_compression_type = let flags_with_compression_type = self.flags.bits() | (self.compression_type.to_u32().unwrap() << 9);
self.flags.bits() | (self.compression_type.to_u32().unwrap() << 9);
stream.write_u32::<LittleEndian>(flags_with_compression_type)?; stream.write_u32::<LittleEndian>(flags_with_compression_type)?;
let domain = self.credentials.domain.clone().unwrap_or_default(); let domain = self.credentials.domain.clone().unwrap_or_default();
stream.write_u16::<LittleEndian>(string_len(domain.as_str(), character_set))?; stream.write_u16::<LittleEndian>(string_len(domain.as_str(), character_set))?;
stream.write_u16::<LittleEndian>(string_len( stream.write_u16::<LittleEndian>(string_len(self.credentials.username.as_str(), character_set))?;
self.credentials.username.as_str(), stream.write_u16::<LittleEndian>(string_len(self.credentials.password.as_str(), character_set))?;
character_set, stream.write_u16::<LittleEndian>(string_len(self.alternate_shell.as_str(), character_set))?;
))?;
stream.write_u16::<LittleEndian>(string_len(
self.credentials.password.as_str(),
character_set,
))?;
stream
.write_u16::<LittleEndian>(string_len(self.alternate_shell.as_str(), character_set))?;
stream.write_u16::<LittleEndian>(string_len(self.work_dir.as_str(), character_set))?; stream.write_u16::<LittleEndian>(string_len(self.work_dir.as_str(), character_set))?;
utils::write_string_with_null_terminator(&mut stream, domain.as_str(), character_set)?; utils::write_string_with_null_terminator(&mut stream, domain.as_str(), character_set)?;
utils::write_string_with_null_terminator( utils::write_string_with_null_terminator(&mut stream, self.credentials.username.as_str(), character_set)?;
&mut stream, utils::write_string_with_null_terminator(&mut stream, self.credentials.password.as_str(), character_set)?;
self.credentials.username.as_str(), utils::write_string_with_null_terminator(&mut stream, self.alternate_shell.as_str(), character_set)?;
character_set, utils::write_string_with_null_terminator(&mut stream, self.work_dir.as_str(), character_set)?;
)?;
utils::write_string_with_null_terminator(
&mut stream,
self.credentials.password.as_str(),
character_set,
)?;
utils::write_string_with_null_terminator(
&mut stream,
self.alternate_shell.as_str(),
character_set,
)?;
utils::write_string_with_null_terminator(
&mut stream,
self.work_dir.as_str(),
character_set,
)?;
self.extra_info.to_buffer(&mut stream, character_set)?; self.extra_info.to_buffer(&mut stream, character_set)?;
@ -199,12 +167,9 @@ pub struct ExtendedClientInfo {
} }
impl ExtendedClientInfo { impl ExtendedClientInfo {
fn from_buffer( fn from_buffer(mut stream: impl io::Read, character_set: CharacterSet) -> Result<Self, ClientInfoError> {
mut stream: impl io::Read, let address_family =
character_set: CharacterSet, AddressFamily::from_u16(stream.read_u16::<LittleEndian>()?).ok_or(ClientInfoError::InvalidAddressFamily)?;
) -> Result<Self, ClientInfoError> {
let address_family = AddressFamily::from_u16(stream.read_u16::<LittleEndian>()?)
.ok_or(ClientInfoError::InvalidAddressFamily)?;
// This size includes the length of the mandatory null terminator. // This size includes the length of the mandatory null terminator.
let address_size = stream.read_u16::<LittleEndian>()? as usize; let address_size = stream.read_u16::<LittleEndian>()? as usize;
@ -224,22 +189,14 @@ impl ExtendedClientInfo {
}) })
} }
fn to_buffer( fn to_buffer(&self, mut stream: impl io::Write, character_set: CharacterSet) -> Result<(), ClientInfoError> {
&self,
mut stream: impl io::Write,
character_set: CharacterSet,
) -> Result<(), ClientInfoError> {
stream.write_u16::<LittleEndian>(self.address_family.to_u16().unwrap())?; stream.write_u16::<LittleEndian>(self.address_family.to_u16().unwrap())?;
// + size of null terminator, which will write in the write_string function // + size of null terminator, which will write in the write_string function
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
string_len(self.address.as_str(), character_set) + character_set.to_u16().unwrap(), string_len(self.address.as_str(), character_set) + character_set.to_u16().unwrap(),
)?; )?;
utils::write_string_with_null_terminator( utils::write_string_with_null_terminator(&mut stream, self.address.as_str(), character_set)?;
&mut stream,
self.address.as_str(),
character_set,
)?;
stream.write_u16::<LittleEndian>( stream.write_u16::<LittleEndian>(
string_len(self.dir.as_str(), character_set) + character_set.to_u16().unwrap(), string_len(self.dir.as_str(), character_set) + character_set.to_u16().unwrap(),
@ -285,20 +242,13 @@ impl PduParsing for ExtendedClientOptionalInfo {
} }
Err(e) => return Err(e), Err(e) => return Err(e),
}; };
optional_data.session_id = Some(try_read_optional!( optional_data.session_id = Some(try_read_optional!(stream.read_u32::<LittleEndian>(), optional_data));
stream.read_u32::<LittleEndian>(),
optional_data
));
optional_data.performance_flags = Some( optional_data.performance_flags = Some(
PerformanceFlags::from_bits(try_read_optional!( PerformanceFlags::from_bits(try_read_optional!(stream.read_u32::<LittleEndian>(), optional_data))
stream.read_u32::<LittleEndian>(), .ok_or(ClientInfoError::InvalidPerformanceFlags)?,
optional_data
))
.ok_or(ClientInfoError::InvalidPerformanceFlags)?,
); );
let reconnect_cookie_size = let reconnect_cookie_size = try_read_optional!(stream.read_u16::<LittleEndian>(), optional_data);
try_read_optional!(stream.read_u16::<LittleEndian>(), optional_data);
if reconnect_cookie_size != RECONNECT_COOKIE_LEN as u16 && reconnect_cookie_size != 0 { if reconnect_cookie_size != RECONNECT_COOKIE_LEN as u16 && reconnect_cookie_size != 0 {
return Err(ClientInfoError::InvalidReconnectCookie); return Err(ClientInfoError::InvalidReconnectCookie);
} }
@ -317,10 +267,8 @@ impl PduParsing for ExtendedClientOptionalInfo {
} }
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
try_write_optional!(self.timezone, |value: &TimezoneInfo| value try_write_optional!(self.timezone, |value: &TimezoneInfo| value.to_buffer(&mut stream));
.to_buffer(&mut stream)); try_write_optional!(self.session_id, |value: &u32| stream.write_u32::<LittleEndian>(*value));
try_write_optional!(self.session_id, |value: &u32| stream
.write_u32::<LittleEndian>(*value));
try_write_optional!(self.performance_flags, |value: &PerformanceFlags| { try_write_optional!(self.performance_flags, |value: &PerformanceFlags| {
stream.write_u32::<LittleEndian>(value.bits()) stream.write_u32::<LittleEndian>(value.bits())
}); });
@ -369,21 +317,11 @@ impl PduParsing for TimezoneInfo {
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> { fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
let bias = stream.read_u32::<LittleEndian>()?; let bias = stream.read_u32::<LittleEndian>()?;
let standard_name = utils::read_string( let standard_name = utils::read_string(&mut stream, TIMEZONE_INFO_NAME_LEN, CharacterSet::Unicode, false)?;
&mut stream,
TIMEZONE_INFO_NAME_LEN,
CharacterSet::Unicode,
false,
)?;
let standard_date = Option::<SystemTime>::from_buffer(&mut stream)?; let standard_date = Option::<SystemTime>::from_buffer(&mut stream)?;
let standard_bias = stream.read_u32::<LittleEndian>()?; let standard_bias = stream.read_u32::<LittleEndian>()?;
let daylight_name = utils::read_string( let daylight_name = utils::read_string(&mut stream, TIMEZONE_INFO_NAME_LEN, CharacterSet::Unicode, false)?;
&mut stream,
TIMEZONE_INFO_NAME_LEN,
CharacterSet::Unicode,
false,
)?;
let daylight_date = Option::<SystemTime>::from_buffer(&mut stream)?; let daylight_date = Option::<SystemTime>::from_buffer(&mut stream)?;
let daylight_bias = stream.read_u32::<LittleEndian>()?; let daylight_bias = stream.read_u32::<LittleEndian>()?;
@ -622,11 +560,7 @@ pub enum ClientInfoError {
} }
impl_from_error!(io::Error, ClientInfoError, ClientInfoError::IOError); impl_from_error!(io::Error, ClientInfoError, ClientInfoError::IOError);
impl_from_error!( impl_from_error!(std::string::FromUtf8Error, ClientInfoError, ClientInfoError::Utf8Error);
std::string::FromUtf8Error,
ClientInfoError,
ClientInfoError::Utf8Error
);
fn string_len(value: &str, character_set: CharacterSet) -> u16 { fn string_len(value: &str, character_set: CharacterSet) -> u16 {
value.len() as u16 * character_set.to_u16().unwrap() value.len() as u16 * character_set.to_u16().unwrap()

View file

@ -14,37 +14,33 @@ pub const CLIENT_INFO_BUFFER_UNICODE: [u8; CLIENT_INFO_BUFFER_UNICODE_LEN] = [
0x00, 0x00, // alternate shell size 0x00, 0x00, // alternate shell size
0x00, 0x00, // work dir size 0x00, 0x00, // work dir size
0x4e, 0x00, 0x54, 0x00, 0x44, 0x00, 0x45, 0x00, 0x56, 0x00, 0x00, 0x00, // domain 0x4e, 0x00, 0x54, 0x00, 0x44, 0x00, 0x45, 0x00, 0x56, 0x00, 0x00, 0x00, // domain
0x65, 0x00, 0x6c, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x00, 0x00, // user name
0x00, // user name
0x00, 0x00, // password 0x00, 0x00, // password
0x00, 0x00, // alternate shell 0x00, 0x00, // alternate shell
0x00, 0x00, // work dir 0x00, 0x00, // work dir
0x02, 0x00, // client address family 0x02, 0x00, // client address family
0x1e, 0x00, // client address size 0x1e, 0x00, // client address size
0x31, 0x00, 0x35, 0x00, 0x37, 0x00, 0x2e, 0x00, 0x35, 0x00, 0x39, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x31, 0x00, 0x35, 0x00, 0x37, 0x00, 0x2e, 0x00, 0x35, 0x00, 0x39, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x34, 0x00, 0x32,
0x34, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x35, 0x00, 0x36, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x35, 0x00, 0x36, 0x00, 0x00, 0x00, // client address
0x00, // client address
0x84, 0x00, // client dir size 0x84, 0x00, // client dir size
0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x73, 0x00, 0x5c,
0x73, 0x00, 0x5c, 0x00, 0x77, 0x00, 0x32, 0x00, 0x6b, 0x00, 0x33, 0x00, 0x5f, 0x00, 0x31, 0x00, 0x00, 0x77, 0x00, 0x32, 0x00, 0x6b, 0x00, 0x33, 0x00, 0x5f, 0x00, 0x31, 0x00, 0x5c, 0x00, 0x74, 0x00, 0x65, 0x00,
0x5c, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x73, 0x00, 0x72, 0x00, 0x76, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x73, 0x00, 0x72, 0x00, 0x76, 0x00, 0x5c, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x77, 0x00, 0x63,
0x5c, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x77, 0x00, 0x63, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x65, 0x00, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x5c, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x62, 0x00,
0x6e, 0x00, 0x74, 0x00, 0x5c, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x62, 0x00, 0x5c, 0x00, 0x77, 0x00, 0x5c, 0x00, 0x77, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x33, 0x00, 0x32, 0x00, 0x5c, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x6a,
0x69, 0x00, 0x6e, 0x00, 0x33, 0x00, 0x32, 0x00, 0x5c, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x6a, 0x00, 0x00, 0x5c, 0x00, 0x69, 0x00, 0x33, 0x00, 0x38, 0x00, 0x36, 0x00, 0x5c, 0x00, 0x6d, 0x00, 0x73, 0x00, 0x74, 0x00,
0x5c, 0x00, 0x69, 0x00, 0x33, 0x00, 0x38, 0x00, 0x36, 0x00, 0x5c, 0x00, 0x6d, 0x00, 0x73, 0x00, 0x73, 0x00, 0x63, 0x00, 0x61, 0x00, 0x78, 0x00, 0x2e, 0x00, 0x64, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x00,
0x74, 0x00, 0x73, 0x00, 0x63, 0x00, 0x61, 0x00, 0x78, 0x00, 0x2e, 0x00, 0x64, 0x00, 0x6c, 0x00, 0x00, // client dir
0x6c, 0x00, 0x00, 0x00, // client dir 0xe0, 0x01, 0x00, 0x00, 0x50, 0x00, 0x61, 0x00, 0x63, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x20,
0xe0, 0x01, 0x00, 0x00, 0x50, 0x00, 0x61, 0x00, 0x63, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x53, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, 0x20, 0x00,
0x63, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x61, 0x00, 0x54, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x72, 0x00, 0x64, 0x00, 0x20, 0x00, 0x54, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x61, 0x00, 0x63, 0x00, 0x69,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x20, 0x00, 0x44, 0x00, 0x61, 0x00, 0x79, 0x00, 0x6c, 0x00, 0x69, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x61, 0x00, 0x63, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x54, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00,
0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x20, 0x00, 0x44, 0x00, 0x61, 0x00, 0x79, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x54, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0xff, 0xff,
0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, // TimezoneInfo
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0xff, 0xff, 0xff, // TimezoneInfo
0x00, 0x00, 0x00, 0x00, // session id 0x00, 0x00, 0x00, 0x00, // session id
0x01, 0x00, 0x00, 0x00, // performance flags 0x01, 0x00, 0x00, 0x00, // performance flags
]; ];
@ -65,25 +61,22 @@ const CLIENT_INFO_BUFFER_ANSI: [u8; CLIENT_INFO_BUFFER_ANSI_LEN] = [
0x00, // work dir 0x00, // work dir
0x02, 0x00, // client address family 0x02, 0x00, // client address family
0x0f, 0x00, // client address size 0x0f, 0x00, // client address size
0x31, 0x35, 0x37, 0x2e, 0x35, 0x39, 0x2e, 0x32, 0x34, 0x32, 0x2e, 0x31, 0x35, 0x36, 0x31, 0x35, 0x37, 0x2e, 0x35, 0x39, 0x2e, 0x32, 0x34, 0x32, 0x2e, 0x31, 0x35, 0x36, 0x00, // client address
0x00, // client address
0x42, 0x00, // client dir size 0x42, 0x00, // client dir size
0x43, 0x3a, 0x5c, 0x64, 0x65, 0x70, 0x6f, 0x74, 0x73, 0x5c, 0x77, 0x32, 0x6b, 0x33, 0x5f, 0x31, 0x43, 0x3a, 0x5c, 0x64, 0x65, 0x70, 0x6f, 0x74, 0x73, 0x5c, 0x77, 0x32, 0x6b, 0x33, 0x5f, 0x31, 0x5c, 0x74, 0x65,
0x5c, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x72, 0x76, 0x5c, 0x6e, 0x65, 0x77, 0x63, 0x6c, 0x69, 0x65, 0x72, 0x6d, 0x73, 0x72, 0x76, 0x5c, 0x6e, 0x65, 0x77, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5c, 0x6c, 0x69, 0x62,
0x6e, 0x74, 0x5c, 0x6c, 0x69, 0x62, 0x5c, 0x77, 0x69, 0x6e, 0x33, 0x32, 0x5c, 0x6f, 0x62, 0x6a, 0x5c, 0x77, 0x69, 0x6e, 0x33, 0x32, 0x5c, 0x6f, 0x62, 0x6a, 0x5c, 0x69, 0x33, 0x38, 0x36, 0x5c, 0x6d, 0x73, 0x74,
0x5c, 0x69, 0x33, 0x38, 0x36, 0x5c, 0x6d, 0x73, 0x74, 0x73, 0x63, 0x61, 0x78, 0x2e, 0x64, 0x6c, 0x73, 0x63, 0x61, 0x78, 0x2e, 0x64, 0x6c, 0x6c, 0x00, // client dir
0x6c, 0x00, // client dir 0xe0, 0x01, 0x00, 0x00, 0x50, 0x00, 0x61, 0x00, 0x63, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x20,
0xe0, 0x01, 0x00, 0x00, 0x50, 0x00, 0x61, 0x00, 0x63, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x53, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, 0x20, 0x00,
0x63, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x61, 0x00, 0x54, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x72, 0x00, 0x64, 0x00, 0x20, 0x00, 0x54, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x61, 0x00, 0x63, 0x00, 0x69,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x20, 0x00, 0x44, 0x00, 0x61, 0x00, 0x79, 0x00, 0x6c, 0x00, 0x69, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x61, 0x00, 0x63, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x54, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00,
0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x20, 0x00, 0x44, 0x00, 0x61, 0x00, 0x79, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x54, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0xff, 0xff,
0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, // TimezoneInfo
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0xff, 0xff, 0xff, // TimezoneInfo
0x00, 0x00, 0x00, 0x00, // session id 0x00, 0x00, 0x00, 0x00, // session id
0x01, 0x00, 0x00, 0x00, // performance flags 0x01, 0x00, 0x00, 0x00, // performance flags
]; ];
@ -109,9 +102,7 @@ lazy_static! {
extra_info: ExtendedClientInfo { extra_info: ExtendedClientInfo {
address_family: AddressFamily::INet, address_family: AddressFamily::INet,
address: String::from("157.59.242.156"), address: String::from("157.59.242.156"),
dir: String::from( dir: String::from("C:\\depots\\w2k3_1\\termsrv\\newclient\\lib\\win32\\obj\\i386\\mstscax.dll"),
"C:\\depots\\w2k3_1\\termsrv\\newclient\\lib\\win32\\obj\\i386\\mstscax.dll"
),
optional_data: ExtendedClientOptionalInfo { optional_data: ExtendedClientOptionalInfo {
timezone: Some(TimezoneInfo { timezone: Some(TimezoneInfo {
bias: 0x01e0, bias: 0x01e0,
@ -184,8 +175,7 @@ fn from_buffer_correct_parses_client_info_pdu_unicode() {
fn from_buffer_correct_parses_client_info_pdu_unicode_without_optional_fields() { fn from_buffer_correct_parses_client_info_pdu_unicode_without_optional_fields() {
assert_eq!( assert_eq!(
CLIENT_INFO_UNICODE_WITHOUT_OPTIONAL_FIELDS.clone(), CLIENT_INFO_UNICODE_WITHOUT_OPTIONAL_FIELDS.clone(),
ClientInfo::from_buffer(CLIENT_INFO_BUFFER_UNICODE_WITHOUT_OPTIONAL_FIELDS.as_slice()) ClientInfo::from_buffer(CLIENT_INFO_BUFFER_UNICODE_WITHOUT_OPTIONAL_FIELDS.as_slice()).unwrap()
.unwrap()
); );
} }

View file

@ -132,9 +132,7 @@ impl PduParsing for MonitorLayoutPdu {
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> { fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
let monitor_count = stream.read_u32::<LittleEndian>()?; let monitor_count = stream.read_u32::<LittleEndian>()?;
if monitor_count > MAX_MONITOR_COUNT { if monitor_count > MAX_MONITOR_COUNT {
return Err(FinalizationMessagesError::InvalidMonitorCount( return Err(FinalizationMessagesError::InvalidMonitorCount(monitor_count));
monitor_count,
));
} }
let mut monitors = Vec::with_capacity(monitor_count as usize); let mut monitors = Vec::with_capacity(monitor_count as usize);
@ -196,11 +194,7 @@ pub enum FinalizationMessagesError {
InvalidMonitorCount(u32), InvalidMonitorCount(u32),
} }
impl_from_error!( impl_from_error!(io::Error, FinalizationMessagesError, FinalizationMessagesError::IOError);
io::Error,
FinalizationMessagesError,
FinalizationMessagesError::IOError
);
impl_from_error!( impl_from_error!(
gcc::MonitorDataError, gcc::MonitorDataError,
FinalizationMessagesError, FinalizationMessagesError,

View file

@ -9,11 +9,10 @@ use super::{
client_info, ClientConfirmActive, ControlPdu, MonitorLayoutPdu, RdpError, ServerDemandActive, client_info, ClientConfirmActive, ControlPdu, MonitorLayoutPdu, RdpError, ServerDemandActive,
ServerSetErrorInfoPdu, SynchronizePdu, ServerSetErrorInfoPdu, SynchronizePdu,
}; };
use crate::{ use crate::codecs::rfx::FrameAcknowledgePdu;
codecs::rfx::FrameAcknowledgePdu, use crate::rdp::finalization_messages::FontPdu;
rdp::{finalization_messages::FontPdu, session_info::SaveSessionInfoPdu}, use crate::rdp::session_info::SaveSessionInfoPdu;
PduParsing, use crate::PduParsing;
};
pub const BASIC_SECURITY_HEADER_SIZE: usize = 4; pub const BASIC_SECURITY_HEADER_SIZE: usize = 4;
const SHARE_CONTROL_HEADER_MASK: u16 = 0xf; const SHARE_CONTROL_HEADER_MASK: u16 = 0xf;
@ -74,11 +73,8 @@ impl PduParsing for ShareControlHeader {
let pdu_source = stream.read_u16::<LittleEndian>()?; let pdu_source = stream.read_u16::<LittleEndian>()?;
let share_id = stream.read_u32::<LittleEndian>()?; let share_id = stream.read_u32::<LittleEndian>()?;
let pdu_type = let pdu_type = ShareControlPduType::from_u16(pdu_type_with_version & SHARE_CONTROL_HEADER_MASK)
ShareControlPduType::from_u16(pdu_type_with_version & SHARE_CONTROL_HEADER_MASK) .ok_or_else(|| RdpError::InvalidShareControlHeader(String::from("Invalid pdu type")))?;
.ok_or_else(|| {
RdpError::InvalidShareControlHeader(String::from("Invalid pdu type"))
})?;
let pdu_version = pdu_type_with_version & !SHARE_CONTROL_HEADER_MASK; let pdu_version = pdu_type_with_version & !SHARE_CONTROL_HEADER_MASK;
if pdu_version != PROTOCOL_VERSION { if pdu_version != PROTOCOL_VERSION {
return Err(RdpError::InvalidShareControlHeader(format!( return Err(RdpError::InvalidShareControlHeader(format!(
@ -96,12 +92,10 @@ impl PduParsing for ShareControlHeader {
}) })
} }
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
let pdu_type_with_version = let pdu_type_with_version = PROTOCOL_VERSION | self.share_control_pdu.share_header_type().to_u16().unwrap();
PROTOCOL_VERSION | self.share_control_pdu.share_header_type().to_u16().unwrap();
stream.write_u16::<LittleEndian>( stream
(self.share_control_pdu.buffer_length() + SHARE_CONTROL_HEADER_SIZE) as u16, .write_u16::<LittleEndian>((self.share_control_pdu.buffer_length() + SHARE_CONTROL_HEADER_SIZE) as u16)?;
)?;
stream.write_u16::<LittleEndian>(pdu_type_with_version)?; stream.write_u16::<LittleEndian>(pdu_type_with_version)?;
stream.write_u16::<LittleEndian>(self.pdu_source)?; stream.write_u16::<LittleEndian>(self.pdu_source)?;
stream.write_u32::<LittleEndian>(self.share_id)?; stream.write_u32::<LittleEndian>(self.share_id)?;
@ -131,10 +125,7 @@ impl ShareControlPdu {
} }
impl ShareControlPdu { impl ShareControlPdu {
pub fn from_type( pub fn from_type(mut stream: impl io::Read, share_type: ShareControlPduType) -> Result<Self, RdpError> {
mut stream: impl io::Read,
share_type: ShareControlPduType,
) -> Result<Self, RdpError> {
match share_type { match share_type {
ShareControlPduType::DemandActivePdu => Ok(ShareControlPdu::ServerDemandActive( ShareControlPduType::DemandActivePdu => Ok(ShareControlPdu::ServerDemandActive(
ServerDemandActive::from_buffer(&mut stream)?, ServerDemandActive::from_buffer(&mut stream)?,
@ -142,20 +133,14 @@ impl ShareControlPdu {
ShareControlPduType::ConfirmActivePdu => Ok(ShareControlPdu::ClientConfirmActive( ShareControlPduType::ConfirmActivePdu => Ok(ShareControlPdu::ClientConfirmActive(
ClientConfirmActive::from_buffer(&mut stream)?, ClientConfirmActive::from_buffer(&mut stream)?,
)), )),
ShareControlPduType::DataPdu => Ok(ShareControlPdu::Data( ShareControlPduType::DataPdu => Ok(ShareControlPdu::Data(ShareDataHeader::from_buffer(&mut stream)?)),
ShareDataHeader::from_buffer(&mut stream)?,
)),
_ => Err(RdpError::UnexpectedShareControlPdu(share_type)), _ => Err(RdpError::UnexpectedShareControlPdu(share_type)),
} }
} }
pub fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), RdpError> { pub fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), RdpError> {
match self { match self {
ShareControlPdu::ServerDemandActive(pdu) => { ShareControlPdu::ServerDemandActive(pdu) => pdu.to_buffer(&mut stream).map_err(RdpError::from),
pdu.to_buffer(&mut stream).map_err(RdpError::from) ShareControlPdu::ClientConfirmActive(pdu) => pdu.to_buffer(&mut stream).map_err(RdpError::from),
}
ShareControlPdu::ClientConfirmActive(pdu) => {
pdu.to_buffer(&mut stream).map_err(RdpError::from)
}
ShareControlPdu::Data(share_data_header) => share_data_header.to_buffer(&mut stream), ShareControlPdu::Data(share_data_header) => share_data_header.to_buffer(&mut stream),
} }
} }
@ -188,23 +173,18 @@ impl PduParsing for ShareDataHeader {
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> { fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
let _padding = stream.read_u8()?; let _padding = stream.read_u8()?;
let stream_priority = StreamPriority::from_u8(stream.read_u8()?).ok_or_else(|| { let stream_priority = StreamPriority::from_u8(stream.read_u8()?)
RdpError::InvalidShareDataHeader(String::from("Invalid stream priority")) .ok_or_else(|| RdpError::InvalidShareDataHeader(String::from("Invalid stream priority")))?;
})?;
let _uncompressed_length = stream.read_u16::<LittleEndian>()?; let _uncompressed_length = stream.read_u16::<LittleEndian>()?;
let pdu_type = ShareDataPduType::from_u8(stream.read_u8()?) let pdu_type = ShareDataPduType::from_u8(stream.read_u8()?)
.ok_or_else(|| RdpError::InvalidShareDataHeader(String::from("Invalid pdu type")))?; .ok_or_else(|| RdpError::InvalidShareDataHeader(String::from("Invalid pdu type")))?;
let compression_flags_with_type = stream.read_u8()?; let compression_flags_with_type = stream.read_u8()?;
let compression_flags = CompressionFlags::from_bits_truncate( let compression_flags =
compression_flags_with_type & SHARE_DATA_HEADER_MASK, CompressionFlags::from_bits_truncate(compression_flags_with_type & SHARE_DATA_HEADER_MASK);
); let compression_type =
let compression_type = client_info::CompressionType::from_u8( client_info::CompressionType::from_u8(compression_flags_with_type & !SHARE_DATA_HEADER_MASK)
compression_flags_with_type & !SHARE_DATA_HEADER_MASK, .ok_or_else(|| RdpError::InvalidShareDataHeader(String::from("Invalid compression type")))?;
)
.ok_or_else(|| {
RdpError::InvalidShareDataHeader(String::from("Invalid compression type"))
})?;
let _compressed_length = stream.read_u16::<LittleEndian>()?; let _compressed_length = stream.read_u16::<LittleEndian>()?;
let share_data_pdu = ShareDataPdu::from_type(&mut stream, pdu_type)?; let share_data_pdu = ShareDataPdu::from_type(&mut stream, pdu_type)?;
@ -219,8 +199,7 @@ impl PduParsing for ShareDataHeader {
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
if self.compression_flags.is_empty() { if self.compression_flags.is_empty() {
let compression_flags_with_type = let compression_flags_with_type = self.compression_flags.bits() | self.compression_type.to_u8().unwrap();
self.compression_flags.bits() | self.compression_type.to_u8().unwrap();
stream.write_u8(0)?; // padding stream.write_u8(0)?; // padding
stream.write_u8(self.stream_priority.to_u8().unwrap())?; stream.write_u8(self.stream_priority.to_u8().unwrap())?;
@ -281,29 +260,18 @@ impl ShareDataPdu {
} }
impl ShareDataPdu { impl ShareDataPdu {
pub fn from_type( pub fn from_type(mut stream: impl io::Read, share_type: ShareDataPduType) -> Result<Self, RdpError> {
mut stream: impl io::Read,
share_type: ShareDataPduType,
) -> Result<Self, RdpError> {
match share_type { match share_type {
ShareDataPduType::Synchronize => Ok(ShareDataPdu::Synchronize( ShareDataPduType::Synchronize => Ok(ShareDataPdu::Synchronize(SynchronizePdu::from_buffer(&mut stream)?)),
SynchronizePdu::from_buffer(&mut stream)?, ShareDataPduType::Control => Ok(ShareDataPdu::Control(ControlPdu::from_buffer(&mut stream)?)),
)), ShareDataPduType::FontList => Ok(ShareDataPdu::FontList(FontPdu::from_buffer(&mut stream)?)),
ShareDataPduType::Control => { ShareDataPduType::FontMap => Ok(ShareDataPdu::FontMap(FontPdu::from_buffer(&mut stream)?)),
Ok(ShareDataPdu::Control(ControlPdu::from_buffer(&mut stream)?)) ShareDataPduType::MonitorLayoutPdu => {
Ok(ShareDataPdu::MonitorLayout(MonitorLayoutPdu::from_buffer(&mut stream)?))
} }
ShareDataPduType::FontList => { ShareDataPduType::SaveSessionInfo => Ok(ShareDataPdu::SaveSessionInfo(SaveSessionInfoPdu::from_buffer(
Ok(ShareDataPdu::FontList(FontPdu::from_buffer(&mut stream)?)) &mut stream,
} )?)),
ShareDataPduType::FontMap => {
Ok(ShareDataPdu::FontMap(FontPdu::from_buffer(&mut stream)?))
}
ShareDataPduType::MonitorLayoutPdu => Ok(ShareDataPdu::MonitorLayout(
MonitorLayoutPdu::from_buffer(&mut stream)?,
)),
ShareDataPduType::SaveSessionInfo => Ok(ShareDataPdu::SaveSessionInfo(
SaveSessionInfoPdu::from_buffer(&mut stream)?,
)),
ShareDataPduType::FrameAcknowledgePdu => Ok(ShareDataPdu::FrameAcknowledge( ShareDataPduType::FrameAcknowledgePdu => Ok(ShareDataPdu::FrameAcknowledge(
FrameAcknowledgePdu::from_buffer(&mut stream)?, FrameAcknowledgePdu::from_buffer(&mut stream)?,
)), )),
@ -337,15 +305,9 @@ impl ShareDataPdu {
pdu.to_buffer(&mut stream).map_err(RdpError::from) pdu.to_buffer(&mut stream).map_err(RdpError::from)
} }
ShareDataPdu::MonitorLayout(pdu) => pdu.to_buffer(&mut stream).map_err(RdpError::from), ShareDataPdu::MonitorLayout(pdu) => pdu.to_buffer(&mut stream).map_err(RdpError::from),
ShareDataPdu::SaveSessionInfo(pdu) => { ShareDataPdu::SaveSessionInfo(pdu) => pdu.to_buffer(&mut stream).map_err(RdpError::from),
pdu.to_buffer(&mut stream).map_err(RdpError::from) ShareDataPdu::FrameAcknowledge(pdu) => pdu.to_buffer(&mut stream).map_err(RdpError::from),
} ShareDataPdu::ServerSetErrorInfo(pdu) => pdu.to_buffer(&mut stream).map_err(RdpError::from),
ShareDataPdu::FrameAcknowledge(pdu) => {
pdu.to_buffer(&mut stream).map_err(RdpError::from)
}
ShareDataPdu::ServerSetErrorInfo(pdu) => {
pdu.to_buffer(&mut stream).map_err(RdpError::from)
}
} }
} }
pub fn buffer_length(&self) -> usize { pub fn buffer_length(&self) -> usize {

View file

@ -15,8 +15,8 @@ impl PduParsing for ServerSetErrorInfoPdu {
fn from_buffer(mut buffer: impl io::Read) -> Result<Self, Self::Error> { fn from_buffer(mut buffer: impl io::Read) -> Result<Self, Self::Error> {
let error_info = buffer.read_u32::<LittleEndian>()?; let error_info = buffer.read_u32::<LittleEndian>()?;
let error_info = ErrorInfo::from_u32(error_info) let error_info =
.ok_or(ServerSetErrorInfoError::UnexpectedInfoCode(error_info))?; ErrorInfo::from_u32(error_info).ok_or(ServerSetErrorInfoError::UnexpectedInfoCode(error_info))?;
Ok(Self(error_info)) Ok(Self(error_info))
} }
@ -49,10 +49,9 @@ impl ErrorInfo {
Self::ProtocolIndependentLicensingCode(c) => { Self::ProtocolIndependentLicensingCode(c) => {
format!("[Protocol independent licensing error] {}", c.description()) format!("[Protocol independent licensing error] {}", c.description())
} }
Self::ProtocolIndependentConnectionBrokerCode(c) => format!( Self::ProtocolIndependentConnectionBrokerCode(c) => {
"[Protocol independent connection broker error] {}", format!("[Protocol independent connection broker error] {}", c.description())
c.description() }
),
Self::RdpSpecificCode(c) => format!("[RDP specific code]: {}", c.description()), Self::RdpSpecificCode(c) => format!("[RDP specific code]: {}", c.description()),
} }
} }
@ -169,35 +168,19 @@ pub enum ProtocolIndependentLicensingCode {
impl ProtocolIndependentLicensingCode { impl ProtocolIndependentLicensingCode {
pub fn description(&self) -> &str { pub fn description(&self) -> &str {
match self { match self {
Self::Internal => { Self::Internal => "An internal error has occurred in the Terminal Services licensing component",
"An internal error has occurred in the Terminal Services licensing component" Self::NoLicenseServer => "A Remote Desktop License Server could not be found to provide a license",
} Self::NoLicense => "There are no Client Access Licenses available for the target remote computer",
Self::NoLicenseServer => { Self::BadClientMsg => "The remote computer received an invalid licensing message from the client",
"A Remote Desktop License Server could not be found to provide a license" Self::HwidDoesntMatchLicense => "The Client Access License stored by the client has been modified",
} Self::BadClientLicense => "The Client Access License stored by the client is in an invalid format",
Self::NoLicense => { Self::CantFinishProtocol => "Network problems have caused the licensing protocol to be terminated",
"There are no Client Access Licenses available for the target remote computer"
}
Self::BadClientMsg => {
"The remote computer received an invalid licensing message from the client"
}
Self::HwidDoesntMatchLicense => {
"The Client Access License stored by the client has been modified"
}
Self::BadClientLicense => {
"The Client Access License stored by the client is in an invalid format"
}
Self::CantFinishProtocol => {
"Network problems have caused the licensing protocol to be terminated"
}
Self::ClientEndedProtocol => "The client prematurely ended the licensing protocol", Self::ClientEndedProtocol => "The client prematurely ended the licensing protocol",
Self::BadClientEncryption => "A licensing message was incorrectly encrypted", Self::BadClientEncryption => "A licensing message was incorrectly encrypted",
Self::CantUpgradeLicense => { Self::CantUpgradeLicense => {
"The Client Access License stored by the client could not be upgraded or renewed" "The Client Access License stored by the client could not be upgraded or renewed"
} }
Self::NoRemoteConnections => { Self::NoRemoteConnections => "The remote computer is not licensed to accept remote connections",
"The remote computer is not licensed to accept remote connections"
}
} }
} }
} }
@ -410,11 +393,7 @@ pub enum ServerSetErrorInfoError {
UnexpectedInfoCode(u32), UnexpectedInfoCode(u32),
} }
impl_from_error!( impl_from_error!(io::Error, ServerSetErrorInfoError, ServerSetErrorInfoError::IoError);
io::Error,
ServerSetErrorInfoError,
ServerSetErrorInfoError::IoError
);
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
@ -439,9 +418,7 @@ mod tests {
let expected = SERVER_SET_ERROR_INFO_BUFFER.as_ref(); let expected = SERVER_SET_ERROR_INFO_BUFFER.as_ref();
let mut buffer = vec![0; expected.len()]; let mut buffer = vec![0; expected.len()];
SERVER_SET_ERROR_INFO SERVER_SET_ERROR_INFO.to_buffer(&mut buffer.as_mut_slice()).unwrap();
.to_buffer(&mut buffer.as_mut_slice())
.unwrap();
assert_eq!(expected, buffer.as_slice()); assert_eq!(expected, buffer.as_slice());
} }

View file

@ -18,16 +18,12 @@ use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
use ring::digest; use ring::digest;
pub use self::{ pub use self::client_new_license_request::{ClientNewLicenseRequest, PLATFORM_ID};
client_new_license_request::{ClientNewLicenseRequest, PLATFORM_ID}, pub use self::client_platform_challenge_response::ClientPlatformChallengeResponse;
client_platform_challenge_response::ClientPlatformChallengeResponse, pub use self::licensing_error_message::{LicenseErrorCode, LicensingErrorMessage, LicensingStateTransition};
licensing_error_message::{LicenseErrorCode, LicensingErrorMessage, LicensingStateTransition}, pub use self::server_license_request::{InitialMessageType, InitialServerLicenseMessage, ServerLicenseRequest};
server_license_request::{ pub use self::server_platform_challenge::ServerPlatformChallenge;
InitialMessageType, InitialServerLicenseMessage, ServerLicenseRequest, pub use self::server_upgrade_license::ServerUpgradeLicense;
},
server_platform_challenge::ServerPlatformChallenge,
server_upgrade_license::ServerUpgradeLicense,
};
use crate::rdp::{BasicSecurityHeader, BasicSecurityHeaderFlags, BASIC_SECURITY_HEADER_SIZE}; use crate::rdp::{BasicSecurityHeader, BasicSecurityHeaderFlags, BASIC_SECURITY_HEADER_SIZE};
use crate::{impl_from_error, PduParsing}; use crate::{impl_from_error, PduParsing};
@ -74,31 +70,23 @@ impl PduParsing for LicenseHeader {
)) ))
})?; })?;
if !security_header if !security_header.flags.contains(BasicSecurityHeaderFlags::LICENSE_PKT) {
.flags
.contains(BasicSecurityHeaderFlags::LICENSE_PKT)
{
return Err(ServerLicenseError::InvalidSecurityFlags); return Err(ServerLicenseError::InvalidSecurityFlags);
} }
let preamble_message_type = PreambleType::from_u8(stream.read_u8()?) let preamble_message_type =
.ok_or(ServerLicenseError::InvalidLicenseType)?; PreambleType::from_u8(stream.read_u8()?).ok_or(ServerLicenseError::InvalidLicenseType)?;
let flags_with_version = stream.read_u8()?; let flags_with_version = stream.read_u8()?;
let preamble_message_size = stream.read_u16::<LittleEndian>()?; let preamble_message_size = stream.read_u16::<LittleEndian>()?;
let preamble_flags = PreambleFlags::from_bits(flags_with_version & !PROTOCOL_VERSION_MASK) let preamble_flags = PreambleFlags::from_bits(flags_with_version & !PROTOCOL_VERSION_MASK)
.ok_or_else(|| { .ok_or_else(|| ServerLicenseError::InvalidPreamble(String::from("Got invalid flags field")))?;
ServerLicenseError::InvalidPreamble(String::from("Got invalid flags field"))
})?;
let preamble_version = let preamble_version = PreambleVersion::from_u8((flags_with_version & PROTOCOL_VERSION_MASK) as u8)
PreambleVersion::from_u8((flags_with_version & PROTOCOL_VERSION_MASK) as u8) .ok_or_else(|| {
.ok_or_else(|| { ServerLicenseError::InvalidPreamble(String::from("Got invalid version in the flags field"))
ServerLicenseError::InvalidPreamble(String::from( })?;
"Got invalid version in the flags field",
))
})?;
Ok(Self { Ok(Self {
security_header, security_header,
@ -117,8 +105,7 @@ impl PduParsing for LicenseHeader {
)) ))
})?; })?;
let flags_with_version = let flags_with_version = self.preamble_flags.bits() | self.preamble_version.to_u8().unwrap();
self.preamble_flags.bits() | self.preamble_version.to_u8().unwrap();
stream.write_u8(self.preamble_message_type.to_u8().unwrap())?; stream.write_u8(self.preamble_message_type.to_u8().unwrap())?;
stream.write_u8(flags_with_version)?; stream.write_u8(flags_with_version)?;
@ -197,9 +184,7 @@ pub enum ServerLicenseError {
RsaKeyEncryptionError, RsaKeyEncryptionError,
#[fail(display = "Invalid License Request key exchange algorithm value")] #[fail(display = "Invalid License Request key exchange algorithm value")]
InvalidKeyExchangeValue, InvalidKeyExchangeValue,
#[fail( #[fail(display = "MAC checksum generated over decrypted data does not match the server's checksum")]
display = "MAC checksum generated over decrypted data does not match the server's checksum"
)]
InvalidMacData, InvalidMacData,
#[fail(display = "Invalid platform challenge response data version")] #[fail(display = "Invalid platform challenge response data version")]
InvalidChallengeResponseDataVersion, InvalidChallengeResponseDataVersion,
@ -235,15 +220,9 @@ pub enum ServerLicenseError {
UnexpectedValidClientError(LicensingErrorMessage), UnexpectedValidClientError(LicensingErrorMessage),
#[fail(display = "Invalid Key Exchange List field")] #[fail(display = "Invalid Key Exchange List field")]
InvalidKeyExchangeAlgorithm, InvalidKeyExchangeAlgorithm,
#[fail( #[fail(display = "Received invalid company name length (Product Information): {}", _0)]
display = "Received invalid company name length (Product Information): {}",
_0
)]
InvalidCompanyNameLength(u32), InvalidCompanyNameLength(u32),
#[fail( #[fail(display = "Received invalid product ID length (Product Information): {}", _0)]
display = "Received invalid product ID length (Product Information): {}",
_0
)]
InvalidProductIdLength(u32), InvalidProductIdLength(u32),
#[fail(display = "Received invalid scope count field: {}", _0)] #[fail(display = "Received invalid scope count field: {}", _0)]
InvalidScopeCount(u32), InvalidScopeCount(u32),
@ -279,9 +258,7 @@ impl BlobHeader {
Ok(Self { blob_type, length }) Ok(Self { blob_type, length })
} }
pub fn read_any_blob_from_buffer( pub fn read_any_blob_from_buffer(mut stream: impl io::Read) -> Result<Self, ServerLicenseError> {
mut stream: impl io::Read,
) -> Result<Self, ServerLicenseError> {
let _blob_type = stream.read_u16::<LittleEndian>()?; let _blob_type = stream.read_u16::<LittleEndian>()?;
let length = stream.read_u16::<LittleEndian>()? as usize; let length = stream.read_u16::<LittleEndian>()? as usize;
@ -312,14 +289,9 @@ fn compute_mac_data(mac_salt_key: &[u8], data: &[u8]) -> Vec<u8> {
let sha_result = digest::digest( let sha_result = digest::digest(
&digest::SHA1_FOR_LEGACY_USE_ONLY, &digest::SHA1_FOR_LEGACY_USE_ONLY,
[ [mac_salt_key, pad_one.as_ref(), data_len_buffer.as_ref(), data]
mac_salt_key, .concat()
pad_one.as_ref(), .as_slice(),
data_len_buffer.as_ref(),
data,
]
.concat()
.as_slice(),
); );
let pad_two: [u8; 48] = [0x5c; 48]; let pad_two: [u8; 48] = [0x5c; 48];
@ -347,9 +319,7 @@ fn read_license_header(
if license_error.error_code == LicenseErrorCode::StatusValidClient if license_error.error_code == LicenseErrorCode::StatusValidClient
&& license_error.state_transition == LicensingStateTransition::NoTransition && license_error.state_transition == LicensingStateTransition::NoTransition
{ {
return Err(ServerLicenseError::UnexpectedValidClientError( return Err(ServerLicenseError::UnexpectedValidClientError(license_error));
license_error,
));
} else { } else {
return Err(ServerLicenseError::UnexpectedServerError(license_error)); return Err(ServerLicenseError::UnexpectedServerError(license_error));
} }

View file

@ -3,20 +3,19 @@ pub mod test;
use std::io; use std::io;
use crate::utils::rsa::encrypt_with_public_key;
use bitflags::bitflags; use bitflags::bitflags;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use md5::Digest; use md5::Digest;
use ring::digest; use ring::digest;
use super::{ use super::{
BasicSecurityHeader, BasicSecurityHeaderFlags, BlobHeader, BlobType, LicenseEncryptionData, BasicSecurityHeader, BasicSecurityHeaderFlags, BlobHeader, BlobType, LicenseEncryptionData, LicenseHeader,
LicenseHeader, PreambleFlags, PreambleType, PreambleVersion, ServerLicenseError, PreambleFlags, PreambleType, PreambleVersion, ServerLicenseError, ServerLicenseRequest, KEY_EXCHANGE_ALGORITHM_RSA,
ServerLicenseRequest, KEY_EXCHANGE_ALGORITHM_RSA, PREAMBLE_SIZE, RANDOM_NUMBER_SIZE, PREAMBLE_SIZE, RANDOM_NUMBER_SIZE, UTF8_NULL_TERMINATOR_SIZE,
UTF8_NULL_TERMINATOR_SIZE,
}; };
use crate::{utils, utils::CharacterSet, PduParsing}; use crate::utils::rsa::encrypt_with_public_key;
use crate::utils::CharacterSet;
use crate::{utils, PduParsing};
const LICENSE_REQUEST_STATIC_FIELDS_SIZE: usize = 20; const LICENSE_REQUEST_STATIC_FIELDS_SIZE: usize = 20;
@ -142,28 +141,15 @@ impl PduParsing for ClientNewLicenseRequest {
let mut client_random = vec![0u8; RANDOM_NUMBER_SIZE]; let mut client_random = vec![0u8; RANDOM_NUMBER_SIZE];
stream.read_exact(&mut client_random)?; stream.read_exact(&mut client_random)?;
let premaster_secret_blob_header = let premaster_secret_blob_header = BlobHeader::read_from_buffer(BlobType::Random, &mut stream)?;
BlobHeader::read_from_buffer(BlobType::Random, &mut stream)?;
let mut encrypted_premaster_secret = vec![0u8; premaster_secret_blob_header.length]; let mut encrypted_premaster_secret = vec![0u8; premaster_secret_blob_header.length];
stream.read_exact(&mut encrypted_premaster_secret)?; stream.read_exact(&mut encrypted_premaster_secret)?;
let username_blob_header = let username_blob_header = BlobHeader::read_from_buffer(BlobType::ClientUserName, &mut stream)?;
BlobHeader::read_from_buffer(BlobType::ClientUserName, &mut stream)?; let client_username = utils::read_string(&mut stream, username_blob_header.length, CharacterSet::Ansi, false)?;
let client_username = utils::read_string(
&mut stream,
username_blob_header.length,
CharacterSet::Ansi,
false,
)?;
let machine_name_blob = let machine_name_blob = BlobHeader::read_from_buffer(BlobType::ClientMachineNameBlob, &mut stream)?;
BlobHeader::read_from_buffer(BlobType::ClientMachineNameBlob, &mut stream)?; let client_machine_name = utils::read_string(&mut stream, machine_name_blob.length, CharacterSet::Ansi, false)?;
let client_machine_name = utils::read_string(
&mut stream,
machine_name_blob.length,
CharacterSet::Ansi,
false,
)?;
Ok(Self { Ok(Self {
license_header, license_header,
@ -181,8 +167,7 @@ impl PduParsing for ClientNewLicenseRequest {
stream.write_u32::<LittleEndian>(PLATFORM_ID)?; stream.write_u32::<LittleEndian>(PLATFORM_ID)?;
stream.write_all(&self.client_random)?; stream.write_all(&self.client_random)?;
BlobHeader::new(BlobType::Random, self.encrypted_premaster_secret.len()) BlobHeader::new(BlobType::Random, self.encrypted_premaster_secret.len()).write_to_buffer(&mut stream)?;
.write_to_buffer(&mut stream)?;
stream.write_all(&self.encrypted_premaster_secret)?; stream.write_all(&self.encrypted_premaster_secret)?;
BlobHeader::new( BlobHeader::new(
@ -190,22 +175,14 @@ impl PduParsing for ClientNewLicenseRequest {
self.client_username.len() + UTF8_NULL_TERMINATOR_SIZE, self.client_username.len() + UTF8_NULL_TERMINATOR_SIZE,
) )
.write_to_buffer(&mut stream)?; .write_to_buffer(&mut stream)?;
utils::write_string_with_null_terminator( utils::write_string_with_null_terminator(&mut stream, &self.client_username, CharacterSet::Ansi)?;
&mut stream,
&self.client_username,
CharacterSet::Ansi,
)?;
BlobHeader::new( BlobHeader::new(
BlobType::ClientMachineNameBlob, BlobType::ClientMachineNameBlob,
self.client_machine_name.len() + UTF8_NULL_TERMINATOR_SIZE, self.client_machine_name.len() + UTF8_NULL_TERMINATOR_SIZE,
) )
.write_to_buffer(&mut stream)?; .write_to_buffer(&mut stream)?;
utils::write_string_with_null_terminator( utils::write_string_with_null_terminator(&mut stream, &self.client_machine_name, CharacterSet::Ansi)?;
&mut stream,
&self.client_machine_name,
CharacterSet::Ansi,
)?;
Ok(()) Ok(())
} }
@ -235,11 +212,7 @@ fn salted_hash(salt: &[u8], salt_first: &[u8], salt_second: &[u8], input: &[u8])
} }
// According to https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/88061224-4a2f-4a28-a52e-e896b75ed2d3 // According to https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/88061224-4a2f-4a28-a52e-e896b75ed2d3
fn compute_master_secret( fn compute_master_secret(premaster_secret: &[u8], client_random: &[u8], server_random: &[u8]) -> Vec<u8> {
premaster_secret: &[u8],
client_random: &[u8],
server_random: &[u8],
) -> Vec<u8> {
[ [
salted_hash(premaster_secret, client_random, server_random, b"A"), salted_hash(premaster_secret, client_random, server_random, b"A"),
salted_hash(premaster_secret, client_random, server_random, b"BB"), salted_hash(premaster_secret, client_random, server_random, b"BB"),
@ -249,11 +222,7 @@ fn compute_master_secret(
} }
// According to https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/88061224-4a2f-4a28-a52e-e896b75ed2d3 // According to https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpele/88061224-4a2f-4a28-a52e-e896b75ed2d3
fn compute_session_key_blob( fn compute_session_key_blob(master_secret: &[u8], client_random: &[u8], server_random: &[u8]) -> Vec<u8> {
master_secret: &[u8],
client_random: &[u8],
server_random: &[u8],
) -> Vec<u8> {
[ [
salted_hash(master_secret, server_random, client_random, b"A"), salted_hash(master_secret, server_random, client_random, b"A"),
salted_hash(master_secret, server_random, client_random, b"BB"), salted_hash(master_secret, server_random, client_random, b"BB"),

View file

@ -1,14 +1,10 @@
use super::*;
use crate::rdp::server_license::{
server_license_request::{
cert::{CertificateType, X509CertificateChain},
ProductInfo, Scope, ServerCertificate,
},
PREAMBLE_SIZE,
};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use super::*;
use crate::rdp::server_license::server_license_request::cert::{CertificateType, X509CertificateChain};
use crate::rdp::server_license::server_license_request::{ProductInfo, Scope, ServerCertificate};
use crate::rdp::server_license::PREAMBLE_SIZE;
const LICENSE_HEADER_BUFFER_NO_SIZE: [u8; 6] = [ const LICENSE_HEADER_BUFFER_NO_SIZE: [u8; 6] = [
0x80, 0x00, // flags 0x80, 0x00, // flags
0x00, 0x00, // flagsHi 0x00, 0x00, // flagsHi
@ -16,27 +12,26 @@ const LICENSE_HEADER_BUFFER_NO_SIZE: [u8; 6] = [
]; ];
const CLIENT_RANDOM_BUFFER: [u8; 32] = [ const CLIENT_RANDOM_BUFFER: [u8; 32] = [
0x4b, 0x5b, 0x7b, 0x43, 0x63, 0x8a, 0x8, 0xfe, 0xd1, 0x7a, 0xba, 0xf5, 0x91, 0x85, 0x77, 0xfe, 0x4b, 0x5b, 0x7b, 0x43, 0x63, 0x8a, 0x8, 0xfe, 0xd1, 0x7a, 0xba, 0xf5, 0x91, 0x85, 0x77, 0xfe, 0x39, 0x36, 0xf6,
0x39, 0x36, 0xf6, 0xd7, 0x78, 0xec, 0x6a, 0xcc, 0x89, 0x4a, 0x90, 0x41, 0x2c, 0xac, 0x5a, 0x49, 0xd7, 0x78, 0xec, 0x6a, 0xcc, 0x89, 0x4a, 0x90, 0x41, 0x2c, 0xac, 0x5a, 0x49,
]; ];
const SERVER_RANDOM_BUFFER: [u8; 32] = [ const SERVER_RANDOM_BUFFER: [u8; 32] = [
0x5c, 0x81, 0xf0, 0x11, 0xeb, 0xcf, 0xd1, 0xe, 0xb4, 0x1f, 0xb3, 0xba, 0x93, 0xa2, 0xd7, 0x39, 0x5c, 0x81, 0xf0, 0x11, 0xeb, 0xcf, 0xd1, 0xe, 0xb4, 0x1f, 0xb3, 0xba, 0x93, 0xa2, 0xd7, 0x39, 0x9, 0xaa, 0x99,
0x9, 0xaa, 0x99, 0xe9, 0x10, 0xd4, 0xd7, 0x95, 0xdd, 0xad, 0x91, 0x69, 0x5, 0x26, 0x6b, 0x6a, 0xe9, 0x10, 0xd4, 0xd7, 0x95, 0xdd, 0xad, 0x91, 0x69, 0x5, 0x26, 0x6b, 0x6a,
]; ];
const ENCRYPTED_PREMASTER_SECRET: [u8; 72] = [ const ENCRYPTED_PREMASTER_SECRET: [u8; 72] = [
0xb0, 0x95, 0xf7, 0xcb, 0x81, 0x34, 0x45, 0x85, 0x65, 0x83, 0xb2, 0xcf, 0x5b, 0xdf, 0xfe, 0x40, 0xb0, 0x95, 0xf7, 0xcb, 0x81, 0x34, 0x45, 0x85, 0x65, 0x83, 0xb2, 0xcf, 0x5b, 0xdf, 0xfe, 0x40, 0x6f, 0xd8, 0x14,
0x6f, 0xd8, 0x14, 0x14, 0x18, 0xb, 0x2b, 0x6d, 0xaa, 0xd0, 0x38, 0xa, 0xaf, 0x74, 0xe9, 0x51, 0x14, 0x18, 0xb, 0x2b, 0x6d, 0xaa, 0xd0, 0x38, 0xa, 0xaf, 0x74, 0xe9, 0x51, 0x55, 0x2b, 0xdb, 0xfd, 0x3b, 0xd3,
0x55, 0x2b, 0xdb, 0xfd, 0x3b, 0xd3, 0xfb, 0x2f, 0x34, 0x92, 0xdd, 0xc8, 0xaf, 0x48, 0xf3, 0x91, 0xfb, 0x2f, 0x34, 0x92, 0xdd, 0xc8, 0xaf, 0x48, 0xf3, 0x91, 0x61, 0x8a, 0x5b, 0xbd, 0x81, 0x87, 0xec, 0xb8, 0xcc,
0x61, 0x8a, 0x5b, 0xbd, 0x81, 0x87, 0xec, 0xb8, 0xcc, 0xb, 0xb, 0xc9, 0xd, 0x1c, 0xe7, 0x17, 0, 0xb, 0xb, 0xc9, 0xd, 0x1c, 0xe7, 0x17, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
]; ];
const PREMASTER_SECRET_BUFFER: [u8; 48] = [ const PREMASTER_SECRET_BUFFER: [u8; 48] = [
0x14, 0x28, 0xda, 0xfb, 0xb9, 0xea, 0x38, 0xab, 0x5e, 0xa2, 0xf9, 0x4, 0xf7, 0x89, 0x9c, 0x98, 0x14, 0x28, 0xda, 0xfb, 0xb9, 0xea, 0x38, 0xab, 0x5e, 0xa2, 0xf9, 0x4, 0xf7, 0x89, 0x9c, 0x98, 0x3d, 0x50, 0x45,
0x3d, 0x50, 0x45, 0x77, 0xbf, 0x17, 0x81, 0x1c, 0x37, 0x87, 0xc2, 0x48, 0x13, 0xe8, 0xc9, 0x20, 0x77, 0xbf, 0x17, 0x81, 0x1c, 0x37, 0x87, 0xc2, 0x48, 0x13, 0xe8, 0xc9, 0x20, 0x4d, 0xdf, 0xf3, 0x27, 0xbd, 0xb6,
0x4d, 0xdf, 0xf3, 0x27, 0xbd, 0xb6, 0x98, 0x7e, 0x64, 0xda, 0xfe, 0x1d, 0x31, 0x2f, 0x62, 0xca, 0x98, 0x7e, 0x64, 0xda, 0xfe, 0x1d, 0x31, 0x2f, 0x62, 0xca,
]; ];
const SALTED_HASH_BUFFER: [u8; 16] = [ const SALTED_HASH_BUFFER: [u8; 16] = [
@ -44,15 +39,15 @@ const SALTED_HASH_BUFFER: [u8; 16] = [
]; ];
const MASTER_SECRET_BUFFER: [u8; 48] = [ const MASTER_SECRET_BUFFER: [u8; 48] = [
0xfe, 0xdc, 0x51, 0x9a, 0xdb, 0x3a, 0xc9, 0x61, 0x4, 0x7, 0x24, 0x94, 0x5d, 0xc, 0x43, 0xa7, 0xfe, 0xdc, 0x51, 0x9a, 0xdb, 0x3a, 0xc9, 0x61, 0x4, 0x7, 0x24, 0x94, 0x5d, 0xc, 0x43, 0xa7, 0x70, 0xe3, 0xf3, 0x0,
0x70, 0xe3, 0xf3, 0x0, 0x50, 0xd7, 0xa8, 0x72, 0x3e, 0xab, 0x7e, 0x1b, 0xe4, 0x64, 0xe5, 0xc5, 0x50, 0xd7, 0xa8, 0x72, 0x3e, 0xab, 0x7e, 0x1b, 0xe4, 0x64, 0xe5, 0xc5, 0x74, 0xae, 0xed, 0x10, 0x72, 0x96, 0x2a,
0x74, 0xae, 0xed, 0x10, 0x72, 0x96, 0x2a, 0x4c, 0x65, 0x9, 0x4f, 0x60, 0x12, 0xa9, 0x12, 0xa1, 0x4c, 0x65, 0x9, 0x4f, 0x60, 0x12, 0xa9, 0x12, 0xa1,
]; ];
const SESSION_KEY_BLOB: [u8; 48] = [ const SESSION_KEY_BLOB: [u8; 48] = [
0xf7, 0x3, 0x75, 0xb9, 0x5f, 0xda, 0xd0, 0xbe, 0xb4, 0x2a, 0xf5, 0xc1, 0x3d, 0x98, 0x85, 0x7a, 0xf7, 0x3, 0x75, 0xb9, 0x5f, 0xda, 0xd0, 0xbe, 0xb4, 0x2a, 0xf5, 0xc1, 0x3d, 0x98, 0x85, 0x7a, 0xd6, 0xc5, 0x39,
0xd6, 0xc5, 0x39, 0x4c, 0xe3, 0xcb, 0x76, 0x61, 0xaa, 0x4a, 0xb6, 0x15, 0x7e, 0x89, 0x21, 0x3d, 0x4c, 0xe3, 0xcb, 0x76, 0x61, 0xaa, 0x4a, 0xb6, 0x15, 0x7e, 0x89, 0x21, 0x3d, 0xdf, 0x5b, 0x25, 0x32, 0xee, 0x5,
0xdf, 0x5b, 0x25, 0x32, 0xee, 0x5, 0x6, 0xd, 0x5b, 0xaa, 0x63, 0x14, 0xaf, 0xa5, 0x46, 0xf, 0x6, 0xd, 0x5b, 0xaa, 0x63, 0x14, 0xaf, 0xa5, 0x46, 0xf,
]; ];
const LICENSE_KEY_BUFFER: [u8; 16] = [ const LICENSE_KEY_BUFFER: [u8; 16] = [
@ -276,32 +271,26 @@ fn from_buffer_correctly_parses_client_new_license_request() {
#[test] #[test]
fn to_buffer_correctly_serializes_client_new_license_request() { fn to_buffer_correctly_serializes_client_new_license_request() {
let mut serialized_request = Vec::new(); let mut serialized_request = Vec::new();
CLIENT_NEW_LICENSE_REQUEST CLIENT_NEW_LICENSE_REQUEST.to_buffer(&mut serialized_request).unwrap();
.to_buffer(&mut serialized_request)
.unwrap();
assert_eq!(REQUEST_BUFFER.as_slice(), serialized_request.as_slice()); assert_eq!(REQUEST_BUFFER.as_slice(), serialized_request.as_slice());
} }
#[test] #[test]
fn buffer_length_is_correct_for_client_new_license_request() { fn buffer_length_is_correct_for_client_new_license_request() {
assert_eq!( assert_eq!(REQUEST_BUFFER.len(), CLIENT_NEW_LICENSE_REQUEST.buffer_length());
REQUEST_BUFFER.len(),
CLIENT_NEW_LICENSE_REQUEST.buffer_length()
);
} }
#[test] #[test]
fn client_new_license_request_creates_correctly() { fn client_new_license_request_creates_correctly() {
let (client_new_license_request, encryption_data) = let (client_new_license_request, encryption_data) = ClientNewLicenseRequest::from_server_license_request(
ClientNewLicenseRequest::from_server_license_request( &SERVER_LICENSE_REQUEST,
&SERVER_LICENSE_REQUEST, CLIENT_RANDOM_BUFFER.as_ref(),
CLIENT_RANDOM_BUFFER.as_ref(), PREMASTER_SECRET_BUFFER.as_ref(),
PREMASTER_SECRET_BUFFER.as_ref(), CLIENT_USERNAME,
CLIENT_USERNAME, CLIENT_MACHINE_NAME,
CLIENT_MACHINE_NAME, )
) .unwrap();
.unwrap();
assert_eq!(encryption_data.license_key, LICENSE_KEY_BUFFER.as_ref()); assert_eq!(encryption_data.license_key, LICENSE_KEY_BUFFER.as_ref());
assert_eq!(client_new_license_request, *CLIENT_NEW_LICENSE_REQUEST); assert_eq!(client_new_license_request, *CLIENT_NEW_LICENSE_REQUEST);

View file

@ -1,7 +1,8 @@
#[cfg(test)] #[cfg(test)]
mod test; mod test;
use std::{io, io::Write}; use std::io;
use std::io::Write;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use md5::Digest; use md5::Digest;
@ -9,12 +10,12 @@ use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
use super::{ use super::{
BasicSecurityHeader, BasicSecurityHeaderFlags, BlobHeader, BlobType, LicenseEncryptionData, BasicSecurityHeader, BasicSecurityHeaderFlags, BlobHeader, BlobType, LicenseEncryptionData, LicenseHeader,
LicenseHeader, PreambleFlags, PreambleType, PreambleVersion, ServerLicenseError, PreambleFlags, PreambleType, PreambleVersion, ServerLicenseError, ServerPlatformChallenge, BLOB_LENGTH_SIZE,
ServerPlatformChallenge, BLOB_LENGTH_SIZE, BLOB_TYPE_SIZE, MAC_SIZE, PLATFORM_ID, BLOB_TYPE_SIZE, MAC_SIZE, PLATFORM_ID, PREAMBLE_SIZE,
PREAMBLE_SIZE,
}; };
use crate::{utils::rc4::Rc4, PduParsing}; use crate::utils::rc4::Rc4;
use crate::PduParsing;
const RESPONSE_DATA_VERSION: u16 = 0x100; const RESPONSE_DATA_VERSION: u16 = 0x100;
const RESPONSE_DATA_STATIC_FIELDS_SIZE: usize = 8; const RESPONSE_DATA_STATIC_FIELDS_SIZE: usize = 8;
@ -36,13 +37,10 @@ impl ClientPlatformChallengeResponse {
encryption_data: &LicenseEncryptionData, encryption_data: &LicenseEncryptionData,
) -> Result<Self, ServerLicenseError> { ) -> Result<Self, ServerLicenseError> {
let mut rc4 = Rc4::new(&encryption_data.license_key); let mut rc4 = Rc4::new(&encryption_data.license_key);
let decrypted_challenge = let decrypted_challenge = rc4.process(platform_challenge.encrypted_platform_challenge.as_slice());
rc4.process(platform_challenge.encrypted_platform_challenge.as_slice());
let decrypted_challenge_mac = super::compute_mac_data( let decrypted_challenge_mac =
encryption_data.mac_salt_key.as_slice(), super::compute_mac_data(encryption_data.mac_salt_key.as_slice(), decrypted_challenge.as_slice());
decrypted_challenge.as_slice(),
);
if decrypted_challenge_mac != platform_challenge.mac_data { if decrypted_challenge_mac != platform_challenge.mac_data {
return Err(ServerLicenseError::InvalidMacData); return Err(ServerLicenseError::InvalidMacData);
@ -51,8 +49,7 @@ impl ClientPlatformChallengeResponse {
let mut challenge_response_data = vec![0u8; RESPONSE_DATA_STATIC_FIELDS_SIZE]; let mut challenge_response_data = vec![0u8; RESPONSE_DATA_STATIC_FIELDS_SIZE];
challenge_response_data.write_u16::<LittleEndian>(RESPONSE_DATA_VERSION)?; challenge_response_data.write_u16::<LittleEndian>(RESPONSE_DATA_VERSION)?;
challenge_response_data.write_u16::<LittleEndian>(ClientType::Other.to_u16().unwrap())?; challenge_response_data.write_u16::<LittleEndian>(ClientType::Other.to_u16().unwrap())?;
challenge_response_data challenge_response_data.write_u16::<LittleEndian>(LicenseDetailLevel::Detail.to_u16().unwrap())?;
.write_u16::<LittleEndian>(LicenseDetailLevel::Detail.to_u16().unwrap())?;
challenge_response_data.write_u16::<LittleEndian>(decrypted_challenge.len() as u16)?; challenge_response_data.write_u16::<LittleEndian>(decrypted_challenge.len() as u16)?;
challenge_response_data.write_all(&decrypted_challenge)?; challenge_response_data.write_all(&decrypted_challenge)?;
@ -111,14 +108,12 @@ impl PduParsing for ClientPlatformChallengeResponse {
))); )));
} }
let encrypted_challenge_blob = let encrypted_challenge_blob = BlobHeader::read_from_buffer(BlobType::EncryptedData, &mut stream)?;
BlobHeader::read_from_buffer(BlobType::EncryptedData, &mut stream)?;
let mut encrypted_challenge_response_data = vec![0u8; encrypted_challenge_blob.length]; let mut encrypted_challenge_response_data = vec![0u8; encrypted_challenge_blob.length];
stream.read_exact(&mut encrypted_challenge_response_data)?; stream.read_exact(&mut encrypted_challenge_response_data)?;
let encrypted_hwid_blob = let encrypted_hwid_blob = BlobHeader::read_from_buffer(BlobType::EncryptedData, &mut stream)?;
BlobHeader::read_from_buffer(BlobType::EncryptedData, &mut stream)?;
let mut encrypted_hwid = vec![0u8; encrypted_hwid_blob.length]; let mut encrypted_hwid = vec![0u8; encrypted_hwid_blob.length];
stream.read_exact(&mut encrypted_hwid)?; stream.read_exact(&mut encrypted_hwid)?;
@ -136,15 +131,11 @@ impl PduParsing for ClientPlatformChallengeResponse {
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
self.license_header.to_buffer(&mut stream)?; self.license_header.to_buffer(&mut stream)?;
BlobHeader::new( BlobHeader::new(BlobType::EncryptedData, self.encrypted_challenge_response_data.len())
BlobType::EncryptedData, .write_to_buffer(&mut stream)?;
self.encrypted_challenge_response_data.len(),
)
.write_to_buffer(&mut stream)?;
stream.write_all(&self.encrypted_challenge_response_data)?; stream.write_all(&self.encrypted_challenge_response_data)?;
BlobHeader::new(BlobType::EncryptedData, self.encrypted_hwid.len()) BlobHeader::new(BlobType::EncryptedData, self.encrypted_hwid.len()).write_to_buffer(&mut stream)?;
.write_to_buffer(&mut stream)?;
stream.write_all(&self.encrypted_hwid)?; stream.write_all(&self.encrypted_hwid)?;
stream.write_all(&self.mac_data)?; stream.write_all(&self.mac_data)?;

View file

@ -1,11 +1,11 @@
use lazy_static::lazy_static;
use super::*; use super::*;
use crate::rdp::server_license::{ use crate::rdp::server_license::{
BasicSecurityHeader, BasicSecurityHeaderFlags, LicenseHeader, PreambleFlags, PreambleType, BasicSecurityHeader, BasicSecurityHeaderFlags, LicenseHeader, PreambleFlags, PreambleType, PreambleVersion,
PreambleVersion, BASIC_SECURITY_HEADER_SIZE, PREAMBLE_SIZE, BASIC_SECURITY_HEADER_SIZE, PREAMBLE_SIZE,
}; };
use lazy_static::lazy_static;
const PLATFORM_CHALLENGE_RESPONSE_DATA_BUFFER: [u8; 18] = [ const PLATFORM_CHALLENGE_RESPONSE_DATA_BUFFER: [u8; 18] = [
0x00, 0x01, // version 0x00, 0x01, // version
0x00, 0x01, // client type 0x00, 0x01, // client type
@ -28,14 +28,13 @@ const CLIENT_PLATFORM_CHALLENGE_RESPONSE_BUFFER: [u8; 70] = [
0x15, 0x03, 0x42, 0x00, // preamble 0x15, 0x03, 0x42, 0x00, // preamble
0x09, 0x00, // blob type, ignored 0x09, 0x00, // blob type, ignored
0x12, 0x00, // blob len 0x12, 0x00, // blob len
0xfa, 0xb4, 0xe8, 0x24, 0xcf, 0x56, 0xb2, 0x4e, 0x80, 0x02, 0xbd, 0xb6, 0x61, 0xfc, 0xdf, 0xe9, 0xfa, 0xb4, 0xe8, 0x24, 0xcf, 0x56, 0xb2, 0x4e, 0x80, 0x02, 0xbd, 0xb6, 0x61, 0xfc, 0xdf, 0xe9, 0x6c,
0x6c, 0x44, // encrypted platform challenge response 0x44, // encrypted platform challenge response
0x09, 0x00, // blob type, ignored 0x09, 0x00, // blob type, ignored
0x14, 0x00, // blob len 0x14, 0x00, // blob len
0xf8, 0xb5, 0xe8, 0x25, 0x3d, 0x0f, 0x3f, 0x70, 0x1d, 0xda, 0x60, 0x19, 0x16, 0xfe, 0x73, 0x1a, 0xf8, 0xb5, 0xe8, 0x25, 0x3d, 0x0f, 0x3f, 0x70, 0x1d, 0xda, 0x60, 0x19, 0x16, 0xfe, 0x73, 0x1a, 0x45, 0x7e, 0x02,
0x45, 0x7e, 0x02, 0x71, // encrypted hwid 0x71, // encrypted hwid
0x38, 0x23, 0x62, 0x5d, 0x10, 0x8b, 0x93, 0xc3, 0xf1, 0xe4, 0x67, 0x1f, 0x4a, 0xb6, 0x00, 0x38, 0x23, 0x62, 0x5d, 0x10, 0x8b, 0x93, 0xc3, 0xf1, 0xe4, 0x67, 0x1f, 0x4a, 0xb6, 0x00, 0x0a, // mac data
0x0a, // mac data
]; ];
const CHALLENGE_BUFFER: [u8; 10] = [ const CHALLENGE_BUFFER: [u8; 10] = [
@ -53,11 +52,10 @@ lazy_static! {
license_detail_level: LicenseDetailLevel::Detail, license_detail_level: LicenseDetailLevel::Detail,
challenge: Vec::from(CHALLENGE_BUFFER.as_ref()), challenge: Vec::from(CHALLENGE_BUFFER.as_ref()),
}; };
pub static ref CLIENT_HARDWARE_IDENTIFICATION: ClientHardwareIdentification = pub static ref CLIENT_HARDWARE_IDENTIFICATION: ClientHardwareIdentification = ClientHardwareIdentification {
ClientHardwareIdentification { platform_id: HARDWARE_ID,
platform_id: HARDWARE_ID, data: Vec::from(DATA_BUFFER.as_ref()),
data: Vec::from(DATA_BUFFER.as_ref()), };
};
pub static ref CLIENT_PLATFORM_CHALLENGE_RESPONSE: ClientPlatformChallengeResponse = pub static ref CLIENT_PLATFORM_CHALLENGE_RESPONSE: ClientPlatformChallengeResponse =
ClientPlatformChallengeResponse { ClientPlatformChallengeResponse {
license_header: LicenseHeader { license_header: LicenseHeader {
@ -67,16 +65,13 @@ lazy_static! {
preamble_message_type: PreambleType::PlatformChallengeResponse, preamble_message_type: PreambleType::PlatformChallengeResponse,
preamble_flags: PreambleFlags::empty(), preamble_flags: PreambleFlags::empty(),
preamble_version: PreambleVersion::V3, preamble_version: PreambleVersion::V3,
preamble_message_size: (CLIENT_PLATFORM_CHALLENGE_RESPONSE_BUFFER.len() preamble_message_size: (CLIENT_PLATFORM_CHALLENGE_RESPONSE_BUFFER.len() - BASIC_SECURITY_HEADER_SIZE)
- BASIC_SECURITY_HEADER_SIZE) as u16, as u16,
}, },
encrypted_challenge_response_data: Vec::from( encrypted_challenge_response_data: Vec::from(&CLIENT_PLATFORM_CHALLENGE_RESPONSE_BUFFER[12..30]),
&CLIENT_PLATFORM_CHALLENGE_RESPONSE_BUFFER[12..30]
),
encrypted_hwid: Vec::from(&CLIENT_PLATFORM_CHALLENGE_RESPONSE_BUFFER[34..54]), encrypted_hwid: Vec::from(&CLIENT_PLATFORM_CHALLENGE_RESPONSE_BUFFER[34..54]),
mac_data: Vec::from( mac_data: Vec::from(
&CLIENT_PLATFORM_CHALLENGE_RESPONSE_BUFFER &CLIENT_PLATFORM_CHALLENGE_RESPONSE_BUFFER[CLIENT_PLATFORM_CHALLENGE_RESPONSE_BUFFER.len() - 16..]
[CLIENT_PLATFORM_CHALLENGE_RESPONSE_BUFFER.len() - 16..]
), ),
}; };
} }
@ -85,10 +80,7 @@ lazy_static! {
fn from_buffer_correctly_parses_platform_challenge_response_data() { fn from_buffer_correctly_parses_platform_challenge_response_data() {
assert_eq!( assert_eq!(
*RESPONSE, *RESPONSE,
PlatformChallengeResponseData::from_buffer( PlatformChallengeResponseData::from_buffer(PLATFORM_CHALLENGE_RESPONSE_DATA_BUFFER.as_ref()).unwrap()
PLATFORM_CHALLENGE_RESPONSE_DATA_BUFFER.as_ref()
)
.unwrap()
); );
} }
@ -105,18 +97,14 @@ fn to_buffer_correctly_serializes_platform_challenge_response_data() {
#[test] #[test]
fn buffer_length_is_correct_for_platform_challenge_response_data() { fn buffer_length_is_correct_for_platform_challenge_response_data() {
assert_eq!( assert_eq!(PLATFORM_CHALLENGE_RESPONSE_DATA_BUFFER.len(), RESPONSE.buffer_length());
PLATFORM_CHALLENGE_RESPONSE_DATA_BUFFER.len(),
RESPONSE.buffer_length()
);
} }
#[test] #[test]
fn from_buffer_correctly_parses_client_hardware_identification() { fn from_buffer_correctly_parses_client_hardware_identification() {
assert_eq!( assert_eq!(
*CLIENT_HARDWARE_IDENTIFICATION, *CLIENT_HARDWARE_IDENTIFICATION,
ClientHardwareIdentification::from_buffer(CLIENT_HARDWARE_IDENTIFICATION_BUFFER.as_ref()) ClientHardwareIdentification::from_buffer(CLIENT_HARDWARE_IDENTIFICATION_BUFFER.as_ref()).unwrap()
.unwrap()
); );
} }
@ -145,10 +133,7 @@ fn buffer_length_is_correct_for_client_hardware_identification() {
fn from_buffer_correctly_parses_client_platform_challenge_response() { fn from_buffer_correctly_parses_client_platform_challenge_response() {
assert_eq!( assert_eq!(
*CLIENT_PLATFORM_CHALLENGE_RESPONSE, *CLIENT_PLATFORM_CHALLENGE_RESPONSE,
ClientPlatformChallengeResponse::from_buffer( ClientPlatformChallengeResponse::from_buffer(CLIENT_PLATFORM_CHALLENGE_RESPONSE_BUFFER.as_ref()).unwrap()
CLIENT_PLATFORM_CHALLENGE_RESPONSE_BUFFER.as_ref()
)
.unwrap()
); );
} }
@ -175,12 +160,10 @@ fn buffer_length_is_correct_for_client_platform_challege_response() {
#[test] #[test]
fn challenge_response_creates_from_server_challenge_and_encryption_data_correctly() { fn challenge_response_creates_from_server_challenge_and_encryption_data_correctly() {
let encrypted_platform_challenge = let encrypted_platform_challenge = vec![0x26, 0x38, 0x88, 0x77, 0xcb, 0xe8, 0xbf, 0xce, 0x2c, 0x51];
vec![0x26, 0x38, 0x88, 0x77, 0xcb, 0xe8, 0xbf, 0xce, 0x2c, 0x51];
let mac_data = vec![ let mac_data = vec![
0x51, 0x4a, 0x27, 0x2c, 0x74, 0x18, 0xec, 0x88, 0x95, 0xdd, 0xac, 0x10, 0x3e, 0x3f, 0xa, 0x51, 0x4a, 0x27, 0x2c, 0x74, 0x18, 0xec, 0x88, 0x95, 0xdd, 0xac, 0x10, 0x3e, 0x3f, 0xa, 0x72,
0x72,
]; ];
let server_challenge = ServerPlatformChallenge { let server_challenge = ServerPlatformChallenge {
@ -191,9 +174,7 @@ fn challenge_response_creates_from_server_challenge_and_encryption_data_correctl
preamble_message_type: PreambleType::PlatformChallenge, preamble_message_type: PreambleType::PlatformChallenge,
preamble_flags: PreambleFlags::empty(), preamble_flags: PreambleFlags::empty(),
preamble_version: PreambleVersion::V3, preamble_version: PreambleVersion::V3,
preamble_message_size: (encrypted_platform_challenge.len() preamble_message_size: (encrypted_platform_challenge.len() + mac_data.len() + PREAMBLE_SIZE) as u16,
+ mac_data.len()
+ PREAMBLE_SIZE) as u16,
}, },
encrypted_platform_challenge, encrypted_platform_challenge,
mac_data, mac_data,
@ -202,12 +183,10 @@ fn challenge_response_creates_from_server_challenge_and_encryption_data_correctl
let encryption_data = LicenseEncryptionData { let encryption_data = LicenseEncryptionData {
premaster_secret: Vec::new(), // premaster secret is not involved in this unit test premaster_secret: Vec::new(), // premaster secret is not involved in this unit test
mac_salt_key: vec![ mac_salt_key: vec![
0x1, 0x5b, 0x9e, 0x5f, 0x6, 0x97, 0x71, 0x58, 0xc3, 0xb8, 0x8b, 0x8c, 0x6e, 0x77, 0x21, 0x1, 0x5b, 0x9e, 0x5f, 0x6, 0x97, 0x71, 0x58, 0xc3, 0xb8, 0x8b, 0x8c, 0x6e, 0x77, 0x21, 0x37,
0x37,
], ],
license_key: vec![ license_key: vec![
0xe1, 0x78, 0xe4, 0xa0, 0x2a, 0xc5, 0xca, 0xb8, 0xa2, 0xd1, 0x53, 0xb8, 0x7, 0x23, 0xe1, 0x78, 0xe4, 0xa0, 0x2a, 0xc5, 0xca, 0xb8, 0xa2, 0xd1, 0x53, 0xb8, 0x7, 0x23, 0xf3, 0xd2,
0xf3, 0xd2,
], ],
}; };
@ -223,8 +202,8 @@ fn challenge_response_creates_from_server_challenge_and_encryption_data_correctl
let encrypted_hwid = rc4.process(&hardware_id); let encrypted_hwid = rc4.process(&hardware_id);
let response_data: [u8; 26] = [ let response_data: [u8; 26] = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xff, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xff, 0x03, 0x00, 0x0a, 0x00, 0x54, 0x00,
0x00, 0x54, 0x00, 0x45, 0x00, 0x53, 0x00, 0x54, 0x00, 0x00, 0x00, 0x45, 0x00, 0x53, 0x00, 0x54, 0x00, 0x00, 0x00,
]; ];
let mut rc4 = Rc4::new(&encryption_data.license_key); let mut rc4 = Rc4::new(&encryption_data.license_key);
@ -232,9 +211,7 @@ fn challenge_response_creates_from_server_challenge_and_encryption_data_correctl
let mac_data = crate::rdp::server_license::compute_mac_data( let mac_data = crate::rdp::server_license::compute_mac_data(
encryption_data.mac_salt_key.as_slice(), encryption_data.mac_salt_key.as_slice(),
[response_data.as_ref(), hardware_id.as_slice()] [response_data.as_ref(), hardware_id.as_slice()].concat().as_slice(),
.concat()
.as_slice(),
); );
let correct_challenge_response = ClientPlatformChallengeResponse { let correct_challenge_response = ClientPlatformChallengeResponse {

View file

@ -8,7 +8,6 @@ use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
use super::{BlobHeader, BlobType, ServerLicenseError, BLOB_LENGTH_SIZE, BLOB_TYPE_SIZE}; use super::{BlobHeader, BlobType, ServerLicenseError, BLOB_LENGTH_SIZE, BLOB_TYPE_SIZE};
use crate::PduParsing; use crate::PduParsing;
const ERROR_CODE_SIZE: usize = 4; const ERROR_CODE_SIZE: usize = 4;
@ -27,9 +26,8 @@ impl PduParsing for LicensingErrorMessage {
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> { fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
let error_code = LicenseErrorCode::from_u32(stream.read_u32::<LittleEndian>()?) let error_code = LicenseErrorCode::from_u32(stream.read_u32::<LittleEndian>()?)
.ok_or(ServerLicenseError::InvalidErrorCode)?; .ok_or(ServerLicenseError::InvalidErrorCode)?;
let state_transition = let state_transition = LicensingStateTransition::from_u32(stream.read_u32::<LittleEndian>()?)
LicensingStateTransition::from_u32(stream.read_u32::<LittleEndian>()?) .ok_or(ServerLicenseError::InvalidStateTransition)?;
.ok_or(ServerLicenseError::InvalidStateTransition)?;
let error_info_blob = BlobHeader::read_from_buffer(BlobType::Error, &mut stream)?; let error_info_blob = BlobHeader::read_from_buffer(BlobType::Error, &mut stream)?;
let error_info = vec![0u8; error_info_blob.length]; let error_info = vec![0u8; error_info_blob.length];
@ -52,11 +50,7 @@ impl PduParsing for LicensingErrorMessage {
} }
fn buffer_length(&self) -> usize { fn buffer_length(&self) -> usize {
ERROR_CODE_SIZE ERROR_CODE_SIZE + STATE_TRANSITION_SIZE + self.error_info.len() + BLOB_LENGTH_SIZE + BLOB_TYPE_SIZE
+ STATE_TRANSITION_SIZE
+ self.error_info.len()
+ BLOB_LENGTH_SIZE
+ BLOB_TYPE_SIZE
} }
} }

View file

@ -32,8 +32,5 @@ fn to_buffer_correctly_serializes_licensing_error_message() {
#[test] #[test]
fn buffer_length_is_correct_for_licensing_error_message() { fn buffer_length_is_correct_for_licensing_error_message() {
assert_eq!( assert_eq!(LICENSE_MESSAGE_BUFFER.len(), LICENSING_ERROR_MESSAGE.buffer_length());
LICENSE_MESSAGE_BUFFER.len(),
LICENSING_ERROR_MESSAGE.buffer_length()
);
} }

View file

@ -5,16 +5,14 @@ pub mod test;
use std::io; use std::io;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use cert::{CertificateType, ProprietaryCertificate, X509CertificateChain};
use x509_parser::parse_x509_certificate; use x509_parser::parse_x509_certificate;
use cert::{CertificateType, ProprietaryCertificate, X509CertificateChain};
use super::{ use super::{
BasicSecurityHeader, BasicSecurityHeaderFlags, BlobHeader, BlobType, LicenseErrorCode, BasicSecurityHeader, BasicSecurityHeaderFlags, BlobHeader, BlobType, LicenseErrorCode, LicenseHeader,
LicenseHeader, LicensingErrorMessage, LicensingStateTransition, PreambleFlags, PreambleType, LicensingErrorMessage, LicensingStateTransition, PreambleFlags, PreambleType, PreambleVersion, ServerLicenseError,
PreambleVersion, ServerLicenseError, BLOB_LENGTH_SIZE, BLOB_TYPE_SIZE, BLOB_LENGTH_SIZE, BLOB_TYPE_SIZE, KEY_EXCHANGE_ALGORITHM_RSA, PREAMBLE_SIZE, RANDOM_NUMBER_SIZE,
KEY_EXCHANGE_ALGORITHM_RSA, PREAMBLE_SIZE, RANDOM_NUMBER_SIZE, UTF16_NULL_TERMINATOR_SIZE, UTF16_NULL_TERMINATOR_SIZE, UTF8_NULL_TERMINATOR_SIZE,
UTF8_NULL_TERMINATOR_SIZE,
}; };
use crate::{utils, PduParsing}; use crate::{utils, PduParsing};
@ -58,8 +56,7 @@ impl InitialServerLicenseMessage {
preamble_message_type: PreambleType::ErrorAlert, preamble_message_type: PreambleType::ErrorAlert,
preamble_flags: PreambleFlags::empty(), preamble_flags: PreambleFlags::empty(),
preamble_version: PreambleVersion::V3, preamble_version: PreambleVersion::V3,
preamble_message_size: (PREAMBLE_SIZE + valid_client_message.buffer_length()) preamble_message_size: (PREAMBLE_SIZE + valid_client_message.buffer_length()) as u16,
as u16,
}, },
message_type: InitialMessageType::StatusValidClient(valid_client_message), message_type: InitialMessageType::StatusValidClient(valid_client_message),
} }
@ -127,9 +124,7 @@ impl PduParsing for InitialServerLicenseMessage {
fn buffer_length(&self) -> usize { fn buffer_length(&self) -> usize {
self.license_header.buffer_length() self.license_header.buffer_length()
+ match &self.message_type { + match &self.message_type {
InitialMessageType::LicenseRequest(license_request) => { InitialMessageType::LicenseRequest(license_request) => license_request.buffer_length(),
license_request.buffer_length()
}
InitialMessageType::StatusValidClient(valid_client) => valid_client.buffer_length(), InitialMessageType::StatusValidClient(valid_client) => valid_client.buffer_length(),
} }
} }
@ -145,10 +140,7 @@ pub struct ServerLicenseRequest {
impl ServerLicenseRequest { impl ServerLicenseRequest {
pub fn get_public_key(&self) -> Result<Option<Vec<u8>>, ServerLicenseError> { pub fn get_public_key(&self) -> Result<Option<Vec<u8>>, ServerLicenseError> {
self.server_certificate self.server_certificate.as_ref().map(|c| c.get_public_key()).transpose()
.as_ref()
.map(|c| c.get_public_key())
.transpose()
} }
} }
@ -161,8 +153,7 @@ impl PduParsing for ServerLicenseRequest {
let product_info = ProductInfo::from_buffer(&mut stream)?; let product_info = ProductInfo::from_buffer(&mut stream)?;
let _key_exchange_algorithm_blob = let _key_exchange_algorithm_blob = BlobHeader::read_from_buffer(BlobType::KeyExchangeAlgorithm, &mut stream)?;
BlobHeader::read_from_buffer(BlobType::KeyExchangeAlgorithm, &mut stream)?;
let key_exchange_algorithm = stream.read_u32::<LittleEndian>()?; let key_exchange_algorithm = stream.read_u32::<LittleEndian>()?;
if key_exchange_algorithm != RSA_EXCHANGE_ALGORITHM { if key_exchange_algorithm != RSA_EXCHANGE_ALGORITHM {
@ -201,15 +192,10 @@ impl PduParsing for ServerLicenseRequest {
stream.write_all(&self.server_random)?; stream.write_all(&self.server_random)?;
self.product_info.to_buffer(&mut stream)?; self.product_info.to_buffer(&mut stream)?;
BlobHeader::new(BlobType::KeyExchangeAlgorithm, KEY_EXCHANGE_FIELD_SIZE) BlobHeader::new(BlobType::KeyExchangeAlgorithm, KEY_EXCHANGE_FIELD_SIZE).write_to_buffer(&mut stream)?;
.write_to_buffer(&mut stream)?;
stream.write_u32::<LittleEndian>(KEY_EXCHANGE_ALGORITHM_RSA)?; stream.write_u32::<LittleEndian>(KEY_EXCHANGE_ALGORITHM_RSA)?;
let cert_size = self let cert_size = self.server_certificate.as_ref().map(|v| v.buffer_length()).unwrap_or(0);
.server_certificate
.as_ref()
.map(|v| v.buffer_length())
.unwrap_or(0);
BlobHeader::new(BlobType::Certificate, cert_size).write_to_buffer(&mut stream)?; BlobHeader::new(BlobType::Certificate, cert_size).write_to_buffer(&mut stream)?;
if let Some(cert) = &self.server_certificate { if let Some(cert) = &self.server_certificate {
@ -283,19 +269,15 @@ impl ServerCertificate {
pub fn get_public_key(&self) -> Result<Vec<u8>, ServerLicenseError> { pub fn get_public_key(&self) -> Result<Vec<u8>, ServerLicenseError> {
match &self.certificate { match &self.certificate {
CertificateType::Proprietary(certificate) => { CertificateType::Proprietary(certificate) => {
let mut public_key_buffer = let mut public_key_buffer = Vec::with_capacity(certificate.public_key.buffer_length());
Vec::with_capacity(certificate.public_key.buffer_length());
certificate.public_key.to_buffer(&mut public_key_buffer)?; certificate.public_key.to_buffer(&mut public_key_buffer)?;
Ok(public_key_buffer) Ok(public_key_buffer)
} }
CertificateType::X509(certificate) => { CertificateType::X509(certificate) => {
if let Ok((_, tbs)) = parse_x509_certificate( if let Ok((_, tbs)) = parse_x509_certificate(
certificate.certificate_array[certificate.certificate_array.len() - 1] certificate.certificate_array[certificate.certificate_array.len() - 1].as_slice(),
.as_slice(),
) { ) {
Ok(Vec::from( Ok(Vec::from(tbs.tbs_certificate.subject_pki.subject_public_key.data))
tbs.tbs_certificate.subject_pki.subject_public_key.data,
))
} else { } else {
Err(ServerLicenseError::InvalidX509Certificate) Err(ServerLicenseError::InvalidX509Certificate)
} }
@ -370,9 +352,7 @@ impl PduParsing for ProductInfo {
let company_name_len = stream.read_u32::<LittleEndian>()?; let company_name_len = stream.read_u32::<LittleEndian>()?;
if !(2..=MAX_COMPANY_NAME_LEN).contains(&company_name_len) { if !(2..=MAX_COMPANY_NAME_LEN).contains(&company_name_len) {
return Err(ServerLicenseError::InvalidCompanyNameLength( return Err(ServerLicenseError::InvalidCompanyNameLength(company_name_len));
company_name_len,
));
} }
let mut company_name = vec![0u8; company_name_len as usize]; let mut company_name = vec![0u8; company_name_len as usize];

View file

@ -42,9 +42,7 @@ impl PduParsing for X509CertificateChain {
.map(|_| { .map(|_| {
let certificate_len = stream.read_u32::<LittleEndian>()?; let certificate_len = stream.read_u32::<LittleEndian>()?;
if certificate_len > MAX_CERTIFICATE_LEN { if certificate_len > MAX_CERTIFICATE_LEN {
return Err(ServerLicenseError::InvalidCertificateLength( return Err(ServerLicenseError::InvalidCertificateLength(certificate_len));
certificate_len,
));
} }
let mut certificate = vec![0u8; certificate_len as usize]; let mut certificate = vec![0u8; certificate_len as usize];
@ -113,32 +111,24 @@ impl PduParsing for ProprietaryCertificate {
let mut signature = vec![0u8; sig_blob_header.length]; let mut signature = vec![0u8; sig_blob_header.length];
stream.read_exact(&mut signature)?; stream.read_exact(&mut signature)?;
Ok(Self { Ok(Self { public_key, signature })
public_key,
signature,
})
} }
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
stream.write_u32::<LittleEndian>(SIGNATURE_ALGORITHM_RSA as u32)?; stream.write_u32::<LittleEndian>(SIGNATURE_ALGORITHM_RSA as u32)?;
stream.write_u32::<LittleEndian>(KEY_EXCHANGE_ALGORITHM_RSA as u32)?; stream.write_u32::<LittleEndian>(KEY_EXCHANGE_ALGORITHM_RSA as u32)?;
BlobHeader::new(BlobType::RsaKey, self.public_key.buffer_length()) BlobHeader::new(BlobType::RsaKey, self.public_key.buffer_length()).write_to_buffer(&mut stream)?;
.write_to_buffer(&mut stream)?;
self.public_key.to_buffer(&mut stream)?; self.public_key.to_buffer(&mut stream)?;
BlobHeader::new(BlobType::RsaSignature, self.signature.len()) BlobHeader::new(BlobType::RsaSignature, self.signature.len()).write_to_buffer(&mut stream)?;
.write_to_buffer(&mut stream)?;
stream.write_all(&self.signature)?; stream.write_all(&self.signature)?;
Ok(()) Ok(())
} }
fn buffer_length(&self) -> usize { fn buffer_length(&self) -> usize {
PROP_CERT_BLOBS_HEADERS_SIZE PROP_CERT_BLOBS_HEADERS_SIZE + PROP_CERT_NO_BLOBS_SIZE + self.public_key.buffer_length() + self.signature.len()
+ PROP_CERT_NO_BLOBS_SIZE
+ self.public_key.buffer_length()
+ self.signature.len()
} }
} }

View file

@ -1,22 +1,19 @@
use lazy_static::lazy_static; use lazy_static::lazy_static;
use super::cert::{ use super::cert::{RsaPublicKey, PROP_CERT_BLOBS_HEADERS_SIZE, PROP_CERT_NO_BLOBS_SIZE, RSA_KEY_SIZE_WITHOUT_MODULUS};
RsaPublicKey, PROP_CERT_BLOBS_HEADERS_SIZE, PROP_CERT_NO_BLOBS_SIZE,
RSA_KEY_SIZE_WITHOUT_MODULUS,
};
use super::*; use super::*;
const SERVER_RANDOM_BUFFER: [u8; 32] = [ const SERVER_RANDOM_BUFFER: [u8; 32] = [
0x84, 0xef, 0xae, 0x20, 0xb1, 0xd5, 0x9e, 0x36, 0x49, 0x1a, 0xe8, 0x2e, 0x0a, 0x99, 0x89, 0xac, 0x84, 0xef, 0xae, 0x20, 0xb1, 0xd5, 0x9e, 0x36, 0x49, 0x1a, 0xe8, 0x2e, 0x0a, 0x99, 0x89, 0xac, 0x49, 0xa6, 0x47,
0x49, 0xa6, 0x47, 0x4f, 0x33, 0x9b, 0x5a, 0xb9, 0x95, 0x03, 0xa6, 0xc6, 0xc2, 0x3c, 0x3f, 0x61, 0x4f, 0x33, 0x9b, 0x5a, 0xb9, 0x95, 0x03, 0xa6, 0xc6, 0xc2, 0x3c, 0x3f, 0x61,
]; ];
const PRODUCT_INFO_BUFFER: [u8; 64] = [ const PRODUCT_INFO_BUFFER: [u8; 64] = [
0x00, 0x00, 0x06, 0x00, // version 0x00, 0x00, 0x06, 0x00, // version
0x2c, 0x00, 0x00, 0x00, // company name len 0x2c, 0x00, 0x00, 0x00, // company name len
0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x20,
0x74, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00,
0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, // company name 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, // company name
0x08, 0x00, 0x00, 0x00, // product id len 0x08, 0x00, 0x00, 0x00, // product id len
0x41, 0x00, 0x30, 0x00, 0x32, 0x00, 0x00, 0x00, // product id 0x41, 0x00, 0x30, 0x00, 0x32, 0x00, 0x00, 0x00, // product id
]; ];
@ -39,150 +36,129 @@ const CERT_HEADER_BUFFER: [u8; 8] = [
]; ];
const CERT_1_BUFFER: [u8; 757] = [ const CERT_1_BUFFER: [u8; 757] = [
0x30, 0x82, 0x02, 0xf1, 0x30, 0x82, 0x01, 0xdd, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x01, 0x30, 0x82, 0x02, 0xf1, 0x30, 0x82, 0x01, 0xdd, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x01, 0x9e, 0x24, 0xa2,
0x9e, 0x24, 0xa2, 0xf2, 0xae, 0x90, 0x80, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0xf2, 0xae, 0x90, 0x80, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x32, 0x31, 0x30,
0x05, 0x00, 0x30, 0x32, 0x31, 0x30, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x1e, 0x0c, 0x00, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x1e, 0x0c, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4e,
0x52, 0x00, 0x4f, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x30, 0x19, 0x06, 0x03, 0x55, 0x00, 0x54, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x07, 0x1e, 0x12, 0x00, 0x57, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x4b,
0x04, 0x07, 0x1e, 0x12, 0x00, 0x57, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x4b, 0x00, 0x47, 0x00, 0x52, 0x00, 0x47, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x55, 0x00, 0x50, 0x30, 0x1e, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x35, 0x32,
0x00, 0x4f, 0x00, 0x55, 0x00, 0x50, 0x30, 0x1e, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x35, 0x32, 0x37, 0x37, 0x30, 0x31, 0x31, 0x31, 0x30, 0x33, 0x5a, 0x17, 0x0d, 0x34, 0x39, 0x30, 0x35, 0x32, 0x37, 0x30, 0x31, 0x31,
0x30, 0x31, 0x31, 0x31, 0x30, 0x33, 0x5a, 0x17, 0x0d, 0x34, 0x39, 0x30, 0x35, 0x32, 0x37, 0x30, 0x31, 0x30, 0x33, 0x5a, 0x30, 0x32, 0x31, 0x30, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x1e, 0x0c, 0x00, 0x52,
0x31, 0x31, 0x31, 0x30, 0x33, 0x5a, 0x30, 0x32, 0x31, 0x30, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x00, 0x4f, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x07, 0x1e, 0x12,
0x03, 0x1e, 0x0c, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x30, 0x00, 0x57, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x4b, 0x00, 0x47, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x55, 0x00, 0x50, 0x30,
0x19, 0x06, 0x03, 0x55, 0x04, 0x07, 0x1e, 0x12, 0x00, 0x57, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x4b, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
0x00, 0x47, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x55, 0x00, 0x50, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0x88, 0xad, 0x7c, 0x8f, 0x8b, 0x82,
0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x76, 0x5a, 0xbd, 0x8f, 0x6f, 0x62, 0x18, 0xe1, 0xd9, 0xaa, 0x41, 0xfd, 0xed, 0x68, 0x01, 0xc6, 0x34, 0x35, 0xb0,
0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0x88, 0xad, 0x7c, 0x8f, 0x8b, 0x29, 0x04, 0xca, 0x4a, 0x4a, 0x1c, 0x7e, 0x80, 0x14, 0xf7, 0x8e, 0x77, 0xb8, 0x25, 0xff, 0x16, 0x47, 0x6f, 0xbd,
0x82, 0x76, 0x5a, 0xbd, 0x8f, 0x6f, 0x62, 0x18, 0xe1, 0xd9, 0xaa, 0x41, 0xfd, 0xed, 0x68, 0x01, 0xe2, 0x34, 0x3d, 0x2e, 0x02, 0xb9, 0x53, 0xe4, 0x33, 0x75, 0xad, 0x73, 0x28, 0x80, 0xa0, 0x4d, 0xfc, 0x6c, 0xc0,
0xc6, 0x34, 0x35, 0xb0, 0x29, 0x04, 0xca, 0x4a, 0x4a, 0x1c, 0x7e, 0x80, 0x14, 0xf7, 0x8e, 0x77, 0x22, 0x53, 0x1b, 0x2c, 0xf8, 0xf5, 0x01, 0x60, 0x19, 0x7e, 0x79, 0x19, 0x39, 0x8d, 0xb5, 0xce, 0x39, 0x58, 0xdd,
0xb8, 0x25, 0xff, 0x16, 0x47, 0x6f, 0xbd, 0xe2, 0x34, 0x3d, 0x2e, 0x02, 0xb9, 0x53, 0xe4, 0x33, 0x55, 0x24, 0x3b, 0x55, 0x7b, 0x43, 0xc1, 0x7f, 0x14, 0x2f, 0xb0, 0x64, 0x3a, 0x54, 0x95, 0x2b, 0x88, 0x49, 0x0c,
0x75, 0xad, 0x73, 0x28, 0x80, 0xa0, 0x4d, 0xfc, 0x6c, 0xc0, 0x22, 0x53, 0x1b, 0x2c, 0xf8, 0xf5, 0x61, 0x2d, 0xac, 0xf8, 0x45, 0xf5, 0xda, 0x88, 0x18, 0x5f, 0xae, 0x42, 0xf8, 0x75, 0xc7, 0x26, 0x6d, 0xb5, 0xbb,
0x01, 0x60, 0x19, 0x7e, 0x79, 0x19, 0x39, 0x8d, 0xb5, 0xce, 0x39, 0x58, 0xdd, 0x55, 0x24, 0x3b, 0x39, 0x6f, 0xcc, 0x55, 0x1b, 0x32, 0x11, 0x38, 0x8d, 0xe4, 0xe9, 0x44, 0x84, 0x11, 0x36, 0xa2, 0x61, 0x76, 0xaa,
0x55, 0x7b, 0x43, 0xc1, 0x7f, 0x14, 0x2f, 0xb0, 0x64, 0x3a, 0x54, 0x95, 0x2b, 0x88, 0x49, 0x0c, 0x4c, 0xb4, 0xe3, 0x55, 0x0f, 0xe4, 0x77, 0x8e, 0xde, 0xe3, 0xa9, 0xea, 0xb7, 0x41, 0x94, 0x00, 0x58, 0xaa, 0xc9,
0x61, 0x2d, 0xac, 0xf8, 0x45, 0xf5, 0xda, 0x88, 0x18, 0x5f, 0xae, 0x42, 0xf8, 0x75, 0xc7, 0x26, 0x34, 0xa2, 0x98, 0xc6, 0x01, 0x1a, 0x76, 0x14, 0x01, 0xa8, 0xdc, 0x30, 0x7c, 0x77, 0x5a, 0x20, 0x71, 0x5a, 0xa2,
0x6d, 0xb5, 0xbb, 0x39, 0x6f, 0xcc, 0x55, 0x1b, 0x32, 0x11, 0x38, 0x8d, 0xe4, 0xe9, 0x44, 0x84, 0x3f, 0xaf, 0x13, 0x7e, 0xe8, 0xfd, 0x84, 0xa2, 0x5b, 0xcf, 0x25, 0xe9, 0xc7, 0x8f, 0xa8, 0xf2, 0x8b, 0x84, 0xc7,
0x11, 0x36, 0xa2, 0x61, 0x76, 0xaa, 0x4c, 0xb4, 0xe3, 0x55, 0x0f, 0xe4, 0x77, 0x8e, 0xde, 0xe3, 0x04, 0x5e, 0x53, 0x73, 0x4e, 0x0e, 0x89, 0xa3, 0x3c, 0xe7, 0x68, 0x5c, 0x24, 0xb7, 0x80, 0x53, 0x3c, 0x54, 0xc8,
0xa9, 0xea, 0xb7, 0x41, 0x94, 0x00, 0x58, 0xaa, 0xc9, 0x34, 0xa2, 0x98, 0xc6, 0x01, 0x1a, 0x76, 0xc1, 0x53, 0xaa, 0x71, 0x71, 0x3d, 0x36, 0x15, 0xd6, 0x6a, 0x9d, 0x7d, 0xde, 0xae, 0xf9, 0xe6, 0xaf, 0x57, 0xae,
0x14, 0x01, 0xa8, 0xdc, 0x30, 0x7c, 0x77, 0x5a, 0x20, 0x71, 0x5a, 0xa2, 0x3f, 0xaf, 0x13, 0x7e, 0xb9, 0x01, 0x96, 0x5d, 0xe0, 0x4d, 0xcd, 0xed, 0xc8, 0xd7, 0xf3, 0x01, 0x03, 0x38, 0x10, 0xbe, 0x7c, 0x42, 0x67,
0xe8, 0xfd, 0x84, 0xa2, 0x5b, 0xcf, 0x25, 0xe9, 0xc7, 0x8f, 0xa8, 0xf2, 0x8b, 0x84, 0xc7, 0x04, 0x01, 0xa7, 0x23, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x13, 0x30, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13,
0x5e, 0x53, 0x73, 0x4e, 0x0e, 0x89, 0xa3, 0x3c, 0xe7, 0x68, 0x5c, 0x24, 0xb7, 0x80, 0x53, 0x3c, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
0x54, 0xc8, 0xc1, 0x53, 0xaa, 0x71, 0x71, 0x3d, 0x36, 0x15, 0xd6, 0x6a, 0x9d, 0x7d, 0xde, 0xae, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x81, 0xdd, 0xd2, 0xd3, 0x33, 0xd4, 0xa3, 0xb6, 0x8e, 0x6e, 0x7d, 0x9f,
0xf9, 0xe6, 0xaf, 0x57, 0xae, 0xb9, 0x01, 0x96, 0x5d, 0xe0, 0x4d, 0xcd, 0xed, 0xc8, 0xd7, 0xf3, 0xfd, 0x73, 0x9f, 0x31, 0x0b, 0xdd, 0x42, 0x82, 0x3f, 0x7e, 0x21, 0xdf, 0x28, 0xcc, 0x59, 0xca, 0x6a, 0xc0, 0xa9,
0x01, 0x03, 0x38, 0x10, 0xbe, 0x7c, 0x42, 0x67, 0x01, 0xa7, 0x23, 0x02, 0x03, 0x01, 0x00, 0x01, 0x3d, 0x30, 0x7d, 0xe1, 0x91, 0xdb, 0x77, 0x6b, 0x8b, 0x10, 0xe6, 0xfd, 0xbc, 0x3c, 0xa3, 0x58, 0x48, 0xc2, 0x36,
0xa3, 0x13, 0x30, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x08, 0x30, 0x06, 0x01, 0xdd, 0xa0, 0x0b, 0xf5, 0x8e, 0x13, 0xda, 0x7b, 0x04, 0x08, 0x44, 0xb4, 0xf2, 0xa8, 0x0d, 0x1e, 0x0b, 0x1d, 0x1a,
0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x3f, 0xf9, 0x9b, 0x4b, 0x5a, 0x54, 0xc5, 0xb3, 0xb4, 0x03, 0x93, 0x75, 0xb3, 0x72, 0x5c, 0x3d, 0xcf, 0x63, 0x0f,
0x03, 0x82, 0x01, 0x01, 0x00, 0x81, 0xdd, 0xd2, 0xd3, 0x33, 0xd4, 0xa3, 0xb6, 0x8e, 0x6e, 0x7d, 0x15, 0xe1, 0x64, 0x58, 0xde, 0x52, 0x8d, 0x97, 0x79, 0x0e, 0xa4, 0x34, 0xd5, 0x66, 0x05, 0x58, 0xb8, 0x6e, 0x79,
0x9f, 0xfd, 0x73, 0x9f, 0x31, 0x0b, 0xdd, 0x42, 0x82, 0x3f, 0x7e, 0x21, 0xdf, 0x28, 0xcc, 0x59, 0xb2, 0x09, 0x86, 0xd5, 0xf0, 0xed, 0xc4, 0x6b, 0x4c, 0xab, 0x02, 0xb8, 0x16, 0x5f, 0x3b, 0xed, 0x88, 0x5f, 0xd1,
0xca, 0x6a, 0xc0, 0xa9, 0x3d, 0x30, 0x7d, 0xe1, 0x91, 0xdb, 0x77, 0x6b, 0x8b, 0x10, 0xe6, 0xfd, 0xde, 0x44, 0xe3, 0x73, 0x47, 0x21, 0xf7, 0x03, 0xce, 0xe1, 0x6d, 0x10, 0x0f, 0x95, 0xcf, 0x7c, 0xa2, 0x7a, 0xa6,
0xbc, 0x3c, 0xa3, 0x58, 0x48, 0xc2, 0x36, 0xdd, 0xa0, 0x0b, 0xf5, 0x8e, 0x13, 0xda, 0x7b, 0x04, 0xbf, 0x20, 0xdb, 0xe1, 0x93, 0x04, 0xc8, 0x5e, 0x6a, 0xbe, 0xc8, 0x01, 0x5d, 0x27, 0xb2, 0x03, 0x0f, 0x66, 0x75,
0x08, 0x44, 0xb4, 0xf2, 0xa8, 0x0d, 0x1e, 0x0b, 0x1d, 0x1a, 0x3f, 0xf9, 0x9b, 0x4b, 0x5a, 0x54, 0xe7, 0xcb, 0xea, 0x8d, 0x4e, 0x98, 0x9d, 0x22, 0xed, 0x28, 0x40, 0xd2, 0x7d, 0xa4, 0x4b, 0xef, 0xcc, 0xbf, 0x01,
0xc5, 0xb3, 0xb4, 0x03, 0x93, 0x75, 0xb3, 0x72, 0x5c, 0x3d, 0xcf, 0x63, 0x0f, 0x15, 0xe1, 0x64, 0x2a, 0x6d, 0x3a, 0x3e, 0xbe, 0x47, 0x38, 0xf8, 0xea, 0xa4, 0xc6, 0x30, 0x1d, 0x5e, 0x25, 0xcf, 0xfb, 0xe8, 0x3d,
0x58, 0xde, 0x52, 0x8d, 0x97, 0x79, 0x0e, 0xa4, 0x34, 0xd5, 0x66, 0x05, 0x58, 0xb8, 0x6e, 0x79, 0x42, 0xdd, 0x29, 0xe8, 0x99, 0x89, 0x9e, 0xbf, 0x39, 0xee, 0x77, 0x09, 0xd9, 0x3e, 0x8b, 0x52, 0x36, 0xb6, 0xbb,
0xb2, 0x09, 0x86, 0xd5, 0xf0, 0xed, 0xc4, 0x6b, 0x4c, 0xab, 0x02, 0xb8, 0x16, 0x5f, 0x3b, 0xed, 0x8b, 0xbd, 0x0d, 0xb2, 0x52, 0xaa, 0x2c, 0xcf, 0x38, 0x4e, 0x4d, 0xcf, 0x1d, 0x6d, 0x5d, 0x25, 0x17, 0xac, 0x2c,
0x88, 0x5f, 0xd1, 0xde, 0x44, 0xe3, 0x73, 0x47, 0x21, 0xf7, 0x03, 0xce, 0xe1, 0x6d, 0x10, 0x0f, 0xf6, 0xf0, 0x65, 0x5a, 0xc9, 0xfe, 0x31, 0x53, 0xb4, 0xf0, 0x0c, 0x94, 0x4e, 0x0d, 0x54, 0x8e,
0x95, 0xcf, 0x7c, 0xa2, 0x7a, 0xa6, 0xbf, 0x20, 0xdb, 0xe1, 0x93, 0x04, 0xc8, 0x5e, 0x6a, 0xbe,
0xc8, 0x01, 0x5d, 0x27, 0xb2, 0x03, 0x0f, 0x66, 0x75, 0xe7, 0xcb, 0xea, 0x8d, 0x4e, 0x98, 0x9d,
0x22, 0xed, 0x28, 0x40, 0xd2, 0x7d, 0xa4, 0x4b, 0xef, 0xcc, 0xbf, 0x01, 0x2a, 0x6d, 0x3a, 0x3e,
0xbe, 0x47, 0x38, 0xf8, 0xea, 0xa4, 0xc6, 0x30, 0x1d, 0x5e, 0x25, 0xcf, 0xfb, 0xe8, 0x3d, 0x42,
0xdd, 0x29, 0xe8, 0x99, 0x89, 0x9e, 0xbf, 0x39, 0xee, 0x77, 0x09, 0xd9, 0x3e, 0x8b, 0x52, 0x36,
0xb6, 0xbb, 0x8b, 0xbd, 0x0d, 0xb2, 0x52, 0xaa, 0x2c, 0xcf, 0x38, 0x4e, 0x4d, 0xcf, 0x1d, 0x6d,
0x5d, 0x25, 0x17, 0xac, 0x2c, 0xf6, 0xf0, 0x65, 0x5a, 0xc9, 0xfe, 0x31, 0x53, 0xb4, 0xf0, 0x0c,
0x94, 0x4e, 0x0d, 0x54, 0x8e,
]; ];
const CERT_2_BUFFER: [u8; 1277] = [ const CERT_2_BUFFER: [u8; 1277] = [
0x30, 0x82, 0x04, 0xf9, 0x30, 0x82, 0x03, 0xe5, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x05, 0x01, 0x30, 0x82, 0x04, 0xf9, 0x30, 0x82, 0x03, 0xe5, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x05, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x02, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x32, 0x31, 0x30, 0x30, 0x13, 0x06,
0x32, 0x31, 0x30, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x1e, 0x0c, 0x00, 0x52, 0x00, 0x4f, 0x03, 0x55, 0x04, 0x03, 0x1e, 0x0c, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x30,
0x00, 0x44, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x07, 0x1e, 0x19, 0x06, 0x03, 0x55, 0x04, 0x07, 0x1e, 0x12, 0x00, 0x57, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x4b, 0x00, 0x47, 0x00,
0x12, 0x00, 0x57, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x4b, 0x00, 0x47, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x55, 0x00, 0x50, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x35, 0x32, 0x36, 0x31, 0x32,
0x55, 0x00, 0x50, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x35, 0x32, 0x36, 0x31, 0x32, 0x34, 0x34, 0x35, 0x35, 0x33, 0x5a, 0x17, 0x0d, 0x33, 0x38, 0x30, 0x31, 0x31, 0x39, 0x30, 0x33, 0x31, 0x34, 0x30, 0x37,
0x35, 0x35, 0x33, 0x5a, 0x17, 0x0d, 0x33, 0x38, 0x30, 0x31, 0x31, 0x39, 0x30, 0x33, 0x31, 0x34, 0x5a, 0x30, 0x81, 0x92, 0x31, 0x81, 0x8f, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x1e, 0x1c, 0x00, 0x6e, 0x00,
0x30, 0x37, 0x5a, 0x30, 0x81, 0x92, 0x31, 0x81, 0x8f, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x72, 0x00, 0x70, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x44,
0x1e, 0x1c, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x72, 0x00, 0x70, 0x00, 0x63, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x07, 0x1e, 0x1c, 0x00, 0x6e, 0x00, 0x63,
0x00, 0x3a, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x30, 0x23, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x72, 0x00, 0x70, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x44, 0x00,
0x06, 0x03, 0x55, 0x04, 0x07, 0x1e, 0x1c, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x30, 0x43, 0x06, 0x03, 0x55, 0x04, 0x05, 0x1e, 0x3c, 0x00, 0x31, 0x00, 0x42, 0x00,
0x72, 0x00, 0x70, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x44, 0x00, 0x45, 0x00, 0x63, 0x00, 0x4b, 0x00, 0x65, 0x00, 0x62, 0x00, 0x68, 0x00, 0x70, 0x00, 0x58, 0x00, 0x5a, 0x00, 0x74, 0x00, 0x4c,
0x4e, 0x00, 0x54, 0x30, 0x43, 0x06, 0x03, 0x55, 0x04, 0x05, 0x1e, 0x3c, 0x00, 0x31, 0x00, 0x42, 0x00, 0x71, 0x00, 0x4f, 0x00, 0x37, 0x00, 0x53, 0x00, 0x51, 0x00, 0x6e, 0x00, 0x42, 0x00, 0x70, 0x00, 0x52, 0x00,
0x00, 0x63, 0x00, 0x4b, 0x00, 0x65, 0x00, 0x62, 0x00, 0x68, 0x00, 0x70, 0x00, 0x58, 0x00, 0x5a, 0x66, 0x00, 0x75, 0x00, 0x64, 0x00, 0x64, 0x00, 0x64, 0x00, 0x59, 0x00, 0x3d, 0x00, 0x0d, 0x00, 0x0a, 0x30, 0x82,
0x00, 0x74, 0x00, 0x4c, 0x00, 0x71, 0x00, 0x4f, 0x00, 0x37, 0x00, 0x53, 0x00, 0x51, 0x00, 0x6e, 0x01, 0x1e, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x0f, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30,
0x00, 0x42, 0x00, 0x70, 0x00, 0x52, 0x00, 0x66, 0x00, 0x75, 0x00, 0x64, 0x00, 0x64, 0x00, 0x64, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc8, 0x90, 0x6b, 0xf0, 0xc6, 0x58, 0x81, 0xa6, 0x89, 0x1c, 0x0e,
0x00, 0x59, 0x00, 0x3d, 0x00, 0x0d, 0x00, 0x0a, 0x30, 0x82, 0x01, 0x1e, 0x30, 0x09, 0x06, 0x05, 0xf2, 0xf6, 0xd9, 0x82, 0x12, 0x71, 0xa5, 0x6e, 0x51, 0xdb, 0xe0, 0x32, 0x66, 0xaa, 0x91, 0x77, 0x0e, 0x88, 0xab,
0x2b, 0x0e, 0x03, 0x02, 0x0f, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x44, 0xb7, 0xd3, 0x97, 0xda, 0x78, 0x8f, 0x0e, 0x44, 0x26, 0x46, 0x7f, 0x16, 0xd4, 0xc6, 0x63, 0xeb, 0xca, 0x55,
0x02, 0x82, 0x01, 0x01, 0x00, 0xc8, 0x90, 0x6b, 0xf0, 0xc6, 0x58, 0x81, 0xa6, 0x89, 0x1c, 0x0e, 0xe5, 0x4e, 0x8b, 0x2d, 0xa6, 0x6d, 0x83, 0x95, 0xa7, 0xa8, 0x6a, 0xfa, 0xd0, 0xbe, 0x26, 0x80, 0xae, 0xab, 0x0a,
0xf2, 0xf6, 0xd9, 0x82, 0x12, 0x71, 0xa5, 0x6e, 0x51, 0xdb, 0xe0, 0x32, 0x66, 0xaa, 0x91, 0x77, 0x64, 0x90, 0x32, 0x8c, 0xdf, 0x5c, 0xf8, 0xf9, 0xd0, 0x7e, 0xd1, 0x6b, 0x3a, 0x29, 0x7e, 0x7d, 0xbd, 0x02, 0xa3,
0x0e, 0x88, 0xab, 0x44, 0xb7, 0xd3, 0x97, 0xda, 0x78, 0x8f, 0x0e, 0x44, 0x26, 0x46, 0x7f, 0x16, 0x86, 0x6c, 0xfd, 0xa5, 0x35, 0x71, 0xda, 0x21, 0xb4, 0xee, 0xa4, 0x97, 0xf3, 0xa8, 0xb2, 0x12, 0xdb, 0xa4, 0x27,
0xd4, 0xc6, 0x63, 0xeb, 0xca, 0x55, 0xe5, 0x4e, 0x8b, 0x2d, 0xa6, 0x6d, 0x83, 0x95, 0xa7, 0xa8, 0x57, 0x36, 0xc9, 0x08, 0x22, 0x5c, 0x54, 0xf7, 0x99, 0x7b, 0xa3, 0x2f, 0xb8, 0x5c, 0xd5, 0x16, 0xb8, 0x19, 0x27,
0x6a, 0xfa, 0xd0, 0xbe, 0x26, 0x80, 0xae, 0xab, 0x0a, 0x64, 0x90, 0x32, 0x8c, 0xdf, 0x5c, 0xf8, 0x6b, 0x71, 0x97, 0x14, 0x5b, 0xe8, 0x1f, 0x23, 0xe8, 0x5c, 0xb8, 0x1b, 0x73, 0x4b, 0x6e, 0x7a, 0x03, 0x13, 0xff,
0xf9, 0xd0, 0x7e, 0xd1, 0x6b, 0x3a, 0x29, 0x7e, 0x7d, 0xbd, 0x02, 0xa3, 0x86, 0x6c, 0xfd, 0xa5, 0x97, 0xe9, 0x62, 0xb9, 0x4a, 0xa0, 0x51, 0x23, 0xc3, 0x6c, 0x32, 0x3e, 0x02, 0xf2, 0x63, 0x97, 0x23, 0x1c, 0xc5,
0x35, 0x71, 0xda, 0x21, 0xb4, 0xee, 0xa4, 0x97, 0xf3, 0xa8, 0xb2, 0x12, 0xdb, 0xa4, 0x27, 0x57, 0x78, 0xd8, 0xfc, 0xb7, 0x07, 0x4b, 0xb0, 0x56, 0x0f, 0x74, 0xdf, 0xc5, 0x56, 0x28, 0xe4, 0x96, 0xfd, 0x20, 0x8e,
0x36, 0xc9, 0x08, 0x22, 0x5c, 0x54, 0xf7, 0x99, 0x7b, 0xa3, 0x2f, 0xb8, 0x5c, 0xd5, 0x16, 0xb8, 0x65, 0x5a, 0xe6, 0x45, 0xed, 0xc1, 0x05, 0x3e, 0xab, 0x58, 0x55, 0x40, 0xaf, 0xe2, 0x47, 0xa0, 0x4c, 0x49, 0xa3,
0x19, 0x27, 0x6b, 0x71, 0x97, 0x14, 0x5b, 0xe8, 0x1f, 0x23, 0xe8, 0x5c, 0xb8, 0x1b, 0x73, 0x4b, 0x8d, 0x39, 0xe3, 0x66, 0x5f, 0x93, 0x33, 0x6d, 0xf8, 0x5f, 0xc5, 0x54, 0xe5, 0xfb, 0x57, 0x3a, 0xde, 0x45, 0x12,
0x6e, 0x7a, 0x03, 0x13, 0xff, 0x97, 0xe9, 0x62, 0xb9, 0x4a, 0xa0, 0x51, 0x23, 0xc3, 0x6c, 0x32, 0xb5, 0xc7, 0x05, 0x4b, 0x88, 0x1f, 0xb4, 0x35, 0x0f, 0x7c, 0xc0, 0x75, 0x17, 0xc6, 0x67, 0xdd, 0x48, 0x80, 0xcb,
0x3e, 0x02, 0xf2, 0x63, 0x97, 0x23, 0x1c, 0xc5, 0x78, 0xd8, 0xfc, 0xb7, 0x07, 0x4b, 0xb0, 0x56, 0x0a, 0xbe, 0x9d, 0xf6, 0x93, 0x60, 0x65, 0x34, 0xeb, 0x97, 0xaf, 0x65, 0x6d, 0xdf, 0xbf, 0x6f, 0x5b, 0x02, 0x03,
0x0f, 0x74, 0xdf, 0xc5, 0x56, 0x28, 0xe4, 0x96, 0xfd, 0x20, 0x8e, 0x65, 0x5a, 0xe6, 0x45, 0xed, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xbf, 0x30, 0x82, 0x01, 0xbb, 0x30, 0x14, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04,
0xc1, 0x05, 0x3e, 0xab, 0x58, 0x55, 0x40, 0xaf, 0xe2, 0x47, 0xa0, 0x4c, 0x49, 0xa3, 0x8d, 0x39, 0x01, 0x82, 0x37, 0x12, 0x04, 0x01, 0x01, 0xff, 0x04, 0x04, 0x01, 0x00, 0x05, 0x00, 0x30, 0x3c, 0x06, 0x09, 0x2b,
0xe3, 0x66, 0x5f, 0x93, 0x33, 0x6d, 0xf8, 0x5f, 0xc5, 0x54, 0xe5, 0xfb, 0x57, 0x3a, 0xde, 0x45, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x12, 0x02, 0x01, 0x01, 0xff, 0x04, 0x2c, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00,
0x12, 0xb5, 0xc7, 0x05, 0x4b, 0x88, 0x1f, 0xb4, 0x35, 0x0f, 0x7c, 0xc0, 0x75, 0x17, 0xc6, 0x67, 0x72, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x72,
0xdd, 0x48, 0x80, 0xcb, 0x0a, 0xbe, 0x9d, 0xf6, 0x93, 0x60, 0x65, 0x34, 0xeb, 0x97, 0xaf, 0x65, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00,
0x6d, 0xdf, 0xbf, 0x6f, 0x5b, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xbf, 0x30, 0x82, 0x30, 0x81, 0xcd, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x12, 0x05, 0x01, 0x01, 0xff, 0x04, 0x81,
0x01, 0xbb, 0x30, 0x14, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x12, 0x04, 0x01, 0xbc, 0x00, 0x30, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x1c, 0x00,
0x01, 0xff, 0x04, 0x04, 0x01, 0x00, 0x05, 0x00, 0x30, 0x3c, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x4a, 0x00, 0x66, 0x00, 0x4a, 0x00, 0xb0, 0x00, 0x01, 0x00, 0x33, 0x00, 0x64, 0x00, 0x32, 0x00, 0x36, 0x00, 0x37,
0x01, 0x82, 0x37, 0x12, 0x02, 0x01, 0x01, 0xff, 0x04, 0x2c, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x00, 0x39, 0x00, 0x35, 0x00, 0x34, 0x00, 0x2d, 0x00, 0x65, 0x00, 0x65, 0x00, 0x62, 0x00, 0x37, 0x00, 0x2d, 0x00,
0x72, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x20, 0x00, 0x43, 0x00, 0x31, 0x00, 0x31, 0x00, 0x64, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x39, 0x00, 0x34, 0x00, 0x65, 0x00, 0x2d,
0x6f, 0x00, 0x72, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x63, 0x00, 0x30, 0x00, 0x34, 0x00, 0x66, 0x00, 0x61, 0x00, 0x33, 0x00, 0x30, 0x00,
0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x30, 0x81, 0xcd, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x38, 0x00, 0x30, 0x00, 0x64, 0x00, 0x00, 0x00, 0x33, 0x00, 0x64, 0x00, 0x32, 0x00, 0x36, 0x00, 0x37, 0x00, 0x39,
0x82, 0x37, 0x12, 0x05, 0x01, 0x01, 0xff, 0x04, 0x81, 0xbc, 0x00, 0x30, 0x00, 0x00, 0x01, 0x00, 0x00, 0x35, 0x00, 0x34, 0x00, 0x2d, 0x00, 0x65, 0x00, 0x65, 0x00, 0x62, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x31, 0x00,
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x1c, 0x00, 0x4a, 0x00, 0x66, 0x00, 0x31, 0x00, 0x64, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x39, 0x00, 0x34, 0x00, 0x65, 0x00, 0x2d, 0x00, 0x30,
0x4a, 0x00, 0xb0, 0x00, 0x01, 0x00, 0x33, 0x00, 0x64, 0x00, 0x32, 0x00, 0x36, 0x00, 0x37, 0x00, 0x00, 0x30, 0x00, 0x63, 0x00, 0x30, 0x00, 0x34, 0x00, 0x66, 0x00, 0x61, 0x00, 0x33, 0x00, 0x30, 0x00, 0x38, 0x00,
0x39, 0x00, 0x35, 0x00, 0x34, 0x00, 0x2d, 0x00, 0x65, 0x00, 0x65, 0x00, 0x62, 0x00, 0x37, 0x00, 0x30, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x2d, 0x00, 0x31, 0x00, 0x31, 0x00, 0x64, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x39, 0x00, 0x6e, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x12, 0x06, 0x01, 0x01, 0xff, 0x04, 0x5e, 0x00, 0x30,
0x34, 0x00, 0x65, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x30, 0x00, 0x63, 0x00, 0x30, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x3e, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54,
0x66, 0x00, 0x61, 0x00, 0x33, 0x00, 0x30, 0x00, 0x38, 0x00, 0x30, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x38, 0x00, 0x34, 0x00, 0x34, 0x00, 0x30, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x30, 0x00,
0x33, 0x00, 0x64, 0x00, 0x32, 0x00, 0x36, 0x00, 0x37, 0x00, 0x39, 0x00, 0x35, 0x00, 0x34, 0x00, 0x36, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x38, 0x00, 0x36, 0x00, 0x37, 0x00, 0x30, 0x00, 0x34, 0x00, 0x35, 0x00, 0x2d,
0x2d, 0x00, 0x65, 0x00, 0x65, 0x00, 0x62, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x31, 0x00, 0x00, 0x37, 0x00, 0x30, 0x00, 0x33, 0x00, 0x34, 0x00, 0x37, 0x00, 0x00, 0x00, 0x57, 0x00, 0x4f, 0x00, 0x52, 0x00,
0x64, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x39, 0x00, 0x34, 0x00, 0x65, 0x00, 0x2d, 0x00, 0x4b, 0x00, 0x47, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x55, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x25, 0x06,
0x30, 0x00, 0x30, 0x00, 0x63, 0x00, 0x30, 0x00, 0x34, 0x00, 0x66, 0x00, 0x61, 0x00, 0x33, 0x00, 0x03, 0x55, 0x1d, 0x23, 0x01, 0x01, 0xff, 0x04, 0x1b, 0x30, 0x19, 0xa1, 0x10, 0xa4, 0x0e, 0x52, 0x00, 0x4f, 0x00,
0x30, 0x00, 0x38, 0x00, 0x30, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x44, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x00, 0x00, 0x82, 0x05, 0x01, 0x00, 0x00, 0x00, 0x02, 0x30, 0x09,
0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x6e, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x2e, 0xeb, 0xc7, 0x0d, 0xb8,
0x37, 0x12, 0x06, 0x01, 0x01, 0xff, 0x04, 0x5e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x1d, 0x47, 0x11, 0x9d, 0x09, 0x88, 0x9b, 0x51, 0xdc, 0x45, 0xdd, 0x56, 0x51, 0xe2, 0xd1, 0x23, 0x11, 0x39, 0x9b,
0x3e, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x00, 0x00, 0x2d, 0xda, 0xc7, 0xfe, 0x7a, 0xd7, 0x84, 0xe3, 0x3d, 0x54, 0x77, 0x97, 0x4d, 0x19, 0x92, 0x30, 0x64, 0xa0, 0x47,
0x37, 0x00, 0x38, 0x00, 0x34, 0x00, 0x34, 0x00, 0x30, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x30, 0x00, 0xc6, 0x2f, 0x6d, 0x93, 0xd2, 0x64, 0x7c, 0x76, 0xc8, 0x26, 0x45, 0xad, 0x5a, 0x44, 0x54, 0xea, 0xf6, 0x4b, 0x28,
0x36, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x38, 0x00, 0x36, 0x00, 0x37, 0x00, 0x30, 0x00, 0x34, 0x00, 0x77, 0x1f, 0x77, 0xea, 0xec, 0x74, 0x02, 0x38, 0x68, 0x9e, 0x79, 0x14, 0x72, 0x83, 0x34, 0x74, 0x62, 0xd2, 0xc1,
0x35, 0x00, 0x2d, 0x00, 0x37, 0x00, 0x30, 0x00, 0x33, 0x00, 0x34, 0x00, 0x37, 0x00, 0x00, 0x00, 0x0c, 0xa4, 0x0b, 0xf2, 0xa9, 0xb0, 0x38, 0xbb, 0x7c, 0xd0, 0xae, 0xbe, 0xbf, 0x74, 0x47, 0x16, 0xa0, 0xa2, 0xd3,
0x57, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x4b, 0x00, 0x47, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x55, 0x00, 0xfc, 0x1d, 0xb9, 0xba, 0x26, 0x10, 0x06, 0xef, 0xba, 0x1d, 0x43, 0x01, 0x4e, 0x4e, 0x6f, 0x56, 0xca, 0xe0, 0xee,
0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x25, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x01, 0x01, 0xff, 0xd0, 0xf9, 0x4e, 0xa6, 0x62, 0x63, 0xff, 0xda, 0x0b, 0xc9, 0x15, 0x61, 0x6c, 0xed, 0x6b, 0x0b, 0xc4, 0x58, 0x53,
0x04, 0x1b, 0x30, 0x19, 0xa1, 0x10, 0xa4, 0x0e, 0x52, 0x00, 0x4f, 0x00, 0x44, 0x00, 0x45, 0x00, 0x86, 0x0f, 0x8c, 0x0c, 0x1a, 0x2e, 0xdf, 0xc1, 0xf2, 0x43, 0x48, 0xd4, 0xaf, 0x0a, 0x78, 0x36, 0xb2, 0x51, 0x32,
0x4e, 0x00, 0x54, 0x00, 0x00, 0x00, 0x82, 0x05, 0x01, 0x00, 0x00, 0x00, 0x02, 0x30, 0x09, 0x06, 0x28, 0x6c, 0xc2, 0x75, 0x79, 0x3f, 0x6e, 0x99, 0x66, 0x88, 0x3e, 0x34, 0xd3, 0x7f, 0x6d, 0x9d, 0x07, 0xe4, 0x6b,
0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x2e, 0xeb, 0xc7, 0xeb, 0x84, 0xe2, 0x0a, 0xbb, 0xca, 0x7d, 0x3a, 0x40, 0x71, 0xb0, 0xbe, 0x47, 0x9f, 0x12, 0x58, 0x31, 0x61, 0x2b,
0x0d, 0xb8, 0x1d, 0x47, 0x11, 0x9d, 0x09, 0x88, 0x9b, 0x51, 0xdc, 0x45, 0xdd, 0x56, 0x51, 0xe2, 0x9b, 0x4a, 0x9a, 0x49, 0x8f, 0xe5, 0xb4, 0x0c, 0xf5, 0x04, 0x4d, 0x3c, 0xce, 0xbc, 0xd2, 0x79, 0x15, 0xd9, 0x28,
0xd1, 0x23, 0x11, 0x39, 0x9b, 0x2d, 0xda, 0xc7, 0xfe, 0x7a, 0xd7, 0x84, 0xe3, 0x3d, 0x54, 0x77, 0xf4, 0x23, 0x56, 0x77, 0x9f, 0x38, 0x64, 0x3e, 0x03, 0x88, 0x92, 0x04, 0x26, 0x76, 0xb9, 0xb5, 0xdf, 0x19, 0xd0,
0x97, 0x4d, 0x19, 0x92, 0x30, 0x64, 0xa0, 0x47, 0xc6, 0x2f, 0x6d, 0x93, 0xd2, 0x64, 0x7c, 0x76, 0x78, 0x4b, 0x7a, 0x60, 0x40, 0x23, 0x91, 0xf1, 0x15, 0x22, 0x2b, 0xb4, 0xe7, 0x02, 0x54, 0xa9, 0x16, 0x21, 0x5b,
0xc8, 0x26, 0x45, 0xad, 0x5a, 0x44, 0x54, 0xea, 0xf6, 0x4b, 0x28, 0x77, 0x1f, 0x77, 0xea, 0xec, 0x60, 0x96, 0xa9, 0x5c,
0x74, 0x02, 0x38, 0x68, 0x9e, 0x79, 0x14, 0x72, 0x83, 0x34, 0x74, 0x62, 0xd2, 0xc1, 0x0c, 0xa4,
0x0b, 0xf2, 0xa9, 0xb0, 0x38, 0xbb, 0x7c, 0xd0, 0xae, 0xbe, 0xbf, 0x74, 0x47, 0x16, 0xa0, 0xa2,
0xd3, 0xfc, 0x1d, 0xb9, 0xba, 0x26, 0x10, 0x06, 0xef, 0xba, 0x1d, 0x43, 0x01, 0x4e, 0x4e, 0x6f,
0x56, 0xca, 0xe0, 0xee, 0xd0, 0xf9, 0x4e, 0xa6, 0x62, 0x63, 0xff, 0xda, 0x0b, 0xc9, 0x15, 0x61,
0x6c, 0xed, 0x6b, 0x0b, 0xc4, 0x58, 0x53, 0x86, 0x0f, 0x8c, 0x0c, 0x1a, 0x2e, 0xdf, 0xc1, 0xf2,
0x43, 0x48, 0xd4, 0xaf, 0x0a, 0x78, 0x36, 0xb2, 0x51, 0x32, 0x28, 0x6c, 0xc2, 0x75, 0x79, 0x3f,
0x6e, 0x99, 0x66, 0x88, 0x3e, 0x34, 0xd3, 0x7f, 0x6d, 0x9d, 0x07, 0xe4, 0x6b, 0xeb, 0x84, 0xe2,
0x0a, 0xbb, 0xca, 0x7d, 0x3a, 0x40, 0x71, 0xb0, 0xbe, 0x47, 0x9f, 0x12, 0x58, 0x31, 0x61, 0x2b,
0x9b, 0x4a, 0x9a, 0x49, 0x8f, 0xe5, 0xb4, 0x0c, 0xf5, 0x04, 0x4d, 0x3c, 0xce, 0xbc, 0xd2, 0x79,
0x15, 0xd9, 0x28, 0xf4, 0x23, 0x56, 0x77, 0x9f, 0x38, 0x64, 0x3e, 0x03, 0x88, 0x92, 0x04, 0x26,
0x76, 0xb9, 0xb5, 0xdf, 0x19, 0xd0, 0x78, 0x4b, 0x7a, 0x60, 0x40, 0x23, 0x91, 0xf1, 0x15, 0x22,
0x2b, 0xb4, 0xe7, 0x02, 0x54, 0xa9, 0x16, 0x21, 0x5b, 0x60, 0x96, 0xa9, 0x5c,
]; ];
const CERT_2_LEN_BUFFER: [u8; 4] = [0xfd, 0x04, 0x00, 0x00]; const CERT_2_LEN_BUFFER: [u8; 4] = [0xfd, 0x04, 0x00, 0x00];
const PADDING_BUFFER: [u8; 16] = [ const PADDING_BUFFER: [u8; 16] = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // padding
0x00, // padding
]; ];
const SCOPE_BUFFER_WITH_COUNT: [u8; 22] = [ const SCOPE_BUFFER_WITH_COUNT: [u8; 22] = [
0x01, 0x00, 0x00, 0x00, // scope count 0x01, 0x00, 0x00, 0x00, // scope count
0x0e, 0x00, 0x0e, 0x00, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e, 0x63, 0x6f, 0x0e, 0x00, 0x0e, 0x00, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e, 0x63, 0x6f, 0x6d,
0x6d, 0x00, // scope list 0x00, // scope list
]; ];
const MAGIC: [u8; 4] = [0x52, 0x53, 0x41, 0x31]; const MAGIC: [u8; 4] = [0x52, 0x53, 0x41, 0x31];
@ -192,11 +168,10 @@ const DATALEN: [u8; 4] = [0x3f, 0x00, 0x00, 0x00];
const PUB_EXP: [u8; 4] = [0x01, 0x00, 0x01, 0x00]; const PUB_EXP: [u8; 4] = [0x01, 0x00, 0x01, 0x00];
const MODULUS: [u8; 72] = [ const MODULUS: [u8; 72] = [
0xcb, 0x81, 0xfe, 0xba, 0x6d, 0x61, 0xc3, 0x55, 0x05, 0xd5, 0x5f, 0x2e, 0x87, 0xf8, 0x71, 0x94, 0xcb, 0x81, 0xfe, 0xba, 0x6d, 0x61, 0xc3, 0x55, 0x05, 0xd5, 0x5f, 0x2e, 0x87, 0xf8, 0x71, 0x94, 0xd6, 0xf1, 0xa5,
0xd6, 0xf1, 0xa5, 0xcb, 0xf1, 0x5f, 0x0c, 0x3d, 0xf8, 0x70, 0x02, 0x96, 0xc4, 0xfb, 0x9b, 0xc8, 0xcb, 0xf1, 0x5f, 0x0c, 0x3d, 0xf8, 0x70, 0x02, 0x96, 0xc4, 0xfb, 0x9b, 0xc8, 0x3c, 0x2d, 0x55, 0xae, 0xe8, 0xff,
0x3c, 0x2d, 0x55, 0xae, 0xe8, 0xff, 0x32, 0x75, 0xea, 0x68, 0x79, 0xe5, 0xa2, 0x01, 0xfd, 0x31, 0x32, 0x75, 0xea, 0x68, 0x79, 0xe5, 0xa2, 0x01, 0xfd, 0x31, 0xa0, 0xb1, 0x1f, 0x55, 0xa6, 0x1f, 0xc1, 0xf6, 0xd1,
0xa0, 0xb1, 0x1f, 0x55, 0xa6, 0x1f, 0xc1, 0xf6, 0xd1, 0x83, 0x88, 0x63, 0x26, 0x56, 0x12, 0xbc, 0x83, 0x88, 0x63, 0x26, 0x56, 0x12, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
const CERT_HEADER_WITH_PARTIAL_RSA: [u8; 32] = [ const CERT_HEADER_WITH_PARTIAL_RSA: [u8; 32] = [
@ -204,16 +179,15 @@ const CERT_HEADER_WITH_PARTIAL_RSA: [u8; 32] = [
0x01, 0x00, 0x00, 0x00, // dwkeyal 0x01, 0x00, 0x00, 0x00, // dwkeyal
0x06, 0x00, // blob type 0x06, 0x00, // blob type
0x5c, 0x00, // len 0x5c, 0x00, // len
0x52, 0x53, 0x41, 0x31, 0x48, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x52, 0x53, 0x41, 0x31, 0x48, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
0x01, 0x00, 0x01, 0x00, // rsa without modulus 0x00, // rsa without modulus
]; ];
const SIGNATURE: [u8; 72] = [ const SIGNATURE: [u8; 72] = [
0xe9, 0xe1, 0xd6, 0x28, 0x46, 0x8b, 0x4e, 0xf5, 0x0a, 0xdf, 0xfd, 0xee, 0x21, 0x99, 0xac, 0xb4, 0xe9, 0xe1, 0xd6, 0x28, 0x46, 0x8b, 0x4e, 0xf5, 0x0a, 0xdf, 0xfd, 0xee, 0x21, 0x99, 0xac, 0xb4, 0xe1, 0x8f, 0x5f,
0xe1, 0x8f, 0x5f, 0x81, 0x57, 0x82, 0xef, 0x9d, 0x96, 0x52, 0x63, 0x27, 0x18, 0x29, 0xdb, 0xb3, 0x81, 0x57, 0x82, 0xef, 0x9d, 0x96, 0x52, 0x63, 0x27, 0x18, 0x29, 0xdb, 0xb3, 0x4a, 0xfd, 0x9a, 0xda, 0x42, 0xad,
0x4a, 0xfd, 0x9a, 0xda, 0x42, 0xad, 0xb5, 0x69, 0x21, 0x89, 0x0e, 0x1d, 0xc0, 0x4c, 0x1a, 0xa8, 0xb5, 0x69, 0x21, 0x89, 0x0e, 0x1d, 0xc0, 0x4c, 0x1a, 0xa8, 0xaa, 0x71, 0x3e, 0x0f, 0x54, 0xb9, 0x9a, 0xe4, 0x99,
0xaa, 0x71, 0x3e, 0x0f, 0x54, 0xb9, 0x9a, 0xe4, 0x99, 0x68, 0x3f, 0x6c, 0xd6, 0x76, 0x84, 0x61, 0x68, 0x3f, 0x6c, 0xd6, 0x76, 0x84, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
const SIGNATURE_BLOB_HEADER: [u8; 4] = [ const SIGNATURE_BLOB_HEADER: [u8; 4] = [
@ -226,8 +200,8 @@ const SERVER_CERTIFICATE_HEADER_BUFFER: [u8; 4] = [
]; ];
const SCOPE_BUFFER: [u8; 18] = [ const SCOPE_BUFFER: [u8; 18] = [
0x0e, 0x00, 0x0e, 0x00, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e, 0x63, 0x6f, 0x0e, 0x00, 0x0e, 0x00, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e, 0x63, 0x6f, 0x6d,
0x6d, 0x00, // scope array 0x00, // scope array
]; ];
lazy_static! { lazy_static! {
@ -257,10 +231,7 @@ lazy_static! {
server_certificate: Some(ServerCertificate { server_certificate: Some(ServerCertificate {
issued_permanently: true, issued_permanently: true,
certificate: CertificateType::X509(X509CertificateChain { certificate: CertificateType::X509(X509CertificateChain {
certificate_array: vec![ certificate_array: vec![Vec::from(CERT_1_BUFFER.as_ref()), Vec::from(CERT_2_BUFFER.as_ref()),],
Vec::from(CERT_1_BUFFER.as_ref()),
Vec::from(CERT_2_BUFFER.as_ref()),
],
}), }),
}), }),
scope_list: vec![Scope(String::from("microsoft.com"))], scope_list: vec![Scope(String::from("microsoft.com"))],
@ -268,18 +239,12 @@ lazy_static! {
pub static ref X509_CERTIFICATE: ServerCertificate = ServerCertificate { pub static ref X509_CERTIFICATE: ServerCertificate = ServerCertificate {
issued_permanently: true, issued_permanently: true,
certificate: CertificateType::X509(X509CertificateChain { certificate: CertificateType::X509(X509CertificateChain {
certificate_array: vec![ certificate_array: vec![Vec::from(CERT_1_BUFFER.as_ref()), Vec::from(CERT_2_BUFFER.as_ref()),],
Vec::from(CERT_1_BUFFER.as_ref()),
Vec::from(CERT_2_BUFFER.as_ref()),
],
}), }),
}; };
pub static ref SCOPE: Scope = Scope(String::from("microsoft.com")); pub static ref SCOPE: Scope = Scope(String::from("microsoft.com"));
static ref CERT_CHAIN: X509CertificateChain = X509CertificateChain { static ref CERT_CHAIN: X509CertificateChain = X509CertificateChain {
certificate_array: vec![ certificate_array: vec![Vec::from(CERT_1_BUFFER.as_ref()), Vec::from(CERT_2_BUFFER.as_ref()),],
Vec::from(CERT_1_BUFFER.as_ref()),
Vec::from(CERT_2_BUFFER.as_ref()),
],
}; };
} }
@ -364,10 +329,7 @@ fn to_buffer_correctly_serializes_server_license_request() {
server_certificate: Some(ServerCertificate { server_certificate: Some(ServerCertificate {
issued_permanently: true, issued_permanently: true,
certificate: CertificateType::X509(X509CertificateChain { certificate: CertificateType::X509(X509CertificateChain {
certificate_array: vec![ certificate_array: vec![Vec::from(CERT_1_BUFFER.as_ref()), Vec::from(CERT_2_BUFFER.as_ref())],
Vec::from(CERT_1_BUFFER.as_ref()),
Vec::from(CERT_2_BUFFER.as_ref()),
],
}), }),
}), }),
scope_list: vec![Scope(String::from("microsoft.com"))], scope_list: vec![Scope(String::from("microsoft.com"))],
@ -410,10 +372,7 @@ fn from_buffer_correctly_parses_rsa_public_key() {
] ]
.concat(); .concat();
assert_eq!( assert_eq!(*PUBLIC_KEY, RsaPublicKey::from_buffer(&mut buffer.as_slice()).unwrap());
*PUBLIC_KEY,
RsaPublicKey::from_buffer(&mut buffer.as_slice()).unwrap()
);
} }
#[test] #[test]
@ -436,10 +395,7 @@ fn to_buffer_correctly_serializes_rsa_public_key() {
#[test] #[test]
fn buffer_length_is_correct_for_rsa_public_key() { fn buffer_length_is_correct_for_rsa_public_key() {
assert_eq!( assert_eq!(PUBLIC_KEY.buffer_length(), RSA_KEY_SIZE_WITHOUT_MODULUS + MODULUS.len());
PUBLIC_KEY.buffer_length(),
RSA_KEY_SIZE_WITHOUT_MODULUS + MODULUS.len()
);
} }
#[test] #[test]
@ -469,9 +425,7 @@ fn to_buffer_correctly_serializes_proprietary_certificate() {
.concat(); .concat();
let mut serialized_certificate = Vec::new(); let mut serialized_certificate = Vec::new();
PROPRIETARY_CERTIFICATE PROPRIETARY_CERTIFICATE.to_buffer(&mut serialized_certificate).unwrap();
.to_buffer(&mut serialized_certificate)
.unwrap();
assert_eq!(serialized_certificate, certificate_buffer); assert_eq!(serialized_certificate, certificate_buffer);
} }
@ -485,10 +439,7 @@ fn buffer_length_is_correct_for_proprietary_certificate() {
assert_eq!( assert_eq!(
certificate.buffer_length(), certificate.buffer_length(),
PUBLIC_KEY.buffer_length() PUBLIC_KEY.buffer_length() + SIGNATURE.len() + PROP_CERT_NO_BLOBS_SIZE + PROP_CERT_BLOBS_HEADERS_SIZE
+ SIGNATURE.len()
+ PROP_CERT_NO_BLOBS_SIZE
+ PROP_CERT_BLOBS_HEADERS_SIZE
); );
} }
@ -529,23 +480,20 @@ fn buffer_length_is_correct_for_product_information() {
#[test] #[test]
fn get_public_key_correctly_gets_key_from_server_certificate() { fn get_public_key_correctly_gets_key_from_server_certificate() {
let public_key: [u8; 270] = [ let public_key: [u8; 270] = [
0x30, 0x82, 0x1, 0xa, 0x2, 0x82, 0x1, 0x1, 0x0, 0xc8, 0x90, 0x6b, 0xf0, 0xc6, 0x58, 0x81, 0x30, 0x82, 0x1, 0xa, 0x2, 0x82, 0x1, 0x1, 0x0, 0xc8, 0x90, 0x6b, 0xf0, 0xc6, 0x58, 0x81, 0xa6, 0x89, 0x1c,
0xa6, 0x89, 0x1c, 0xe, 0xf2, 0xf6, 0xd9, 0x82, 0x12, 0x71, 0xa5, 0x6e, 0x51, 0xdb, 0xe0, 0xe, 0xf2, 0xf6, 0xd9, 0x82, 0x12, 0x71, 0xa5, 0x6e, 0x51, 0xdb, 0xe0, 0x32, 0x66, 0xaa, 0x91, 0x77, 0xe, 0x88,
0x32, 0x66, 0xaa, 0x91, 0x77, 0xe, 0x88, 0xab, 0x44, 0xb7, 0xd3, 0x97, 0xda, 0x78, 0x8f, 0xab, 0x44, 0xb7, 0xd3, 0x97, 0xda, 0x78, 0x8f, 0xe, 0x44, 0x26, 0x46, 0x7f, 0x16, 0xd4, 0xc6, 0x63, 0xeb,
0xe, 0x44, 0x26, 0x46, 0x7f, 0x16, 0xd4, 0xc6, 0x63, 0xeb, 0xca, 0x55, 0xe5, 0x4e, 0x8b, 0xca, 0x55, 0xe5, 0x4e, 0x8b, 0x2d, 0xa6, 0x6d, 0x83, 0x95, 0xa7, 0xa8, 0x6a, 0xfa, 0xd0, 0xbe, 0x26, 0x80,
0x2d, 0xa6, 0x6d, 0x83, 0x95, 0xa7, 0xa8, 0x6a, 0xfa, 0xd0, 0xbe, 0x26, 0x80, 0xae, 0xab, 0xae, 0xab, 0xa, 0x64, 0x90, 0x32, 0x8c, 0xdf, 0x5c, 0xf8, 0xf9, 0xd0, 0x7e, 0xd1, 0x6b, 0x3a, 0x29, 0x7e,
0xa, 0x64, 0x90, 0x32, 0x8c, 0xdf, 0x5c, 0xf8, 0xf9, 0xd0, 0x7e, 0xd1, 0x6b, 0x3a, 0x29, 0x7d, 0xbd, 0x2, 0xa3, 0x86, 0x6c, 0xfd, 0xa5, 0x35, 0x71, 0xda, 0x21, 0xb4, 0xee, 0xa4, 0x97, 0xf3, 0xa8,
0x7e, 0x7d, 0xbd, 0x2, 0xa3, 0x86, 0x6c, 0xfd, 0xa5, 0x35, 0x71, 0xda, 0x21, 0xb4, 0xee, 0xb2, 0x12, 0xdb, 0xa4, 0x27, 0x57, 0x36, 0xc9, 0x8, 0x22, 0x5c, 0x54, 0xf7, 0x99, 0x7b, 0xa3, 0x2f, 0xb8,
0xa4, 0x97, 0xf3, 0xa8, 0xb2, 0x12, 0xdb, 0xa4, 0x27, 0x57, 0x36, 0xc9, 0x8, 0x22, 0x5c, 0x5c, 0xd5, 0x16, 0xb8, 0x19, 0x27, 0x6b, 0x71, 0x97, 0x14, 0x5b, 0xe8, 0x1f, 0x23, 0xe8, 0x5c, 0xb8, 0x1b,
0x54, 0xf7, 0x99, 0x7b, 0xa3, 0x2f, 0xb8, 0x5c, 0xd5, 0x16, 0xb8, 0x19, 0x27, 0x6b, 0x71, 0x73, 0x4b, 0x6e, 0x7a, 0x3, 0x13, 0xff, 0x97, 0xe9, 0x62, 0xb9, 0x4a, 0xa0, 0x51, 0x23, 0xc3, 0x6c, 0x32,
0x97, 0x14, 0x5b, 0xe8, 0x1f, 0x23, 0xe8, 0x5c, 0xb8, 0x1b, 0x73, 0x4b, 0x6e, 0x7a, 0x3, 0x3e, 0x2, 0xf2, 0x63, 0x97, 0x23, 0x1c, 0xc5, 0x78, 0xd8, 0xfc, 0xb7, 0x7, 0x4b, 0xb0, 0x56, 0xf, 0x74, 0xdf,
0x13, 0xff, 0x97, 0xe9, 0x62, 0xb9, 0x4a, 0xa0, 0x51, 0x23, 0xc3, 0x6c, 0x32, 0x3e, 0x2, 0xc5, 0x56, 0x28, 0xe4, 0x96, 0xfd, 0x20, 0x8e, 0x65, 0x5a, 0xe6, 0x45, 0xed, 0xc1, 0x5, 0x3e, 0xab, 0x58,
0xf2, 0x63, 0x97, 0x23, 0x1c, 0xc5, 0x78, 0xd8, 0xfc, 0xb7, 0x7, 0x4b, 0xb0, 0x56, 0xf, 0x55, 0x40, 0xaf, 0xe2, 0x47, 0xa0, 0x4c, 0x49, 0xa3, 0x8d, 0x39, 0xe3, 0x66, 0x5f, 0x93, 0x33, 0x6d, 0xf8,
0x74, 0xdf, 0xc5, 0x56, 0x28, 0xe4, 0x96, 0xfd, 0x20, 0x8e, 0x65, 0x5a, 0xe6, 0x45, 0xed, 0x5f, 0xc5, 0x54, 0xe5, 0xfb, 0x57, 0x3a, 0xde, 0x45, 0x12, 0xb5, 0xc7, 0x5, 0x4b, 0x88, 0x1f, 0xb4, 0x35, 0xf,
0xc1, 0x5, 0x3e, 0xab, 0x58, 0x55, 0x40, 0xaf, 0xe2, 0x47, 0xa0, 0x4c, 0x49, 0xa3, 0x8d, 0x7c, 0xc0, 0x75, 0x17, 0xc6, 0x67, 0xdd, 0x48, 0x80, 0xcb, 0xa, 0xbe, 0x9d, 0xf6, 0x93, 0x60, 0x65, 0x34,
0x39, 0xe3, 0x66, 0x5f, 0x93, 0x33, 0x6d, 0xf8, 0x5f, 0xc5, 0x54, 0xe5, 0xfb, 0x57, 0x3a,
0xde, 0x45, 0x12, 0xb5, 0xc7, 0x5, 0x4b, 0x88, 0x1f, 0xb4, 0x35, 0xf, 0x7c, 0xc0, 0x75,
0x17, 0xc6, 0x67, 0xdd, 0x48, 0x80, 0xcb, 0xa, 0xbe, 0x9d, 0xf6, 0x93, 0x60, 0x65, 0x34,
0xeb, 0x97, 0xaf, 0x65, 0x6d, 0xdf, 0xbf, 0x6f, 0x5b, 0x2, 0x3, 0x1, 0x0, 0x1, 0xeb, 0x97, 0xaf, 0x65, 0x6d, 0xdf, 0xbf, 0x6f, 0x5b, 0x2, 0x3, 0x1, 0x0, 0x1,
]; ];
@ -586,9 +534,7 @@ fn to_buffer_correctly_serializes_server_certificate() {
.concat(); .concat();
let mut serialized_certificate = Vec::new(); let mut serialized_certificate = Vec::new();
X509_CERTIFICATE X509_CERTIFICATE.to_buffer(&mut serialized_certificate).unwrap();
.to_buffer(&mut serialized_certificate)
.unwrap();
assert_eq!(serialized_certificate, certificate_buffer); assert_eq!(serialized_certificate, certificate_buffer);
} }
@ -610,10 +556,7 @@ fn buffer_length_is_correct_for_server_certificate() {
#[test] #[test]
fn from_buffer_correctly_parses_scope() { fn from_buffer_correctly_parses_scope() {
assert_eq!( assert_eq!(*SCOPE, Scope::from_buffer(&mut SCOPE_BUFFER.as_ref()).unwrap());
*SCOPE,
Scope::from_buffer(&mut SCOPE_BUFFER.as_ref()).unwrap()
);
} }
#[test] #[test]

View file

@ -6,8 +6,8 @@ use std::io;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use super::{ use super::{
read_license_header, BlobHeader, BlobType, LicenseHeader, PreambleType, ServerLicenseError, read_license_header, BlobHeader, BlobType, LicenseHeader, PreambleType, ServerLicenseError, BLOB_LENGTH_SIZE,
BLOB_LENGTH_SIZE, BLOB_TYPE_SIZE, MAC_SIZE, BLOB_TYPE_SIZE, MAC_SIZE,
}; };
use crate::PduParsing; use crate::PduParsing;
@ -48,8 +48,7 @@ impl PduParsing for ServerPlatformChallenge {
stream.write_u32::<LittleEndian>(0)?; // connect_flags, ignored stream.write_u32::<LittleEndian>(0)?; // connect_flags, ignored
BlobHeader::new(BlobType::Any, self.encrypted_platform_challenge.len()) BlobHeader::new(BlobType::Any, self.encrypted_platform_challenge.len()).write_to_buffer(&mut stream)?;
.write_to_buffer(&mut stream)?;
stream.write_all(&self.encrypted_platform_challenge)?; stream.write_all(&self.encrypted_platform_challenge)?;
stream.write_all(&self.mac_data)?; stream.write_all(&self.mac_data)?;

View file

@ -1,11 +1,10 @@
use lazy_static::lazy_static;
use super::*; use super::*;
use crate::rdp::server_license::{ use crate::rdp::server_license::{
BasicSecurityHeader, BasicSecurityHeaderFlags, PreambleFlags, PreambleVersion, BasicSecurityHeader, BasicSecurityHeaderFlags, PreambleFlags, PreambleVersion, BASIC_SECURITY_HEADER_SIZE,
BASIC_SECURITY_HEADER_SIZE,
}; };
use lazy_static::lazy_static;
const PLATFORM_CHALLENGE_BUFFER: [u8; 42] = [ const PLATFORM_CHALLENGE_BUFFER: [u8; 42] = [
0x80, 0x00, // flags 0x80, 0x00, // flags
0x00, 0x00, // flagsHi 0x00, 0x00, // flagsHi
@ -14,8 +13,7 @@ const PLATFORM_CHALLENGE_BUFFER: [u8; 42] = [
0x00, 0x00, // ignored 0x00, 0x00, // ignored
0x0a, 0x00, // blob len 0x0a, 0x00, // blob len
0x46, 0x37, 0x85, 0x54, 0x8e, 0xc5, 0x91, 0x34, 0x97, 0x5d, // challenge 0x46, 0x37, 0x85, 0x54, 0x8e, 0xc5, 0x91, 0x34, 0x97, 0x5d, // challenge
0x38, 0x23, 0x62, 0x5d, 0x10, 0x8b, 0x93, 0xc3, 0xf1, 0xe4, 0x67, 0x1f, 0x4a, 0xb6, 0x00, 0x38, 0x23, 0x62, 0x5d, 0x10, 0x8b, 0x93, 0xc3, 0xf1, 0xe4, 0x67, 0x1f, 0x4a, 0xb6, 0x00, 0x0a, // mac data
0x0a, // mac data
]; ];
const CHALLENGE_BUFFER: [u8; 10] = [ const CHALLENGE_BUFFER: [u8; 10] = [
@ -23,8 +21,7 @@ const CHALLENGE_BUFFER: [u8; 10] = [
]; ];
const MAC_DATA_BUFFER: [u8; MAC_SIZE] = [ const MAC_DATA_BUFFER: [u8; MAC_SIZE] = [
0x38, 0x23, 0x62, 0x5d, 0x10, 0x8b, 0x93, 0xc3, 0xf1, 0xe4, 0x67, 0x1f, 0x4a, 0xb6, 0x00, 0x38, 0x23, 0x62, 0x5d, 0x10, 0x8b, 0x93, 0xc3, 0xf1, 0xe4, 0x67, 0x1f, 0x4a, 0xb6, 0x00, 0x0a, // mac data
0x0a, // mac data
]; ];
lazy_static! { lazy_static! {
@ -36,8 +33,7 @@ lazy_static! {
preamble_message_type: PreambleType::PlatformChallenge, preamble_message_type: PreambleType::PlatformChallenge,
preamble_flags: PreambleFlags::empty(), preamble_flags: PreambleFlags::empty(),
preamble_version: PreambleVersion::V3, preamble_version: PreambleVersion::V3,
preamble_message_size: (PLATFORM_CHALLENGE_BUFFER.len() - BASIC_SECURITY_HEADER_SIZE) preamble_message_size: (PLATFORM_CHALLENGE_BUFFER.len() - BASIC_SECURITY_HEADER_SIZE) as u16,
as u16,
}, },
encrypted_platform_challenge: Vec::from(CHALLENGE_BUFFER.as_ref()), encrypted_platform_challenge: Vec::from(CHALLENGE_BUFFER.as_ref()),
mac_data: Vec::from(MAC_DATA_BUFFER.as_ref()), mac_data: Vec::from(MAC_DATA_BUFFER.as_ref()),
@ -67,8 +63,5 @@ fn to_buffer_correctly_serializes_server_platform_challenge() {
#[test] #[test]
fn buffer_length_is_correct_for_server_platform_challenge() { fn buffer_length_is_correct_for_server_platform_challenge() {
assert_eq!( assert_eq!(PLATFORM_CHALLENGE_BUFFER.len(), PLATFORM_CHALLENGE.buffer_length());
PLATFORM_CHALLENGE_BUFFER.len(),
PLATFORM_CHALLENGE.buffer_length()
);
} }

View file

@ -6,15 +6,12 @@ use std::io;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use super::{ use super::{
read_license_header, BlobHeader, BlobType, LicenseEncryptionData, LicenseHeader, PreambleType, read_license_header, BlobHeader, BlobType, LicenseEncryptionData, LicenseHeader, PreambleType, ServerLicenseError,
ServerLicenseError, BLOB_LENGTH_SIZE, BLOB_TYPE_SIZE, MAC_SIZE, UTF16_NULL_TERMINATOR_SIZE, BLOB_LENGTH_SIZE, BLOB_TYPE_SIZE, MAC_SIZE, UTF16_NULL_TERMINATOR_SIZE, UTF8_NULL_TERMINATOR_SIZE,
UTF8_NULL_TERMINATOR_SIZE,
};
use crate::{
utils,
utils::{rc4::Rc4, CharacterSet},
PduParsing,
}; };
use crate::utils::rc4::Rc4;
use crate::utils::CharacterSet;
use crate::{utils, PduParsing};
const NEW_LICENSE_INFO_STATIC_FIELDS_SIZE: usize = 20; const NEW_LICENSE_INFO_STATIC_FIELDS_SIZE: usize = 20;
@ -26,16 +23,11 @@ pub struct ServerUpgradeLicense {
} }
impl ServerUpgradeLicense { impl ServerUpgradeLicense {
pub fn verify_server_license( pub fn verify_server_license(&self, encryption_data: &LicenseEncryptionData) -> Result<(), ServerLicenseError> {
&self,
encryption_data: &LicenseEncryptionData,
) -> Result<(), ServerLicenseError> {
let mut rc4 = Rc4::new(encryption_data.license_key.as_slice()); let mut rc4 = Rc4::new(encryption_data.license_key.as_slice());
let decrypted_license_info = rc4.process(self.encrypted_license_info.as_slice()); let decrypted_license_info = rc4.process(self.encrypted_license_info.as_slice());
let mac_data = super::compute_mac_data( let mac_data =
encryption_data.mac_salt_key.as_slice(), super::compute_mac_data(encryption_data.mac_salt_key.as_slice(), decrypted_license_info.as_ref());
decrypted_license_info.as_ref(),
);
if mac_data != self.mac_data { if mac_data != self.mac_data {
return Err(ServerLicenseError::InvalidMacData); return Err(ServerLicenseError::InvalidMacData);
@ -62,8 +54,7 @@ impl PduParsing for ServerUpgradeLicense {
))); )));
} }
let encrypted_license_info_blob = let encrypted_license_info_blob = BlobHeader::read_from_buffer(BlobType::EncryptedData, &mut stream)?;
BlobHeader::read_from_buffer(BlobType::EncryptedData, &mut stream)?;
let mut encrypted_license_info = vec![0u8; encrypted_license_info_blob.length as usize]; let mut encrypted_license_info = vec![0u8; encrypted_license_info_blob.length as usize];
stream.read_exact(&mut encrypted_license_info)?; stream.read_exact(&mut encrypted_license_info)?;
@ -81,8 +72,7 @@ impl PduParsing for ServerUpgradeLicense {
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> { fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
self.license_header.to_buffer(&mut stream)?; self.license_header.to_buffer(&mut stream)?;
BlobHeader::new(BlobType::EncryptedData, self.encrypted_license_info.len()) BlobHeader::new(BlobType::EncryptedData, self.encrypted_license_info.len()).write_to_buffer(&mut stream)?;
.write_to_buffer(&mut stream)?;
stream.write_all(&self.encrypted_license_info)?; stream.write_all(&self.encrypted_license_info)?;
stream.write_all(&self.mac_data)?; stream.write_all(&self.mac_data)?;
@ -157,23 +147,11 @@ impl PduParsing for NewLicenseInformation {
stream.write_u32::<LittleEndian>((self.scope.len() + UTF8_NULL_TERMINATOR_SIZE) as u32)?; stream.write_u32::<LittleEndian>((self.scope.len() + UTF8_NULL_TERMINATOR_SIZE) as u32)?;
utils::write_string_with_null_terminator(&mut stream, &self.scope, CharacterSet::Ansi)?; utils::write_string_with_null_terminator(&mut stream, &self.scope, CharacterSet::Ansi)?;
stream.write_u32::<LittleEndian>( stream.write_u32::<LittleEndian>((self.company_name.len() * 2 + UTF16_NULL_TERMINATOR_SIZE) as u32)?;
(self.company_name.len() * 2 + UTF16_NULL_TERMINATOR_SIZE) as u32, utils::write_string_with_null_terminator(&mut stream, &self.company_name, CharacterSet::Unicode)?;
)?;
utils::write_string_with_null_terminator(
&mut stream,
&self.company_name,
CharacterSet::Unicode,
)?;
stream.write_u32::<LittleEndian>( stream.write_u32::<LittleEndian>((self.product_id.len() * 2 + UTF16_NULL_TERMINATOR_SIZE) as u32)?;
(self.product_id.len() * 2 + UTF16_NULL_TERMINATOR_SIZE) as u32, utils::write_string_with_null_terminator(&mut stream, &self.product_id, CharacterSet::Unicode)?;
)?;
utils::write_string_with_null_terminator(
&mut stream,
&self.product_id,
CharacterSet::Unicode,
)?;
stream.write_u32::<LittleEndian>(self.license_info.len() as u32)?; stream.write_u32::<LittleEndian>(self.license_info.len() as u32)?;
stream.write_all(self.license_info.as_slice())?; stream.write_all(self.license_info.as_slice())?;

Some files were not shown because too many files have changed in this diff Show more