refactor(dvc): switch to PduEncode/Decode

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
Marc-André Lureau 2024-02-02 15:33:26 +04:00 committed by Benoît Cortier
parent ed963cefb6
commit b0dd0677a4
18 changed files with 1550 additions and 1309 deletions

View file

@ -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 })
}

View file

@ -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;

View file

@ -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")]

View file

@ -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"
}
}

View file

@ -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 })

View file

@ -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);

View file

@ -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";

View file

@ -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"
}
}

View file

@ -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"
}
}

View file

@ -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)
}
}

View file

@ -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
}
}

View file

@ -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 })
}
}

View file

@ -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);
}

View file

@ -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 })
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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());
}