mirror of
https://github.com/Devolutions/IronRDP.git
synced 2025-07-24 18:03:45 +00:00
refactor(dvc): switch to PduEncode/Decode
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
parent
ed963cefb6
commit
b0dd0677a4
18 changed files with 1550 additions and 1309 deletions
|
@ -9,7 +9,7 @@ use core::fmt;
|
|||
use ironrdp_pdu as pdu;
|
||||
|
||||
use ironrdp_svc::{impl_as_any, CompressionCondition, SvcClientProcessor, SvcMessage, SvcProcessor};
|
||||
use pdu::cursor::WriteCursor;
|
||||
use pdu::cursor::{ReadCursor, WriteCursor};
|
||||
use pdu::gcc::ChannelName;
|
||||
use pdu::rdp::vc;
|
||||
use pdu::{decode, dvc, PduEncode, PduResult};
|
||||
|
@ -239,11 +239,11 @@ fn decode_dvc_message(user_data: &[u8]) -> PduResult<DynamicChannelCtx<'_>> {
|
|||
debug_assert_eq!(user_data_len, channel_header.length as usize);
|
||||
|
||||
// … | dvc::ServerPdu | …
|
||||
let dvc_pdu =
|
||||
vc::dvc::ServerPdu::from_buffer(user_data, user_data_len).map_err(|e| custom_err!("DVC server PDU", e))?;
|
||||
let mut cursor = ReadCursor::new(user_data);
|
||||
let dvc_pdu = vc::dvc::ServerPdu::decode(&mut cursor, user_data_len)?;
|
||||
|
||||
// … | DvcData ]
|
||||
let dvc_data = user_data;
|
||||
let dvc_data = cursor.remaining();
|
||||
|
||||
Ok(DynamicChannelCtx { dvc_pdu, dvc_data })
|
||||
}
|
||||
|
|
|
@ -5,13 +5,13 @@ use alloc::string::String;
|
|||
use alloc::vec::Vec;
|
||||
use core::any::Any;
|
||||
use core::fmt;
|
||||
use pdu::dvc::{CreateRequestPdu, DataFirstPdu, DataPdu};
|
||||
use slab::Slab;
|
||||
|
||||
use ironrdp_pdu as pdu;
|
||||
|
||||
use ironrdp_svc::{impl_as_any, ChannelFlags, CompressionCondition, SvcMessage, SvcProcessor, SvcServerProcessor};
|
||||
use pdu::cursor::WriteCursor;
|
||||
use pdu::cursor::{ReadCursor, WriteCursor};
|
||||
use pdu::dvc::{CreateRequestPdu, DataFirstPdu, DataPdu};
|
||||
use pdu::gcc::ChannelName;
|
||||
use pdu::rdp::vc;
|
||||
use pdu::write_buf::WriteBuf;
|
||||
|
@ -203,24 +203,18 @@ struct DynamicChannelCtx<'a> {
|
|||
}
|
||||
|
||||
fn decode_dvc_message(user_data: &[u8]) -> PduResult<DynamicChannelCtx<'_>> {
|
||||
let mut user_data = user_data;
|
||||
let user_data_len = user_data.len();
|
||||
|
||||
// … | dvc::ClientPdu | …
|
||||
let dvc_pdu =
|
||||
vc::dvc::ClientPdu::from_buffer(&mut user_data, user_data_len).map_err(|e| custom_err!("DVC client PDU", e))?;
|
||||
let mut cur = ReadCursor::new(user_data);
|
||||
let dvc_pdu = vc::dvc::ClientPdu::decode(&mut cur, user_data.len())?;
|
||||
|
||||
// … | DvcData ]
|
||||
let dvc_data = user_data;
|
||||
let dvc_data = cur.remaining();
|
||||
|
||||
Ok(DynamicChannelCtx { dvc_pdu, dvc_data })
|
||||
}
|
||||
|
||||
fn encode_dvc_message(pdu: vc::dvc::ServerPdu) -> PduResult<SvcMessage> {
|
||||
// FIXME: use PduEncode instead
|
||||
let mut buf = Vec::new();
|
||||
pdu.to_buffer(&mut buf).map_err(|e| custom_err!("DVC server pdu", e))?;
|
||||
Ok(SvcMessage::from(buf).with_flags(ChannelFlags::SHOW_PROTOCOL))
|
||||
Ok(SvcMessage::from(pdu).with_flags(ChannelFlags::SHOW_PROTOCOL))
|
||||
}
|
||||
|
||||
fn encode_dvc_data(channel_id: u32, messages: DvcMessages) -> PduResult<Vec<SvcMessage>> {
|
||||
|
@ -245,8 +239,7 @@ fn encode_dvc_data(channel_id: u32, messages: DvcMessages) -> PduResult<Vec<SvcM
|
|||
let end = off
|
||||
.checked_add(size)
|
||||
.ok_or_else(|| other_err!("encode_dvc_data", "overflow occurred"))?;
|
||||
let mut data = Vec::new();
|
||||
pdu.to_buffer(&mut data).map_err(|e| custom_err!("DVC server pdu", e))?;
|
||||
let mut data = encode_vec(&pdu)?;
|
||||
data.extend_from_slice(&msg[off..end]);
|
||||
res.push(SvcMessage::from(data).with_flags(ChannelFlags::SHOW_PROTOCOL));
|
||||
off = end;
|
||||
|
|
|
@ -28,7 +28,7 @@ pub use self::core_data::server::{ServerCoreData, ServerCoreOptionalData, Server
|
|||
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,
|
||||
ClientMonitorData, Monitor, MonitorFlags, MONITOR_COUNT_SIZE, MONITOR_FLAGS_SIZE, MONITOR_SIZE,
|
||||
};
|
||||
pub use self::monitor_extended_data::{
|
||||
ClientMonitorExtendedData, ExtendedMonitorInfo, MonitorExtendedDataError, MonitorOrientation,
|
||||
|
@ -379,8 +379,6 @@ pub enum GccError {
|
|||
NetworkError(#[from] NetworkDataError),
|
||||
#[error("cluster data block error")]
|
||||
ClusterError(#[from] ClusterDataError),
|
||||
#[error("monitor data block error")]
|
||||
MonitorError(#[from] MonitorDataError),
|
||||
#[error("multi-transport channel data block error")]
|
||||
MultiTransportChannelError(#[from] MultiTransportChannelDataError),
|
||||
#[error("monitor extended data block error")]
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
use std::io;
|
||||
|
||||
use bitflags::bitflags;
|
||||
use byteorder::{LittleEndian, ReadBytesExt as _, WriteBytesExt as _};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::{PduError, PduParsing};
|
||||
use crate::cursor::{ReadCursor, WriteCursor};
|
||||
use crate::{PduDecode, PduEncode, PduResult};
|
||||
|
||||
pub const MONITOR_COUNT_SIZE: usize = 4;
|
||||
pub const MONITOR_SIZE: usize = 20;
|
||||
|
@ -17,40 +14,57 @@ pub struct ClientMonitorData {
|
|||
pub monitors: Vec<Monitor>,
|
||||
}
|
||||
|
||||
impl PduParsing for ClientMonitorData {
|
||||
type Error = MonitorDataError;
|
||||
impl ClientMonitorData {
|
||||
const NAME: &'static str = "ClientMonitorData";
|
||||
|
||||
fn from_buffer(mut buffer: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let _flags = buffer.read_u32::<LittleEndian>()?; // is unused
|
||||
let monitor_count = buffer.read_u32::<LittleEndian>()?;
|
||||
const FIXED_PART_SIZE: usize = 4 /* flags */ + 4 /* count */;
|
||||
}
|
||||
|
||||
if monitor_count > MONITOR_COUNT_MAX as u32 {
|
||||
return Err(MonitorDataError::InvalidMonitorCount);
|
||||
}
|
||||
impl PduEncode for ClientMonitorData {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_fixed_part_size!(in: dst);
|
||||
|
||||
let mut monitors = Vec::with_capacity(monitor_count as usize);
|
||||
for _ in 0..monitor_count {
|
||||
monitors.push(Monitor::from_buffer(&mut buffer)?);
|
||||
}
|
||||
|
||||
Ok(Self { monitors })
|
||||
}
|
||||
fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> {
|
||||
buffer.write_u32::<LittleEndian>(0)?; // flags
|
||||
buffer.write_u32::<LittleEndian>(self.monitors.len() as u32)?;
|
||||
dst.write_u32(0); // flags
|
||||
dst.write_u32(cast_length!("nMonitors", self.monitors.len())?);
|
||||
|
||||
for monitor in self.monitors.iter().take(MONITOR_COUNT_MAX) {
|
||||
monitor.to_buffer(&mut buffer)?;
|
||||
monitor.encode(dst)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
MONITOR_FLAGS_SIZE + MONITOR_COUNT_SIZE + self.monitors.len() * MONITOR_SIZE
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE + self.monitors.len() * Monitor::FIXED_PART_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for ClientMonitorData {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let _flags = src.read_u32(); // is unused
|
||||
let monitor_count = src.read_u32();
|
||||
|
||||
if monitor_count > MONITOR_COUNT_MAX as u32 {
|
||||
return Err(invalid_message_err!("nMonitors", "too many monitors"));
|
||||
}
|
||||
|
||||
let mut monitors = Vec::with_capacity(monitor_count as usize);
|
||||
for _ in 0..monitor_count {
|
||||
monitors.push(Monitor::decode(src)?);
|
||||
}
|
||||
|
||||
Ok(Self { monitors })
|
||||
}
|
||||
}
|
||||
|
||||
impl_pdu_parsing_max!(ClientMonitorData);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Monitor {
|
||||
pub left: i32,
|
||||
|
@ -60,16 +74,44 @@ pub struct Monitor {
|
|||
pub flags: MonitorFlags,
|
||||
}
|
||||
|
||||
impl PduParsing for Monitor {
|
||||
type Error = MonitorDataError;
|
||||
impl Monitor {
|
||||
const NAME: &'static str = "Monitor";
|
||||
|
||||
fn from_buffer(mut buffer: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let left = buffer.read_i32::<LittleEndian>()?;
|
||||
let top = buffer.read_i32::<LittleEndian>()?;
|
||||
let right = buffer.read_i32::<LittleEndian>()?;
|
||||
let bottom = buffer.read_i32::<LittleEndian>()?;
|
||||
let flags =
|
||||
MonitorFlags::from_bits(buffer.read_u32::<LittleEndian>()?).ok_or(MonitorDataError::InvalidMonitorFlags)?;
|
||||
const FIXED_PART_SIZE: usize = 4 /* left */ + 4 /* top */ + 4 /* right */ + 4 /* bottom */ + 4 /* flags */;
|
||||
}
|
||||
|
||||
impl PduEncode for Monitor {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_fixed_part_size!(in: dst);
|
||||
|
||||
dst.write_i32(self.left);
|
||||
dst.write_i32(self.top);
|
||||
dst.write_i32(self.right);
|
||||
dst.write_i32(self.bottom);
|
||||
dst.write_u32(self.flags.bits());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for Monitor {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let left = src.read_i32();
|
||||
let top = src.read_i32();
|
||||
let right = src.read_i32();
|
||||
let bottom = src.read_i32();
|
||||
let flags = MonitorFlags::from_bits(src.read_u32())
|
||||
.ok_or_else(|| invalid_message_err!("flags", "invalid monitor flags"))?;
|
||||
|
||||
Ok(Self {
|
||||
left,
|
||||
|
@ -79,41 +121,13 @@ impl PduParsing for Monitor {
|
|||
flags,
|
||||
})
|
||||
}
|
||||
fn to_buffer(&self, mut buffer: impl io::Write) -> Result<(), Self::Error> {
|
||||
buffer.write_i32::<LittleEndian>(self.left)?;
|
||||
buffer.write_i32::<LittleEndian>(self.top)?;
|
||||
buffer.write_i32::<LittleEndian>(self.right)?;
|
||||
buffer.write_i32::<LittleEndian>(self.bottom)?;
|
||||
buffer.write_u32::<LittleEndian>(self.flags.bits())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn buffer_length(&self) -> usize {
|
||||
MONITOR_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
impl_pdu_parsing!(Monitor);
|
||||
|
||||
bitflags! {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct MonitorFlags: u32 {
|
||||
const PRIMARY = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum MonitorDataError {
|
||||
#[error("IO error")]
|
||||
IOError(#[from] io::Error),
|
||||
#[error("invalid monitor count field")]
|
||||
InvalidMonitorCount,
|
||||
#[error("invalid monitor flags field")]
|
||||
InvalidMonitorFlags,
|
||||
#[error("PDU error")]
|
||||
Pdu(#[from] PduError),
|
||||
}
|
||||
|
||||
impl ironrdp_error::legacy::ErrorContext for MonitorDataError {
|
||||
fn context(&self) -> &'static str {
|
||||
"monitor data"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -199,7 +199,7 @@ impl PduEncode for MonitorLayoutPdu {
|
|||
dst.write_u32(cast_length!("nMonitors", self.monitors.len())?);
|
||||
|
||||
for monitor in self.monitors.iter() {
|
||||
crate::PduParsing::to_buffer(&monitor, &mut *dst)?;
|
||||
monitor.encode(dst)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -225,7 +225,7 @@ impl<'de> PduDecode<'de> for MonitorLayoutPdu {
|
|||
|
||||
let mut monitors = Vec::with_capacity(monitor_count as usize);
|
||||
for _ in 0..monitor_count {
|
||||
monitors.push(<gcc::Monitor as crate::PduParsing>::from_buffer(&mut *src)?);
|
||||
monitors.push(gcc::Monitor::decode(src)?);
|
||||
}
|
||||
|
||||
Ok(Self { monitors })
|
||||
|
|
|
@ -3,7 +3,7 @@ use num_derive::{FromPrimitive, ToPrimitive};
|
|||
use num_traits::{FromPrimitive, ToPrimitive};
|
||||
|
||||
use crate::cursor::{ReadCursor, WriteCursor};
|
||||
use crate::{decode_cursor, PduDecode, PduEncode, PduError, PduResult};
|
||||
use crate::{decode_cursor, PduDecode, PduEncode, PduResult};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -107,28 +107,6 @@ impl ServerPdu {
|
|||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn from_buffer(mut stream: impl std::io::Read, dvc_data_size: usize) -> Result<Self, PduError> {
|
||||
let mut buf = [0; crate::legacy::MAX_PDU_SIZE];
|
||||
let len = match stream.read(&mut buf) {
|
||||
// if not enough data is read, decode will through NotEnoughBytes
|
||||
Ok(len) => len,
|
||||
Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
|
||||
return Err(not_enough_bytes_err!(0, crate::legacy::MAX_PDU_SIZE));
|
||||
}
|
||||
Err(e) => return Err(custom_err!(e)),
|
||||
};
|
||||
let mut cur = ReadCursor::new(&buf[0..len]);
|
||||
Self::decode(&mut cur, dvc_data_size)
|
||||
}
|
||||
|
||||
pub fn to_buffer(&self, mut stream: impl std::io::Write) -> Result<(), PduError> {
|
||||
to_buffer!(self, stream, size: self.size())
|
||||
}
|
||||
|
||||
pub fn buffer_length(&self) -> usize {
|
||||
self.size()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -170,28 +148,6 @@ impl ClientPdu {
|
|||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn from_buffer(mut stream: impl std::io::Read, dvc_data_size: usize) -> Result<Self, PduError> {
|
||||
let mut buf = [0; crate::legacy::MAX_PDU_SIZE];
|
||||
let len = match stream.read(&mut buf) {
|
||||
// if not enough data is read, decode will through NotEnoughBytes
|
||||
Ok(len) => len,
|
||||
Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
|
||||
return Err(not_enough_bytes_err!(0, crate::legacy::MAX_PDU_SIZE));
|
||||
}
|
||||
Err(e) => return Err(custom_err!(e)),
|
||||
};
|
||||
let mut cur = ReadCursor::new(&buf[0..len]);
|
||||
Self::decode(&mut cur, dvc_data_size)
|
||||
}
|
||||
|
||||
pub fn to_buffer(&self, mut stream: impl std::io::Write) -> Result<(), PduError> {
|
||||
to_buffer!(self, stream, size: self.size())
|
||||
}
|
||||
|
||||
pub fn buffer_length(&self) -> usize {
|
||||
self.size()
|
||||
}
|
||||
}
|
||||
|
||||
impl PduEncode for ClientPdu {
|
||||
|
@ -316,5 +272,3 @@ impl<'de> PduDecode<'de> for Header {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl_pdu_parsing!(Header);
|
||||
|
|
|
@ -38,8 +38,6 @@ impl CapabilitiesRequestPdu {
|
|||
const FIXED_PART_SIZE: usize = HEADER_SIZE + DVC_CAPABILITIES_PAD_SIZE + DVC_CAPABILITIES_VERSION_SIZE;
|
||||
}
|
||||
|
||||
impl_pdu_parsing!(CapabilitiesRequestPdu);
|
||||
|
||||
impl PduEncode for CapabilitiesRequestPdu {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_size!(in: dst, size: self.size());
|
||||
|
@ -120,8 +118,6 @@ pub struct CapabilitiesResponsePdu {
|
|||
pub version: CapsVersion,
|
||||
}
|
||||
|
||||
impl_pdu_parsing!(CapabilitiesResponsePdu);
|
||||
|
||||
impl CapabilitiesResponsePdu {
|
||||
const NAME: &'static str = "CapabilitiesResponsePdu";
|
||||
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
use std::io;
|
||||
|
||||
use bitflags::bitflags;
|
||||
use byteorder::{LittleEndian, ReadBytesExt as _, WriteBytesExt as _};
|
||||
use num_derive::{FromPrimitive, ToPrimitive};
|
||||
use num_traits::{FromPrimitive as _, ToPrimitive as _};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::PduParsing;
|
||||
use crate::cursor::{ReadCursor, WriteCursor};
|
||||
use crate::{PduDecode, PduEncode, PduResult};
|
||||
|
||||
pub const CHANNEL_NAME: &str = "Microsoft::Windows::RDS::DisplayControl";
|
||||
|
||||
|
@ -19,13 +16,39 @@ pub struct DisplayControlCapsPdu {
|
|||
pub max_monitor_area_factorb: u32,
|
||||
}
|
||||
|
||||
impl PduParsing for DisplayControlCapsPdu {
|
||||
type Error = io::Error;
|
||||
impl DisplayControlCapsPdu {
|
||||
const NAME: &'static str = "DisplayControlCapsPdu";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let max_num_monitors = stream.read_u32::<LittleEndian>()?;
|
||||
let max_monitor_area_factora = stream.read_u32::<LittleEndian>()?;
|
||||
let max_monitor_area_factorb = stream.read_u32::<LittleEndian>()?;
|
||||
const FIXED_PART_SIZE: usize = 4 /* MaxNumMonitors */ + 4 /* MaxFactorA */ + 4 /* MaxFactorB */;
|
||||
}
|
||||
|
||||
impl PduEncode for DisplayControlCapsPdu {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_fixed_part_size!(in: dst);
|
||||
|
||||
dst.write_u32(self.max_num_monitors);
|
||||
dst.write_u32(self.max_monitor_area_factora);
|
||||
dst.write_u32(self.max_monitor_area_factorb);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for DisplayControlCapsPdu {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let max_num_monitors = src.read_u32();
|
||||
let max_monitor_area_factora = src.read_u32();
|
||||
let max_monitor_area_factorb = src.read_u32();
|
||||
|
||||
Ok(Self {
|
||||
max_num_monitors,
|
||||
|
@ -33,18 +56,6 @@ impl PduParsing for DisplayControlCapsPdu {
|
|||
max_monitor_area_factorb,
|
||||
})
|
||||
}
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
stream.write_u32::<LittleEndian>(self.max_num_monitors)?;
|
||||
stream.write_u32::<LittleEndian>(self.max_monitor_area_factora)?;
|
||||
stream.write_u32::<LittleEndian>(self.max_monitor_area_factorb)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
12
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
|
@ -79,22 +90,54 @@ pub struct Monitor {
|
|||
const MONITOR_SIZE: usize = 40;
|
||||
const MONITOR_PDU_HEADER_SIZE: usize = 8;
|
||||
|
||||
impl PduParsing for Monitor {
|
||||
type Error = io::Error;
|
||||
impl Monitor {
|
||||
const NAME: &'static str = "DisplayMonitor";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let flags = MonitorFlags::from_bits(stream.read_u32::<LittleEndian>()?)
|
||||
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Invalid monitor flags"))?;
|
||||
let left = stream.read_u32::<LittleEndian>()?;
|
||||
let top = stream.read_u32::<LittleEndian>()?;
|
||||
let width = stream.read_u32::<LittleEndian>()?;
|
||||
let height = stream.read_u32::<LittleEndian>()?;
|
||||
let physical_width = stream.read_u32::<LittleEndian>()?;
|
||||
let physical_height = stream.read_u32::<LittleEndian>()?;
|
||||
let orientation = Orientation::from_u32(stream.read_u32::<LittleEndian>()?)
|
||||
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Invalid monitor orientation"))?;
|
||||
let desktop_scale_factor = stream.read_u32::<LittleEndian>()?;
|
||||
let device_scale_factor = stream.read_u32::<LittleEndian>()?;
|
||||
const FIXED_PART_SIZE: usize = MONITOR_SIZE;
|
||||
}
|
||||
|
||||
impl PduEncode for Monitor {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_fixed_part_size!(in: dst);
|
||||
|
||||
dst.write_u32(self.flags.bits());
|
||||
dst.write_u32(self.left);
|
||||
dst.write_u32(self.top);
|
||||
dst.write_u32(self.width);
|
||||
dst.write_u32(self.height);
|
||||
dst.write_u32(self.physical_width);
|
||||
dst.write_u32(self.physical_height);
|
||||
dst.write_u32(self.orientation.to_u32().unwrap());
|
||||
dst.write_u32(self.desktop_scale_factor);
|
||||
dst.write_u32(self.device_scale_factor);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for Monitor {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let flags = MonitorFlags::from_bits_retain(src.read_u32());
|
||||
let left = src.read_u32();
|
||||
let top = src.read_u32();
|
||||
let width = src.read_u32();
|
||||
let height = src.read_u32();
|
||||
let physical_width = src.read_u32();
|
||||
let physical_height = src.read_u32();
|
||||
let orientation = Orientation::from_u32(src.read_u32())
|
||||
.ok_or_else(|| invalid_message_err!("orientation", "invalid value"))?;
|
||||
let desktop_scale_factor = src.read_u32();
|
||||
let device_scale_factor = src.read_u32();
|
||||
|
||||
Ok(Self {
|
||||
flags,
|
||||
|
@ -109,25 +152,6 @@ impl PduParsing for Monitor {
|
|||
device_scale_factor,
|
||||
})
|
||||
}
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
stream.write_u32::<LittleEndian>(self.flags.bits())?;
|
||||
stream.write_u32::<LittleEndian>(self.left)?;
|
||||
stream.write_u32::<LittleEndian>(self.top)?;
|
||||
stream.write_u32::<LittleEndian>(self.width)?;
|
||||
stream.write_u32::<LittleEndian>(self.height)?;
|
||||
stream.write_u32::<LittleEndian>(self.physical_width)?;
|
||||
stream.write_u32::<LittleEndian>(self.physical_height)?;
|
||||
stream.write_u32::<LittleEndian>(self.orientation.to_u32().unwrap())?;
|
||||
stream.write_u32::<LittleEndian>(self.desktop_scale_factor)?;
|
||||
stream.write_u32::<LittleEndian>(self.device_scale_factor)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
MONITOR_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -135,82 +159,105 @@ pub struct MonitorLayoutPdu {
|
|||
pub monitors: Vec<Monitor>,
|
||||
}
|
||||
|
||||
impl PduParsing for MonitorLayoutPdu {
|
||||
type Error = io::Error;
|
||||
impl MonitorLayoutPdu {
|
||||
const NAME: &'static str = "MonitorLayoutPdu";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let _size = stream.read_u32::<LittleEndian>()?;
|
||||
let num_monitors = stream.read_u32::<LittleEndian>()?;
|
||||
let mut monitors = Vec::new();
|
||||
for _ in 0..num_monitors {
|
||||
monitors.push(Monitor::from_buffer(&mut stream)?);
|
||||
}
|
||||
Ok(Self { monitors })
|
||||
}
|
||||
const FIXED_PART_SIZE: usize = MONITOR_PDU_HEADER_SIZE;
|
||||
}
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
stream.write_u32::<LittleEndian>(MONITOR_SIZE as u32)?;
|
||||
stream.write_u32::<LittleEndian>(self.monitors.len() as u32)?;
|
||||
impl PduEncode for MonitorLayoutPdu {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_size!(in: dst, size: self.size());
|
||||
|
||||
dst.write_u32(cast_length!("size", MONITOR_SIZE)?);
|
||||
dst.write_u32(cast_length!("len", self.monitors.len())?);
|
||||
|
||||
for monitor in &self.monitors {
|
||||
monitor.to_buffer(stream.by_ref())?;
|
||||
monitor.encode(dst)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
MONITOR_PDU_HEADER_SIZE + self.monitors.len() * MONITOR_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for MonitorLayoutPdu {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let _size = src.read_u32();
|
||||
let num_monitors = src.read_u32();
|
||||
let mut monitors = Vec::new();
|
||||
for _ in 0..num_monitors {
|
||||
monitors.push(Monitor::decode(src)?);
|
||||
}
|
||||
Ok(Self { monitors })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ServerPdu {
|
||||
DisplayControlCaps(DisplayControlCapsPdu),
|
||||
}
|
||||
|
||||
impl PduParsing for ServerPdu {
|
||||
type Error = DisplayPipelineError;
|
||||
impl ServerPdu {
|
||||
const NAME: &'static str = "DisplayServerPdu";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let pdu_type =
|
||||
ServerPduType::from_u32(stream.read_u32::<LittleEndian>()?).ok_or(DisplayPipelineError::InvalidCmdId)?;
|
||||
let pdu_length = stream.read_u32::<LittleEndian>()? as usize;
|
||||
const FIXED_PART_SIZE: usize = RDP_DISPLAY_HEADER_SIZE;
|
||||
}
|
||||
|
||||
impl PduEncode for ServerPdu {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
let size = self.size();
|
||||
|
||||
ensure_size!(in: dst, size: size);
|
||||
|
||||
dst.write_u32(ServerPduType::from(self).to_u32().unwrap());
|
||||
dst.write_u32(cast_length!("len", size)?);
|
||||
|
||||
match self {
|
||||
ServerPdu::DisplayControlCaps(pdu) => pdu.encode(dst),
|
||||
}
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
RDP_DISPLAY_HEADER_SIZE
|
||||
+ match self {
|
||||
ServerPdu::DisplayControlCaps(pdu) => pdu.size(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for ServerPdu {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let pdu_type = ServerPduType::from_u32(src.read_u32())
|
||||
.ok_or_else(|| invalid_message_err!("pduType", "invalid PDU type"))?;
|
||||
let pdu_length = src.read_u32() as usize;
|
||||
|
||||
let server_pdu = match pdu_type {
|
||||
ServerPduType::DisplayControlCaps => {
|
||||
ServerPdu::DisplayControlCaps(DisplayControlCapsPdu::from_buffer(&mut stream)?)
|
||||
}
|
||||
ServerPduType::DisplayControlCaps => ServerPdu::DisplayControlCaps(DisplayControlCapsPdu::decode(src)?),
|
||||
};
|
||||
let buffer_length = server_pdu.buffer_length();
|
||||
let actual_size = server_pdu.size();
|
||||
|
||||
if buffer_length != pdu_length {
|
||||
Err(DisplayPipelineError::InvalidPduLength {
|
||||
expected: pdu_length,
|
||||
actual: buffer_length,
|
||||
})
|
||||
if actual_size != pdu_length {
|
||||
Err(not_enough_bytes_err!(actual_size, pdu_length))
|
||||
} else {
|
||||
Ok(server_pdu)
|
||||
}
|
||||
}
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
let buffer_length = self.buffer_length();
|
||||
|
||||
stream.write_u32::<LittleEndian>(ServerPduType::from(self).to_u32().unwrap())?;
|
||||
stream.write_u32::<LittleEndian>(buffer_length as u32)?;
|
||||
|
||||
match self {
|
||||
ServerPdu::DisplayControlCaps(pdu) => pdu.to_buffer(&mut stream).map_err(DisplayPipelineError::from),
|
||||
}
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
RDP_DISPLAY_HEADER_SIZE
|
||||
+ match self {
|
||||
ServerPdu::DisplayControlCaps(pdu) => pdu.buffer_length(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
|
||||
|
@ -218,8 +265,8 @@ pub enum ServerPduType {
|
|||
DisplayControlCaps = 0x05,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ServerPdu> for ServerPduType {
|
||||
fn from(s: &'a ServerPdu) -> Self {
|
||||
impl From<&ServerPdu> for ServerPduType {
|
||||
fn from(s: &ServerPdu) -> Self {
|
||||
match s {
|
||||
ServerPdu::DisplayControlCaps(_) => Self::DisplayControlCaps,
|
||||
}
|
||||
|
@ -231,78 +278,70 @@ pub enum ClientPdu {
|
|||
DisplayControlMonitorLayout(MonitorLayoutPdu),
|
||||
}
|
||||
|
||||
impl PduParsing for ClientPdu {
|
||||
type Error = DisplayPipelineError;
|
||||
impl ClientPdu {
|
||||
const NAME: &'static str = "DisplayClientPdu";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let pdu_type =
|
||||
ClientPduType::from_u32(stream.read_u32::<LittleEndian>()?).ok_or(DisplayPipelineError::InvalidCmdId)?;
|
||||
let pdu_length = stream.read_u32::<LittleEndian>()? as usize;
|
||||
const FIXED_PART_SIZE: usize = RDP_DISPLAY_HEADER_SIZE;
|
||||
}
|
||||
|
||||
let server_pdu = match pdu_type {
|
||||
ClientPduType::DisplayControlMonitorLayout => {
|
||||
ClientPdu::DisplayControlMonitorLayout(MonitorLayoutPdu::from_buffer(&mut stream)?)
|
||||
}
|
||||
};
|
||||
let buffer_length = server_pdu.buffer_length();
|
||||
impl PduEncode for ClientPdu {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
let size = self.size();
|
||||
|
||||
if buffer_length != pdu_length {
|
||||
Err(DisplayPipelineError::InvalidPduLength {
|
||||
expected: pdu_length,
|
||||
actual: buffer_length,
|
||||
})
|
||||
} else {
|
||||
Ok(server_pdu)
|
||||
}
|
||||
}
|
||||
ensure_size!(in: dst, size: size);
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
let buffer_length = self.buffer_length();
|
||||
|
||||
stream.write_u32::<LittleEndian>(ClientPduType::from(self).to_u32().unwrap())?;
|
||||
stream.write_u32::<LittleEndian>(buffer_length as u32)?;
|
||||
dst.write_u32(ClientPduType::from(self).to_u32().unwrap());
|
||||
dst.write_u32(cast_length!("len", size)?);
|
||||
|
||||
match self {
|
||||
ClientPdu::DisplayControlMonitorLayout(pdu) => {
|
||||
pdu.to_buffer(&mut stream).map_err(DisplayPipelineError::from)
|
||||
}
|
||||
ClientPdu::DisplayControlMonitorLayout(pdu) => pdu.encode(dst),
|
||||
}
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
RDP_DISPLAY_HEADER_SIZE
|
||||
+ match self {
|
||||
ClientPdu::DisplayControlMonitorLayout(pdu) => pdu.buffer_length(),
|
||||
ClientPdu::DisplayControlMonitorLayout(pdu) => pdu.size(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for ClientPdu {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let pdu_type = ClientPduType::from_u32(src.read_u32())
|
||||
.ok_or_else(|| invalid_message_err!("pduType", "invalid PDU type"))?;
|
||||
let pdu_length = src.read_u32() as usize;
|
||||
|
||||
let client_pdu = match pdu_type {
|
||||
ClientPduType::DisplayControlMonitorLayout => {
|
||||
ClientPdu::DisplayControlMonitorLayout(MonitorLayoutPdu::decode(src)?)
|
||||
}
|
||||
};
|
||||
let actual_size = client_pdu.size();
|
||||
|
||||
if actual_size != pdu_length {
|
||||
Err(not_enough_bytes_err!(actual_size, pdu_length))
|
||||
} else {
|
||||
Ok(client_pdu)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
|
||||
pub enum ClientPduType {
|
||||
DisplayControlMonitorLayout = 0x02,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ClientPdu> for ClientPduType {
|
||||
fn from(s: &'a ClientPdu) -> Self {
|
||||
impl From<&ClientPdu> for ClientPduType {
|
||||
fn from(s: &ClientPdu) -> Self {
|
||||
match s {
|
||||
ClientPdu::DisplayControlMonitorLayout(_) => Self::DisplayControlMonitorLayout,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum DisplayPipelineError {
|
||||
#[error("IO error")]
|
||||
IOError(#[from] io::Error),
|
||||
#[error("invalid Header cmd ID")]
|
||||
InvalidCmdId,
|
||||
#[error("invalid PDU length: expected ({expected}) != actual ({actual})")]
|
||||
InvalidPduLength { expected: usize, actual: usize },
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl ironrdp_error::legacy::ErrorContext for DisplayPipelineError {
|
||||
fn context(&self) -> &'static str {
|
||||
"display pipeline"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
mod graphics_messages;
|
||||
|
||||
use std::io;
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use graphics_messages::RESET_GRAPHICS_PDU_SIZE;
|
||||
pub use graphics_messages::{
|
||||
Avc420BitmapStream, Avc444BitmapStream, CacheImportReplyPdu, CacheToSurfacePdu, CapabilitiesAdvertisePdu,
|
||||
CapabilitiesConfirmPdu, CapabilitiesV103Flags, CapabilitiesV104Flags, CapabilitiesV107Flags, CapabilitiesV10Flags,
|
||||
|
@ -15,11 +11,9 @@ pub use graphics_messages::{
|
|||
};
|
||||
use num_derive::{FromPrimitive, ToPrimitive};
|
||||
use num_traits::{FromPrimitive as _, ToPrimitive as _};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::{PduError, PduParsing};
|
||||
|
||||
const RDP_GFX_HEADER_SIZE: usize = 8;
|
||||
use crate::cursor::{ReadCursor, WriteCursor};
|
||||
use crate::{PduDecode, PduEncode, PduResult};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ServerPdu {
|
||||
|
@ -43,137 +37,125 @@ pub enum ServerPdu {
|
|||
MapSurfaceToScaledWindow(MapSurfaceToScaledWindowPdu),
|
||||
}
|
||||
|
||||
impl PduParsing for ServerPdu {
|
||||
type Error = GraphicsPipelineError;
|
||||
const RDP_GFX_HEADER_SIZE: usize = 2 /* PduType */ + 2 /* flags */ + 4 /* bufferLen */;
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let pdu_type =
|
||||
ServerPduType::from_u16(stream.read_u16::<LittleEndian>()?).ok_or(GraphicsPipelineError::InvalidCmdId)?;
|
||||
let _flags = stream.read_u16::<LittleEndian>()?;
|
||||
let pdu_length = stream.read_u32::<LittleEndian>()? as usize;
|
||||
impl ServerPdu {
|
||||
const NAME: &'static str = "GfxServerPdu";
|
||||
|
||||
if let ServerPduType::ResetGraphics = pdu_type {
|
||||
if pdu_length != RESET_GRAPHICS_PDU_SIZE {
|
||||
return Err(GraphicsPipelineError::InvalidResetGraphicsPduSize {
|
||||
expected: RESET_GRAPHICS_PDU_SIZE,
|
||||
actual: pdu_length,
|
||||
});
|
||||
}
|
||||
const FIXED_PART_SIZE: usize = RDP_GFX_HEADER_SIZE;
|
||||
}
|
||||
|
||||
impl PduEncode for ServerPdu {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_size!(in: dst, size: self.size());
|
||||
|
||||
let buffer_length = self.size();
|
||||
|
||||
dst.write_u16(ServerPduType::from(self).to_u16().unwrap());
|
||||
dst.write_u16(0); // flags
|
||||
dst.write_u32(cast_length!("bufferLen", buffer_length)?);
|
||||
|
||||
match self {
|
||||
ServerPdu::WireToSurface1(pdu) => pdu.encode(dst),
|
||||
ServerPdu::WireToSurface2(pdu) => pdu.encode(dst),
|
||||
ServerPdu::DeleteEncodingContext(pdu) => pdu.encode(dst),
|
||||
ServerPdu::SolidFill(pdu) => pdu.encode(dst),
|
||||
ServerPdu::SurfaceToSurface(pdu) => pdu.encode(dst),
|
||||
ServerPdu::SurfaceToCache(pdu) => pdu.encode(dst),
|
||||
ServerPdu::CacheToSurface(pdu) => pdu.encode(dst),
|
||||
ServerPdu::CreateSurface(pdu) => pdu.encode(dst),
|
||||
ServerPdu::DeleteSurface(pdu) => pdu.encode(dst),
|
||||
ServerPdu::ResetGraphics(pdu) => pdu.encode(dst),
|
||||
ServerPdu::MapSurfaceToOutput(pdu) => pdu.encode(dst),
|
||||
ServerPdu::MapSurfaceToScaledOutput(pdu) => pdu.encode(dst),
|
||||
ServerPdu::MapSurfaceToScaledWindow(pdu) => pdu.encode(dst),
|
||||
ServerPdu::StartFrame(pdu) => pdu.encode(dst),
|
||||
ServerPdu::EndFrame(pdu) => pdu.encode(dst),
|
||||
ServerPdu::EvictCacheEntry(pdu) => pdu.encode(dst),
|
||||
ServerPdu::CapabilitiesConfirm(pdu) => pdu.encode(dst),
|
||||
ServerPdu::CacheImportReply(pdu) => pdu.encode(dst),
|
||||
}
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE
|
||||
+ match self {
|
||||
ServerPdu::WireToSurface1(pdu) => pdu.size(),
|
||||
ServerPdu::WireToSurface2(pdu) => pdu.size(),
|
||||
ServerPdu::DeleteEncodingContext(pdu) => pdu.size(),
|
||||
ServerPdu::SolidFill(pdu) => pdu.size(),
|
||||
ServerPdu::SurfaceToSurface(pdu) => pdu.size(),
|
||||
ServerPdu::SurfaceToCache(pdu) => pdu.size(),
|
||||
ServerPdu::CacheToSurface(pdu) => pdu.size(),
|
||||
ServerPdu::CreateSurface(pdu) => pdu.size(),
|
||||
ServerPdu::DeleteSurface(pdu) => pdu.size(),
|
||||
ServerPdu::ResetGraphics(pdu) => pdu.size(),
|
||||
ServerPdu::MapSurfaceToOutput(pdu) => pdu.size(),
|
||||
ServerPdu::MapSurfaceToScaledOutput(pdu) => pdu.size(),
|
||||
ServerPdu::MapSurfaceToScaledWindow(pdu) => pdu.size(),
|
||||
ServerPdu::StartFrame(pdu) => pdu.size(),
|
||||
ServerPdu::EndFrame(pdu) => pdu.size(),
|
||||
ServerPdu::EvictCacheEntry(pdu) => pdu.size(),
|
||||
ServerPdu::CapabilitiesConfirm(pdu) => pdu.size(),
|
||||
ServerPdu::CacheImportReply(pdu) => pdu.size(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PduDecode<'a> for ServerPdu {
|
||||
fn decode(src: &mut ReadCursor<'a>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let pdu_type = ServerPduType::from_u16(src.read_u16())
|
||||
.ok_or_else(|| invalid_message_err!("serverPduType", "invalid pdu type"))?;
|
||||
let _flags = src.read_u16();
|
||||
let pdu_length = cast_length!("pduLen", src.read_u32())?;
|
||||
|
||||
let (server_pdu, buffer_length) = {
|
||||
let pdu = match pdu_type {
|
||||
ServerPduType::DeleteEncodingContext => {
|
||||
ServerPdu::DeleteEncodingContext(DeleteEncodingContextPdu::from_buffer(&mut stream)?)
|
||||
}
|
||||
ServerPduType::WireToSurface1 => {
|
||||
ServerPdu::WireToSurface1(WireToSurface1Pdu::from_buffer(&mut stream)?)
|
||||
}
|
||||
ServerPduType::WireToSurface2 => {
|
||||
ServerPdu::WireToSurface2(WireToSurface2Pdu::from_buffer(&mut stream)?)
|
||||
}
|
||||
ServerPduType::SolidFill => ServerPdu::SolidFill(SolidFillPdu::from_buffer(&mut stream)?),
|
||||
ServerPduType::SurfaceToSurface => {
|
||||
ServerPdu::SurfaceToSurface(SurfaceToSurfacePdu::from_buffer(&mut stream)?)
|
||||
}
|
||||
ServerPduType::SurfaceToCache => {
|
||||
ServerPdu::SurfaceToCache(SurfaceToCachePdu::from_buffer(&mut stream)?)
|
||||
}
|
||||
ServerPduType::CacheToSurface => {
|
||||
ServerPdu::CacheToSurface(CacheToSurfacePdu::from_buffer(&mut stream)?)
|
||||
}
|
||||
ServerPduType::EvictCacheEntry => {
|
||||
ServerPdu::EvictCacheEntry(EvictCacheEntryPdu::from_buffer(&mut stream)?)
|
||||
}
|
||||
ServerPduType::CreateSurface => ServerPdu::CreateSurface(CreateSurfacePdu::from_buffer(&mut stream)?),
|
||||
ServerPduType::DeleteSurface => ServerPdu::DeleteSurface(DeleteSurfacePdu::from_buffer(&mut stream)?),
|
||||
ServerPduType::StartFrame => ServerPdu::StartFrame(StartFramePdu::from_buffer(&mut stream)?),
|
||||
ServerPduType::EndFrame => ServerPdu::EndFrame(EndFramePdu::from_buffer(&mut stream)?),
|
||||
ServerPduType::ResetGraphics => ServerPdu::ResetGraphics(ResetGraphicsPdu::from_buffer(&mut stream)?),
|
||||
ServerPduType::MapSurfaceToOutput => {
|
||||
ServerPdu::MapSurfaceToOutput(MapSurfaceToOutputPdu::from_buffer(&mut stream)?)
|
||||
ServerPdu::DeleteEncodingContext(DeleteEncodingContextPdu::decode(src)?)
|
||||
}
|
||||
ServerPduType::WireToSurface1 => ServerPdu::WireToSurface1(WireToSurface1Pdu::decode(src)?),
|
||||
ServerPduType::WireToSurface2 => ServerPdu::WireToSurface2(WireToSurface2Pdu::decode(src)?),
|
||||
ServerPduType::SolidFill => ServerPdu::SolidFill(SolidFillPdu::decode(src)?),
|
||||
ServerPduType::SurfaceToSurface => ServerPdu::SurfaceToSurface(SurfaceToSurfacePdu::decode(src)?),
|
||||
ServerPduType::SurfaceToCache => ServerPdu::SurfaceToCache(SurfaceToCachePdu::decode(src)?),
|
||||
ServerPduType::CacheToSurface => ServerPdu::CacheToSurface(CacheToSurfacePdu::decode(src)?),
|
||||
ServerPduType::EvictCacheEntry => ServerPdu::EvictCacheEntry(EvictCacheEntryPdu::decode(src)?),
|
||||
ServerPduType::CreateSurface => ServerPdu::CreateSurface(CreateSurfacePdu::decode(src)?),
|
||||
ServerPduType::DeleteSurface => ServerPdu::DeleteSurface(DeleteSurfacePdu::decode(src)?),
|
||||
ServerPduType::StartFrame => ServerPdu::StartFrame(StartFramePdu::decode(src)?),
|
||||
ServerPduType::EndFrame => ServerPdu::EndFrame(EndFramePdu::decode(src)?),
|
||||
ServerPduType::ResetGraphics => ServerPdu::ResetGraphics(ResetGraphicsPdu::decode(src)?),
|
||||
ServerPduType::MapSurfaceToOutput => ServerPdu::MapSurfaceToOutput(MapSurfaceToOutputPdu::decode(src)?),
|
||||
ServerPduType::CapabilitiesConfirm => {
|
||||
ServerPdu::CapabilitiesConfirm(CapabilitiesConfirmPdu::from_buffer(&mut stream)?)
|
||||
}
|
||||
ServerPduType::CacheImportReply => {
|
||||
ServerPdu::CacheImportReply(CacheImportReplyPdu::from_buffer(&mut stream)?)
|
||||
ServerPdu::CapabilitiesConfirm(CapabilitiesConfirmPdu::decode(src)?)
|
||||
}
|
||||
ServerPduType::CacheImportReply => ServerPdu::CacheImportReply(CacheImportReplyPdu::decode(src)?),
|
||||
ServerPduType::MapSurfaceToScaledOutput => {
|
||||
ServerPdu::MapSurfaceToScaledOutput(MapSurfaceToScaledOutputPdu::from_buffer(&mut stream)?)
|
||||
ServerPdu::MapSurfaceToScaledOutput(MapSurfaceToScaledOutputPdu::decode(src)?)
|
||||
}
|
||||
ServerPduType::MapSurfaceToScaledWindow => {
|
||||
ServerPdu::MapSurfaceToScaledWindow(MapSurfaceToScaledWindowPdu::from_buffer(&mut stream)?)
|
||||
ServerPdu::MapSurfaceToScaledWindow(MapSurfaceToScaledWindowPdu::decode(src)?)
|
||||
}
|
||||
_ => return Err(GraphicsPipelineError::UnexpectedServerPduType(pdu_type)),
|
||||
_ => return Err(invalid_message_err!("pduType", "invalid pdu type")),
|
||||
};
|
||||
let buffer_length = pdu.buffer_length();
|
||||
let buffer_length = pdu.size();
|
||||
|
||||
(pdu, buffer_length)
|
||||
};
|
||||
|
||||
if buffer_length != pdu_length {
|
||||
Err(GraphicsPipelineError::InvalidPduLength {
|
||||
expected: pdu_length,
|
||||
actual: buffer_length,
|
||||
})
|
||||
Err(invalid_message_err!("len", "invalid pdu length"))
|
||||
} else {
|
||||
Ok(server_pdu)
|
||||
}
|
||||
}
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
let buffer_length = self.buffer_length();
|
||||
|
||||
stream.write_u16::<LittleEndian>(ServerPduType::from(self).to_u16().unwrap())?;
|
||||
stream.write_u16::<LittleEndian>(0)?; // flags
|
||||
stream.write_u32::<LittleEndian>(buffer_length as u32)?;
|
||||
|
||||
match self {
|
||||
ServerPdu::WireToSurface1(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
ServerPdu::WireToSurface2(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
ServerPdu::DeleteEncodingContext(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
ServerPdu::SolidFill(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
ServerPdu::SurfaceToSurface(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
ServerPdu::SurfaceToCache(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
ServerPdu::CacheToSurface(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
ServerPdu::CreateSurface(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
ServerPdu::DeleteSurface(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
ServerPdu::ResetGraphics(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
ServerPdu::MapSurfaceToOutput(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
ServerPdu::MapSurfaceToScaledOutput(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
ServerPdu::MapSurfaceToScaledWindow(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
ServerPdu::StartFrame(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
ServerPdu::EndFrame(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
ServerPdu::EvictCacheEntry(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
ServerPdu::CapabilitiesConfirm(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
ServerPdu::CacheImportReply(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
}
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
RDP_GFX_HEADER_SIZE
|
||||
+ match self {
|
||||
ServerPdu::WireToSurface1(pdu) => pdu.buffer_length(),
|
||||
ServerPdu::WireToSurface2(pdu) => pdu.buffer_length(),
|
||||
ServerPdu::DeleteEncodingContext(pdu) => pdu.buffer_length(),
|
||||
ServerPdu::SolidFill(pdu) => pdu.buffer_length(),
|
||||
ServerPdu::SurfaceToSurface(pdu) => pdu.buffer_length(),
|
||||
ServerPdu::SurfaceToCache(pdu) => pdu.buffer_length(),
|
||||
ServerPdu::CacheToSurface(pdu) => pdu.buffer_length(),
|
||||
ServerPdu::CreateSurface(pdu) => pdu.buffer_length(),
|
||||
ServerPdu::DeleteSurface(pdu) => pdu.buffer_length(),
|
||||
ServerPdu::ResetGraphics(pdu) => pdu.buffer_length(),
|
||||
ServerPdu::MapSurfaceToOutput(pdu) => pdu.buffer_length(),
|
||||
ServerPdu::MapSurfaceToScaledOutput(pdu) => pdu.buffer_length(),
|
||||
ServerPdu::MapSurfaceToScaledWindow(pdu) => pdu.buffer_length(),
|
||||
ServerPdu::StartFrame(pdu) => pdu.buffer_length(),
|
||||
ServerPdu::EndFrame(pdu) => pdu.buffer_length(),
|
||||
ServerPdu::EvictCacheEntry(pdu) => pdu.buffer_length(),
|
||||
ServerPdu::CapabilitiesConfirm(pdu) => pdu.buffer_length(),
|
||||
ServerPdu::CacheImportReply(pdu) => pdu.buffer_length(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -182,53 +164,60 @@ pub enum ClientPdu {
|
|||
CapabilitiesAdvertise(CapabilitiesAdvertisePdu),
|
||||
}
|
||||
|
||||
impl PduParsing for ClientPdu {
|
||||
type Error = GraphicsPipelineError;
|
||||
impl ClientPdu {
|
||||
const NAME: &'static str = "GfxClientPdu";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let pdu_type =
|
||||
ClientPduType::from_u16(stream.read_u16::<LittleEndian>()?).ok_or(GraphicsPipelineError::InvalidCmdId)?;
|
||||
let _flags = stream.read_u16::<LittleEndian>()?;
|
||||
let pdu_length = stream.read_u32::<LittleEndian>()? as usize;
|
||||
const FIXED_PART_SIZE: usize = RDP_GFX_HEADER_SIZE;
|
||||
}
|
||||
|
||||
impl PduEncode for ClientPdu {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_size!(in: dst, size: self.size());
|
||||
|
||||
dst.write_u16(ClientPduType::from(self).to_u16().unwrap());
|
||||
dst.write_u16(0); // flags
|
||||
dst.write_u32(cast_length!("bufferLen", self.size())?);
|
||||
|
||||
match self {
|
||||
ClientPdu::FrameAcknowledge(pdu) => pdu.encode(dst),
|
||||
ClientPdu::CapabilitiesAdvertise(pdu) => pdu.encode(dst),
|
||||
}
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE
|
||||
+ match self {
|
||||
ClientPdu::FrameAcknowledge(pdu) => pdu.size(),
|
||||
ClientPdu::CapabilitiesAdvertise(pdu) => pdu.size(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PduDecode<'a> for ClientPdu {
|
||||
fn decode(src: &mut ReadCursor<'a>) -> PduResult<Self> {
|
||||
let pdu_type = ClientPduType::from_u16(src.read_u16())
|
||||
.ok_or_else(|| invalid_message_err!("clientPduType", "invalid pdu type"))?;
|
||||
let _flags = src.read_u16();
|
||||
let pdu_length = cast_length!("bufferLen", src.read_u32())?;
|
||||
|
||||
let client_pdu = match pdu_type {
|
||||
ClientPduType::FrameAcknowledge => {
|
||||
ClientPdu::FrameAcknowledge(FrameAcknowledgePdu::from_buffer(&mut stream)?)
|
||||
}
|
||||
ClientPduType::FrameAcknowledge => ClientPdu::FrameAcknowledge(FrameAcknowledgePdu::decode(src)?),
|
||||
ClientPduType::CapabilitiesAdvertise => {
|
||||
ClientPdu::CapabilitiesAdvertise(CapabilitiesAdvertisePdu::from_buffer(&mut stream)?)
|
||||
ClientPdu::CapabilitiesAdvertise(CapabilitiesAdvertisePdu::decode(src)?)
|
||||
}
|
||||
_ => return Err(GraphicsPipelineError::UnexpectedClientPduType(pdu_type)),
|
||||
_ => return Err(invalid_message_err!("pduType", "invalid pdu type")),
|
||||
};
|
||||
|
||||
if client_pdu.buffer_length() != pdu_length {
|
||||
Err(GraphicsPipelineError::InvalidPduLength {
|
||||
expected: pdu_length,
|
||||
actual: client_pdu.buffer_length(),
|
||||
})
|
||||
if client_pdu.size() != pdu_length {
|
||||
Err(invalid_message_err!("len", "invalid pdu length"))
|
||||
} else {
|
||||
Ok(client_pdu)
|
||||
}
|
||||
}
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
stream.write_u16::<LittleEndian>(ClientPduType::from(self).to_u16().unwrap())?;
|
||||
stream.write_u16::<LittleEndian>(0)?; // flags
|
||||
stream.write_u32::<LittleEndian>(self.buffer_length() as u32)?;
|
||||
|
||||
match self {
|
||||
ClientPdu::FrameAcknowledge(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
ClientPdu::CapabilitiesAdvertise(pdu) => pdu.to_buffer(&mut stream).map_err(GraphicsPipelineError::from),
|
||||
}
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
RDP_GFX_HEADER_SIZE
|
||||
+ match self {
|
||||
ClientPdu::FrameAcknowledge(pdu) => pdu.buffer_length(),
|
||||
ClientPdu::CapabilitiesAdvertise(pdu) => pdu.buffer_length(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
|
||||
|
@ -295,36 +284,3 @@ impl<'a> From<&'a ServerPdu> for ServerPduType {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum GraphicsPipelineError {
|
||||
#[error("IO error")]
|
||||
IOError(#[from] io::Error),
|
||||
#[error("graphics messages error")]
|
||||
GraphicsMessagesError(#[from] graphics_messages::GraphicsMessagesError),
|
||||
#[error("invalid Header cmd ID")]
|
||||
InvalidCmdId,
|
||||
#[error("unexpected client's PDU type: {0:?}")]
|
||||
UnexpectedClientPduType(ClientPduType),
|
||||
#[error("unexpected server's PDU type: {0:?}")]
|
||||
UnexpectedServerPduType(ServerPduType),
|
||||
#[error("invalid ResetGraphics PDU size: expected ({expected}) != actual ({actual})")]
|
||||
InvalidResetGraphicsPduSize { expected: usize, actual: usize },
|
||||
#[error("invalid PDU length: expected ({expected}) != actual ({actual})")]
|
||||
InvalidPduLength { expected: usize, actual: usize },
|
||||
#[error("PDU error: {0}")]
|
||||
Pdu(PduError),
|
||||
}
|
||||
|
||||
impl From<PduError> for GraphicsPipelineError {
|
||||
fn from(e: PduError) -> Self {
|
||||
Self::Pdu(e)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl ironrdp_error::legacy::ErrorContext for GraphicsPipelineError {
|
||||
fn context(&self) -> &'static str {
|
||||
"graphics pipeline"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
mod client;
|
||||
mod server;
|
||||
|
||||
use std::io;
|
||||
mod avc_messages;
|
||||
use bitflags::bitflags;
|
||||
use byteorder::{LittleEndian, ReadBytesExt as _, WriteBytesExt as _};
|
||||
use num_derive::{FromPrimitive, ToPrimitive};
|
||||
use num_traits::{FromPrimitive as _, ToPrimitive as _};
|
||||
use thiserror::Error;
|
||||
|
||||
#[rustfmt::skip] // do not re-order this
|
||||
pub use avc_messages::{Avc420BitmapStream, Avc444BitmapStream, Encoding, QuantQuality};
|
||||
pub use client::{CacheImportReplyPdu, CapabilitiesAdvertisePdu, FrameAcknowledgePdu, QueueDepth};
|
||||
pub(crate) use server::RESET_GRAPHICS_PDU_SIZE;
|
||||
pub use server::{
|
||||
CacheToSurfacePdu, CapabilitiesConfirmPdu, Codec1Type, Codec2Type, CreateSurfacePdu, DeleteEncodingContextPdu,
|
||||
DeleteSurfacePdu, EndFramePdu, EvictCacheEntryPdu, MapSurfaceToOutputPdu, MapSurfaceToScaledOutputPdu,
|
||||
|
@ -21,8 +17,8 @@ pub use server::{
|
|||
};
|
||||
|
||||
use super::RDP_GFX_HEADER_SIZE;
|
||||
use crate::gcc::MonitorDataError;
|
||||
use crate::{PduError, PduParsing};
|
||||
use crate::cursor::{ReadCursor, WriteCursor};
|
||||
use crate::{PduDecode, PduEncode, PduResult};
|
||||
|
||||
const CAPABILITY_SET_HEADER_SIZE: usize = 8;
|
||||
|
||||
|
@ -63,79 +59,42 @@ impl CapabilitySet {
|
|||
}
|
||||
}
|
||||
|
||||
impl PduParsing for CapabilitySet {
|
||||
type Error = GraphicsMessagesError;
|
||||
impl CapabilitySet {
|
||||
const NAME: &'static str = "GfxCapabilitySet";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, GraphicsMessagesError> {
|
||||
let version = CapabilityVersion::from_u32(stream.read_u32::<LittleEndian>()?)
|
||||
.ok_or(GraphicsMessagesError::InvalidCapabilitiesVersion)?;
|
||||
let data_length = stream.read_u32::<LittleEndian>()?;
|
||||
const FIXED_PART_SIZE: usize = CAPABILITY_SET_HEADER_SIZE;
|
||||
}
|
||||
|
||||
let mut data = vec![0; data_length as usize];
|
||||
stream.read_exact(data.as_mut())?;
|
||||
impl PduEncode for CapabilitySet {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_size!(in: dst, size: self.size());
|
||||
|
||||
match version {
|
||||
CapabilityVersion::V8 => Ok(CapabilitySet::V8 {
|
||||
flags: CapabilitiesV8Flags::from_bits_truncate(data.as_slice().read_u32::<LittleEndian>()?),
|
||||
}),
|
||||
CapabilityVersion::V8_1 => Ok(CapabilitySet::V8_1 {
|
||||
flags: CapabilitiesV81Flags::from_bits_truncate(data.as_slice().read_u32::<LittleEndian>()?),
|
||||
}),
|
||||
CapabilityVersion::V10 => Ok(CapabilitySet::V10 {
|
||||
flags: CapabilitiesV10Flags::from_bits_truncate(data.as_slice().read_u32::<LittleEndian>()?),
|
||||
}),
|
||||
CapabilityVersion::V10_1 => {
|
||||
data.as_slice().read_u128::<LittleEndian>()?;
|
||||
|
||||
Ok(CapabilitySet::V10_1)
|
||||
}
|
||||
CapabilityVersion::V10_2 => Ok(CapabilitySet::V10_2 {
|
||||
flags: CapabilitiesV10Flags::from_bits_truncate(data.as_slice().read_u32::<LittleEndian>()?),
|
||||
}),
|
||||
CapabilityVersion::V10_3 => Ok(CapabilitySet::V10_3 {
|
||||
flags: CapabilitiesV103Flags::from_bits_truncate(data.as_slice().read_u32::<LittleEndian>()?),
|
||||
}),
|
||||
CapabilityVersion::V10_4 => Ok(CapabilitySet::V10_4 {
|
||||
flags: CapabilitiesV104Flags::from_bits_truncate(data.as_slice().read_u32::<LittleEndian>()?),
|
||||
}),
|
||||
CapabilityVersion::V10_5 => Ok(CapabilitySet::V10_5 {
|
||||
flags: CapabilitiesV104Flags::from_bits_truncate(data.as_slice().read_u32::<LittleEndian>()?),
|
||||
}),
|
||||
CapabilityVersion::V10_6 => Ok(CapabilitySet::V10_6 {
|
||||
flags: CapabilitiesV104Flags::from_bits_truncate(data.as_slice().read_u32::<LittleEndian>()?),
|
||||
}),
|
||||
CapabilityVersion::V10_6Err => Ok(CapabilitySet::V10_6Err {
|
||||
flags: CapabilitiesV104Flags::from_bits_truncate(data.as_slice().read_u32::<LittleEndian>()?),
|
||||
}),
|
||||
CapabilityVersion::V10_7 => Ok(CapabilitySet::V10_7 {
|
||||
flags: CapabilitiesV107Flags::from_bits_truncate(data.as_slice().read_u32::<LittleEndian>()?),
|
||||
}),
|
||||
CapabilityVersion::Unknown => Ok(CapabilitySet::Unknown(data)),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), GraphicsMessagesError> {
|
||||
stream.write_u32::<LittleEndian>(self.version().to_u32().unwrap())?;
|
||||
stream.write_u32::<LittleEndian>((self.buffer_length() - CAPABILITY_SET_HEADER_SIZE) as u32)?;
|
||||
dst.write_u32(self.version().to_u32().unwrap());
|
||||
dst.write_u32(cast_length!("dataLength", self.size() - CAPABILITY_SET_HEADER_SIZE)?);
|
||||
|
||||
match self {
|
||||
CapabilitySet::V8 { flags } => stream.write_u32::<LittleEndian>(flags.bits())?,
|
||||
CapabilitySet::V8_1 { flags } => stream.write_u32::<LittleEndian>(flags.bits())?,
|
||||
CapabilitySet::V10 { flags } => stream.write_u32::<LittleEndian>(flags.bits())?,
|
||||
CapabilitySet::V10_1 => stream.write_u128::<LittleEndian>(V10_1_RESERVED)?,
|
||||
CapabilitySet::V10_2 { flags } => stream.write_u32::<LittleEndian>(flags.bits())?,
|
||||
CapabilitySet::V10_3 { flags } => stream.write_u32::<LittleEndian>(flags.bits())?,
|
||||
CapabilitySet::V10_4 { flags } => stream.write_u32::<LittleEndian>(flags.bits())?,
|
||||
CapabilitySet::V10_5 { flags } => stream.write_u32::<LittleEndian>(flags.bits())?,
|
||||
CapabilitySet::V10_6 { flags } => stream.write_u32::<LittleEndian>(flags.bits())?,
|
||||
CapabilitySet::V10_6Err { flags } => stream.write_u32::<LittleEndian>(flags.bits())?,
|
||||
CapabilitySet::V10_7 { flags } => stream.write_u32::<LittleEndian>(flags.bits())?,
|
||||
CapabilitySet::Unknown(data) => stream.write_all(data)?,
|
||||
CapabilitySet::V8 { flags } => dst.write_u32(flags.bits()),
|
||||
CapabilitySet::V8_1 { flags } => dst.write_u32(flags.bits()),
|
||||
CapabilitySet::V10 { flags } => dst.write_u32(flags.bits()),
|
||||
CapabilitySet::V10_1 => dst.write_u128(V10_1_RESERVED),
|
||||
CapabilitySet::V10_2 { flags } => dst.write_u32(flags.bits()),
|
||||
CapabilitySet::V10_3 { flags } => dst.write_u32(flags.bits()),
|
||||
CapabilitySet::V10_4 { flags } => dst.write_u32(flags.bits()),
|
||||
CapabilitySet::V10_5 { flags } => dst.write_u32(flags.bits()),
|
||||
CapabilitySet::V10_6 { flags } => dst.write_u32(flags.bits()),
|
||||
CapabilitySet::V10_6Err { flags } => dst.write_u32(flags.bits()),
|
||||
CapabilitySet::V10_7 { flags } => dst.write_u32(flags.bits()),
|
||||
CapabilitySet::Unknown(data) => dst.write_slice(data),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn buffer_length(&self) -> usize {
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
CAPABILITY_SET_HEADER_SIZE
|
||||
+ match self {
|
||||
CapabilitySet::V8 { .. }
|
||||
|
@ -154,6 +113,75 @@ impl PduParsing for CapabilitySet {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for CapabilitySet {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let version = CapabilityVersion::from_u32(src.read_u32())
|
||||
.ok_or_else(|| invalid_message_err!("version", "unhandled version"))?;
|
||||
let data_length: usize = cast_length!("dataLength", src.read_u32())?;
|
||||
|
||||
ensure_size!(in: src, size: data_length);
|
||||
let data = src.read_slice(data_length);
|
||||
let mut cur = ReadCursor::new(data);
|
||||
|
||||
let size = match version {
|
||||
CapabilityVersion::V8
|
||||
| CapabilityVersion::V8_1
|
||||
| CapabilityVersion::V10
|
||||
| CapabilityVersion::V10_2
|
||||
| CapabilityVersion::V10_3
|
||||
| CapabilityVersion::V10_4
|
||||
| CapabilityVersion::V10_5
|
||||
| CapabilityVersion::V10_6
|
||||
| CapabilityVersion::V10_6Err
|
||||
| CapabilityVersion::V10_7 => 4,
|
||||
CapabilityVersion::V10_1 => 16,
|
||||
CapabilityVersion::Unknown => 0,
|
||||
};
|
||||
|
||||
ensure_size!(in: cur, size: size);
|
||||
match version {
|
||||
CapabilityVersion::V8 => Ok(CapabilitySet::V8 {
|
||||
flags: CapabilitiesV8Flags::from_bits_truncate(cur.read_u32()),
|
||||
}),
|
||||
CapabilityVersion::V8_1 => Ok(CapabilitySet::V8_1 {
|
||||
flags: CapabilitiesV81Flags::from_bits_truncate(cur.read_u32()),
|
||||
}),
|
||||
CapabilityVersion::V10 => Ok(CapabilitySet::V10 {
|
||||
flags: CapabilitiesV10Flags::from_bits_truncate(cur.read_u32()),
|
||||
}),
|
||||
CapabilityVersion::V10_1 => {
|
||||
cur.read_u128();
|
||||
|
||||
Ok(CapabilitySet::V10_1)
|
||||
}
|
||||
CapabilityVersion::V10_2 => Ok(CapabilitySet::V10_2 {
|
||||
flags: CapabilitiesV10Flags::from_bits_truncate(cur.read_u32()),
|
||||
}),
|
||||
CapabilityVersion::V10_3 => Ok(CapabilitySet::V10_3 {
|
||||
flags: CapabilitiesV103Flags::from_bits_truncate(cur.read_u32()),
|
||||
}),
|
||||
CapabilityVersion::V10_4 => Ok(CapabilitySet::V10_4 {
|
||||
flags: CapabilitiesV104Flags::from_bits_truncate(cur.read_u32()),
|
||||
}),
|
||||
CapabilityVersion::V10_5 => Ok(CapabilitySet::V10_5 {
|
||||
flags: CapabilitiesV104Flags::from_bits_truncate(cur.read_u32()),
|
||||
}),
|
||||
CapabilityVersion::V10_6 => Ok(CapabilitySet::V10_6 {
|
||||
flags: CapabilitiesV104Flags::from_bits_truncate(cur.read_u32()),
|
||||
}),
|
||||
CapabilityVersion::V10_6Err => Ok(CapabilitySet::V10_6Err {
|
||||
flags: CapabilitiesV104Flags::from_bits_truncate(cur.read_u32()),
|
||||
}),
|
||||
CapabilityVersion::V10_7 => Ok(CapabilitySet::V10_7 {
|
||||
flags: CapabilitiesV107Flags::from_bits_truncate(cur.read_u32()),
|
||||
}),
|
||||
CapabilityVersion::Unknown => Ok(CapabilitySet::Unknown(data.to_vec())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Color {
|
||||
pub b: u8,
|
||||
|
@ -162,29 +190,43 @@ pub struct Color {
|
|||
pub xa: u8,
|
||||
}
|
||||
|
||||
impl PduParsing for Color {
|
||||
type Error = GraphicsMessagesError;
|
||||
impl Color {
|
||||
const NAME: &'static str = "GfxColor";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let b = stream.read_u8()?;
|
||||
let g = stream.read_u8()?;
|
||||
let r = stream.read_u8()?;
|
||||
let xa = stream.read_u8()?;
|
||||
const FIXED_PART_SIZE: usize = 4 /* BGRA */;
|
||||
}
|
||||
|
||||
Ok(Self { b, g, r, xa })
|
||||
}
|
||||
impl PduEncode for Color {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_fixed_part_size!(in: dst);
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
stream.write_u8(self.b)?;
|
||||
stream.write_u8(self.g)?;
|
||||
stream.write_u8(self.r)?;
|
||||
stream.write_u8(self.xa)?;
|
||||
dst.write_u8(self.b);
|
||||
dst.write_u8(self.g);
|
||||
dst.write_u8(self.r);
|
||||
dst.write_u8(self.xa);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
4
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for Color {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let b = src.read_u8();
|
||||
let g = src.read_u8();
|
||||
let r = src.read_u8();
|
||||
let xa = src.read_u8();
|
||||
|
||||
Ok(Self { b, g, r, xa })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,25 +236,39 @@ pub struct Point {
|
|||
pub y: u16,
|
||||
}
|
||||
|
||||
impl PduParsing for Point {
|
||||
type Error = GraphicsMessagesError;
|
||||
impl Point {
|
||||
const NAME: &'static str = "GfxPoint";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let x = stream.read_u16::<LittleEndian>()?;
|
||||
let y = stream.read_u16::<LittleEndian>()?;
|
||||
const FIXED_PART_SIZE: usize = 2 /* X */ + 2 /* Y */;
|
||||
}
|
||||
|
||||
Ok(Self { x, y })
|
||||
}
|
||||
impl PduEncode for Point {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_fixed_part_size!(in: dst);
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
stream.write_u16::<LittleEndian>(self.x)?;
|
||||
stream.write_u16::<LittleEndian>(self.y)?;
|
||||
dst.write_u16(self.x);
|
||||
dst.write_u16(self.y);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
4
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for Point {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let x = src.read_u16();
|
||||
let y = src.read_u16();
|
||||
|
||||
Ok(Self { x, y })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,35 +340,3 @@ bitflags! {
|
|||
const SCALEDMAP_DISABLE = 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum GraphicsMessagesError {
|
||||
#[error("IO error")]
|
||||
IOError(#[from] io::Error),
|
||||
#[error("invalid codec ID version 1")]
|
||||
InvalidCodec1Id,
|
||||
#[error("invalid codec ID version 2")]
|
||||
InvalidCodec2Id,
|
||||
#[error("invalid pixel format")]
|
||||
InvalidPixelFormat,
|
||||
#[error("monitor error")]
|
||||
MonitorError(#[from] MonitorDataError),
|
||||
#[error("invalid ResetGraphics PDU width: {} > MAX ({})", actual, max)]
|
||||
InvalidResetGraphicsPduWidth { actual: u32, max: u32 },
|
||||
#[error("invalid ResetGraphics PDU height: {} > MAX ({})", actual, max)]
|
||||
InvalidResetGraphicsPduHeight { actual: u32, max: u32 },
|
||||
#[error("invalid ResetGraphics PDU monitors count: {} > MAX ({})", actual, max)]
|
||||
InvalidResetGraphicsPduMonitorsCount { actual: u32, max: u32 },
|
||||
#[error("invalid capabilities version")]
|
||||
InvalidCapabilitiesVersion,
|
||||
#[error("both luma and chroma packets specified but length is missing")]
|
||||
InvalidAvcEncoding,
|
||||
#[error("PDU error: {0}")]
|
||||
Pdu(PduError),
|
||||
}
|
||||
|
||||
impl From<PduError> for GraphicsMessagesError {
|
||||
fn from(e: PduError) -> Self {
|
||||
Self::Pdu(e)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
use std::fmt::Debug;
|
||||
use std::io::Write as _;
|
||||
|
||||
use bit_field::BitField;
|
||||
use bitflags::bitflags;
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use super::GraphicsMessagesError;
|
||||
use crate::cursor::{ReadCursor, WriteCursor};
|
||||
use crate::geometry::InclusiveRectangle;
|
||||
use crate::{PduBufferParsing, PduParsing};
|
||||
use crate::{PduDecode, PduEncode, PduResult};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct QuantQuality {
|
||||
|
@ -16,36 +14,47 @@ pub struct QuantQuality {
|
|||
pub quality: u8,
|
||||
}
|
||||
|
||||
impl PduParsing for QuantQuality {
|
||||
type Error = GraphicsMessagesError;
|
||||
impl QuantQuality {
|
||||
const NAME: &'static str = "GfxQuantQuality";
|
||||
|
||||
fn from_buffer(mut stream: impl std::io::Read) -> Result<Self, Self::Error>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let data = stream.read_u8()?;
|
||||
const FIXED_PART_SIZE: usize = 1 /* data */ + 1 /* quality */;
|
||||
}
|
||||
|
||||
impl PduEncode for QuantQuality {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_fixed_part_size!(in: dst);
|
||||
|
||||
let mut data = 0u8;
|
||||
data.set_bits(0..6, self.quantization_parameter);
|
||||
data.set_bit(7, self.progressive);
|
||||
dst.write_u8(data);
|
||||
dst.write_u8(self.quality);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for QuantQuality {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let data = src.read_u8();
|
||||
let qp = data.get_bits(0..6);
|
||||
let progressive = data.get_bit(7);
|
||||
let quality = stream.read_u8()?;
|
||||
let quality = src.read_u8();
|
||||
Ok(QuantQuality {
|
||||
quantization_parameter: qp,
|
||||
progressive,
|
||||
quality,
|
||||
})
|
||||
}
|
||||
|
||||
fn to_buffer(&self, mut stream: impl std::io::Write) -> Result<(), Self::Error> {
|
||||
let mut data = 0u8;
|
||||
data.set_bits(0..6, self.quantization_parameter);
|
||||
data.set_bit(7, self.progressive);
|
||||
stream.write_u8(data)?;
|
||||
stream.write_u8(self.quality)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
2
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
|
@ -65,44 +74,58 @@ impl Debug for Avc420BitmapStream<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> PduBufferParsing<'a> for Avc420BitmapStream<'a> {
|
||||
type Error = GraphicsMessagesError;
|
||||
impl Avc420BitmapStream<'_> {
|
||||
const NAME: &'static str = "Avc420BitmapStream";
|
||||
|
||||
fn from_buffer_consume(mut buffer: &mut &'a [u8]) -> Result<Self, Self::Error> {
|
||||
let num_regions = buffer.read_u32::<LittleEndian>()?;
|
||||
const FIXED_PART_SIZE: usize = 4 /* nRect */;
|
||||
}
|
||||
|
||||
impl PduEncode for Avc420BitmapStream<'_> {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_size!(in: dst, size: self.size());
|
||||
|
||||
dst.write_u32(cast_length!("len", self.rectangles.len())?);
|
||||
for rectangle in &self.rectangles {
|
||||
rectangle.encode(dst)?;
|
||||
}
|
||||
for quant_qual_val in &self.quant_qual_vals {
|
||||
quant_qual_val.encode(dst)?;
|
||||
}
|
||||
dst.write_slice(self.data);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
// Each rectangle is 8 bytes and 2 bytes for each quant val
|
||||
Self::FIXED_PART_SIZE + self.rectangles.len() * 10 + self.data.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for Avc420BitmapStream<'de> {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let num_regions = src.read_u32();
|
||||
let mut rectangles = Vec::with_capacity(num_regions as usize);
|
||||
let mut quant_qual_vals = Vec::with_capacity(num_regions as usize);
|
||||
for _ in 0..num_regions {
|
||||
rectangles.push(InclusiveRectangle::from_buffer(&mut buffer)?);
|
||||
rectangles.push(InclusiveRectangle::decode(src)?);
|
||||
}
|
||||
for _ in 0..num_regions {
|
||||
quant_qual_vals.push(QuantQuality::from_buffer(&mut buffer)?);
|
||||
quant_qual_vals.push(QuantQuality::decode(src)?);
|
||||
}
|
||||
let data = buffer;
|
||||
let data = src.remaining();
|
||||
Ok(Avc420BitmapStream {
|
||||
rectangles,
|
||||
quant_qual_vals,
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
fn to_buffer_consume(&self, mut buffer: &mut &mut [u8]) -> Result<(), Self::Error> {
|
||||
buffer.write_u32::<LittleEndian>(self.rectangles.len() as u32)?;
|
||||
for rectangle in &self.rectangles {
|
||||
rectangle.to_buffer(&mut buffer)?;
|
||||
}
|
||||
for quant_qual_val in &self.quant_qual_vals {
|
||||
quant_qual_val.to_buffer(&mut buffer)?;
|
||||
}
|
||||
buffer.write_all(self.data)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
// Each rectangle is 8 bytes and 2 bytes for each quant val
|
||||
4 + self.rectangles.len() * 10 + self.data.len()
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
|
@ -121,30 +144,66 @@ pub struct Avc444BitmapStream<'a> {
|
|||
pub stream2: Option<Avc420BitmapStream<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> PduBufferParsing<'a> for Avc444BitmapStream<'a> {
|
||||
type Error = GraphicsMessagesError;
|
||||
impl Avc444BitmapStream<'_> {
|
||||
const NAME: &'static str = "Avc444BitmapStream";
|
||||
|
||||
fn from_buffer_consume(buffer: &mut &'a [u8]) -> Result<Self, Self::Error> {
|
||||
let stream_info = buffer.read_u32::<LittleEndian>()?;
|
||||
const FIXED_PART_SIZE: usize = 4 /* streamInfo */;
|
||||
}
|
||||
|
||||
impl PduEncode for Avc444BitmapStream<'_> {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_fixed_part_size!(in: dst);
|
||||
|
||||
let mut stream_info = 0u32;
|
||||
stream_info.set_bits(0..30, cast_length!("stream1size", self.stream1.size())?);
|
||||
stream_info.set_bits(30..32, self.encoding.bits() as u32);
|
||||
dst.write_u32(stream_info);
|
||||
self.stream1.encode(dst)?;
|
||||
if let Some(stream) = self.stream2.as_ref() {
|
||||
stream.encode(dst)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
let stream2_size = if let Some(stream) = self.stream2.as_ref() {
|
||||
stream.size()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
Self::FIXED_PART_SIZE + self.stream1.size() + stream2_size
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for Avc444BitmapStream<'de> {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let stream_info = src.read_u32();
|
||||
let stream_len = stream_info.get_bits(0..30);
|
||||
let encoding = Encoding::from_bits_truncate(stream_info.get_bits(30..32) as u8);
|
||||
|
||||
if stream_len == 0 {
|
||||
if encoding == Encoding::LUMA_AND_CHROMA {
|
||||
return Err(GraphicsMessagesError::InvalidAvcEncoding);
|
||||
return Err(invalid_message_err!("encoding", "invalid encoding"));
|
||||
}
|
||||
|
||||
let stream1 = Avc420BitmapStream::from_buffer_consume(buffer)?;
|
||||
let stream1 = Avc420BitmapStream::decode(src)?;
|
||||
Ok(Avc444BitmapStream {
|
||||
encoding,
|
||||
stream1,
|
||||
stream2: None,
|
||||
})
|
||||
} else {
|
||||
let (mut stream1, mut stream2) = buffer.split_at(stream_len as usize);
|
||||
let stream1 = Avc420BitmapStream::from_buffer_consume(&mut stream1)?;
|
||||
let (mut stream1, mut stream2) = src.split_at(stream_len as usize);
|
||||
let stream1 = Avc420BitmapStream::decode(&mut stream1)?;
|
||||
let stream2 = if encoding == Encoding::LUMA_AND_CHROMA {
|
||||
Some(Avc420BitmapStream::from_buffer_consume(&mut stream2)?)
|
||||
Some(Avc420BitmapStream::decode(&mut stream2)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -155,26 +214,4 @@ impl<'a> PduBufferParsing<'a> for Avc444BitmapStream<'a> {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn to_buffer_consume(&self, buffer: &mut &mut [u8]) -> Result<(), Self::Error> {
|
||||
let mut stream_info = 0u32;
|
||||
stream_info.set_bits(0..30, self.stream1.buffer_length() as u32);
|
||||
stream_info.set_bits(30..32, self.encoding.bits() as u32);
|
||||
buffer.write_u32::<LittleEndian>(stream_info)?;
|
||||
self.stream1.to_buffer_consume(buffer)?;
|
||||
if let Some(stream) = self.stream2.as_ref() {
|
||||
stream.to_buffer_consume(buffer)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
let stream2_len = if let Some(stream) = self.stream2.as_ref() {
|
||||
stream.buffer_length()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
4 + self.stream1.buffer_length() + stream2_len
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,38 +1,51 @@
|
|||
use std::io;
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use super::{CapabilitySet, GraphicsMessagesError};
|
||||
use crate::PduParsing;
|
||||
use super::CapabilitySet;
|
||||
use crate::cursor::{ReadCursor, WriteCursor};
|
||||
use crate::{PduDecode, PduEncode, PduResult};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct CapabilitiesAdvertisePdu(pub Vec<CapabilitySet>);
|
||||
|
||||
impl PduParsing for CapabilitiesAdvertisePdu {
|
||||
type Error = GraphicsMessagesError;
|
||||
impl CapabilitiesAdvertisePdu {
|
||||
const NAME: &'static str = "CapabilitiesAdvertisePdu";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let capabilities_count = stream.read_u16::<LittleEndian>()? as usize;
|
||||
const FIXED_PART_SIZE: usize = 2 /* Count */;
|
||||
}
|
||||
|
||||
let capabilities = (0..capabilities_count)
|
||||
.map(|_| CapabilitySet::from_buffer(&mut stream))
|
||||
.collect::<Result<Vec<_>, Self::Error>>()?;
|
||||
impl PduEncode for CapabilitiesAdvertisePdu {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_size!(in: dst, size: self.size());
|
||||
|
||||
Ok(Self(capabilities))
|
||||
}
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
stream.write_u16::<LittleEndian>(self.0.len() as u16)?;
|
||||
dst.write_u16(cast_length!("Count", self.0.len())?);
|
||||
|
||||
for capability_set in self.0.iter() {
|
||||
capability_set.to_buffer(&mut stream)?;
|
||||
capability_set.encode(dst)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
2 + self.0.iter().map(|c| c.buffer_length()).sum::<usize>()
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE + self.0.iter().map(|c| c.size()).sum::<usize>()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PduDecode<'a> for CapabilitiesAdvertisePdu {
|
||||
fn decode(src: &mut ReadCursor<'a>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let capabilities_count = cast_length!("Count", src.read_u16())?;
|
||||
|
||||
ensure_size!(in: src, size: capabilities_count * CapabilitySet::FIXED_PART_SIZE);
|
||||
|
||||
let capabilities = (0..capabilities_count)
|
||||
.map(|_| CapabilitySet::decode(src))
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
Ok(Self(capabilities))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,13 +56,39 @@ pub struct FrameAcknowledgePdu {
|
|||
pub total_frames_decoded: u32,
|
||||
}
|
||||
|
||||
impl PduParsing for FrameAcknowledgePdu {
|
||||
type Error = GraphicsMessagesError;
|
||||
impl FrameAcknowledgePdu {
|
||||
const NAME: &'static str = "FrameAcknowledgePdu";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let queue_depth = QueueDepth::from_u32(stream.read_u32::<LittleEndian>()?);
|
||||
let frame_id = stream.read_u32::<LittleEndian>()?;
|
||||
let total_frames_decoded = stream.read_u32::<LittleEndian>()?;
|
||||
const FIXED_PART_SIZE: usize = 4 /* QueueDepth */ + 4 /* FrameId */ + 4 /* TotalFramesDecoded */;
|
||||
}
|
||||
|
||||
impl PduEncode for FrameAcknowledgePdu {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_fixed_part_size!(in: dst);
|
||||
|
||||
dst.write_u32(self.queue_depth.to_u32());
|
||||
dst.write_u32(self.frame_id);
|
||||
dst.write_u32(self.total_frames_decoded);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PduDecode<'a> for FrameAcknowledgePdu {
|
||||
fn decode(src: &mut ReadCursor<'a>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let queue_depth = QueueDepth::from_u32(src.read_u32());
|
||||
let frame_id = src.read_u32();
|
||||
let total_frames_decoded = src.read_u32();
|
||||
|
||||
Ok(Self {
|
||||
queue_depth,
|
||||
|
@ -57,18 +96,6 @@ impl PduParsing for FrameAcknowledgePdu {
|
|||
total_frames_decoded,
|
||||
})
|
||||
}
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
stream.write_u32::<LittleEndian>(self.queue_depth.to_u32())?;
|
||||
stream.write_u32::<LittleEndian>(self.frame_id)?;
|
||||
stream.write_u32::<LittleEndian>(self.total_frames_decoded)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
12
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -76,31 +103,43 @@ pub struct CacheImportReplyPdu {
|
|||
pub cache_slots: Vec<u16>,
|
||||
}
|
||||
|
||||
impl PduParsing for CacheImportReplyPdu {
|
||||
type Error = GraphicsMessagesError;
|
||||
impl CacheImportReplyPdu {
|
||||
const NAME: &'static str = "CacheImportReplyPdu";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let entries_count = stream.read_u16::<LittleEndian>()? as usize;
|
||||
const FIXED_PART_SIZE: usize = 2 /* Count */;
|
||||
}
|
||||
|
||||
let cache_slots = (0..entries_count)
|
||||
.map(|_| stream.read_u16::<LittleEndian>())
|
||||
.collect::<io::Result<Vec<_>>>()?;
|
||||
impl PduEncode for CacheImportReplyPdu {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_size!(in: dst, size: self.size());
|
||||
|
||||
Ok(Self { cache_slots })
|
||||
}
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
stream.write_u16::<LittleEndian>(self.cache_slots.len() as u16)?;
|
||||
dst.write_u16(cast_length!("Count", self.cache_slots.len())?);
|
||||
|
||||
for cache_slot in self.cache_slots.iter() {
|
||||
stream.write_u16::<LittleEndian>(*cache_slot)?;
|
||||
dst.write_u16(*cache_slot);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
2 + self.cache_slots.iter().map(|_| 2).sum::<usize>()
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE + self.cache_slots.iter().map(|_| 2).sum::<usize>()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PduDecode<'a> for CacheImportReplyPdu {
|
||||
fn decode(src: &mut ReadCursor<'a>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let entries_count = src.read_u16();
|
||||
|
||||
let cache_slots = (0..entries_count).map(|_| src.read_u16()).collect();
|
||||
|
||||
Ok(Self { cache_slots })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -11,7 +11,7 @@ use ironrdp_pdu::input::fast_path::{FastPathInput, FastPathInputEvent};
|
|||
use ironrdp_pdu::input::InputEventPdu;
|
||||
use ironrdp_pdu::mcs::SendDataRequest;
|
||||
use ironrdp_pdu::rdp::capability_sets::{CapabilitySet, CmdFlags, GeneralExtraFlags};
|
||||
use ironrdp_pdu::{self, custom_err, decode, mcs, nego, rdp, Action, PduParsing, PduResult};
|
||||
use ironrdp_pdu::{self, decode, mcs, nego, rdp, Action, PduParsing, PduResult};
|
||||
use ironrdp_svc::{server_encode_svc_messages, StaticChannelSet};
|
||||
use ironrdp_tokio::{Framed, FramedRead, FramedWrite, TokioFramed};
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
|
@ -59,15 +59,13 @@ impl dvc::DvcProcessor for DisplayControlHandler {
|
|||
max_monitor_area_factorb: 2400,
|
||||
});
|
||||
|
||||
let mut buf = vec![];
|
||||
pdu.to_buffer(&mut buf).map_err(|e| custom_err!(e))?;
|
||||
Ok(vec![Box::new(buf)])
|
||||
Ok(vec![Box::new(pdu)])
|
||||
}
|
||||
|
||||
fn process(&mut self, _channel_id: u32, payload: &[u8]) -> PduResult<dvc::DvcMessages> {
|
||||
use ironrdp_pdu::dvc::display::ClientPdu;
|
||||
|
||||
match ClientPdu::from_buffer(payload).map_err(|e| custom_err!(e))? {
|
||||
match decode(payload)? {
|
||||
ClientPdu::DisplayControlMonitorLayout(layout) => {
|
||||
debug!(?layout);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use ironrdp_connector::encode_send_data_request;
|
||||
use ironrdp_connector::legacy::SendDataIndicationCtx;
|
||||
use ironrdp_pdu::cursor::WriteCursor;
|
||||
use ironrdp_pdu::cursor::{ReadCursor, WriteCursor};
|
||||
use ironrdp_pdu::rdp::vc;
|
||||
use ironrdp_pdu::write_buf::WriteBuf;
|
||||
use ironrdp_pdu::{decode, ensure_size, PduEncode, PduResult};
|
||||
use ironrdp_pdu::{decode, PduEncode, PduResult};
|
||||
|
||||
use crate::{SessionError, SessionErrorExt, SessionResult};
|
||||
|
||||
|
@ -14,7 +14,7 @@ pub fn encode_dvc_message(
|
|||
dvc_data: &[u8],
|
||||
buf: &mut WriteBuf,
|
||||
) -> SessionResult<()> {
|
||||
let dvc_length = dvc_pdu.buffer_length() + dvc_data.len();
|
||||
let dvc_length = dvc_pdu.size() + dvc_data.len();
|
||||
|
||||
let channel_header = vc::ChannelPduHeader {
|
||||
length: u32::try_from(dvc_length).expect("dvc message size"),
|
||||
|
@ -47,7 +47,7 @@ impl DvcMessage<'_> {
|
|||
|
||||
impl PduEncode for DvcMessage<'_> {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_size!(in: dst, size: self.size());
|
||||
ironrdp_pdu::ensure_size!(in: dst, size: self.size());
|
||||
|
||||
self.channel_header.encode(dst)?;
|
||||
self.dvc_pdu.encode(dst)?;
|
||||
|
@ -70,7 +70,7 @@ pub struct DynamicChannelCtx<'a> {
|
|||
}
|
||||
|
||||
pub fn decode_dvc_message(ctx: SendDataIndicationCtx<'_>) -> SessionResult<DynamicChannelCtx<'_>> {
|
||||
let mut user_data = ctx.user_data;
|
||||
let user_data = ctx.user_data;
|
||||
|
||||
// [ vc::ChannelPduHeader | …
|
||||
let channel_header: vc::ChannelPduHeader = decode(user_data).map_err(SessionError::pdu)?;
|
||||
|
@ -78,10 +78,11 @@ pub fn decode_dvc_message(ctx: SendDataIndicationCtx<'_>) -> SessionResult<Dynam
|
|||
debug_assert_eq!(dvc_data_len, channel_header.length as usize);
|
||||
|
||||
// … | dvc::ServerPdu | …
|
||||
let dvc_pdu = vc::dvc::ServerPdu::from_buffer(&mut user_data, dvc_data_len).map_err(SessionError::pdu)?;
|
||||
let mut cur = ReadCursor::new(user_data);
|
||||
let dvc_pdu = vc::dvc::ServerPdu::decode(&mut cur, dvc_data_len).map_err(SessionError::pdu)?;
|
||||
|
||||
// … | DvcData ]
|
||||
let dvc_data = user_data;
|
||||
let dvc_data = cur.remaining();
|
||||
|
||||
Ok(DynamicChannelCtx { dvc_pdu, dvc_data })
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use ironrdp_pdu::decode;
|
||||
use ironrdp_pdu::dvc::display::ServerPdu;
|
||||
use ironrdp_pdu::PduParsing;
|
||||
|
||||
use super::DynamicChannelDataHandler;
|
||||
use crate::SessionResult;
|
||||
use crate::{SessionError, SessionErrorExt, SessionResult};
|
||||
|
||||
pub(crate) struct Handler;
|
||||
|
||||
impl DynamicChannelDataHandler for Handler {
|
||||
fn process_complete_data(&mut self, complete_data: Vec<u8>) -> SessionResult<Option<Vec<u8>>> {
|
||||
let gfx_pdu = ServerPdu::from_buffer(&mut complete_data.as_slice())?;
|
||||
let gfx_pdu: ServerPdu = decode(&complete_data).map_err(SessionError::pdu)?;
|
||||
debug!("Got Display PDU: {:?}", gfx_pdu);
|
||||
Ok(None)
|
||||
}
|
||||
|
|
|
@ -6,10 +6,10 @@ use ironrdp_pdu::dvc::gfx::{
|
|||
CapabilitiesV10Flags, CapabilitiesV81Flags, CapabilitiesV8Flags, CapabilitySet, ClientPdu, FrameAcknowledgePdu,
|
||||
QueueDepth, ServerPdu,
|
||||
};
|
||||
use ironrdp_pdu::PduParsing;
|
||||
use ironrdp_pdu::{decode, encode_vec};
|
||||
|
||||
use crate::x224::DynamicChannelDataHandler;
|
||||
use crate::SessionResult;
|
||||
use crate::{SessionError, SessionErrorExt, SessionResult};
|
||||
|
||||
pub trait GfxHandler {
|
||||
fn on_message(&self, message: ServerPdu) -> SessionResult<Option<ClientPdu>>;
|
||||
|
@ -39,9 +39,9 @@ impl DynamicChannelDataHandler for Handler {
|
|||
self.decompressed_buffer.clear();
|
||||
self.decompressor
|
||||
.decompress(complete_data.as_slice(), &mut self.decompressed_buffer)?;
|
||||
let mut slice = &mut self.decompressed_buffer.as_slice();
|
||||
let slice = &mut self.decompressed_buffer.as_slice();
|
||||
while !slice.is_empty() {
|
||||
let gfx_pdu = ServerPdu::from_buffer(&mut slice)?;
|
||||
let gfx_pdu: ServerPdu = decode(slice).map_err(SessionError::pdu)?;
|
||||
debug!("Got GFX PDU: {:?}", gfx_pdu);
|
||||
|
||||
if let ServerPdu::EndFrame(end_frame_pdu) = &gfx_pdu {
|
||||
|
@ -53,8 +53,7 @@ impl DynamicChannelDataHandler for Handler {
|
|||
total_frames_decoded: self.frames_decoded,
|
||||
});
|
||||
debug!("Sending GFX PDU: {:?}", client_pdu);
|
||||
client_pdu_buffer.reserve(client_pdu_buffer.len() + client_pdu.buffer_length());
|
||||
client_pdu.to_buffer(&mut client_pdu_buffer)?;
|
||||
client_pdu_buffer.append(&mut encode_vec(&client_pdu).map_err(SessionError::pdu)?);
|
||||
} else {
|
||||
// Handle the normal PDU
|
||||
}
|
||||
|
@ -65,8 +64,7 @@ impl DynamicChannelDataHandler for Handler {
|
|||
let client_pdu = handler.on_message(gfx_pdu)?;
|
||||
|
||||
if let Some(client_pdu) = client_pdu {
|
||||
client_pdu_buffer.reserve(client_pdu_buffer.len() + client_pdu.buffer_length());
|
||||
client_pdu.to_buffer(&mut client_pdu_buffer)?;
|
||||
client_pdu_buffer.append(&mut encode_vec(&client_pdu).map_err(SessionError::pdu)?);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -195,8 +193,6 @@ pub(crate) fn create_capabilities_advertise(graphics_config: &Option<GraphicsCon
|
|||
}
|
||||
info!(?capabilities);
|
||||
let capabilities_advertise = ClientPdu::CapabilitiesAdvertise(CapabilitiesAdvertisePdu(capabilities));
|
||||
let mut capabilities_advertise_buffer = Vec::with_capacity(capabilities_advertise.buffer_length());
|
||||
capabilities_advertise.to_buffer(&mut capabilities_advertise_buffer)?;
|
||||
|
||||
Ok(capabilities_advertise_buffer)
|
||||
encode_vec(&capabilities_advertise).map_err(SessionError::pdu)
|
||||
}
|
||||
|
|
|
@ -1,22 +1,18 @@
|
|||
use ironrdp_pdu::rdp::vc::dvc::gfx::*;
|
||||
use ironrdp_pdu::{PduBufferParsing, PduParsing};
|
||||
use ironrdp_pdu::cursor::ReadCursor;
|
||||
use ironrdp_pdu::{decode, decode_cursor, encode_vec, PduEncode};
|
||||
use ironrdp_testsuite_core::gfx::*;
|
||||
use ironrdp_testsuite_core::graphics_messages::*;
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_server_pdu() {
|
||||
let mut buffer = HEADER_WITH_WIRE_TO_SURFACE_1_BUFFER.as_slice();
|
||||
let buffer = HEADER_WITH_WIRE_TO_SURFACE_1_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(
|
||||
*HEADER_WITH_WIRE_TO_SURFACE_1,
|
||||
ServerPdu::from_buffer(&mut buffer).unwrap()
|
||||
);
|
||||
assert_eq!(*HEADER_WITH_WIRE_TO_SURFACE_1, decode(buffer).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_server_pdu() {
|
||||
let mut buffer = Vec::with_capacity(HEADER_WITH_WIRE_TO_SURFACE_1_BUFFER.len());
|
||||
HEADER_WITH_WIRE_TO_SURFACE_1.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*HEADER_WITH_WIRE_TO_SURFACE_1).unwrap();
|
||||
|
||||
assert_eq!(buffer, HEADER_WITH_WIRE_TO_SURFACE_1_BUFFER.as_slice());
|
||||
}
|
||||
|
@ -25,21 +21,20 @@ fn to_buffer_correctly_serializes_server_pdu() {
|
|||
fn buffer_length_is_correct_for_server_pdu() {
|
||||
assert_eq!(
|
||||
HEADER_WITH_WIRE_TO_SURFACE_1_BUFFER.len(),
|
||||
HEADER_WITH_WIRE_TO_SURFACE_1.buffer_length()
|
||||
HEADER_WITH_WIRE_TO_SURFACE_1.size()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_client_pdu() {
|
||||
let buffer = HEADER_WITH_FRAME_ACKNOWLEDGE_BUFFER.as_slice();
|
||||
let buffer = HEADER_WITH_FRAME_ACKNOWLEDGE_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(*HEADER_WITH_FRAME_ACKNOWLEDGE, ClientPdu::from_buffer(buffer).unwrap());
|
||||
assert_eq!(*HEADER_WITH_FRAME_ACKNOWLEDGE, decode(buffer).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_client_pdu() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
HEADER_WITH_FRAME_ACKNOWLEDGE.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*HEADER_WITH_FRAME_ACKNOWLEDGE).unwrap();
|
||||
|
||||
assert_eq!(buffer, HEADER_WITH_FRAME_ACKNOWLEDGE_BUFFER.as_slice());
|
||||
}
|
||||
|
@ -48,441 +43,405 @@ fn to_buffer_correctly_serializes_client_pdu() {
|
|||
fn buffer_length_is_correct_for_client_pdu() {
|
||||
assert_eq!(
|
||||
HEADER_WITH_FRAME_ACKNOWLEDGE_BUFFER.len(),
|
||||
HEADER_WITH_FRAME_ACKNOWLEDGE.buffer_length()
|
||||
HEADER_WITH_FRAME_ACKNOWLEDGE.size()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_wire_to_surface_1_pdu() {
|
||||
let mut buffer = WIRE_TO_SURFACE_1_BUFFER.as_ref();
|
||||
let buffer = WIRE_TO_SURFACE_1_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(*WIRE_TO_SURFACE_1, WireToSurface1Pdu::from_buffer(&mut buffer).unwrap());
|
||||
assert_eq!(*WIRE_TO_SURFACE_1, decode(buffer).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_wire_to_surface_1_pdu() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
WIRE_TO_SURFACE_1.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*WIRE_TO_SURFACE_1).unwrap();
|
||||
|
||||
assert_eq!(buffer, WIRE_TO_SURFACE_1_BUFFER.as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_length_is_correct_for_wire_to_surface_1_pdu() {
|
||||
assert_eq!(WIRE_TO_SURFACE_1_BUFFER.len(), WIRE_TO_SURFACE_1.buffer_length());
|
||||
assert_eq!(WIRE_TO_SURFACE_1_BUFFER.len(), WIRE_TO_SURFACE_1.size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_wire_to_surface_2_pdu() {
|
||||
let mut buffer = WIRE_TO_SURFACE_2_BUFFER.as_ref();
|
||||
let buffer = WIRE_TO_SURFACE_2_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(*WIRE_TO_SURFACE_2, WireToSurface2Pdu::from_buffer(&mut buffer).unwrap());
|
||||
assert_eq!(*WIRE_TO_SURFACE_2, decode(buffer).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_wire_to_surface_2_pdu() {
|
||||
let mut buffer = Vec::with_capacity(WIRE_TO_SURFACE_2_BUFFER.len());
|
||||
WIRE_TO_SURFACE_2.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*WIRE_TO_SURFACE_2).unwrap();
|
||||
|
||||
assert_eq!(buffer, WIRE_TO_SURFACE_2_BUFFER.as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_length_is_correct_for_wire_to_surface_2_pdu() {
|
||||
assert_eq!(WIRE_TO_SURFACE_2_BUFFER.len(), WIRE_TO_SURFACE_2.buffer_length());
|
||||
assert_eq!(WIRE_TO_SURFACE_2_BUFFER.len(), WIRE_TO_SURFACE_2.size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_delete_encoding_context_pdu() {
|
||||
let mut buffer = DELETE_ENCODING_CONTEXT_BUFFER.as_ref();
|
||||
let buffer = DELETE_ENCODING_CONTEXT_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(
|
||||
*DELETE_ENCODING_CONTEXT,
|
||||
DeleteEncodingContextPdu::from_buffer(&mut buffer).unwrap()
|
||||
);
|
||||
assert!(buffer.is_empty());
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*DELETE_ENCODING_CONTEXT, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_delete_encoding_context_pdu() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
DELETE_ENCODING_CONTEXT.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*DELETE_ENCODING_CONTEXT).unwrap();
|
||||
|
||||
assert_eq!(buffer, DELETE_ENCODING_CONTEXT_BUFFER.as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_length_is_correct_for_delete_encoding_context_pdu() {
|
||||
assert_eq!(
|
||||
DELETE_ENCODING_CONTEXT_BUFFER.len(),
|
||||
DELETE_ENCODING_CONTEXT.buffer_length()
|
||||
);
|
||||
assert_eq!(DELETE_ENCODING_CONTEXT_BUFFER.len(), DELETE_ENCODING_CONTEXT.size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_solid_fill_pdu() {
|
||||
let mut buffer = SOLID_FILL_BUFFER.as_ref();
|
||||
let buffer = SOLID_FILL_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(*SOLID_FILL, SolidFillPdu::from_buffer(&mut buffer).unwrap());
|
||||
assert!(buffer.is_empty());
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*SOLID_FILL, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_solid_fill_pdu() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
SOLID_FILL.to_buffer(&mut buffer).unwrap();
|
||||
|
||||
let buffer = encode_vec(&*SOLID_FILL).unwrap();
|
||||
assert_eq!(buffer, SOLID_FILL_BUFFER.as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_length_is_correct_for_solid_fill_pdu() {
|
||||
assert_eq!(SOLID_FILL_BUFFER.len(), SOLID_FILL.buffer_length());
|
||||
assert_eq!(SOLID_FILL_BUFFER.len(), SOLID_FILL.size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_surface_to_surface_pdu() {
|
||||
let mut buffer = SURFACE_TO_SURFACE_BUFFER.as_ref();
|
||||
let buffer = SURFACE_TO_SURFACE_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(
|
||||
*SURFACE_TO_SURFACE,
|
||||
SurfaceToSurfacePdu::from_buffer(&mut buffer).unwrap()
|
||||
);
|
||||
assert!(buffer.is_empty());
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*SURFACE_TO_SURFACE, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_surface_to_surface_pdu() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
SURFACE_TO_SURFACE.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*SURFACE_TO_SURFACE).unwrap();
|
||||
|
||||
assert_eq!(buffer, SURFACE_TO_SURFACE_BUFFER.as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_length_is_correct_for_surface_to_surface_pdu() {
|
||||
assert_eq!(SURFACE_TO_SURFACE_BUFFER.len(), SURFACE_TO_SURFACE.buffer_length());
|
||||
assert_eq!(SURFACE_TO_SURFACE_BUFFER.len(), SURFACE_TO_SURFACE.size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_surface_to_cache_pdu() {
|
||||
let mut buffer = SURFACE_TO_CACHE_BUFFER.as_ref();
|
||||
let buffer = SURFACE_TO_CACHE_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(*SURFACE_TO_CACHE, SurfaceToCachePdu::from_buffer(&mut buffer).unwrap());
|
||||
assert!(buffer.is_empty());
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*SURFACE_TO_CACHE, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_surface_to_cache_pdu() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
SURFACE_TO_CACHE.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*SURFACE_TO_CACHE).unwrap();
|
||||
|
||||
assert_eq!(buffer, SURFACE_TO_CACHE_BUFFER.as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_length_is_correct_for_surface_to_cache_pdu() {
|
||||
assert_eq!(SURFACE_TO_CACHE_BUFFER.len(), SURFACE_TO_CACHE.buffer_length());
|
||||
assert_eq!(SURFACE_TO_CACHE_BUFFER.len(), SURFACE_TO_CACHE.size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_cache_to_surface_pdu() {
|
||||
let mut buffer = CACHE_TO_SURFACE_BUFFER.as_ref();
|
||||
let buffer = CACHE_TO_SURFACE_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(*CACHE_TO_SURFACE, CacheToSurfacePdu::from_buffer(&mut buffer).unwrap());
|
||||
assert!(buffer.is_empty());
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*CACHE_TO_SURFACE, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_cache_to_surface_pdu() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
CACHE_TO_SURFACE.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*CACHE_TO_SURFACE).unwrap();
|
||||
|
||||
assert_eq!(buffer, CACHE_TO_SURFACE_BUFFER.as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_length_is_correct_for_cache_to_surface_pdu() {
|
||||
assert_eq!(CACHE_TO_SURFACE_BUFFER.len(), CACHE_TO_SURFACE.buffer_length());
|
||||
assert_eq!(CACHE_TO_SURFACE_BUFFER.len(), CACHE_TO_SURFACE.size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_create_surface_pdu() {
|
||||
let mut buffer = CREATE_SURFACE_BUFFER.as_ref();
|
||||
let buffer = CREATE_SURFACE_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(*CREATE_SURFACE, CreateSurfacePdu::from_buffer(&mut buffer).unwrap());
|
||||
assert!(buffer.is_empty());
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*CREATE_SURFACE, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_create_surface_pdu() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
CREATE_SURFACE.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*CREATE_SURFACE).unwrap();
|
||||
|
||||
assert_eq!(buffer, CREATE_SURFACE_BUFFER.as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_length_is_correct_for_create_surface_pdu() {
|
||||
assert_eq!(CREATE_SURFACE_BUFFER.len(), CREATE_SURFACE.buffer_length());
|
||||
assert_eq!(CREATE_SURFACE_BUFFER.len(), CREATE_SURFACE.size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_delete_surface_pdu() {
|
||||
let mut buffer = DELETE_SURFACE_BUFFER.as_ref();
|
||||
let buffer = DELETE_SURFACE_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(*DELETE_SURFACE, DeleteSurfacePdu::from_buffer(&mut buffer).unwrap());
|
||||
assert!(buffer.is_empty());
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*DELETE_SURFACE, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_delete_surface_pdu() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
DELETE_SURFACE.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*DELETE_SURFACE).unwrap();
|
||||
|
||||
assert_eq!(buffer, DELETE_SURFACE_BUFFER.as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_length_is_correct_for_delete_surface_pdu() {
|
||||
assert_eq!(DELETE_SURFACE_BUFFER.len(), DELETE_SURFACE.buffer_length());
|
||||
assert_eq!(DELETE_SURFACE_BUFFER.len(), DELETE_SURFACE.size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_reset_graphics() {
|
||||
let mut buffer = RESET_GRAPHICS_BUFFER.as_ref();
|
||||
let buffer = RESET_GRAPHICS_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(*RESET_GRAPHICS, ResetGraphicsPdu::from_buffer(&mut buffer).unwrap());
|
||||
assert!(buffer.is_empty());
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*RESET_GRAPHICS, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_reset_graphics() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
RESET_GRAPHICS.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*RESET_GRAPHICS).unwrap();
|
||||
|
||||
assert_eq!(buffer, RESET_GRAPHICS_BUFFER.as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_length_is_correct_for_reset_graphics() {
|
||||
assert_eq!(RESET_GRAPHICS_BUFFER.len(), RESET_GRAPHICS.buffer_length());
|
||||
assert_eq!(RESET_GRAPHICS_BUFFER.len(), RESET_GRAPHICS.size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_map_surface_to_output_pdu() {
|
||||
let mut buffer = MAP_SURFACE_TO_OUTPUT_BUFFER.as_ref();
|
||||
let buffer = MAP_SURFACE_TO_OUTPUT_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(
|
||||
*MAP_SURFACE_TO_OUTPUT,
|
||||
MapSurfaceToOutputPdu::from_buffer(&mut buffer).unwrap()
|
||||
);
|
||||
assert!(buffer.is_empty());
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*MAP_SURFACE_TO_OUTPUT, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_map_surface_to_output_pdu() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
MAP_SURFACE_TO_OUTPUT.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*MAP_SURFACE_TO_OUTPUT).unwrap();
|
||||
|
||||
assert_eq!(buffer, MAP_SURFACE_TO_OUTPUT_BUFFER.as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_length_is_correct_for_map_surface_to_output_pdu() {
|
||||
assert_eq!(
|
||||
MAP_SURFACE_TO_OUTPUT_BUFFER.len(),
|
||||
MAP_SURFACE_TO_OUTPUT.buffer_length()
|
||||
);
|
||||
assert_eq!(MAP_SURFACE_TO_OUTPUT_BUFFER.len(), MAP_SURFACE_TO_OUTPUT.size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_evict_cache_entry_pdu() {
|
||||
let mut buffer = EVICT_CACHE_ENTRY_BUFFER.as_ref();
|
||||
let buffer = EVICT_CACHE_ENTRY_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(
|
||||
*EVICT_CACHE_ENTRY,
|
||||
EvictCacheEntryPdu::from_buffer(&mut buffer).unwrap()
|
||||
);
|
||||
assert!(buffer.is_empty());
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*EVICT_CACHE_ENTRY, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_evict_cache_entry_pdu() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
EVICT_CACHE_ENTRY.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*EVICT_CACHE_ENTRY).unwrap();
|
||||
|
||||
assert_eq!(buffer, EVICT_CACHE_ENTRY_BUFFER.as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_length_is_correct_for_evict_cache_entry_pdu() {
|
||||
assert_eq!(EVICT_CACHE_ENTRY_BUFFER.len(), EVICT_CACHE_ENTRY.buffer_length());
|
||||
assert_eq!(EVICT_CACHE_ENTRY_BUFFER.len(), EVICT_CACHE_ENTRY.size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_start_frame_pdu() {
|
||||
let mut buffer = START_FRAME_BUFFER.as_ref();
|
||||
let buffer = START_FRAME_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(*START_FRAME, StartFramePdu::from_buffer(&mut buffer).unwrap());
|
||||
assert!(buffer.is_empty());
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*START_FRAME, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_start_frame_pdu() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
START_FRAME.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*START_FRAME).unwrap();
|
||||
|
||||
assert_eq!(buffer, START_FRAME_BUFFER.as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_length_is_correct_for_start_frame_pdu() {
|
||||
assert_eq!(START_FRAME_BUFFER.len(), START_FRAME.buffer_length());
|
||||
assert_eq!(START_FRAME_BUFFER.len(), START_FRAME.size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_end_frame_pdu() {
|
||||
let mut buffer = END_FRAME_BUFFER.as_ref();
|
||||
let buffer = END_FRAME_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(*END_FRAME, EndFramePdu::from_buffer(&mut buffer).unwrap());
|
||||
assert!(buffer.is_empty());
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*END_FRAME, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_end_frame_pdu() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
END_FRAME.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*END_FRAME).unwrap();
|
||||
|
||||
assert_eq!(buffer, END_FRAME_BUFFER.as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_length_is_correct_for_end_frame_pdu() {
|
||||
assert_eq!(END_FRAME_BUFFER.len(), END_FRAME.buffer_length());
|
||||
assert_eq!(END_FRAME_BUFFER.len(), END_FRAME.size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_capabilities_confirm_pdu() {
|
||||
let mut buffer = CAPABILITIES_CONFIRM_BUFFER.as_ref();
|
||||
let buffer = CAPABILITIES_CONFIRM_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(
|
||||
*CAPABILITIES_CONFIRM,
|
||||
CapabilitiesConfirmPdu::from_buffer(&mut buffer).unwrap()
|
||||
);
|
||||
assert!(buffer.is_empty());
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*CAPABILITIES_CONFIRM, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_capabilities_confirm_pdu() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
CAPABILITIES_CONFIRM.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*CAPABILITIES_CONFIRM).unwrap();
|
||||
|
||||
assert_eq!(buffer, CAPABILITIES_CONFIRM_BUFFER.as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_length_is_correct_for_capabilities_confirm_pdu() {
|
||||
assert_eq!(CAPABILITIES_CONFIRM_BUFFER.len(), CAPABILITIES_CONFIRM.buffer_length());
|
||||
assert_eq!(CAPABILITIES_CONFIRM_BUFFER.len(), CAPABILITIES_CONFIRM.size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_capabilities_advertise_pdu() {
|
||||
let mut buffer = CAPABILITIES_ADVERTISE_BUFFER.as_ref();
|
||||
let buffer = CAPABILITIES_ADVERTISE_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(
|
||||
*CAPABILITIES_ADVERTISE,
|
||||
CapabilitiesAdvertisePdu::from_buffer(&mut buffer).unwrap()
|
||||
);
|
||||
assert!(buffer.is_empty());
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*CAPABILITIES_ADVERTISE, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_capabilities_advertise_pdu() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
CAPABILITIES_ADVERTISE.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*CAPABILITIES_ADVERTISE).unwrap();
|
||||
|
||||
assert_eq!(buffer, CAPABILITIES_ADVERTISE_BUFFER.as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_length_is_correct_for_capabilities_advertise_pdu() {
|
||||
assert_eq!(
|
||||
CAPABILITIES_ADVERTISE_BUFFER.len(),
|
||||
CAPABILITIES_ADVERTISE.buffer_length()
|
||||
);
|
||||
assert_eq!(CAPABILITIES_ADVERTISE_BUFFER.len(), CAPABILITIES_ADVERTISE.size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_frame_acknowledge_pdu() {
|
||||
let mut buffer = FRAME_ACKNOWLEDGE_BUFFER.as_ref();
|
||||
let buffer = FRAME_ACKNOWLEDGE_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(
|
||||
*FRAME_ACKNOWLEDGE,
|
||||
FrameAcknowledgePdu::from_buffer(&mut buffer).unwrap()
|
||||
);
|
||||
assert!(buffer.is_empty());
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*FRAME_ACKNOWLEDGE, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_frame_acknowledge_pdu() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
FRAME_ACKNOWLEDGE.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*FRAME_ACKNOWLEDGE).unwrap();
|
||||
|
||||
assert_eq!(buffer, FRAME_ACKNOWLEDGE_BUFFER.as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_length_is_correct_for_frame_acknowledge_pdu() {
|
||||
assert_eq!(FRAME_ACKNOWLEDGE_BUFFER.len(), FRAME_ACKNOWLEDGE.buffer_length());
|
||||
assert_eq!(FRAME_ACKNOWLEDGE_BUFFER.len(), FRAME_ACKNOWLEDGE.size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_cache_import_reply() {
|
||||
let mut buffer = CACHE_IMPORT_REPLY_BUFFER.as_ref();
|
||||
let buffer = CACHE_IMPORT_REPLY_BUFFER.as_ref();
|
||||
|
||||
assert_eq!(
|
||||
*CACHE_IMPORT_REPLY,
|
||||
CacheImportReplyPdu::from_buffer(&mut buffer).unwrap()
|
||||
);
|
||||
assert!(buffer.is_empty());
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*CACHE_IMPORT_REPLY, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_cache_import_reply() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
CACHE_IMPORT_REPLY.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*CACHE_IMPORT_REPLY).unwrap();
|
||||
|
||||
assert_eq!(buffer, CACHE_IMPORT_REPLY_BUFFER.as_ref());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_length_is_correct_for_cache_import_reply() {
|
||||
assert_eq!(CACHE_IMPORT_REPLY_BUFFER.len(), CACHE_IMPORT_REPLY.buffer_length());
|
||||
assert_eq!(CACHE_IMPORT_REPLY_BUFFER.len(), CACHE_IMPORT_REPLY.size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_consume_correctly_parses_incorrect_len_avc_444_message() {
|
||||
let mut buffer = AVC_444_MESSAGE_INCORRECT_LEN.as_ref();
|
||||
assert_eq!(
|
||||
*AVC_444_BITMAP,
|
||||
Avc444BitmapStream::from_buffer_consume(&mut buffer).unwrap()
|
||||
);
|
||||
let buffer = AVC_444_MESSAGE_INCORRECT_LEN.as_ref();
|
||||
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*AVC_444_BITMAP, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(!cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_buffer_consume_correctly_parses_avc_444_message() {
|
||||
let mut buffer = AVC_444_MESSAGE_CORRECT_LEN.as_ref();
|
||||
assert_eq!(
|
||||
*AVC_444_BITMAP,
|
||||
Avc444BitmapStream::from_buffer_consume(&mut buffer).unwrap()
|
||||
);
|
||||
let buffer = AVC_444_MESSAGE_CORRECT_LEN.as_ref();
|
||||
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*AVC_444_BITMAP, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_consume_correctly_serializes_avc_444_message() {
|
||||
let buffer = encode_vec(&*AVC_444_BITMAP).unwrap();
|
||||
let expected = AVC_444_MESSAGE_CORRECT_LEN.as_ref();
|
||||
let mut buffer = vec![0; expected.len()];
|
||||
|
||||
AVC_444_BITMAP.to_buffer_consume(&mut buffer.as_mut_slice()).unwrap();
|
||||
assert_eq!(expected, buffer.as_slice());
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue