Skip to content

Commit

Permalink
refactor: write_padding! and read_padding! macros (#177)
Browse files Browse the repository at this point in the history
Macros ensuring optimal handling of padding at compile time.
  • Loading branch information
CBenoit authored Aug 15, 2023
1 parent 4c38be2 commit 55176ff
Show file tree
Hide file tree
Showing 30 changed files with 135 additions and 74 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/ironrdp-client/src/gui.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use anyhow::Context as _;
use softbuffer::GraphicsContext;
use tokio::sync::mpsc;
use winit::dpi::LogicalPosition;
use winit::event::{self, Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop, EventLoopBuilder};
use winit::window::{Window, WindowBuilder};

use crate::rdp::{RdpInputEvent, RdpOutputEvent};
use winit::dpi::LogicalPosition;

pub struct GuiContext {
pub window: Window,
Expand Down
11 changes: 6 additions & 5 deletions crates/ironrdp-cliprdr/src/pdu/capabilities.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use crate::pdu::PartialHeader;
use bitflags::bitflags;
use ironrdp_pdu::cursor::{ReadCursor, WriteCursor};
use ironrdp_pdu::{
cast_int, cast_length, ensure_fixed_part_size, ensure_size, invalid_message_err, padding, PduDecode, PduEncode,
PduResult,
cast_int, cast_length, ensure_fixed_part_size, ensure_size, invalid_message_err, read_padding, write_padding,
PduDecode, PduEncode, PduResult,
};

use crate::pdu::PartialHeader;

/// Represents `CLIPRDR_CAPS`
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Capabilities {
Expand All @@ -29,7 +30,7 @@ impl PduEncode for Capabilities {
ensure_size!(in: dst, size: self.inner_size());

dst.write_u16(cast_length!(Self::NAME, "cCapabilitiesSets", self.capabilities.len())?);
padding::write(dst, 2);
write_padding!(dst, 2);

for capability in &self.capabilities {
capability.encode(dst)?;
Expand All @@ -53,7 +54,7 @@ impl<'de> PduDecode<'de> for Capabilities {

ensure_fixed_part_size!(in: src);
let capabilities_count = src.read_u16();
padding::read(src, 2);
read_padding!(src, 2);

let mut capabilities = Vec::with_capacity(usize::from(capabilities_count));

Expand Down
6 changes: 4 additions & 2 deletions crates/ironrdp-cliprdr/src/pdu/client_temporary_directory.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use crate::pdu::PartialHeader;
use std::borrow::Cow;

use ironrdp_pdu::cursor::{ReadCursor, WriteCursor};
use ironrdp_pdu::utils::{read_string_from_cursor, write_string_to_cursor, CharacterSet};
use ironrdp_pdu::{
cast_int, ensure_fixed_part_size, ensure_size, invalid_message_err, PduDecode, PduEncode, PduResult,
};
use std::borrow::Cow;

use crate::pdu::PartialHeader;

/// Represents `CLIPRDR_TEMP_DIRECTORY`
#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down
6 changes: 4 additions & 2 deletions crates/ironrdp-cliprdr/src/pdu/file_contents.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::pdu::{ClipboardPduFlags, PartialHeader};
use std::borrow::Cow;

use bitflags::bitflags;
use ironrdp_pdu::cursor::{ReadCursor, WriteCursor};
use ironrdp_pdu::utils::{combine_u64, split_u64};
use ironrdp_pdu::{cast_int, ensure_size, invalid_message_err, PduDecode, PduEncode, PduResult};
use std::borrow::Cow;

use crate::pdu::{ClipboardPduFlags, PartialHeader};

bitflags! {
/// Represents `dwFlags` field of `CLIPRDR_FILECONTENTS_REQUEST` structure.
Expand Down
3 changes: 2 additions & 1 deletion crates/ironrdp-cliprdr/src/pdu/format_data/metafile.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use std::borrow::Cow;

use bitflags::bitflags;
use ironrdp_pdu::cursor::{ReadCursor, WriteCursor};
use ironrdp_pdu::{ensure_fixed_part_size, ensure_size, PduDecode, PduEncode, PduResult};
use std::borrow::Cow;

bitflags! {
/// Represents `mappingMode` fields of `CLIPRDR_MFPICT` strucutre.
Expand Down
13 changes: 8 additions & 5 deletions crates/ironrdp-cliprdr/src/pdu/format_data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ mod file_list;
mod metafile;
mod palette;

pub use file_list::*;
pub use metafile::*;
pub use palette::*;
pub use self::file_list::*;
pub use self::metafile::*;
pub use self::palette::*;

#[rustfmt::skip]
use std::borrow::Cow;

use crate::pdu::{ClipboardPduFlags, PartialHeader};
use ironrdp_pdu::cursor::{ReadCursor, WriteCursor};
use ironrdp_pdu::utils::{read_string_from_cursor, to_utf16_bytes, CharacterSet};
use ironrdp_pdu::{cast_int, ensure_fixed_part_size, ensure_size, PduDecode, PduEncode, PduResult};
use std::borrow::Cow;

use crate::pdu::{ClipboardPduFlags, PartialHeader};

/// Represents `CLIPRDR_FORMAT_DATA_RESPONSE`
#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down
6 changes: 4 additions & 2 deletions crates/ironrdp-cliprdr/src/pdu/format_list.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::pdu::{ClipboardPduFlags, PartialHeader};
use std::borrow::Cow;

use ironrdp_pdu::cursor::{ReadCursor, WriteCursor};
use ironrdp_pdu::utils::{read_string_from_cursor, to_utf16_bytes, write_string_to_cursor, CharacterSet};
use ironrdp_pdu::{cast_int, ensure_size, invalid_message_err, PduDecode, PduEncode, PduResult};
use std::borrow::Cow;

use crate::pdu::{ClipboardPduFlags, PartialHeader};

/// Represents `CLIPRDR_SHORT_FORMAT_NAME` and `CLIPRDR_LONG_FORMAT_NAME`
#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down
3 changes: 2 additions & 1 deletion crates/ironrdp-cliprdr/src/pdu/lock.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::pdu::PartialHeader;
use ironrdp_pdu::cursor::{ReadCursor, WriteCursor};
use ironrdp_pdu::{cast_int, ensure_fixed_part_size, PduDecode, PduEncode, PduResult};

use crate::pdu::PartialHeader;

/// Represents `CLIPRDR_LOCK_CLIPDATA`/`CLIPRDR_UNLOCK_CLIPDATA`
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LockDataId(pub u32);
Expand Down
15 changes: 8 additions & 7 deletions crates/ironrdp-cliprdr/src/pdu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ mod format_data;
mod format_list;
mod lock;

pub use capabilities::*;
pub use client_temporary_directory::*;
pub use file_contents::*;
pub use format_data::*;
pub use format_list::*;
pub use lock::*;

pub use self::capabilities::*;
pub use self::client_temporary_directory::*;
pub use self::file_contents::*;
pub use self::format_data::*;
pub use self::format_list::*;
pub use self::lock::*;

#[rustfmt::skip]
use bitflags::bitflags;
use ironrdp_pdu::cursor::{ReadCursor, WriteCursor};
use ironrdp_pdu::{ensure_fixed_part_size, invalid_message_err, PduDecode, PduEncode, PduResult};
Expand Down
4 changes: 3 additions & 1 deletion crates/ironrdp-connector/src/legacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,9 @@ pub fn decode_share_data(ctx: SendDataIndicationCtx<'_>) -> ConnectorResult<Shar
let ctx = decode_share_control(ctx)?;

let rdp::headers::ShareControlPdu::Data(share_data_header) = ctx.pdu else {
return Err(general_err!("received unexpected Share Control Pdu (expected SHare Data Header)"));
return Err(general_err!(
"received unexpected Share Control Pdu (expected SHare Data Header)"
));
};

Ok(ShareDataCtx {
Expand Down
9 changes: 4 additions & 5 deletions crates/ironrdp-graphics/src/pointer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@
//! - andMask == 1, xorMask == 0(black color) -> Transparent pixel
//! - andMask == 1, xorMask == 1(white color) -> Pixel is inverted

use crate::color_conversion::rdp_16bit_to_rgb;
use ironrdp_pdu::{
cursor::ReadCursor,
pointer::{ColorPointerAttribute, LargePointerAttribute, PointerAttribute},
};
use ironrdp_pdu::cursor::ReadCursor;
use ironrdp_pdu::pointer::{ColorPointerAttribute, LargePointerAttribute, PointerAttribute};
use thiserror::Error;

use crate::color_conversion::rdp_16bit_to_rgb;

#[derive(Debug, Error)]
pub enum PointerError {
#[error("Invalid pointer xorMask size. Expected: {expected}, actual: {actual}")]
Expand Down
3 changes: 2 additions & 1 deletion crates/ironrdp-pdu/src/basic_output/fast_path/tests.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use lazy_static::lazy_static;

use super::*;
use crate::{decode, encode};
use lazy_static::lazy_static;

const FAST_PATH_HEADER_WITH_SHORT_LEN_BUFFER: [u8; 2] = [0x80, 0x08];
const FAST_PATH_HEADER_WITH_LONG_LEN_BUFFER: [u8; 3] = [0x80, 0x81, 0xE7];
Expand Down
6 changes: 2 additions & 4 deletions crates/ironrdp-pdu/src/basic_output/pointer.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use crate::{
cursor::{ReadCursor, WriteCursor},
PduDecode, PduEncode, PduResult,
};
use crate::cursor::{ReadCursor, WriteCursor};
use crate::{PduDecode, PduEncode, PduResult};

// Represents `TS_POINT16` described in [MS-RDPBCGR] 2.2.9.1.1.4.1
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand Down
6 changes: 4 additions & 2 deletions crates/ironrdp-pdu/src/geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,12 @@ impl<'de> PduDecode<'de> for ExclusiveRectangle {
// Legacy code for serializing/deserializing exclusive rectangles as inclusive rectangles structure
// TODO(@pacmancoder) this should be removed later
mod legacy {
use super::*;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use std::io;

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};

use super::*;

impl InclusiveRectangle {
// TODO: clarify code related to rectangles (inclusive vs exclusive bounds, …)
// See for instance:
Expand Down
35 changes: 35 additions & 0 deletions crates/ironrdp-pdu/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,41 @@ macro_rules! impl_pdu_borrowing {
};
}

/// Writes zeroes using as few `write_u*` calls as possible.
///
/// This is similar to `ironrdp_pdu::padding::write`, but the loop is optimized out when a single
/// operation is enough.
#[macro_export]
macro_rules! write_padding {
($dst:expr, 1) => {
$dst.write_u8(0)
};
($dst:expr, 2) => {
$dst.write_u16(0)
};
($dst:expr, 4) => {
$dst.write_u32(0)
};
($dst:expr, 8) => {
$dst.write_u64(0)
};
($dst:expr, $n:expr) => {
$crate::padding::write($dst, $n)
};
}

/// Moves read cursor, ignoring padding bytes.
///
/// This is similar to `ironrdp_pdu::padding::read`, only exists for consistancy with `write_padding!`.
#[macro_export]
macro_rules! read_padding {
($src:expr, $n:expr) => {
$crate::padding::read($src, $n)
};
}

// FIXME: legacy macros below

#[macro_export]
macro_rules! try_read_optional {
($e:expr, $ret:expr) => {
Expand Down
4 changes: 2 additions & 2 deletions crates/ironrdp-pdu/src/mcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ impl<'de> McsPdu<'de> for SendDataRequest<'de> {

// dataPriority + segmentation
ensure_size!(ctx: Self::MCS_NAME, in: src, size: 1);
crate::padding::read(src, 1);
read_padding!(src, 1);

let (length, _) = per::read_length(src).map_err(per_field_err!("userDataLength"))?;
let length = usize::from(length);
Expand Down Expand Up @@ -682,7 +682,7 @@ impl<'de> McsPdu<'de> for SendDataIndication<'de> {

// dataPriority + segmentation
ensure_size!(ctx: Self::MCS_NAME, in: src, size: 1);
crate::padding::read(src, 1);
read_padding!(src, 1);

let (length, _) = per::read_length(src).map_err(per_field_err!("userDataLength"))?;
let length = usize::from(length);
Expand Down
10 changes: 8 additions & 2 deletions crates/ironrdp-pdu/src/nego.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,14 @@ impl<'de> X224Pdu<'de> for ConnectionRequest {

let nego_data = NegoRequestData::read(src)?;

let Some(variable_part_rest_size) = variable_part_size.checked_sub(nego_data.as_ref().map(|data| data.size()).unwrap_or(0)) else {
return Err(PduError::invalid_message(Self::NAME, "TPDU header variable part", "advertised size too small"));
let Some(variable_part_rest_size) =
variable_part_size.checked_sub(nego_data.as_ref().map(|data| data.size()).unwrap_or(0))
else {
return Err(PduError::invalid_message(
Self::NAME,
"TPDU header variable part",
"advertised size too small",
));
};

if variable_part_rest_size >= usize::from(Self::RDP_NEG_REQ_SIZE) {
Expand Down
4 changes: 2 additions & 2 deletions crates/ironrdp-pdu/src/pcb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl<'de> PduDecode<'de> for PreconnectionBlob {
));
}

crate::padding::read(src, 4); // flags
read_padding!(src, 4); // flags

// The version field SHOULD be initialized by the client and SHOULD be ignored by the server,
// as specified in sections 3.1.5.1 and 3.2.5.1.
Expand Down Expand Up @@ -118,7 +118,7 @@ impl PduEncode for PreconnectionBlob {
ensure_size!(in: dst, size: pcb_size);

dst.write_u32(cast_length!("cbSize", pcb_size)?); // cbSize
crate::padding::write(dst, 4); // flags
write_padding!(dst, 4); // flags
dst.write_u32(self.version.0); // version
dst.write_u32(self.id); // id

Expand Down
4 changes: 2 additions & 2 deletions crates/ironrdp-pdu/src/tpdu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,10 @@ impl TpduHeader {
}

if code == TpduCode::DATA {
crate::padding::read(src, 1); // EOT
read_padding!(src, 1); // EOT
} else {
ensure_size!(in: src, size: 5);
crate::padding::read(src, 5); // DST-REF, SRC-REF, Class 0
read_padding!(src, 5); // DST-REF, SRC-REF, Class 0
}

Ok(Self { li, code })
Expand Down
4 changes: 2 additions & 2 deletions crates/ironrdp-pdu/src/tpkt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ impl TpktHeader {
return Err(PduError::unsupported_version("TPKT version", version));
}

crate::padding::read(src, 1);
read_padding!(src, 1);

let packet_length = src.read_u16_be();

Expand All @@ -68,7 +68,7 @@ impl TpktHeader {

dst.write_u8(Self::VERSION);

crate::padding::write(dst, 1);
write_padding!(dst, 1);

dst.write_u16_be(self.packet_length);

Expand Down
7 changes: 3 additions & 4 deletions crates/ironrdp-pdu/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use std::io;

use crate::{
cursor::{ReadCursor, WriteCursor},
PduResult,
};
use byteorder::{LittleEndian, ReadBytesExt as _, WriteBytesExt as _};
use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::ToPrimitive as _;

use crate::cursor::{ReadCursor, WriteCursor};
use crate::PduResult;

pub fn split_u64(value: u64) -> (u32, u32) {
let bytes = value.to_le_bytes();
let (low, high) = bytes.split_at(std::mem::size_of::<u32>());
Expand Down
7 changes: 5 additions & 2 deletions crates/ironrdp-rdcleanpath/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ impl RDCleanPathPdu {
use der::{Decode as _, Encode as _};

let Ok(mut reader) = der::SliceReader::new(src) else {
return DetectionResult::Failed
return DetectionResult::Failed;
};

let header = match der::Header::decode(&mut reader) {
Expand All @@ -139,7 +139,10 @@ impl RDCleanPathPdu {
},
};

let (Ok(header_encoded_len), Ok(body_length)) = (header.encoded_len().and_then(usize::try_from), usize::try_from(header.length)) else {
let (Ok(header_encoded_len), Ok(body_length)) = (
header.encoded_len().and_then(usize::try_from),
usize::try_from(header.length),
) else {
return DetectionResult::Failed;
};

Expand Down
Loading

0 comments on commit 55176ff

Please sign in to comment.