feat(ffi): add graceful shutdown API (#464)

This commit is contained in:
irvingouj @ Devolutions
2024-05-21 21:49:37 -04:00
committed by GitHub
parent 64e64d8cb4
commit 58755938c2
6 changed files with 57 additions and 6 deletions
@@ -6,9 +6,16 @@
x:Class="Devolutions.IronRdp.AvaloniaExample.MainWindow"
Title="Devolutions.IronRdp.AvaloniaExample">
<Canvas Name="MainCanvas" Width="1280" Height="800" Background="Black"
PointerPressed="Canvas_OnPointerPressed" PointerMoved="Canvas_PointerMoved" PointerReleased="Canvas_PointerReleased"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
<DockPanel>
<!-- Disconnect button at the top -->
<Button Content="Disconnect" DockPanel.Dock="Top" HorizontalAlignment="Right"
Margin="10" Click="OnDisconnectClick" />
<!-- Canvas adjusted to fill the remaining space -->
<Canvas Name="MainCanvas" Width="1280" Height="800" Background="Black"
PointerPressed="Canvas_OnPointerPressed" PointerMoved="Canvas_PointerMoved"
PointerReleased="Canvas_PointerReleased"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</DockPanel>
</Window>
@@ -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);
}
});
}
}
@@ -18,6 +18,7 @@ class Program
.StartWithClassicDesktopLifetime(args);
}catch(Exception e){
Trace.TraceError(e.Message);
Trace.TraceError(e.StackTrace);
}
}
@@ -209,6 +209,28 @@ public partial class ActiveStage: IDisposable
}
}
/// <exception cref="IronRdpException"></exception>
/// <returns>
/// A <c>ActiveStageOutputIterator</c> allocated on Rust side.
/// </returns>
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);
}
}
/// <summary>
/// Returns the underlying raw handle.
/// </summary>
@@ -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);
}
+5
View File
@@ -121,6 +121,11 @@ pub mod ffi {
Ok(Box::new(VecU8(frame)))
}
pub fn graceful_shutdown(&mut self) -> Result<Box<ActiveStageOutputIterator>, Box<IronRdpError>> {
let outputs = self.0.graceful_shutdown()?;
Ok(Box::new(ActiveStageOutputIterator(outputs)))
}
}
pub enum ActiveStageOutputType {