Files
PVabel2026/CollabVM/Server/CollabVMv1_2GuacamoleServer.cs

117 lines
4.2 KiB
C#
Raw Normal View History

2026-02-20 12:23:23 +01:00
using ImageConverter;
using PVHelpers;
using RemoteFrameBuffer;
using System.Net;
using System.Net.WebSockets;
using System.Text;
namespace CollabVM.Server
{
public class CollabVMv1_2GuacamoleServer
{
private String tbfile = @"C:\Users\rolan\Downloads\bootsplash.jpg";
private static String[] ParseMessage(String s)
{
List<String> args = [];
while (true)
{
String[] parts = s.Split('.', 2);
if (parts.Length != 2)
{
throw new ArgumentException("Invalid message format: missing `.`", nameof(s));
}
if (Int32.TryParse(parts[0], out Int32 len))
{
if (parts[1].Length < len + 1)
{
throw new ArgumentException("Invalid message format: data doesn't fit in message", nameof(s));
}
args.Add(parts[1][..len]);
s = parts[1][(len+1)..];
if (parts[1][len] == ',')
{
continue;
}else if (parts[1][len] == ';')
{
break;
} else
{
throw new ArgumentException("Invalid message format: parameters must be separated by `,`, list closed by `;`", nameof(s));
}
}
else
{
throw new ArgumentException("Invalid message format: can't parse length field", nameof(s));
}
}
return args.ToArray();
}
private static String ConstructMessage(params String[] args) => String.Join(',', args.Select((s) => $"{s.Length}.{s}")) + ";";
private RemoteFramebufferClient _client;
public CollabVMv1_2GuacamoleServer(RemoteFramebufferClient client)
{
this._client = client;
client.Start();
}
public async void HandleSocket(WebSocket ws, IPEndPoint remote)
{
Console.Error.WriteLine("new WebSocket, who dis?");
#warning we probably don't need this much
Byte[] buf = new Byte[1024];
try
{
while (ws.State == WebSocketState.Open)
{
#warning probably needs a real ctoken
WebSocketReceiveResult recResult = await ws.ReceiveAsync(new ArraySegment<Byte>(buf), CancellationToken.None);
Console.Error.WriteLine(recResult.MessageType);
switch (recResult.MessageType)
{
case WebSocketMessageType.Close:
await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
break;
case WebSocketMessageType.Text:
String msg = Encoding.UTF8.GetString(buf, 0, recResult.Count);
Console.Error.WriteLine(msg);
await this.HandleCommand(ws, ParseMessage(msg));
break;
default:
throw new NotSupportedException();
}
}
} finally
{
ws.Dispose();
}
}
public async Task HandleCommand(WebSocket ws, params String[] args)
{
switch (args[0])
{
case "cap":
break;
case "connect":
break;
case "list":
//await this.Reply(ws, "list", "vmx", "Fake test VM", File.ReadAllBytes(tbfile).EncodeBase64String());
await this.Reply(ws, "list", "vmx", "Somewhat fake test VM", this._client.BitMap.BmpToJpg().EncodeBase64String());
break;
case "rename":
break;
}
}
public async Task Reply(WebSocket ws, params String[] args)
{
Byte[] buf = Encoding.UTF8.GetBytes(ConstructMessage(args));
await ws.SendAsync(new ArraySegment<Byte>(buf, 0, buf.Length), WebSocketMessageType.Text, true, CancellationToken.None);
}
}
}