mirror of
https://github.com/Devolutions/IronRDP.git
synced 2025-07-07 17:45:01 +00:00
feat: implement the connection activation sequence rerun (#421)
This commit is contained in:
parent
d46e7964bf
commit
ba3796f738
8 changed files with 108 additions and 13 deletions
|
@ -25,7 +25,7 @@ where
|
|||
info!("Begin connection procedure");
|
||||
|
||||
while !connector.should_perform_security_upgrade() {
|
||||
single_connect_step(framed, connector, &mut buf)?;
|
||||
single_sequence_step(framed, connector, &mut buf)?;
|
||||
}
|
||||
|
||||
Ok(ShouldUpgrade)
|
||||
|
@ -78,7 +78,7 @@ where
|
|||
debug!("Remaining of connection sequence");
|
||||
|
||||
let result = loop {
|
||||
single_connect_step(framed, &mut connector, &mut buf)?;
|
||||
single_sequence_step(framed, &mut connector, &mut buf)?;
|
||||
|
||||
if let ClientConnectorState::Connected { result } = connector.state {
|
||||
break result;
|
||||
|
@ -173,7 +173,7 @@ where
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn single_connect_step<S>(
|
||||
pub fn single_sequence_step<S>(
|
||||
framed: &mut Framed<S>,
|
||||
connector: &mut ClientConnector,
|
||||
buf: &mut WriteBuf,
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
use ironrdp::cliprdr::backend::{ClipboardMessage, CliprdrBackendFactory};
|
||||
use ironrdp::connector::connection_activation::ConnectionActivationState;
|
||||
use ironrdp::connector::{ConnectionResult, ConnectorResult};
|
||||
use ironrdp::graphics::image_processing::PixelFormat;
|
||||
use ironrdp::pdu::input::fast_path::FastPathInputEvent;
|
||||
use ironrdp::pdu::write_buf::WriteBuf;
|
||||
use ironrdp::session::image::DecodedImage;
|
||||
use ironrdp::session::{ActiveStage, ActiveStageOutput, GracefulDisconnectReason, SessionResult};
|
||||
use ironrdp::session::{fast_path, ActiveStage, ActiveStageOutput, GracefulDisconnectReason, SessionResult};
|
||||
use ironrdp::{cliprdr, connector, rdpdr, rdpsnd, session};
|
||||
use ironrdp_tokio::single_sequence_step_read;
|
||||
use rdpdr::NoopRdpdrBackend;
|
||||
use smallvec::SmallVec;
|
||||
use tokio::net::TcpStream;
|
||||
|
@ -280,7 +283,47 @@ async fn active_session(
|
|||
ActiveStageOutput::PointerBitmap(_) => {
|
||||
// Not applicable, because we use the software cursor rendering.
|
||||
}
|
||||
ActiveStageOutput::DeactivateAll(_) => todo!("DeactivateAll"),
|
||||
ActiveStageOutput::DeactivateAll(mut connection_activation) => {
|
||||
// Execute the Deactivation-Reactivation Sequence:
|
||||
// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/dfc234ce-481a-4674-9a5d-2a7bafb14432
|
||||
debug!("Received Server Deactivate All PDU, executing Deactivation-Reactivation Sequence");
|
||||
let mut buf = WriteBuf::new();
|
||||
'activation_seq: loop {
|
||||
let written = single_sequence_step_read(&mut framed, &mut *connection_activation, &mut buf)
|
||||
.await
|
||||
.map_err(|e| session::custom_err!("read deactivation-reactivation sequence step", e))?;
|
||||
|
||||
if written.size().is_some() {
|
||||
framed.write_all(buf.filled()).await.map_err(|e| {
|
||||
session::custom_err!("write deactivation-reactivation sequence step", e)
|
||||
})?;
|
||||
}
|
||||
|
||||
if let ConnectionActivationState::Finalized {
|
||||
io_channel_id,
|
||||
user_channel_id,
|
||||
desktop_size,
|
||||
no_server_pointer,
|
||||
pointer_software_rendering,
|
||||
} = connection_activation.state
|
||||
{
|
||||
debug!("Deactivation-Reactivation Sequence completed");
|
||||
image = DecodedImage::new(PixelFormat::RgbA32, desktop_size.width, desktop_size.height);
|
||||
// Create a new [`FastPathProcessor`] with potentially updated
|
||||
// io/user channel ids.
|
||||
active_stage.set_fastpath_processor(
|
||||
fast_path::ProcessorBuilder {
|
||||
io_channel_id,
|
||||
user_channel_id,
|
||||
no_server_pointer,
|
||||
pointer_software_rendering,
|
||||
}
|
||||
.build(),
|
||||
);
|
||||
break 'activation_seq;
|
||||
}
|
||||
}
|
||||
}
|
||||
ActiveStageOutput::Terminate(reason) => break 'outer reason,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -551,14 +551,16 @@ impl Sequence for ClientConnector {
|
|||
io_channel_id,
|
||||
user_channel_id,
|
||||
desktop_size,
|
||||
no_server_pointer,
|
||||
pointer_software_rendering,
|
||||
} => ClientConnectorState::Connected {
|
||||
result: ConnectionResult {
|
||||
io_channel_id,
|
||||
user_channel_id,
|
||||
static_channels: mem::take(&mut self.static_channels),
|
||||
desktop_size,
|
||||
no_server_pointer: self.config.no_server_pointer,
|
||||
pointer_software_rendering: self.config.pointer_software_rendering,
|
||||
no_server_pointer,
|
||||
pointer_software_rendering,
|
||||
connection_activation,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -187,6 +187,8 @@ impl Sequence for ConnectionActivationSequence {
|
|||
io_channel_id,
|
||||
user_channel_id,
|
||||
desktop_size,
|
||||
no_server_pointer: self.config.no_server_pointer,
|
||||
pointer_software_rendering: self.config.pointer_software_rendering,
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -218,6 +220,8 @@ pub enum ConnectionActivationState {
|
|||
io_channel_id: u16,
|
||||
user_channel_id: u16,
|
||||
desktop_size: DesktopSize,
|
||||
no_server_pointer: bool,
|
||||
pointer_software_rendering: bool,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ pub struct DesktopSize {
|
|||
pub height: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
pub struct BitmapConfig {
|
||||
pub lossy_compression: bool,
|
||||
|
|
|
@ -146,6 +146,10 @@ impl ActiveStage {
|
|||
Ok(stage_outputs)
|
||||
}
|
||||
|
||||
pub fn set_fastpath_processor(&mut self, processor: fast_path::Processor) {
|
||||
self.fast_path_processor = processor;
|
||||
}
|
||||
|
||||
/// Encodes client-side graceful shutdown request. Note that upon sending this request,
|
||||
/// client should wait for server's ShutdownDenied PDU before closing the connection.
|
||||
///
|
||||
|
@ -192,7 +196,7 @@ pub enum ActiveStageOutput {
|
|||
PointerPosition { x: u16, y: u16 },
|
||||
PointerBitmap(Rc<DecodedPointer>),
|
||||
Terminate(GracefulDisconnectReason),
|
||||
DeactivateAll(ConnectionActivationSequence),
|
||||
DeactivateAll(Box<ConnectionActivationSequence>),
|
||||
}
|
||||
|
||||
impl TryFrom<x224::ProcessorOutput> for ActiveStageOutput {
|
||||
|
|
|
@ -21,7 +21,7 @@ pub enum ProcessorOutput {
|
|||
/// [Deactivation-Reactivation Sequence].
|
||||
///
|
||||
/// [Deactivation-Reactivation Sequence]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/dfc234ce-481a-4674-9a5d-2a7bafb14432
|
||||
DeactivateAll(ConnectionActivationSequence),
|
||||
DeactivateAll(Box<ConnectionActivationSequence>),
|
||||
}
|
||||
|
||||
pub struct Processor {
|
||||
|
@ -155,7 +155,7 @@ impl Processor {
|
|||
}
|
||||
}
|
||||
ironrdp_connector::legacy::IoChannelPdu::DeactivateAll(_) => Ok(vec![ProcessorOutput::DeactivateAll(
|
||||
self.connection_activation.reset_clone(),
|
||||
Box::new(self.connection_activation.reset_clone()),
|
||||
)]),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ use gloo_net::websocket;
|
|||
use gloo_net::websocket::futures::WebSocket;
|
||||
use ironrdp::cliprdr::backend::ClipboardMessage;
|
||||
use ironrdp::cliprdr::CliprdrClient;
|
||||
use ironrdp::connector::connection_activation::ConnectionActivationState;
|
||||
use ironrdp::connector::credssp::KerberosConfig;
|
||||
use ironrdp::connector::{self, ClientConnector, Credentials};
|
||||
use ironrdp::graphics::image_processing::PixelFormat;
|
||||
|
@ -19,7 +20,8 @@ use ironrdp::pdu::input::fast_path::FastPathInputEvent;
|
|||
use ironrdp::pdu::rdp::client_info::PerformanceFlags;
|
||||
use ironrdp::pdu::write_buf::WriteBuf;
|
||||
use ironrdp::session::image::DecodedImage;
|
||||
use ironrdp::session::{ActiveStage, ActiveStageOutput, GracefulDisconnectReason};
|
||||
use ironrdp::session::{fast_path, ActiveStage, ActiveStageOutput, GracefulDisconnectReason};
|
||||
use ironrdp_futures::single_sequence_step_read;
|
||||
use rgb::AsPixels as _;
|
||||
use tap::prelude::*;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
@ -604,7 +606,47 @@ impl Session {
|
|||
hotspot_y,
|
||||
})?;
|
||||
}
|
||||
ActiveStageOutput::DeactivateAll(_) => todo!("DeactivateAll"),
|
||||
ActiveStageOutput::DeactivateAll(mut box_connection_activation) => {
|
||||
// Execute the Deactivation-Reactivation Sequence:
|
||||
// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/dfc234ce-481a-4674-9a5d-2a7bafb14432
|
||||
debug!("Received Server Deactivate All PDU, executing Deactivation-Reactivation Sequence");
|
||||
let mut buf = WriteBuf::new();
|
||||
'activation_seq: loop {
|
||||
let written =
|
||||
single_sequence_step_read(&mut framed, &mut *box_connection_activation, &mut buf)
|
||||
.await?;
|
||||
|
||||
if written.size().is_some() {
|
||||
self.writer_tx
|
||||
.unbounded_send(buf.filled().to_vec())
|
||||
.context("Send frame to writer task")?;
|
||||
}
|
||||
|
||||
if let ConnectionActivationState::Finalized {
|
||||
io_channel_id,
|
||||
user_channel_id,
|
||||
desktop_size,
|
||||
no_server_pointer,
|
||||
pointer_software_rendering,
|
||||
} = box_connection_activation.state
|
||||
{
|
||||
debug!("Deactivation-Reactivation Sequence completed");
|
||||
image = DecodedImage::new(PixelFormat::RgbA32, desktop_size.width, desktop_size.height);
|
||||
// Create a new [`FastPathProcessor`] with potentially updated
|
||||
// io/user channel ids.
|
||||
active_stage.set_fastpath_processor(
|
||||
fast_path::ProcessorBuilder {
|
||||
io_channel_id,
|
||||
user_channel_id,
|
||||
no_server_pointer,
|
||||
pointer_software_rendering,
|
||||
}
|
||||
.build(),
|
||||
);
|
||||
break 'activation_seq;
|
||||
}
|
||||
}
|
||||
}
|
||||
ActiveStageOutput::Terminate(reason) => break 'outer reason,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue