Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 16 additions & 11 deletions crates/ironrdp-dvc/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ impl DrdynvcClient {
self.cap_handshake_done = true;
SvcMessage::from(caps_response)
}

pub fn close_channel(&mut self, channel_id: u32) -> SvcMessage {
self.dynamic_channels.remove_by_channel_id(channel_id);
SvcMessage::from(DrdynvcClientPdu::Close(ClosePdu::new(channel_id)))
}
}

impl_as_any!(DrdynvcClient);
Expand Down Expand Up @@ -227,14 +232,14 @@ impl SvcProcessor for DrdynvcClient {
);
}
}
DrdynvcServerPdu::Close(close_request) => {
debug!("Got DVC Close Request PDU: {close_request:?}");
self.dynamic_channels.remove_by_channel_id(close_request.channel_id());

let close_response = DrdynvcClientPdu::Close(ClosePdu::new(close_request.channel_id()));

debug!("Send DVC Close Response PDU: {close_response:?}");
responses.push(SvcMessage::from(close_response));
DrdynvcServerPdu::Close(close) => {
debug!("Got DVC Close PDU: {close:?}");
let channel_id = close.channel_id();
if self.dynamic_channels.remove_by_channel_id(channel_id).is_some() {
let close_response = DrdynvcClientPdu::Close(ClosePdu::new(channel_id));
debug!("Send DVC Close Response PDU: {close_response:?}");
responses.push(SvcMessage::from(close_response));
}
}
DrdynvcServerPdu::Data(data) => {
let channel_id = data.channel_id();
Expand Down Expand Up @@ -337,8 +342,8 @@ impl DynamicChannelSet {
self.active_channels.get_mut(&id)
}

fn remove_by_channel_id(&mut self, id: DynamicChannelId) {
if let Some(dvc) = self.active_channels.remove(&id) {
fn remove_by_channel_id(&mut self, id: DynamicChannelId) -> Option<DynamicVirtualChannel> {
self.active_channels.remove(&id).inspect(|dvc| {
let type_id = dvc.processor_type_id();

// Only matters for pre-registered channels
Expand All @@ -347,7 +352,7 @@ impl DynamicChannelSet {
{
entry.remove();
}
}
})
}

#[inline]
Expand Down
8 changes: 8 additions & 0 deletions crates/ironrdp-dvc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@ pub struct DynamicVirtualChannel {
channel_id: Option<DynamicChannelId>,
}

impl Drop for DynamicVirtualChannel {
fn drop(&mut self) {
if let Some(id) = self.channel_id {
self.channel_processor.close(id);
}
}
}

impl DynamicVirtualChannel {
fn from_boxed(processor: Box<dyn DvcProcessor + Send>) -> Self {
Self {
Expand Down
13 changes: 7 additions & 6 deletions crates/ironrdp-dvc/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,14 +201,15 @@ impl SvcProcessor for DrdynvcServer {
let msg = c.processor.start(create_resp.channel_id())?;
resp.extend(encode_dvc_messages(id, msg, ChannelFlags::SHOW_PROTOCOL).map_err(|e| encode_err!(e))?);
}
DrdynvcClientPdu::Close(close_resp) => {
debug!("Got DVC Close Response PDU: {close_resp:?}");
let c = self
.channel_by_id(close_resp.channel_id())
.map_err(|e| decode_err!(e))?;
DrdynvcClientPdu::Close(close) => {
debug!("Got DVC Close PDU: {close:?}");
let channel_id = close.channel_id();
let c = self.channel_by_id(channel_id).map_err(|e| decode_err!(e))?;
if c.state != ChannelState::Opened {
return Err(pdu_other_err!("invalid channel state"));
debug!(?channel_id, ?c.state, "Ignoring close for channel not in Opened state");
return Ok(resp);
}
c.processor.close(channel_id);
c.state = ChannelState::Closed;
}
DrdynvcClientPdu::Data(data) => {
Expand Down
Loading