mirror of
https://github.com/Devolutions/IronRDP.git
synced 2025-08-04 15:18:17 +00:00
refactor(pdu): convert input module to PduEncode/Decode
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
parent
2f955f16c3
commit
9faf1ff08d
14 changed files with 517 additions and 339 deletions
|
@ -79,8 +79,8 @@ pub fn pdu_decode(data: &[u8]) {
|
|||
let _ = codecs::rfx::ChannelsPdu::from_buffer(data);
|
||||
let _ = codecs::rfx::RfxChannel::from_buffer(data);
|
||||
|
||||
let _ = input::InputEventPdu::from_buffer(data);
|
||||
let _ = input::InputEvent::from_buffer(data);
|
||||
let _ = decode::<input::InputEventPdu>(data);
|
||||
let _ = decode::<input::InputEvent>(data);
|
||||
|
||||
let _ = decode::<bitmap::rdp6::BitmapStream<'_>>(data);
|
||||
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
use std::io::{self};
|
||||
|
||||
use bit_field::BitField;
|
||||
use bitflags::bitflags;
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use num_derive::{FromPrimitive, ToPrimitive};
|
||||
use num_traits::{FromPrimitive, ToPrimitive};
|
||||
|
||||
use crate::cursor::{ReadCursor, WriteCursor};
|
||||
use crate::fast_path::EncryptionFlags;
|
||||
use crate::input::{InputEventError, MousePdu, MouseRelPdu, MouseXPdu};
|
||||
use crate::{per, PduParsing};
|
||||
use crate::input::{MousePdu, MouseRelPdu, MouseXPdu};
|
||||
use crate::{per, PduDecode, PduEncode, PduResult};
|
||||
|
||||
/// Implements the Fast-Path RDP message header PDU.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -18,21 +16,60 @@ pub struct FastPathInputHeader {
|
|||
pub num_events: u8,
|
||||
}
|
||||
|
||||
impl PduParsing for FastPathInputHeader {
|
||||
type Error = InputEventError;
|
||||
impl FastPathInputHeader {
|
||||
const NAME: &'static str = "FastPathInputHeader";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let header = stream.read_u8()?;
|
||||
const FIXED_PART_SIZE: usize = 1 /* header */;
|
||||
}
|
||||
|
||||
impl PduEncode for FastPathInputHeader {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_size!(in: dst, size: self.size());
|
||||
|
||||
let mut header = 0u8;
|
||||
header.set_bits(0..2, 0); // fast-path action
|
||||
if self.num_events < 16 {
|
||||
header.set_bits(2..7, self.num_events);
|
||||
}
|
||||
header.set_bits(6..8, self.flags.bits());
|
||||
dst.write_u8(header);
|
||||
|
||||
per::write_length(dst, cast_length!("len", self.data_length + self.size())?);
|
||||
if self.num_events > 15 {
|
||||
dst.write_u8(self.num_events);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
let num_events_length = if self.num_events < 16 { 0 } else { 1 };
|
||||
Self::FIXED_PART_SIZE
|
||||
+ per::sizeof_length(self.data_length as u16 + num_events_length as u16 + 1)
|
||||
+ num_events_length
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for FastPathInputHeader {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let header = src.read_u8();
|
||||
let flags = EncryptionFlags::from_bits_truncate(header.get_bits(6..8));
|
||||
let mut num_events = header.get_bits(2..6);
|
||||
let (length, sizeof_length) = per::legacy::read_length(&mut stream)?;
|
||||
let (length, sizeof_length) = per::read_length(src).map_err(|e| custom_err!("perLen", e))?;
|
||||
|
||||
if !flags.is_empty() {
|
||||
return Err(InputEventError::EncryptionNotSupported);
|
||||
return Err(invalid_message_err!("flags", "encryption not supported"));
|
||||
}
|
||||
|
||||
let num_events_length = if num_events == 0 {
|
||||
num_events = stream.read_u8()?;
|
||||
ensure_size!(in: src, size: 1);
|
||||
num_events = src.read_u8();
|
||||
1
|
||||
} else {
|
||||
0
|
||||
|
@ -46,28 +83,6 @@ impl PduParsing for FastPathInputHeader {
|
|||
num_events,
|
||||
})
|
||||
}
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
let mut header = 0u8;
|
||||
header.set_bits(0..2, 0); // fast-path action
|
||||
if self.num_events < 16 {
|
||||
header.set_bits(2..7, self.num_events);
|
||||
}
|
||||
header.set_bits(6..8, self.flags.bits());
|
||||
stream.write_u8(header)?;
|
||||
|
||||
per::legacy::write_length(&mut stream, (self.data_length + self.buffer_length()) as u16)?;
|
||||
if self.num_events > 15 {
|
||||
stream.write_u8(self.num_events)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
let num_events_length = if self.num_events < 16 { 0 } else { 1 };
|
||||
1 + per::sizeof_length(self.data_length as u16 + num_events_length as u16 + 1) + num_events_length
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
|
||||
|
@ -93,52 +108,16 @@ pub enum FastPathInputEvent {
|
|||
SyncEvent(SynchronizeFlags),
|
||||
}
|
||||
|
||||
impl PduParsing for FastPathInputEvent {
|
||||
type Error = InputEventError;
|
||||
impl FastPathInputEvent {
|
||||
const NAME: &'static str = "FastPathInputEvent";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let header = stream.read_u8()?;
|
||||
let flags = header.get_bits(0..5);
|
||||
let code = header.get_bits(5..8);
|
||||
let code: FastpathInputEventType =
|
||||
FastpathInputEventType::from_u8(code).ok_or(InputEventError::EventCodeUnsupported(code))?;
|
||||
let event = match code {
|
||||
FastpathInputEventType::ScanCode => {
|
||||
let code = stream.read_u8()?;
|
||||
let flags = KeyboardFlags::from_bits(flags).ok_or(InputEventError::KeyboardFlagsUnsupported(flags))?;
|
||||
FastPathInputEvent::KeyboardEvent(flags, code)
|
||||
}
|
||||
FastpathInputEventType::Mouse => {
|
||||
let mouse_event = MousePdu::from_buffer(stream)?;
|
||||
FastPathInputEvent::MouseEvent(mouse_event)
|
||||
}
|
||||
FastpathInputEventType::MouseX => {
|
||||
let mouse_event = MouseXPdu::from_buffer(stream)?;
|
||||
FastPathInputEvent::MouseEventEx(mouse_event)
|
||||
}
|
||||
FastpathInputEventType::MouseRel => {
|
||||
let mouse_event = MouseRelPdu::from_buffer(stream)?;
|
||||
FastPathInputEvent::MouseEventRel(mouse_event)
|
||||
}
|
||||
FastpathInputEventType::Sync => {
|
||||
let flags =
|
||||
SynchronizeFlags::from_bits(flags).ok_or(InputEventError::SynchronizeFlagsUnsupported(flags))?;
|
||||
FastPathInputEvent::SyncEvent(flags)
|
||||
}
|
||||
FastpathInputEventType::Unicode => {
|
||||
let code = stream.read_u16::<LittleEndian>()?;
|
||||
let flags = KeyboardFlags::from_bits(flags).ok_or(InputEventError::KeyboardFlagsUnsupported(flags))?;
|
||||
FastPathInputEvent::UnicodeKeyboardEvent(flags, code)
|
||||
}
|
||||
FastpathInputEventType::QoeTimestamp => {
|
||||
let code = stream.read_u32::<LittleEndian>()?;
|
||||
FastPathInputEvent::QoeEvent(code)
|
||||
}
|
||||
};
|
||||
Ok(event)
|
||||
}
|
||||
const FIXED_PART_SIZE: usize = 1 /* header */;
|
||||
}
|
||||
|
||||
impl PduEncode for FastPathInputEvent {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_size!(in: dst, size: self.size());
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
let mut header = 0u8;
|
||||
let (flags, code) = match self {
|
||||
FastPathInputEvent::KeyboardEvent(flags, _) => (flags.bits(), FastpathInputEventType::ScanCode),
|
||||
|
@ -151,41 +130,100 @@ impl PduParsing for FastPathInputEvent {
|
|||
};
|
||||
header.set_bits(0..5, flags);
|
||||
header.set_bits(5..8, code.to_u8().unwrap());
|
||||
stream.write_u8(header)?;
|
||||
dst.write_u8(header);
|
||||
match self {
|
||||
FastPathInputEvent::KeyboardEvent(_, code) => {
|
||||
stream.write_u8(*code)?;
|
||||
dst.write_u8(*code);
|
||||
}
|
||||
FastPathInputEvent::UnicodeKeyboardEvent(_, code) => {
|
||||
stream.write_u16::<LittleEndian>(*code)?;
|
||||
dst.write_u16(*code);
|
||||
}
|
||||
FastPathInputEvent::MouseEvent(pdu) => {
|
||||
pdu.to_buffer(stream)?;
|
||||
pdu.encode(dst)?;
|
||||
}
|
||||
FastPathInputEvent::MouseEventEx(pdu) => {
|
||||
pdu.to_buffer(stream)?;
|
||||
pdu.encode(dst)?;
|
||||
}
|
||||
FastPathInputEvent::QoeEvent(stamp) => {
|
||||
stream.write_u32::<LittleEndian>(*stamp)?;
|
||||
dst.write_u32(*stamp);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
1 + match self {
|
||||
FastPathInputEvent::KeyboardEvent(_, _) => 1,
|
||||
FastPathInputEvent::UnicodeKeyboardEvent(_, _) => 2,
|
||||
FastPathInputEvent::MouseEvent(pdu) => pdu.buffer_length(),
|
||||
FastPathInputEvent::MouseEventEx(pdu) => pdu.buffer_length(),
|
||||
FastPathInputEvent::MouseEventRel(pdu) => pdu.buffer_length(),
|
||||
FastPathInputEvent::QoeEvent(_) => 4,
|
||||
FastPathInputEvent::SyncEvent(_) => 0,
|
||||
}
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE
|
||||
+ match self {
|
||||
FastPathInputEvent::KeyboardEvent(_, _) => 1,
|
||||
FastPathInputEvent::UnicodeKeyboardEvent(_, _) => 2,
|
||||
FastPathInputEvent::MouseEvent(pdu) => pdu.size(),
|
||||
FastPathInputEvent::MouseEventEx(pdu) => pdu.size(),
|
||||
FastPathInputEvent::MouseEventRel(pdu) => pdu.size(),
|
||||
FastPathInputEvent::QoeEvent(_) => 4,
|
||||
FastPathInputEvent::SyncEvent(_) => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for FastPathInputEvent {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let header = src.read_u8();
|
||||
let flags = header.get_bits(0..5);
|
||||
let code = header.get_bits(5..8);
|
||||
let code: FastpathInputEventType = FastpathInputEventType::from_u8(code)
|
||||
.ok_or_else(|| invalid_message_err!("code", "input event code unsupported"))?;
|
||||
let event = match code {
|
||||
FastpathInputEventType::ScanCode => {
|
||||
ensure_size!(in: src, size: 1);
|
||||
let code = src.read_u8();
|
||||
let flags = KeyboardFlags::from_bits(flags)
|
||||
.ok_or_else(|| invalid_message_err!("flags", "input keyboard flags unsupported"))?;
|
||||
FastPathInputEvent::KeyboardEvent(flags, code)
|
||||
}
|
||||
FastpathInputEventType::Mouse => {
|
||||
let mouse_event = MousePdu::decode(src)?;
|
||||
FastPathInputEvent::MouseEvent(mouse_event)
|
||||
}
|
||||
FastpathInputEventType::MouseX => {
|
||||
let mouse_event = MouseXPdu::decode(src)?;
|
||||
FastPathInputEvent::MouseEventEx(mouse_event)
|
||||
}
|
||||
FastpathInputEventType::MouseRel => {
|
||||
let mouse_event = MouseRelPdu::decode(src)?;
|
||||
FastPathInputEvent::MouseEventRel(mouse_event)
|
||||
}
|
||||
FastpathInputEventType::Sync => {
|
||||
let flags = SynchronizeFlags::from_bits(flags)
|
||||
.ok_or_else(|| invalid_message_err!("flags", "input synchronize flags unsupported"))?;
|
||||
FastPathInputEvent::SyncEvent(flags)
|
||||
}
|
||||
FastpathInputEventType::Unicode => {
|
||||
ensure_size!(in: src, size: 2);
|
||||
let code = src.read_u16();
|
||||
let flags = KeyboardFlags::from_bits(flags)
|
||||
.ok_or_else(|| invalid_message_err!("flags", "input keyboard flags unsupported"))?;
|
||||
FastPathInputEvent::UnicodeKeyboardEvent(flags, code)
|
||||
}
|
||||
FastpathInputEventType::QoeTimestamp => {
|
||||
ensure_size!(in: src, size: 4);
|
||||
let code = src.read_u32();
|
||||
FastPathInputEvent::QoeEvent(code)
|
||||
}
|
||||
};
|
||||
Ok(event)
|
||||
}
|
||||
}
|
||||
|
||||
impl_pdu_parsing!(FastPathInputEvent);
|
||||
|
||||
bitflags! {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct KeyboardFlags: u8 {
|
||||
|
@ -208,45 +246,57 @@ bitflags! {
|
|||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct FastPathInput(pub Vec<FastPathInputEvent>);
|
||||
|
||||
impl PduParsing for FastPathInput {
|
||||
type Error = InputEventError;
|
||||
impl FastPathInput {
|
||||
const NAME: &'static str = "FastPathInput";
|
||||
}
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let header = FastPathInputHeader::from_buffer(&mut stream)?;
|
||||
let events = (0..header.num_events)
|
||||
.map(|_| FastPathInputEvent::from_buffer(&mut stream))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
impl PduEncode for FastPathInput {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_size!(in: dst, size: self.size());
|
||||
|
||||
Ok(Self(events))
|
||||
}
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
if self.0.is_empty() {
|
||||
return Err(InputEventError::EmptyFastPathInput);
|
||||
return Err(other_err!("Empty fast-path input"));
|
||||
}
|
||||
|
||||
let data_length = self.0.iter().map(PduParsing::buffer_length).sum::<usize>();
|
||||
let data_length = self.0.iter().map(PduEncode::size).sum::<usize>();
|
||||
let header = FastPathInputHeader {
|
||||
num_events: self.0.len() as u8,
|
||||
flags: EncryptionFlags::empty(),
|
||||
data_length,
|
||||
};
|
||||
header.to_buffer(&mut stream)?;
|
||||
header.encode(dst)?;
|
||||
|
||||
for event in self.0.iter() {
|
||||
event.to_buffer(&mut stream)?;
|
||||
event.encode(dst)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
let data_length = self.0.iter().map(PduParsing::buffer_length).sum::<usize>();
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
let data_length = self.0.iter().map(PduEncode::size).sum::<usize>();
|
||||
let header = FastPathInputHeader {
|
||||
num_events: self.0.len() as u8,
|
||||
flags: EncryptionFlags::empty(),
|
||||
data_length,
|
||||
};
|
||||
header.buffer_length() + data_length
|
||||
header.size() + data_length
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for FastPathInput {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
let header = FastPathInputHeader::decode(src)?;
|
||||
let events = (0..header.num_events)
|
||||
.map(|_| FastPathInputEvent::decode(src))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(Self(events))
|
||||
}
|
||||
}
|
||||
|
||||
impl_pdu_parsing_max!(FastPathInput);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use std::io;
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use num_derive::{FromPrimitive, ToPrimitive};
|
||||
use num_traits::{FromPrimitive, ToPrimitive};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::PduParsing;
|
||||
use crate::cursor::{ReadCursor, WriteCursor};
|
||||
use crate::{PduDecode, PduEncode, PduResult};
|
||||
|
||||
pub mod fast_path;
|
||||
pub mod mouse;
|
||||
|
@ -27,36 +27,52 @@ pub use self::unused::UnusedPdu;
|
|||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct InputEventPdu(pub Vec<InputEvent>);
|
||||
|
||||
impl PduParsing for InputEventPdu {
|
||||
type Error = InputEventError;
|
||||
impl InputEventPdu {
|
||||
const NAME: &'static str = "InputEventPdu";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let number_of_events = stream.read_u16::<LittleEndian>()?;
|
||||
let _padding = stream.read_u16::<LittleEndian>()?;
|
||||
const FIXED_PART_SIZE: usize = 4 /* nEvents */;
|
||||
}
|
||||
|
||||
let events = (0..number_of_events)
|
||||
.map(|_| InputEvent::from_buffer(&mut stream))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
impl PduEncode for InputEventPdu {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_size!(in: dst, size: self.size());
|
||||
|
||||
Ok(Self(events))
|
||||
}
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
stream.write_u16::<LittleEndian>(self.0.len() as u16)?;
|
||||
stream.write_u16::<LittleEndian>(0)?; // padding
|
||||
dst.write_u16(self.0.len() as u16);
|
||||
write_padding!(dst, 2);
|
||||
|
||||
for event in self.0.iter() {
|
||||
event.to_buffer(&mut stream)?;
|
||||
event.encode(dst)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
4 + self.0.iter().map(PduParsing::buffer_length).sum::<usize>()
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
4 + self.0.iter().map(PduEncode::size).sum::<usize>()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for InputEventPdu {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let number_of_events = src.read_u16();
|
||||
read_padding!(src, 2);
|
||||
|
||||
let events = (0..number_of_events)
|
||||
.map(|_| InputEvent::decode(src))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(Self(events))
|
||||
}
|
||||
}
|
||||
|
||||
impl_pdu_parsing_max!(InputEventPdu);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum InputEvent {
|
||||
Sync(SyncPdu),
|
||||
|
@ -68,54 +84,71 @@ pub enum InputEvent {
|
|||
MouseRel(MouseRelPdu),
|
||||
}
|
||||
|
||||
impl PduParsing for InputEvent {
|
||||
type Error = InputEventError;
|
||||
impl InputEvent {
|
||||
const NAME: &'static str = "InputEvent";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let _event_time = stream.read_u32::<LittleEndian>()?; // ignored by a server
|
||||
let event_type = stream.read_u16::<LittleEndian>()?;
|
||||
let event_type =
|
||||
InputEventType::from_u16(event_type).ok_or(InputEventError::InvalidInputEventType(event_type))?;
|
||||
const FIXED_PART_SIZE: usize = 4 /* eventTime */ + 2 /* eventType */;
|
||||
}
|
||||
|
||||
match event_type {
|
||||
InputEventType::Sync => Ok(Self::Sync(SyncPdu::from_buffer(&mut stream)?)),
|
||||
InputEventType::Unused => Ok(Self::Unused(UnusedPdu::from_buffer(&mut stream)?)),
|
||||
InputEventType::ScanCode => Ok(Self::ScanCode(ScanCodePdu::from_buffer(&mut stream)?)),
|
||||
InputEventType::Unicode => Ok(Self::Unicode(UnicodePdu::from_buffer(&mut stream)?)),
|
||||
InputEventType::Mouse => Ok(Self::Mouse(MousePdu::from_buffer(&mut stream)?)),
|
||||
InputEventType::MouseX => Ok(Self::MouseX(MouseXPdu::from_buffer(&mut stream)?)),
|
||||
InputEventType::MouseRel => Ok(Self::MouseRel(MouseRelPdu::from_buffer(&mut stream)?)),
|
||||
}
|
||||
}
|
||||
impl PduEncode for InputEvent {
|
||||
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_u32::<LittleEndian>(0)?; // event time is ignored by a server
|
||||
stream.write_u16::<LittleEndian>(InputEventType::from(self).to_u16().unwrap())?;
|
||||
dst.write_u32(0); // event time is ignored by a server
|
||||
dst.write_u16(InputEventType::from(self).to_u16().unwrap());
|
||||
|
||||
match self {
|
||||
Self::Sync(pdu) => pdu.to_buffer(&mut stream),
|
||||
Self::Unused(pdu) => pdu.to_buffer(&mut stream),
|
||||
Self::ScanCode(pdu) => pdu.to_buffer(&mut stream),
|
||||
Self::Unicode(pdu) => pdu.to_buffer(&mut stream),
|
||||
Self::Mouse(pdu) => pdu.to_buffer(&mut stream),
|
||||
Self::MouseX(pdu) => pdu.to_buffer(&mut stream),
|
||||
Self::MouseRel(pdu) => pdu.to_buffer(&mut stream),
|
||||
Self::Sync(pdu) => pdu.encode(dst),
|
||||
Self::Unused(pdu) => pdu.encode(dst),
|
||||
Self::ScanCode(pdu) => pdu.encode(dst),
|
||||
Self::Unicode(pdu) => pdu.encode(dst),
|
||||
Self::Mouse(pdu) => pdu.encode(dst),
|
||||
Self::MouseX(pdu) => pdu.encode(dst),
|
||||
Self::MouseRel(pdu) => pdu.encode(dst),
|
||||
}
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
6 + match self {
|
||||
Self::Sync(pdu) => pdu.buffer_length(),
|
||||
Self::Unused(pdu) => pdu.buffer_length(),
|
||||
Self::ScanCode(pdu) => pdu.buffer_length(),
|
||||
Self::Unicode(pdu) => pdu.buffer_length(),
|
||||
Self::Mouse(pdu) => pdu.buffer_length(),
|
||||
Self::MouseX(pdu) => pdu.buffer_length(),
|
||||
Self::MouseRel(pdu) => pdu.buffer_length(),
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE
|
||||
+ match self {
|
||||
Self::Sync(pdu) => pdu.size(),
|
||||
Self::Unused(pdu) => pdu.size(),
|
||||
Self::ScanCode(pdu) => pdu.size(),
|
||||
Self::Unicode(pdu) => pdu.size(),
|
||||
Self::Mouse(pdu) => pdu.size(),
|
||||
Self::MouseX(pdu) => pdu.size(),
|
||||
Self::MouseRel(pdu) => pdu.size(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for InputEvent {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let _event_time = src.read_u32(); // ignored by a server
|
||||
let event_type = src.read_u16();
|
||||
let event_type = InputEventType::from_u16(event_type)
|
||||
.ok_or_else(|| invalid_message_err!("eventType", "invalid input event type"))?;
|
||||
|
||||
match event_type {
|
||||
InputEventType::Sync => Ok(Self::Sync(SyncPdu::decode(src)?)),
|
||||
InputEventType::Unused => Ok(Self::Unused(UnusedPdu::decode(src)?)),
|
||||
InputEventType::ScanCode => Ok(Self::ScanCode(ScanCodePdu::decode(src)?)),
|
||||
InputEventType::Unicode => Ok(Self::Unicode(UnicodePdu::decode(src)?)),
|
||||
InputEventType::Mouse => Ok(Self::Mouse(MousePdu::decode(src)?)),
|
||||
InputEventType::MouseX => Ok(Self::MouseX(MouseXPdu::decode(src)?)),
|
||||
InputEventType::MouseRel => Ok(Self::MouseRel(MouseRelPdu::decode(src)?)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_pdu_parsing!(InputEvent);
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, FromPrimitive, ToPrimitive)]
|
||||
#[repr(u16)]
|
||||
enum InputEventType {
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use std::io;
|
||||
|
||||
use bitflags::bitflags;
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use super::InputEventError;
|
||||
use crate::PduParsing;
|
||||
use crate::{
|
||||
cursor::{ReadCursor, WriteCursor},
|
||||
PduDecode, PduEncode, PduResult,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct MousePdu {
|
||||
|
@ -14,11 +13,47 @@ pub struct MousePdu {
|
|||
pub y_position: u16,
|
||||
}
|
||||
|
||||
impl PduParsing for MousePdu {
|
||||
type Error = InputEventError;
|
||||
impl MousePdu {
|
||||
const NAME: &'static str = "MousePdu";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let flags_raw = stream.read_u16::<LittleEndian>()?;
|
||||
const FIXED_PART_SIZE: usize = 2 /* flags */ + 2 /* x */ + 2 /* y */;
|
||||
}
|
||||
|
||||
impl PduEncode for MousePdu {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_fixed_part_size!(in: dst);
|
||||
|
||||
let wheel_negative_bit = if self.number_of_wheel_rotation_units < 0 {
|
||||
PointerFlags::WHEEL_NEGATIVE.bits()
|
||||
} else {
|
||||
PointerFlags::empty().bits()
|
||||
};
|
||||
|
||||
let wheel_rotations_bits = u16::from(self.number_of_wheel_rotation_units as u8); // truncate
|
||||
|
||||
let flags = self.flags.bits() | wheel_negative_bit | wheel_rotations_bits;
|
||||
|
||||
dst.write_u16(flags);
|
||||
dst.write_u16(self.x_position);
|
||||
dst.write_u16(self.y_position);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for MousePdu {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let flags_raw = src.read_u16();
|
||||
|
||||
let flags = PointerFlags::from_bits_truncate(flags_raw);
|
||||
|
||||
|
@ -30,8 +65,8 @@ impl PduParsing for MousePdu {
|
|||
i16::from(wheel_rotations_bits)
|
||||
};
|
||||
|
||||
let x_position = stream.read_u16::<LittleEndian>()?;
|
||||
let y_position = stream.read_u16::<LittleEndian>()?;
|
||||
let x_position = src.read_u16();
|
||||
let y_position = src.read_u16();
|
||||
|
||||
Ok(Self {
|
||||
flags,
|
||||
|
@ -40,29 +75,8 @@ impl PduParsing for MousePdu {
|
|||
y_position,
|
||||
})
|
||||
}
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
let wheel_negative_bit = if self.number_of_wheel_rotation_units < 0 {
|
||||
PointerFlags::WHEEL_NEGATIVE.bits()
|
||||
} else {
|
||||
PointerFlags::empty().bits()
|
||||
};
|
||||
|
||||
let wheel_rotations_bits = u16::from(self.number_of_wheel_rotation_units as u8); // truncate
|
||||
|
||||
let flags = self.flags.bits() | wheel_negative_bit | wheel_rotations_bits;
|
||||
|
||||
stream.write_u16::<LittleEndian>(flags)?;
|
||||
stream.write_u16::<LittleEndian>(self.x_position)?;
|
||||
stream.write_u16::<LittleEndian>(self.y_position)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
6
|
||||
}
|
||||
}
|
||||
impl_pdu_parsing!(MousePdu);
|
||||
|
||||
bitflags! {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use std::io;
|
||||
|
||||
use bitflags::bitflags;
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use super::InputEventError;
|
||||
use crate::PduParsing;
|
||||
use crate::{
|
||||
cursor::{ReadCursor, WriteCursor},
|
||||
PduDecode, PduEncode, PduResult,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct MouseRelPdu {
|
||||
|
@ -13,13 +12,39 @@ pub struct MouseRelPdu {
|
|||
pub y_delta: i16,
|
||||
}
|
||||
|
||||
impl PduParsing for MouseRelPdu {
|
||||
type Error = InputEventError;
|
||||
impl MouseRelPdu {
|
||||
const NAME: &'static str = "MouseRelPdu";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let flags = PointerRelFlags::from_bits_truncate(stream.read_u16::<LittleEndian>()?);
|
||||
let x_delta = stream.read_i16::<LittleEndian>()?;
|
||||
let y_delta = stream.read_i16::<LittleEndian>()?;
|
||||
const FIXED_PART_SIZE: usize = 2 /* flags */ + 2 /* x */ + 2 /* y */;
|
||||
}
|
||||
|
||||
impl PduEncode for MouseRelPdu {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_fixed_part_size!(in: dst);
|
||||
|
||||
dst.write_u16(self.flags.bits());
|
||||
dst.write_i16(self.x_delta);
|
||||
dst.write_i16(self.y_delta);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for MouseRelPdu {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let flags = PointerRelFlags::from_bits_truncate(src.read_u16());
|
||||
let x_delta = src.read_i16();
|
||||
let y_delta = src.read_i16();
|
||||
|
||||
Ok(Self {
|
||||
flags,
|
||||
|
@ -27,20 +52,10 @@ impl PduParsing for MouseRelPdu {
|
|||
y_delta,
|
||||
})
|
||||
}
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
stream.write_u16::<LittleEndian>(self.flags.bits())?;
|
||||
stream.write_i16::<LittleEndian>(self.x_delta)?;
|
||||
stream.write_i16::<LittleEndian>(self.y_delta)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
6
|
||||
}
|
||||
}
|
||||
|
||||
impl_pdu_parsing!(MouseRelPdu);
|
||||
|
||||
bitflags! {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct PointerRelFlags: u16 {
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use std::io;
|
||||
|
||||
use bitflags::bitflags;
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use super::InputEventError;
|
||||
use crate::PduParsing;
|
||||
use crate::{
|
||||
cursor::{ReadCursor, WriteCursor},
|
||||
PduDecode, PduEncode, PduResult,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct MouseXPdu {
|
||||
|
@ -13,13 +12,39 @@ pub struct MouseXPdu {
|
|||
pub y_position: u16,
|
||||
}
|
||||
|
||||
impl PduParsing for MouseXPdu {
|
||||
type Error = InputEventError;
|
||||
impl MouseXPdu {
|
||||
const NAME: &'static str = "MouseXPdu";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let flags = PointerXFlags::from_bits_truncate(stream.read_u16::<LittleEndian>()?);
|
||||
let x_position = stream.read_u16::<LittleEndian>()?;
|
||||
let y_position = stream.read_u16::<LittleEndian>()?;
|
||||
const FIXED_PART_SIZE: usize = 2 /* flags */ + 2 /* x */ + 2 /* y */;
|
||||
}
|
||||
|
||||
impl PduEncode for MouseXPdu {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_fixed_part_size!(in: dst);
|
||||
|
||||
dst.write_u16(self.flags.bits());
|
||||
dst.write_u16(self.x_position);
|
||||
dst.write_u16(self.y_position);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for MouseXPdu {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let flags = PointerXFlags::from_bits_truncate(src.read_u16());
|
||||
let x_position = src.read_u16();
|
||||
let y_position = src.read_u16();
|
||||
|
||||
Ok(Self {
|
||||
flags,
|
||||
|
@ -27,20 +52,10 @@ impl PduParsing for MouseXPdu {
|
|||
y_position,
|
||||
})
|
||||
}
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
stream.write_u16::<LittleEndian>(self.flags.bits())?;
|
||||
stream.write_u16::<LittleEndian>(self.x_position)?;
|
||||
stream.write_u16::<LittleEndian>(self.y_position)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
6
|
||||
}
|
||||
}
|
||||
|
||||
impl_pdu_parsing!(MouseXPdu);
|
||||
|
||||
bitflags! {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct PointerXFlags: u16 {
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use std::io;
|
||||
|
||||
use bitflags::bitflags;
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use super::InputEventError;
|
||||
use crate::PduParsing;
|
||||
use crate::{
|
||||
cursor::{ReadCursor, WriteCursor},
|
||||
PduDecode, PduEncode, PduResult,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ScanCodePdu {
|
||||
|
@ -12,30 +11,46 @@ pub struct ScanCodePdu {
|
|||
pub key_code: u16,
|
||||
}
|
||||
|
||||
impl PduParsing for ScanCodePdu {
|
||||
type Error = InputEventError;
|
||||
impl ScanCodePdu {
|
||||
const NAME: &'static str = "ScanCodePdu";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let flags = KeyboardFlags::from_bits_truncate(stream.read_u16::<LittleEndian>()?);
|
||||
let key_code = stream.read_u16::<LittleEndian>()?;
|
||||
let _padding = stream.read_u16::<LittleEndian>()?;
|
||||
const FIXED_PART_SIZE: usize = 2 /* flags */ + 2 /* keycode */ + 2 /* padding */;
|
||||
}
|
||||
|
||||
Ok(Self { flags, key_code })
|
||||
}
|
||||
impl PduEncode for ScanCodePdu {
|
||||
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.flags.bits())?;
|
||||
stream.write_u16::<LittleEndian>(self.key_code)?;
|
||||
stream.write_u16::<LittleEndian>(0)?; // padding
|
||||
dst.write_u16(self.flags.bits());
|
||||
dst.write_u16(self.key_code);
|
||||
write_padding!(dst, 2);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
6
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for ScanCodePdu {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let flags = KeyboardFlags::from_bits_truncate(src.read_u16());
|
||||
let key_code = src.read_u16();
|
||||
read_padding!(src, 2);
|
||||
|
||||
Ok(Self { flags, key_code })
|
||||
}
|
||||
}
|
||||
|
||||
impl_pdu_parsing!(ScanCodePdu);
|
||||
|
||||
bitflags! {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct KeyboardFlags: u16 {
|
||||
|
|
|
@ -1,38 +1,53 @@
|
|||
use std::io;
|
||||
|
||||
use bitflags::bitflags;
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use super::InputEventError;
|
||||
use crate::PduParsing;
|
||||
use crate::{
|
||||
cursor::{ReadCursor, WriteCursor},
|
||||
PduDecode, PduEncode, PduResult,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct SyncPdu {
|
||||
pub flags: SyncToggleFlags,
|
||||
}
|
||||
|
||||
impl PduParsing for SyncPdu {
|
||||
type Error = InputEventError;
|
||||
impl SyncPdu {
|
||||
const NAME: &'static str = "SyncPdu";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let _padding = stream.read_u16::<LittleEndian>()?;
|
||||
let flags = SyncToggleFlags::from_bits_truncate(stream.read_u32::<LittleEndian>()?);
|
||||
const FIXED_PART_SIZE: usize = 2 /* padding */ + 4 /* flags */;
|
||||
}
|
||||
|
||||
Ok(Self { flags })
|
||||
}
|
||||
impl PduEncode for SyncPdu {
|
||||
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>(0)?; // padding
|
||||
stream.write_u32::<LittleEndian>(self.flags.bits())?;
|
||||
write_padding!(dst, 2);
|
||||
dst.write_u32(self.flags.bits());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
6
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for SyncPdu {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
read_padding!(src, 2);
|
||||
let flags = SyncToggleFlags::from_bits_truncate(src.read_u32());
|
||||
|
||||
Ok(Self { flags })
|
||||
}
|
||||
}
|
||||
|
||||
impl_pdu_parsing!(SyncPdu);
|
||||
|
||||
bitflags! {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct SyncToggleFlags: u32 {
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use std::io;
|
||||
|
||||
use bitflags::bitflags;
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use super::InputEventError;
|
||||
use crate::PduParsing;
|
||||
use crate::{
|
||||
cursor::{ReadCursor, WriteCursor},
|
||||
PduDecode, PduEncode, PduResult,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct UnicodePdu {
|
||||
|
@ -12,30 +11,46 @@ pub struct UnicodePdu {
|
|||
pub unicode_code: u16,
|
||||
}
|
||||
|
||||
impl PduParsing for UnicodePdu {
|
||||
type Error = InputEventError;
|
||||
impl UnicodePdu {
|
||||
const NAME: &'static str = "UnicodePdu";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let flags = KeyboardFlags::from_bits_truncate(stream.read_u16::<LittleEndian>()?);
|
||||
let unicode_code = stream.read_u16::<LittleEndian>()?;
|
||||
let _padding = stream.read_u16::<LittleEndian>()?;
|
||||
const FIXED_PART_SIZE: usize = 2 /* flags */ + 2 /* code */ + 2 /* padding */;
|
||||
}
|
||||
|
||||
Ok(Self { flags, unicode_code })
|
||||
}
|
||||
impl PduEncode for UnicodePdu {
|
||||
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.flags.bits())?;
|
||||
stream.write_u16::<LittleEndian>(self.unicode_code)?;
|
||||
stream.write_u16::<LittleEndian>(0)?; // padding
|
||||
dst.write_u16(self.flags.bits());
|
||||
dst.write_u16(self.unicode_code);
|
||||
write_padding!(dst, 2);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
6
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for UnicodePdu {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
let flags = KeyboardFlags::from_bits_truncate(src.read_u16());
|
||||
let unicode_code = src.read_u16();
|
||||
read_padding!(src, 2);
|
||||
|
||||
Ok(Self { flags, unicode_code })
|
||||
}
|
||||
}
|
||||
|
||||
impl_pdu_parsing!(UnicodePdu);
|
||||
|
||||
bitflags! {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct KeyboardFlags: u16 {
|
||||
|
|
|
@ -1,31 +1,41 @@
|
|||
use std::io;
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use super::InputEventError;
|
||||
use crate::PduParsing;
|
||||
use crate::{
|
||||
cursor::{ReadCursor, WriteCursor},
|
||||
PduDecode, PduEncode, PduResult,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct UnusedPdu;
|
||||
|
||||
impl PduParsing for UnusedPdu {
|
||||
type Error = InputEventError;
|
||||
impl UnusedPdu {
|
||||
const NAME: &'static str = "UnusedPdu";
|
||||
|
||||
fn from_buffer(mut stream: impl io::Read) -> Result<Self, Self::Error> {
|
||||
let _padding = stream.read_u32::<LittleEndian>()?;
|
||||
let _padding = stream.read_u16::<LittleEndian>()?;
|
||||
const FIXED_PART_SIZE: usize = 6 /* padding */;
|
||||
}
|
||||
|
||||
Ok(Self)
|
||||
}
|
||||
|
||||
fn to_buffer(&self, mut stream: impl io::Write) -> Result<(), Self::Error> {
|
||||
stream.write_u32::<LittleEndian>(0)?; // padding
|
||||
stream.write_u16::<LittleEndian>(0)?; // padding
|
||||
impl PduEncode for UnusedPdu {
|
||||
fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_fixed_part_size!(in: dst);
|
||||
|
||||
write_padding!(dst, 6);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn buffer_length(&self) -> usize {
|
||||
6
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
Self::FIXED_PART_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> PduDecode<'de> for UnusedPdu {
|
||||
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
|
||||
ensure_fixed_part_size!(in: src);
|
||||
|
||||
read_padding!(src, 6);
|
||||
Ok(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl_pdu_parsing!(UnusedPdu);
|
||||
|
|
|
@ -321,7 +321,7 @@ impl RdpServer {
|
|||
|
||||
match action {
|
||||
Action::FastPath => {
|
||||
let input = FastPathInput::from_buffer(Cursor::new(&bytes))?;
|
||||
let input = decode(&bytes)?;
|
||||
self.handle_fastpath(input).await;
|
||||
}
|
||||
|
||||
|
@ -378,7 +378,7 @@ impl RdpServer {
|
|||
for frame in frames {
|
||||
match Action::from_fp_output_header(frame[0]) {
|
||||
Ok(Action::FastPath) => {
|
||||
let input = FastPathInput::from_buffer(Cursor::new(&frame))?;
|
||||
let input = decode(&frame)?;
|
||||
self.handle_fastpath(input).await;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,13 +6,13 @@ use ironrdp_pdu::geometry::InclusiveRectangle;
|
|||
use ironrdp_pdu::input::fast_path::{FastPathInput, FastPathInputEvent};
|
||||
use ironrdp_pdu::rdp::headers::ShareDataPdu;
|
||||
use ironrdp_pdu::write_buf::WriteBuf;
|
||||
use ironrdp_pdu::{mcs, Action, PduParsing};
|
||||
use ironrdp_pdu::{mcs, Action};
|
||||
use ironrdp_svc::{SvcProcessor, SvcProcessorMessages};
|
||||
|
||||
use crate::fast_path::UpdateKind;
|
||||
use crate::image::DecodedImage;
|
||||
use crate::x224::GfxHandler;
|
||||
use crate::{fast_path, x224, SessionError, SessionResult};
|
||||
use crate::{fast_path, x224, SessionError, SessionErrorExt, SessionResult};
|
||||
|
||||
pub struct ActiveStage {
|
||||
x224_processor: x224::Processor,
|
||||
|
@ -67,10 +67,7 @@ impl ActiveStage {
|
|||
// Encoding fastpath response frame
|
||||
// PERF: unnecessary copy
|
||||
let fastpath_input = FastPathInput(events.to_vec());
|
||||
let mut frame = Vec::new();
|
||||
fastpath_input
|
||||
.to_buffer(&mut frame)
|
||||
.map_err(|e| custom_err!("FastPathInput encode", e))?;
|
||||
let frame = ironrdp_pdu::encode_vec(&fastpath_input).map_err(SessionError::pdu)?;
|
||||
output.push(ActiveStageOutput::ResponseFrame(frame));
|
||||
|
||||
// If pointer rendering is disabled - we can skip the rest
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use ironrdp_pdu::cursor::ReadCursor;
|
||||
use ironrdp_pdu::input::fast_path::{FastPathInput, FastPathInputEvent};
|
||||
use ironrdp_pdu::input::mouse::PointerFlags;
|
||||
use ironrdp_pdu::input::MousePdu;
|
||||
use ironrdp_pdu::PduParsing;
|
||||
use ironrdp_pdu::{decode_cursor, encode_vec};
|
||||
|
||||
const FASTPATH_INPUT_MESSAGE: [u8; 44] = [
|
||||
0x18, 0x2c, 0x20, 0x0, 0x90, 0x1a, 0x0, 0x26, 0x4, 0x20, 0x0, 0x8, 0x1b, 0x0, 0x26, 0x4, 0x20, 0x0, 0x10, 0x1b,
|
||||
|
@ -52,16 +53,16 @@ lazy_static::lazy_static! {
|
|||
|
||||
#[test]
|
||||
fn from_buffer_correctly_parses_fastpath_input_message() {
|
||||
let mut buffer = FASTPATH_INPUT_MESSAGE.as_ref();
|
||||
let buffer = FASTPATH_INPUT_MESSAGE.as_ref();
|
||||
|
||||
assert_eq!(*FASTPATH_INPUT, FastPathInput::from_buffer(&mut buffer).unwrap());
|
||||
assert!(buffer.is_empty());
|
||||
let mut cursor = ReadCursor::new(buffer);
|
||||
assert_eq!(*FASTPATH_INPUT, decode_cursor(&mut cursor).unwrap());
|
||||
assert!(cursor.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_buffer_correctly_serializes_fastpath_input_message() {
|
||||
let mut buffer = Vec::with_capacity(1024);
|
||||
FASTPATH_INPUT.to_buffer(&mut buffer).unwrap();
|
||||
let buffer = encode_vec(&*FASTPATH_INPUT).unwrap();
|
||||
|
||||
assert_eq!(buffer, FASTPATH_INPUT_MESSAGE.as_ref());
|
||||
}
|
||||
|
|
|
@ -652,13 +652,11 @@ impl Session {
|
|||
kana_lock: bool,
|
||||
) -> Result<(), IronRdpError> {
|
||||
use ironrdp::pdu::input::fast_path::FastPathInput;
|
||||
use ironrdp::pdu::PduParsing as _;
|
||||
|
||||
let event = ironrdp::input::synchronize_event(scroll_lock, num_lock, caps_lock, kana_lock);
|
||||
let fastpath_input = FastPathInput(vec![event]);
|
||||
|
||||
let mut frame = Vec::new();
|
||||
fastpath_input.to_buffer(&mut frame).context("FastPathInput encoding")?;
|
||||
let frame = ironrdp::pdu::encode_vec(&fastpath_input).context("FastPathInput encoding")?;
|
||||
|
||||
self.writer_tx
|
||||
.unbounded_send(frame)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue