Add support for binary JPEG rects, as well as some other minor tweaks
This commit is contained in:
parent
59fa954e11
commit
473756d8b4
5 changed files with 92 additions and 20 deletions
|
@ -14,6 +14,8 @@ using System.Text;
|
|||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using CollabVMSharp.Protocol;
|
||||
using MsgPack.Serialization;
|
||||
using Timer = System.Timers.Timer;
|
||||
// ReSharper disable FieldCanBeMadeReadOnly.Local
|
||||
// ReSharper disable ArrangeObjectCreationWhenTypeNotEvident
|
||||
|
@ -21,7 +23,9 @@ using Timer = System.Timers.Timer;
|
|||
// ReSharper disable ArrangeObjectCreationWhenTypeEvident
|
||||
|
||||
namespace CollabVMSharp;
|
||||
public class CollabVMClient {
|
||||
public class CollabVMClient
|
||||
{
|
||||
private static readonly string[] SupportedCapabilities = { "bin" };
|
||||
// Fields
|
||||
private Uri url;
|
||||
private string? username;
|
||||
|
@ -43,6 +47,7 @@ public class CollabVMClient {
|
|||
private Dictionary<string, Action<string, string>> commandsOneArg;
|
||||
private bool _usesAccountAuth;
|
||||
private Dictionary<string,string> _headers;
|
||||
private MessagePackSerializer<CollabVMProtocolMessage> _msgpack;
|
||||
// Tasks and related
|
||||
private TaskCompletionSource<Node[]> GotNodeList;
|
||||
private TaskCompletionSource<bool> GotConnectionToNode;
|
||||
|
@ -152,6 +157,7 @@ public class CollabVMClient {
|
|||
this.GotIPTasks = new();
|
||||
this.QEMUMonitorResult = new();
|
||||
this.QEMUMonitorSemaphore = new(1, 1);
|
||||
this._msgpack = MessagePackSerializer.Get<CollabVMProtocolMessage>();
|
||||
// Assign empty handlers to prevent exception
|
||||
Chat += delegate { };
|
||||
ChatHistory += delegate { };
|
||||
|
@ -188,6 +194,8 @@ public class CollabVMClient {
|
|||
this.SendMsg(Guacutils.Encode("rename", this.username));
|
||||
else
|
||||
this.SendMsg(Guacutils.Encode("rename"));
|
||||
if (SupportedCapabilities.Length > 0)
|
||||
this.SendMsg(Guacutils.Encode(SupportedCapabilities.Prepend("cap").ToArray()));
|
||||
this.NOPRecieve.Start();
|
||||
this.WebSocketLoop();
|
||||
if (this.node == null) return;
|
||||
|
@ -199,15 +207,13 @@ public class CollabVMClient {
|
|||
private async void WebSocketLoop() {
|
||||
ArraySegment<byte> receivebuffer = new ArraySegment<byte>(new byte[8192]);
|
||||
do {
|
||||
MemoryStream ms = new();
|
||||
using var ms = new MemoryStream();
|
||||
WebSocketReceiveResult res;
|
||||
do {
|
||||
try {
|
||||
res = await socket.ReceiveAsync(receivebuffer, CancellationToken.None);
|
||||
} catch (WebSocketException e) {
|
||||
#if DEBUG
|
||||
Console.Error.WriteLine($"Got {e.Message} while reading from WebSocket, closing connection");
|
||||
#endif
|
||||
Error.Invoke(this, $"Got {e.Message} while reading from WebSocket, closing connection");
|
||||
Cleanup(true);
|
||||
return;
|
||||
}
|
||||
|
@ -218,28 +224,72 @@ public class CollabVMClient {
|
|||
}
|
||||
await ms.WriteAsync(receivebuffer.Array, 0, res.Count);
|
||||
} while (!res.EndOfMessage);
|
||||
string msg;
|
||||
try {
|
||||
msg = Encoding.UTF8.GetString(ms.ToArray());
|
||||
} catch (Exception e) {
|
||||
#if DEBUG
|
||||
await Console.Error.WriteLineAsync($"Failed to read message from socket: {e.Message}");
|
||||
#endif
|
||||
continue;
|
||||
} finally {ms.Dispose();}
|
||||
this.ProcessMessage(msg);
|
||||
if (res.MessageType == WebSocketMessageType.Text)
|
||||
{
|
||||
string msg;
|
||||
try {
|
||||
msg = Encoding.UTF8.GetString(ms.ToArray());
|
||||
} catch (Exception e) {
|
||||
Error.Invoke(this, $"Failed to read message from socket: {e.Message}");
|
||||
continue;
|
||||
}
|
||||
this.ProcessMessage(msg);
|
||||
} else if (res.MessageType == WebSocketMessageType.Binary)
|
||||
{
|
||||
ms.Position = 0;
|
||||
await this.ProcessBinaryMessage(ms);
|
||||
}
|
||||
|
||||
} while (socket.State == WebSocketState.Open);
|
||||
this.Cleanup();
|
||||
}
|
||||
|
||||
private async Task ProcessBinaryMessage(MemoryStream data)
|
||||
{
|
||||
CollabVMProtocolMessage msg;
|
||||
try
|
||||
{
|
||||
msg = await this._msgpack.UnpackAsync(data);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Error.Invoke(this, $"Failed to unpack binary message: {ex.Message}");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg.type)
|
||||
{
|
||||
case CollabVMProtocolMessageType.rect:
|
||||
{
|
||||
if (msg.rect == null || msg.rect!.data == null) return;
|
||||
Image rect;
|
||||
try
|
||||
{
|
||||
rect = Image.Load(msg.rect.data);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Error.Invoke(this, "Server sent an invalid screen rect");
|
||||
return;
|
||||
}
|
||||
framebuffer.Mutate(f => f.DrawImage(rect, new Point(msg.rect.x, msg.rect.y), 1));
|
||||
this.Rect.Invoke(this, new RectEventArgs
|
||||
{
|
||||
X = msg.rect.x,
|
||||
Y = msg.rect.y,
|
||||
Data = rect,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void ProcessMessage(string msg) {
|
||||
string[] msgArr;
|
||||
try {
|
||||
msgArr = Guacutils.Decode(msg);
|
||||
} catch (Exception e) {
|
||||
#if DEBUG
|
||||
await Console.Error.WriteLineAsync($"Failed to decode incoming message: {e.Message}");
|
||||
#endif
|
||||
Error.Invoke(this, $"Failed to decode incoming message: {e.Message}");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -327,7 +377,7 @@ public class CollabVMClient {
|
|||
{
|
||||
rect = Image.Load(Convert.FromBase64String(msgArr[5]));
|
||||
}
|
||||
catch (FormatException ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
Error.Invoke(this, "Server sent an invalid screen rect");
|
||||
return;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>10</LangVersion>
|
||||
<Version>2.7.0</Version>
|
||||
<Version>2.7.1</Version>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
<PackageLicenseExpression>GPL-3.0-or-later</PackageLicenseExpression>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
|
@ -11,6 +11,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MsgPack.Cli" Version="1.0.1" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.3" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
7
CollabVMSharp/Protocol/CollabVMProtocolMessage.cs
Normal file
7
CollabVMSharp/Protocol/CollabVMProtocolMessage.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace CollabVMSharp.Protocol;
|
||||
|
||||
public class CollabVMProtocolMessage
|
||||
{
|
||||
public CollabVMProtocolMessageType type { get; set; }
|
||||
public CollabVMRectMessage? rect { get; set; }
|
||||
}
|
6
CollabVMSharp/Protocol/CollabVMProtocolMessageType.cs
Normal file
6
CollabVMSharp/Protocol/CollabVMProtocolMessageType.cs
Normal file
|
@ -0,0 +1,6 @@
|
|||
namespace CollabVMSharp.Protocol;
|
||||
|
||||
public enum CollabVMProtocolMessageType
|
||||
{
|
||||
rect = 0
|
||||
}
|
8
CollabVMSharp/Protocol/CollabVMRectMessage.cs
Normal file
8
CollabVMSharp/Protocol/CollabVMRectMessage.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace CollabVMSharp.Protocol;
|
||||
|
||||
public class CollabVMRectMessage
|
||||
{
|
||||
public int x { get; set; }
|
||||
public int y { get; set; }
|
||||
public byte[] data { get; set; }
|
||||
}
|
Loading…
Reference in a new issue