Skip to content

Commit 5068740

Browse files
committed
refactor(server): make UpdateFragmenter own its data
Trying to share a common buffer creates all sort of complicated lifetime issues when trying to move the encoding to a 'static handler, or when implementing iterators. It's not worth it. Signed-off-by: Marc-André Lureau <[email protected]>
1 parent 8791dfe commit 5068740

File tree

3 files changed

+77
-124
lines changed

3 files changed

+77
-124
lines changed

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

Lines changed: 22 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,44 +10,28 @@ const MAX_FASTPATH_UPDATE_SIZE: usize = 16_374;
1010

1111
const FASTPATH_HEADER_SIZE: usize = 6;
1212

13-
pub(crate) struct UpdateFragmenterOwned {
13+
pub(crate) struct UpdateFragmenter {
1414
code: UpdateCode,
1515
index: usize,
16-
len: usize,
16+
data: Vec<u8>,
17+
position: usize,
1718
}
1819

19-
pub(crate) struct UpdateFragmenter<'a> {
20-
code: UpdateCode,
21-
index: usize,
22-
data: &'a [u8],
23-
}
24-
25-
impl fmt::Debug for UpdateFragmenter<'_> {
20+
impl fmt::Debug for UpdateFragmenter {
2621
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2722
f.debug_struct("UpdateFragmenter")
2823
.field("len", &self.data.len())
2924
.finish()
3025
}
3126
}
3227

33-
impl<'a> UpdateFragmenter<'a> {
34-
pub(crate) fn new(code: UpdateCode, data: &'a [u8]) -> Self {
35-
Self { code, index: 0, data }
36-
}
37-
38-
pub(crate) fn into_owned(self) -> UpdateFragmenterOwned {
39-
UpdateFragmenterOwned {
40-
code: self.code,
41-
index: self.index,
42-
len: self.data.len(),
43-
}
44-
}
45-
46-
pub(crate) fn from_owned(res: UpdateFragmenterOwned, buffer: &'a [u8]) -> UpdateFragmenter<'a> {
28+
impl UpdateFragmenter {
29+
pub(crate) fn new(code: UpdateCode, data: Vec<u8>) -> Self {
4730
Self {
48-
code: res.code,
49-
index: res.index,
50-
data: &buffer[0..res.len],
31+
code,
32+
index: 0,
33+
data,
34+
position: 0,
5135
}
5236
}
5337

@@ -57,13 +41,13 @@ impl<'a> UpdateFragmenter<'a> {
5741

5842
pub(crate) fn next(&mut self, dst: &mut [u8]) -> Option<usize> {
5943
let (consumed, written) = self.encode_next(dst)?;
60-
self.data = &self.data[consumed..];
44+
self.position += consumed;
6145
self.index = self.index.checked_add(1)?;
6246
Some(written)
6347
}
6448

6549
fn encode_next(&mut self, dst: &mut [u8]) -> Option<(usize, usize)> {
66-
match self.data.len() {
50+
match self.data.len() - self.position {
6751
0 => None,
6852

6953
1..=MAX_FASTPATH_UPDATE_SIZE => {
@@ -73,8 +57,8 @@ impl<'a> UpdateFragmenter<'a> {
7357
Fragmentation::Single
7458
};
7559

76-
self.encode_fastpath(frag, self.data, dst)
77-
.map(|written| (self.data.len(), written))
60+
self.encode_fastpath(frag, &self.data[self.position..], dst)
61+
.map(|written| (self.data.len() - self.position, written))
7862
}
7963

8064
_ => {
@@ -84,8 +68,12 @@ impl<'a> UpdateFragmenter<'a> {
8468
Fragmentation::First
8569
};
8670

87-
self.encode_fastpath(frag, &self.data[..MAX_FASTPATH_UPDATE_SIZE], dst)
88-
.map(|written| (MAX_FASTPATH_UPDATE_SIZE, written))
71+
self.encode_fastpath(
72+
frag,
73+
&self.data[self.position..MAX_FASTPATH_UPDATE_SIZE + self.position],
74+
dst,
75+
)
76+
.map(|written| (MAX_FASTPATH_UPDATE_SIZE, written))
8977
}
9078
}
9179
}
@@ -118,7 +106,7 @@ mod tests {
118106
#[test]
119107
fn test_single_fragment() {
120108
let data = vec![1, 2, 3, 4];
121-
let mut fragmenter = UpdateFragmenter::new(UpdateCode::Bitmap, &data);
109+
let mut fragmenter = UpdateFragmenter::new(UpdateCode::Bitmap, data);
122110
let mut buffer = vec![0; 100];
123111
let written = fragmenter.next(&mut buffer).unwrap();
124112
assert!(written > 0);
@@ -142,7 +130,7 @@ mod tests {
142130
#[test]
143131
fn test_multi_fragment() {
144132
let data = vec![0u8; MAX_FASTPATH_UPDATE_SIZE * 2 + 10];
145-
let mut fragmenter = UpdateFragmenter::new(UpdateCode::Bitmap, &data);
133+
let mut fragmenter = UpdateFragmenter::new(UpdateCode::Bitmap, data);
146134
let mut buffer = vec![0u8; fragmenter.size_hint()];
147135
let written = fragmenter.next(&mut buffer).unwrap();
148136
assert!(written > 0);

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

Lines changed: 53 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use core::fmt;
22

33
use anyhow::{Context, Result};
44
use ironrdp_acceptor::DesktopSize;
5-
use ironrdp_core::{Encode, WriteCursor};
5+
use ironrdp_pdu::encode_vec;
66
use ironrdp_pdu::fast_path::UpdateCode;
77
use ironrdp_pdu::geometry::ExclusiveRectangle;
88
use ironrdp_pdu::pointer::{ColorPointerAttribute, Point16, PointerAttribute, PointerPositionAttribute};
@@ -30,7 +30,6 @@ pub(crate) struct UpdateEncoder {
3030
desktop_size: DesktopSize,
3131
// FIXME: draw updates on the framebuffer
3232
framebuffer: Option<Framebuffer>,
33-
pdu_encoder: PduEncoder,
3433
bitmap_updater: BitmapUpdater,
3534
}
3635

@@ -44,7 +43,6 @@ impl fmt::Debug for UpdateEncoder {
4443

4544
impl UpdateEncoder {
4645
pub(crate) fn new(desktop_size: DesktopSize, surface_flags: CmdFlags, remotefx: Option<(EntropyBits, u8)>) -> Self {
47-
let pdu_encoder = PduEncoder::new();
4846
let bitmap_updater = if !surface_flags.contains(CmdFlags::SET_SURFACE_BITS) {
4947
BitmapUpdater::Bitmap(BitmapHandler::new())
5048
} else if remotefx.is_some() {
@@ -57,7 +55,6 @@ impl UpdateEncoder {
5755
Self {
5856
desktop_size,
5957
framebuffer: None,
60-
pdu_encoder,
6158
bitmap_updater,
6259
}
6360
}
@@ -66,7 +63,8 @@ impl UpdateEncoder {
6663
self.desktop_size = size;
6764
}
6865

69-
pub(crate) fn rgba_pointer(&mut self, ptr: RGBAPointer) -> Result<UpdateFragmenter<'_>> {
66+
#[allow(clippy::unused_self)]
67+
pub(crate) fn rgba_pointer(&mut self, ptr: RGBAPointer) -> Result<UpdateFragmenter> {
7068
let xor_mask = ptr.data;
7169

7270
let hot_spot = Point16 {
@@ -85,11 +83,11 @@ impl UpdateEncoder {
8583
xor_bpp: 32,
8684
color_pointer,
8785
};
88-
let buf = self.pdu_encoder.encode(ptr)?;
89-
Ok(UpdateFragmenter::new(UpdateCode::NewPointer, buf))
86+
Ok(UpdateFragmenter::new(UpdateCode::NewPointer, encode_vec(&ptr)?))
9087
}
9188

92-
pub(crate) fn color_pointer(&mut self, ptr: ColorPointer) -> Result<UpdateFragmenter<'_>> {
89+
#[allow(clippy::unused_self)]
90+
pub(crate) fn color_pointer(&mut self, ptr: ColorPointer) -> Result<UpdateFragmenter> {
9391
let hot_spot = Point16 {
9492
x: ptr.hot_x,
9593
y: ptr.hot_y,
@@ -102,27 +100,26 @@ impl UpdateEncoder {
102100
xor_mask: &ptr.xor_mask,
103101
and_mask: &ptr.and_mask,
104102
};
105-
let buf = self.pdu_encoder.encode(ptr)?;
106-
Ok(UpdateFragmenter::new(UpdateCode::ColorPointer, buf))
103+
Ok(UpdateFragmenter::new(UpdateCode::ColorPointer, encode_vec(&ptr)?))
107104
}
108105

109106
#[allow(clippy::unused_self)]
110-
pub(crate) fn default_pointer(&mut self) -> Result<UpdateFragmenter<'_>> {
111-
Ok(UpdateFragmenter::new(UpdateCode::DefaultPointer, &[]))
107+
pub(crate) fn default_pointer(&mut self) -> Result<UpdateFragmenter> {
108+
Ok(UpdateFragmenter::new(UpdateCode::DefaultPointer, vec![]))
112109
}
113110

114111
#[allow(clippy::unused_self)]
115-
pub(crate) fn hide_pointer(&mut self) -> Result<UpdateFragmenter<'_>> {
116-
Ok(UpdateFragmenter::new(UpdateCode::HiddenPointer, &[]))
112+
pub(crate) fn hide_pointer(&mut self) -> Result<UpdateFragmenter> {
113+
Ok(UpdateFragmenter::new(UpdateCode::HiddenPointer, vec![]))
117114
}
118115

119-
pub(crate) fn pointer_position(&mut self, pos: PointerPositionAttribute) -> Result<UpdateFragmenter<'_>> {
120-
let buf = self.pdu_encoder.encode(pos)?;
121-
Ok(UpdateFragmenter::new(UpdateCode::PositionPointer, buf))
116+
#[allow(clippy::unused_self)]
117+
pub(crate) fn pointer_position(&mut self, pos: PointerPositionAttribute) -> Result<UpdateFragmenter> {
118+
Ok(UpdateFragmenter::new(UpdateCode::PositionPointer, encode_vec(&pos)?))
122119
}
123120

124-
pub(crate) fn bitmap(&mut self, bitmap: BitmapUpdate) -> Result<UpdateFragmenter<'_>> {
125-
let res = self.bitmap_updater.handle(&bitmap, &mut self.pdu_encoder);
121+
pub(crate) fn bitmap(&mut self, bitmap: BitmapUpdate) -> Result<UpdateFragmenter> {
122+
let res = self.bitmap_updater.handle(&bitmap);
126123
if bitmap.x == 0
127124
&& bitmap.y == 0
128125
&& bitmap.width.get() == self.desktop_size.width
@@ -135,10 +132,6 @@ impl UpdateEncoder {
135132
}
136133
res
137134
}
138-
139-
pub(crate) fn fragmenter_from_owned(&self, res: UpdateFragmenterOwned) -> UpdateFragmenter<'_> {
140-
UpdateFragmenter::from_owned(res, &self.pdu_encoder.buffer)
141-
}
142135
}
143136

144137
#[derive(Debug)]
@@ -149,30 +142,30 @@ enum BitmapUpdater {
149142
}
150143

151144
impl BitmapUpdater {
152-
fn handle<'a>(&mut self, bitmap: &BitmapUpdate, encoder: &'a mut PduEncoder) -> Result<UpdateFragmenter<'a>> {
145+
fn handle(&mut self, bitmap: &BitmapUpdate) -> Result<UpdateFragmenter> {
153146
match self {
154-
Self::None(up) => up.handle(bitmap, encoder),
155-
Self::Bitmap(up) => up.handle(bitmap, encoder),
156-
Self::RemoteFx(up) => up.handle(bitmap, encoder),
147+
Self::None(up) => up.handle(bitmap),
148+
Self::Bitmap(up) => up.handle(bitmap),
149+
Self::RemoteFx(up) => up.handle(bitmap),
157150
}
158151
}
159152
}
160153

161154
trait BitmapUpdateHandler {
162-
fn handle<'a>(&mut self, bitmap: &BitmapUpdate, encoder: &'a mut PduEncoder) -> Result<UpdateFragmenter<'a>>;
155+
fn handle(&mut self, bitmap: &BitmapUpdate) -> Result<UpdateFragmenter>;
163156
}
164157

165158
#[derive(Debug)]
166159
struct NoneHandler;
167160

168161
impl BitmapUpdateHandler for NoneHandler {
169-
fn handle<'a>(&mut self, bitmap: &BitmapUpdate, encoder: &'a mut PduEncoder) -> Result<UpdateFragmenter<'a>> {
162+
fn handle(&mut self, bitmap: &BitmapUpdate) -> Result<UpdateFragmenter> {
170163
let stride = usize::from(bitmap.format.bytes_per_pixel()) * usize::from(bitmap.width.get());
171164
let mut data = Vec::with_capacity(stride * usize::from(bitmap.height.get()));
172165
for row in bitmap.data.chunks(bitmap.stride).rev() {
173166
data.extend_from_slice(&row[..stride]);
174167
}
175-
encoder.set_surface(bitmap, CodecId::None as u8, &data)
168+
set_surface(bitmap, CodecId::None as u8, &data)
176169
}
177170
}
178171

@@ -195,13 +188,14 @@ impl BitmapHandler {
195188
}
196189

197190
impl BitmapUpdateHandler for BitmapHandler {
198-
fn handle<'a>(&mut self, bitmap: &BitmapUpdate, encoder: &'a mut PduEncoder) -> Result<UpdateFragmenter<'a>> {
191+
fn handle(&mut self, bitmap: &BitmapUpdate) -> Result<UpdateFragmenter> {
192+
let mut buffer = vec![0; bitmap.data.len() * 2]; // TODO: estimate bitmap encoded size
199193
let len = loop {
200-
match self.bitmap.encode(bitmap, encoder.buffer.as_mut_slice()) {
194+
match self.bitmap.encode(bitmap, buffer.as_mut_slice()) {
201195
Err(e) => match e.kind() {
202196
ironrdp_core::EncodeErrorKind::NotEnoughBytes { .. } => {
203-
encoder.buffer.resize(encoder.buffer.len() * 2, 0);
204-
debug!("encoder buffer resized to: {}", encoder.buffer.len() * 2);
197+
buffer.resize(buffer.len() * 2, 0);
198+
debug!("encoder buffer resized to: {}", buffer.len() * 2);
205199
}
206200

207201
_ => Err(e).context("bitmap encode error")?,
@@ -210,7 +204,8 @@ impl BitmapUpdateHandler for BitmapHandler {
210204
}
211205
};
212206

213-
Ok(UpdateFragmenter::new(UpdateCode::Bitmap, &encoder.buffer[..len]))
207+
buffer.truncate(len);
208+
Ok(UpdateFragmenter::new(UpdateCode::Bitmap, buffer))
214209
}
215210
}
216211

@@ -230,7 +225,7 @@ impl RemoteFxHandler {
230225
}
231226

232227
impl BitmapUpdateHandler for RemoteFxHandler {
233-
fn handle<'a>(&mut self, bitmap: &BitmapUpdate, encoder: &'a mut PduEncoder) -> Result<UpdateFragmenter<'a>> {
228+
fn handle(&mut self, bitmap: &BitmapUpdate) -> Result<UpdateFragmenter> {
234229
let mut buffer = vec![0; bitmap.data.len()];
235230
let len = loop {
236231
match self.remotefx.encode(bitmap, buffer.as_mut_slice()) {
@@ -246,59 +241,29 @@ impl BitmapUpdateHandler for RemoteFxHandler {
246241
}
247242
};
248243

249-
encoder.set_surface(bitmap, self.codec_id, &buffer[..len])
244+
set_surface(bitmap, self.codec_id, &buffer[..len])
250245
}
251246
}
252247

253-
struct PduEncoder {
254-
buffer: Vec<u8>,
255-
}
256-
257-
impl PduEncoder {
258-
fn new() -> Self {
259-
Self { buffer: vec![0; 16384] }
260-
}
261-
262-
fn encode(&mut self, pdu: impl Encode) -> Result<&[u8]> {
263-
let pos = loop {
264-
let mut cursor = WriteCursor::new(self.buffer.as_mut_slice());
265-
match pdu.encode(&mut cursor) {
266-
Err(e) => match e.kind() {
267-
ironrdp_core::EncodeErrorKind::NotEnoughBytes { .. } => {
268-
self.buffer.resize(self.buffer.len() * 2, 0);
269-
debug!("encoder buffer resized to: {}", self.buffer.len() * 2);
270-
}
271-
272-
_ => Err(e).context("PDU encode error")?,
273-
},
274-
Ok(()) => break cursor.pos(),
275-
}
276-
};
277-
278-
Ok(&self.buffer[..pos])
279-
}
280-
281-
fn set_surface(&mut self, bitmap: &BitmapUpdate, codec_id: u8, data: &[u8]) -> Result<UpdateFragmenter<'_>> {
282-
let destination = ExclusiveRectangle {
283-
left: bitmap.x,
284-
top: bitmap.y,
285-
right: bitmap.x + bitmap.width.get(),
286-
bottom: bitmap.y + bitmap.height.get(),
287-
};
288-
let extended_bitmap_data = ExtendedBitmapDataPdu {
289-
bpp: bitmap.format.bytes_per_pixel() * 8,
290-
width: bitmap.width.get(),
291-
height: bitmap.height.get(),
292-
codec_id,
293-
header: None,
294-
data,
295-
};
296-
let pdu = SurfaceBitsPdu {
297-
destination,
298-
extended_bitmap_data,
299-
};
300-
let cmd = SurfaceCommand::SetSurfaceBits(pdu);
301-
let buf = self.encode(cmd)?;
302-
Ok(UpdateFragmenter::new(UpdateCode::SurfaceCommands, buf))
303-
}
248+
fn set_surface(bitmap: &BitmapUpdate, codec_id: u8, data: &[u8]) -> Result<UpdateFragmenter> {
249+
let destination = ExclusiveRectangle {
250+
left: bitmap.x,
251+
top: bitmap.y,
252+
right: bitmap.x + bitmap.width.get(),
253+
bottom: bitmap.y + bitmap.height.get(),
254+
};
255+
let extended_bitmap_data = ExtendedBitmapDataPdu {
256+
bpp: bitmap.format.bytes_per_pixel() * 8,
257+
width: bitmap.width.get(),
258+
height: bitmap.height.get(),
259+
codec_id,
260+
header: None,
261+
data,
262+
};
263+
let pdu = SurfaceBitsPdu {
264+
destination,
265+
extended_bitmap_data,
266+
};
267+
let cmd = SurfaceCommand::SetSurfaceBits(pdu);
268+
Ok(UpdateFragmenter::new(UpdateCode::SurfaceCommands, encode_vec(&cmd)?))
304269
}

crates/ironrdp-server/src/server.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -426,12 +426,12 @@ impl RdpServer {
426426
let mut fragmenter = match update {
427427
DisplayUpdate::Bitmap(bitmap) => {
428428
let (enc, res) = task::spawn_blocking(move || {
429-
let res = time_warn!("Encoding bitmap", 10, encoder.bitmap(bitmap).map(|r| r.into_owned()));
429+
let res = time_warn!("Encoding bitmap", 10, encoder.bitmap(bitmap));
430430
(encoder, res)
431431
})
432432
.await?;
433433
encoder = enc;
434-
res.map(|r| encoder.fragmenter_from_owned(r))
434+
res
435435
}
436436
DisplayUpdate::PointerPosition(pos) => encoder.pointer_position(pos),
437437
DisplayUpdate::Resize(desktop_size) => {

0 commit comments

Comments
 (0)