Skip to content

Commit cc2619b

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 <[email protected]>
1 parent 45722f2 commit cc2619b

File tree

1 file changed

+137
-77
lines changed
  • crates/ironrdp-server/src/encoder

1 file changed

+137
-77
lines changed

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

Lines changed: 137 additions & 77 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,77 @@ 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],
138117
}
139118
}
119+
}
140120

141-
fn bitmap_update(&mut self, bitmap: BitmapUpdate) -> Result<UpdateFragmenter<'_>> {
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, 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 mut data = Vec::with_capacity(stride * usize::from(bitmap.height.get()));
147+
for row in bitmap.data.chunks(bitmap.stride).rev() {
148+
data.extend_from_slice(&row[..stride]);
149+
}
150+
151+
encoder.set_surface(bitmap, CodecId::None as u8, &data)
152+
}
153+
}
154+
155+
struct BitmapHandler {
156+
bitmap: BitmapEncoder,
157+
}
158+
159+
impl BitmapHandler {
160+
fn new() -> Self {
161+
Self {
162+
bitmap: BitmapEncoder::new(),
163+
}
164+
}
165+
}
166+
167+
impl BitmapUpdateHandler for BitmapHandler {
168+
fn handle<'a>(&mut self, bitmap: BitmapUpdate, encoder: &'a mut PduEncoder) -> Result<UpdateFragmenter<'a>> {
142169
let len = loop {
143-
match self.bitmap.encode(&bitmap, self.buffer.as_mut_slice()) {
170+
match self.bitmap.encode(&bitmap, encoder.buffer.as_mut_slice()) {
144171
Err(e) => match e.kind() {
145172
ironrdp_core::EncodeErrorKind::NotEnoughBytes { .. } => {
146-
self.buffer.resize(self.buffer.len() * 2, 0);
147-
debug!("encoder buffer resized to: {}", self.buffer.len() * 2);
173+
encoder.buffer.resize(encoder.buffer.len() * 2, 0);
174+
debug!("encoder buffer resized to: {}", encoder.buffer.len() * 2);
148175
}
149176

150177
_ => Err(e).context("bitmap encode error")?,
@@ -153,7 +180,71 @@ impl UpdateEncoder {
153180
}
154181
};
155182

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

159250
fn set_surface(&mut self, bitmap: BitmapUpdate, codec_id: u8, data: &[u8]) -> Result<UpdateFragmenter<'_>> {
@@ -176,39 +267,8 @@ impl UpdateEncoder {
176267
extended_bitmap_data,
177268
};
178269
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 mut buffer = vec![0; bitmap.data.len()];
187-
let len = loop {
188-
match remotefx.encode(&bitmap, buffer.as_mut_slice()) {
189-
Err(e) => match e.kind() {
190-
ironrdp_core::EncodeErrorKind::NotEnoughBytes { .. } => {
191-
buffer.resize(buffer.len() * 2, 0);
192-
debug!("encoder buffer resized to: {}", self.buffer.len() * 2);
193-
}
194-
195-
_ => Err(e).context("RemoteFX encode error")?,
196-
},
197-
Ok(len) => break len,
198-
}
199-
};
200-
201-
self.set_surface(bitmap, codec_id, &buffer[..len])
202-
}
203-
204-
fn none_update(&mut self, bitmap: BitmapUpdate) -> Result<UpdateFragmenter<'_>> {
205-
let stride = usize::from(bitmap.format.bytes_per_pixel()) * usize::from(bitmap.width.get());
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-
211-
self.set_surface(bitmap, CodecId::None as u8, &data)
270+
let buf = self.encode(cmd)?;
271+
Ok(UpdateFragmenter::new(UpdateCode::SurfaceCommands, buf))
212272
}
213273
}
214274

0 commit comments

Comments
 (0)