From 58755938c2fb88c50f632ae83733656a134e7cad Mon Sep 17 00:00:00 2001
From: "irvingouj @ Devolutions"
<139169536+irvingoujAtDevolution@users.noreply.github.com>
Date: Tue, 21 May 2024 21:49:37 -0400
Subject: [PATCH] feat(ffi): add graceful shutdown API (#464)
---
.../MainWindow.axaml | 17 +++++++++-----
.../MainWindow.axaml.cs | 15 ++++++++++++-
.../Program.cs | 1 +
.../Generated/ActiveStage.cs | 22 +++++++++++++++++++
.../Generated/RawActiveStage.cs | 3 +++
ffi/src/session/mod.rs | 5 +++++
6 files changed, 57 insertions(+), 6 deletions(-)
diff --git a/ffi/dotnet/Devolutions.IronRdp.AvaloniaExample/MainWindow.axaml b/ffi/dotnet/Devolutions.IronRdp.AvaloniaExample/MainWindow.axaml
index 71a325e2..125ba87a 100644
--- a/ffi/dotnet/Devolutions.IronRdp.AvaloniaExample/MainWindow.axaml
+++ b/ffi/dotnet/Devolutions.IronRdp.AvaloniaExample/MainWindow.axaml
@@ -6,9 +6,16 @@
x:Class="Devolutions.IronRdp.AvaloniaExample.MainWindow"
Title="Devolutions.IronRdp.AvaloniaExample">
-
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ffi/dotnet/Devolutions.IronRdp.AvaloniaExample/MainWindow.axaml.cs b/ffi/dotnet/Devolutions.IronRdp.AvaloniaExample/MainWindow.axaml.cs
index 0a25d07b..b86c68a8 100644
--- a/ffi/dotnet/Devolutions.IronRdp.AvaloniaExample/MainWindow.axaml.cs
+++ b/ffi/dotnet/Devolutions.IronRdp.AvaloniaExample/MainWindow.axaml.cs
@@ -10,6 +10,7 @@ using System.Net.Security;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Avalonia.Markup.Xaml;
+using Avalonia.Interactivity;
namespace Devolutions.IronRdp.AvaloniaExample;
@@ -357,7 +358,7 @@ public partial class MainWindow : Window
IntPtr? GetWindowHandle()
{
- var handle = this.TryGetPlatformHandle();
+ var handle = TryGetPlatformHandle();
if (handle == null)
{
return null;
@@ -365,4 +366,16 @@ public partial class MainWindow : Window
return handle.Handle;
}
+
+ public void OnDisconnectClick(object? sender, RoutedEventArgs e)
+ {
+ var output = this._activeStage!.GracefulShutdown();
+
+ HandleActiveStageOutput(output).ContinueWith(t=>{
+ if (t.IsFaulted)
+ {
+ Trace.TraceError("Error processing active stage: " + t.Exception!.Message);
+ }
+ });
+ }
}
\ No newline at end of file
diff --git a/ffi/dotnet/Devolutions.IronRdp.AvaloniaExample/Program.cs b/ffi/dotnet/Devolutions.IronRdp.AvaloniaExample/Program.cs
index 1d0ce255..b805dbbd 100644
--- a/ffi/dotnet/Devolutions.IronRdp.AvaloniaExample/Program.cs
+++ b/ffi/dotnet/Devolutions.IronRdp.AvaloniaExample/Program.cs
@@ -18,6 +18,7 @@ class Program
.StartWithClassicDesktopLifetime(args);
}catch(Exception e){
Trace.TraceError(e.Message);
+ Trace.TraceError(e.StackTrace);
}
}
diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStage.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStage.cs
index dc9fdf32..09f89280 100644
--- a/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStage.cs
+++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStage.cs
@@ -209,6 +209,28 @@ public partial class ActiveStage: IDisposable
}
}
+ ///
+ ///
+ /// A ActiveStageOutputIterator allocated on Rust side.
+ ///
+ public ActiveStageOutputIterator GracefulShutdown()
+ {
+ unsafe
+ {
+ if (_inner == null)
+ {
+ throw new ObjectDisposedException("ActiveStage");
+ }
+ Raw.SessionFfiResultBoxActiveStageOutputIteratorBoxIronRdpError result = Raw.ActiveStage.GracefulShutdown(_inner);
+ if (!result.isOk)
+ {
+ throw new IronRdpException(new IronRdpError(result.Err));
+ }
+ Raw.ActiveStageOutputIterator* retVal = result.Ok;
+ return new ActiveStageOutputIterator(retVal);
+ }
+ }
+
///
/// Returns the underlying raw handle.
///
diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStage.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStage.cs
index b41c328a..e6453a59 100644
--- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStage.cs
+++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStage.cs
@@ -34,6 +34,9 @@ public partial struct ActiveStage
[DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStage_submit_clipboard_format_data", ExactSpelling = true)]
public static unsafe extern SessionFfiResultBoxVecU8BoxIronRdpError SubmitClipboardFormatData(ActiveStage* self, FormatDataResponse* formatDataResponse);
+ [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStage_graceful_shutdown", ExactSpelling = true)]
+ public static unsafe extern SessionFfiResultBoxActiveStageOutputIteratorBoxIronRdpError GracefulShutdown(ActiveStage* self);
+
[DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStage_destroy", ExactSpelling = true)]
public static unsafe extern void Destroy(ActiveStage* self);
}
diff --git a/ffi/src/session/mod.rs b/ffi/src/session/mod.rs
index 2a8d3ed1..1b0f2798 100644
--- a/ffi/src/session/mod.rs
+++ b/ffi/src/session/mod.rs
@@ -121,6 +121,11 @@ pub mod ffi {
Ok(Box::new(VecU8(frame)))
}
+
+ pub fn graceful_shutdown(&mut self) -> Result, Box> {
+ let outputs = self.0.graceful_shutdown()?;
+ Ok(Box::new(ActiveStageOutputIterator(outputs)))
+ }
}
pub enum ActiveStageOutputType {