Skip to content

Commit 81633a1

Browse files
committed
refactor(server): split UpdateEncoder
The bitmap encoder dispatching code was becoming convoluted and the same struct was handling PduEncoding and various bitmap encoding handling. Instead, split UpdateEncoder in different types and concerns. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
1 parent 5555c7b commit 81633a1

File tree

1 file changed

+140
-80
lines changed
  • crates/ironrdp-server/src/encoder

1 file changed

+140
-80
lines changed

crates/ironrdp-server/src/encoder/mod.rs

Lines changed: 140 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -28,44 +28,25 @@ const MAX_FASTPATH_UPDATE_SIZE: usize = 16_374;
2828
const FASTPATH_HEADER_SIZE: usize = 6;
2929

3030
pub(crate) struct UpdateEncoder {
31-
buffer: Vec<u8>,
32-
bitmap: BitmapEncoder,
33-
remotefx: Option<(RfxEncoder, u8)>,
34-
update: for<'a> fn(&'a mut UpdateEncoder, BitmapUpdate) -> Result<UpdateFragmenter<'a>>,
31+
pdu_encoder: PduEncoder,
32+
bitmap_updater: BitmapUpdater,
3533
}
3634

3735
impl UpdateEncoder {
3836
pub(crate) fn new(surface_flags: CmdFlags, remotefx: Option<(EntropyBits, u8)>) -> Self {
39-
let update = if !surface_flags.contains(CmdFlags::SET_SURFACE_BITS) {
40-
Self::bitmap_update
37+
let pdu_encoder = PduEncoder::new();
38+
let bitmap_updater = if !surface_flags.contains(CmdFlags::SET_SURFACE_BITS) {
39+
BitmapUpdater::Bitmap(BitmapHandler::new())
4140
} else if remotefx.is_some() {
42-
Self::remotefx_update
41+
let (algo, id) = remotefx.unwrap();
42+
BitmapUpdater::RemoteFx(RemoteFxHandler::new(algo, id))
4343
} else {
44-
Self::none_update
44+
BitmapUpdater::None(NoneHandler)
4545
};
4646

4747
Self {
48-
buffer: vec![0; 16384],
49-
bitmap: BitmapEncoder::new(),
50-
remotefx: remotefx.map(|(algo, id)| (RfxEncoder::new(algo), id)),
51-
update,
52-
}
53-
}
54-
55-
fn encode_pdu(&mut self, pdu: impl Encode) -> Result<usize> {
56-
loop {
57-
let mut cursor = WriteCursor::new(self.buffer.as_mut_slice());
58-
match pdu.encode(&mut cursor) {
59-
Err(e) => match e.kind() {
60-
ironrdp_core::EncodeErrorKind::NotEnoughBytes { .. } => {
61-
self.buffer.resize(self.buffer.len() * 2, 0);
62-
debug!("encoder buffer resized to: {}", self.buffer.len() * 2);
63-
}
64-
65-
_ => Err(e).context("PDU encode error")?,
66-
},
67-
Ok(()) => return Ok(cursor.pos()),
68-
}
48+
pdu_encoder,
49+
bitmap_updater,
6950
}
7051
}
7152

@@ -88,8 +69,8 @@ impl UpdateEncoder {
8869
xor_bpp: 32,
8970
color_pointer,
9071
};
91-
let len = self.encode_pdu(ptr)?;
92-
Ok(UpdateFragmenter::new(UpdateCode::NewPointer, &self.buffer[..len]))
72+
let buf = self.pdu_encoder.encode(ptr)?;
73+
Ok(UpdateFragmenter::new(UpdateCode::NewPointer, buf))
9374
}
9475

9576
pub(crate) fn color_pointer(&mut self, ptr: ColorPointer) -> Result<UpdateFragmenter<'_>> {
@@ -105,8 +86,8 @@ impl UpdateEncoder {
10586
xor_mask: &ptr.xor_mask,
10687
and_mask: &ptr.and_mask,
10788
};
108-
let len = self.encode_pdu(ptr)?;
109-
Ok(UpdateFragmenter::new(UpdateCode::ColorPointer, &self.buffer[..len]))
89+
let buf = self.pdu_encoder.encode(ptr)?;
90+
Ok(UpdateFragmenter::new(UpdateCode::ColorPointer, buf))
11091
}
11192

11293
#[allow(clippy::unused_self)]
@@ -120,31 +101,93 @@ impl UpdateEncoder {
120101
}
121102

122103
pub(crate) fn pointer_position(&mut self, pos: PointerPositionAttribute) -> Result<UpdateFragmenter<'_>> {
123-
let len = self.encode_pdu(pos)?;
124-
Ok(UpdateFragmenter::new(UpdateCode::PositionPointer, &self.buffer[..len]))
104+
let buf = self.pdu_encoder.encode(pos)?;
105+
Ok(UpdateFragmenter::new(UpdateCode::PositionPointer, buf))
125106
}
126107

127108
pub(crate) fn bitmap(&mut self, bitmap: BitmapUpdate) -> Result<UpdateFragmenter<'_>> {
128-
let update = self.update;
129-
130-
update(self, bitmap)
109+
self.bitmap_updater.handle(bitmap, &mut self.pdu_encoder)
131110
}
132111

133112
pub(crate) fn fragmenter_from_owned(&self, res: UpdateFragmenterOwned) -> UpdateFragmenter<'_> {
134113
UpdateFragmenter {
135114
code: res.code,
136115
index: res.index,
137-
data: &self.buffer[0..res.len],
116+
data: &self.pdu_encoder.buffer[0..res.len],
117+
}
118+
}
119+
}
120+
121+
enum BitmapUpdater {
122+
None(NoneHandler),
123+
Bitmap(BitmapHandler),
124+
RemoteFx(RemoteFxHandler),
125+
}
126+
127+
impl BitmapUpdater {
128+
fn handle<'a>(&mut self, bitmap: BitmapUpdate, encoder: &'a mut PduEncoder) -> Result<UpdateFragmenter<'a>> {
129+
match self {
130+
Self::None(up) => up.handle(bitmap, encoder),
131+
Self::Bitmap(up) => up.handle(bitmap, encoder),
132+
Self::RemoteFx(up) => up.handle(bitmap, encoder),
133+
}
134+
}
135+
}
136+
137+
trait BitmapUpdateHandler {
138+
fn handle<'a>(&mut self, bitmap: BitmapUpdate, encoder: &'a mut PduEncoder) -> Result<UpdateFragmenter<'a>>;
139+
}
140+
141+
struct NoneHandler;
142+
143+
impl BitmapUpdateHandler for NoneHandler {
144+
fn handle<'a>(&mut self, mut bitmap: BitmapUpdate, encoder: &'a mut PduEncoder) -> Result<UpdateFragmenter<'a>> {
145+
let stride = usize::from(bitmap.format.bytes_per_pixel()) * usize::from(bitmap.width.get());
146+
let data = match bitmap.order {
147+
PixelOrder::BottomToTop => {
148+
if stride == bitmap.stride {
149+
mem::take(&mut bitmap.data)
150+
} else {
151+
let mut data = Vec::with_capacity(stride * usize::from(bitmap.height.get()));
152+
for row in bitmap.data.chunks(bitmap.stride) {
153+
data.extend_from_slice(&row[..stride]);
154+
}
155+
data
156+
}
157+
}
158+
PixelOrder::TopToBottom => {
159+
let mut data = Vec::with_capacity(stride * usize::from(bitmap.height.get()));
160+
for row in bitmap.data.chunks(bitmap.stride).rev() {
161+
data.extend_from_slice(&row[..stride]);
162+
}
163+
data
164+
}
165+
};
166+
167+
encoder.set_surface(bitmap, CodecId::None as u8, data)
168+
}
169+
}
170+
171+
struct BitmapHandler {
172+
bitmap: BitmapEncoder,
173+
}
174+
175+
impl BitmapHandler {
176+
fn new() -> Self {
177+
Self {
178+
bitmap: BitmapEncoder::new(),
138179
}
139180
}
181+
}
140182

141-
fn bitmap_update(&mut self, bitmap: BitmapUpdate) -> Result<UpdateFragmenter<'_>> {
183+
impl BitmapUpdateHandler for BitmapHandler {
184+
fn handle<'a>(&mut self, bitmap: BitmapUpdate, encoder: &'a mut PduEncoder) -> Result<UpdateFragmenter<'a>> {
142185
let len = loop {
143-
match self.bitmap.encode(&bitmap, self.buffer.as_mut_slice()) {
186+
match self.bitmap.encode(&bitmap, encoder.buffer.as_mut_slice()) {
144187
Err(e) => match e.kind() {
145188
ironrdp_core::EncodeErrorKind::NotEnoughBytes { .. } => {
146-
self.buffer.resize(self.buffer.len() * 2, 0);
147-
debug!("encoder buffer resized to: {}", self.buffer.len() * 2);
189+
encoder.buffer.resize(encoder.buffer.len() * 2, 0);
190+
debug!("encoder buffer resized to: {}", encoder.buffer.len() * 2);
148191
}
149192

150193
_ => Err(e).context("bitmap encode error")?,
@@ -153,7 +196,58 @@ impl UpdateEncoder {
153196
}
154197
};
155198

156-
Ok(UpdateFragmenter::new(UpdateCode::Bitmap, &self.buffer[..len]))
199+
Ok(UpdateFragmenter::new(UpdateCode::Bitmap, &encoder.buffer[..len]))
200+
}
201+
}
202+
203+
struct RemoteFxHandler {
204+
remotefx: RfxEncoder,
205+
codec_id: u8,
206+
}
207+
208+
impl RemoteFxHandler {
209+
fn new(algo: EntropyBits, codec_id: u8) -> Self {
210+
Self {
211+
remotefx: RfxEncoder::new(algo),
212+
codec_id,
213+
}
214+
}
215+
}
216+
217+
impl BitmapUpdateHandler for RemoteFxHandler {
218+
fn handle<'a>(&mut self, bitmap: BitmapUpdate, encoder: &'a mut PduEncoder) -> Result<UpdateFragmenter<'a>> {
219+
let data = self.remotefx.encode(&bitmap).context("RemoteFX encoding")?;
220+
221+
encoder.set_surface(bitmap, self.codec_id, data)
222+
}
223+
}
224+
225+
struct PduEncoder {
226+
buffer: Vec<u8>,
227+
}
228+
229+
impl PduEncoder {
230+
fn new() -> Self {
231+
Self { buffer: vec![0; 16384] }
232+
}
233+
234+
fn encode(&mut self, pdu: impl Encode) -> Result<&[u8]> {
235+
let pos = loop {
236+
let mut cursor = WriteCursor::new(self.buffer.as_mut_slice());
237+
match pdu.encode(&mut cursor) {
238+
Err(e) => match e.kind() {
239+
ironrdp_core::EncodeErrorKind::NotEnoughBytes { .. } => {
240+
self.buffer.resize(self.buffer.len() * 2, 0);
241+
debug!("encoder buffer resized to: {}", self.buffer.len() * 2);
242+
}
243+
244+
_ => Err(e).context("PDU encode error")?,
245+
},
246+
Ok(()) => break cursor.pos(),
247+
}
248+
};
249+
250+
Ok(&self.buffer[..pos])
157251
}
158252

159253
fn set_surface(&mut self, bitmap: BitmapUpdate, codec_id: u8, data: Vec<u8>) -> Result<UpdateFragmenter<'_>> {
@@ -176,42 +270,8 @@ impl UpdateEncoder {
176270
extended_bitmap_data,
177271
};
178272
let cmd = SurfaceCommand::SetSurfaceBits(pdu);
179-
let len = self.encode_pdu(cmd)?;
180-
Ok(UpdateFragmenter::new(UpdateCode::SurfaceCommands, &self.buffer[..len]))
181-
}
182-
183-
fn remotefx_update(&mut self, bitmap: BitmapUpdate) -> Result<UpdateFragmenter<'_>> {
184-
let (remotefx, codec_id) = self.remotefx.as_mut().unwrap();
185-
let codec_id = *codec_id;
186-
let data = remotefx.encode(&bitmap).context("RemoteFX encoding")?;
187-
188-
self.set_surface(bitmap, codec_id, data)
189-
}
190-
191-
fn none_update(&mut self, mut bitmap: BitmapUpdate) -> Result<UpdateFragmenter<'_>> {
192-
let stride = usize::from(bitmap.format.bytes_per_pixel()) * usize::from(bitmap.width.get());
193-
let data = match bitmap.order {
194-
PixelOrder::BottomToTop => {
195-
if stride == bitmap.stride {
196-
mem::take(&mut bitmap.data)
197-
} else {
198-
let mut data = Vec::with_capacity(stride * usize::from(bitmap.height.get()));
199-
for row in bitmap.data.chunks(bitmap.stride) {
200-
data.extend_from_slice(&row[..stride]);
201-
}
202-
data
203-
}
204-
}
205-
PixelOrder::TopToBottom => {
206-
let mut data = Vec::with_capacity(stride * usize::from(bitmap.height.get()));
207-
for row in bitmap.data.chunks(bitmap.stride).rev() {
208-
data.extend_from_slice(&row[..stride]);
209-
}
210-
data
211-
}
212-
};
213-
214-
self.set_surface(bitmap, CodecId::None as u8, data)
273+
let buf = self.encode(cmd)?;
274+
Ok(UpdateFragmenter::new(UpdateCode::SurfaceCommands, buf))
215275
}
216276
}
217277

0 commit comments

Comments
 (0)