diff --git a/CollabVM/CollabVM.csproj b/CollabVM/CollabVM.csproj
index b760144..c7ca601 100644
--- a/CollabVM/CollabVM.csproj
+++ b/CollabVM/CollabVM.csproj
@@ -6,4 +6,10 @@
enable
+
+
+
+
+
+
diff --git a/CollabVM/Server/CollabVMGuacamoleServer.cs b/CollabVM/Server/CollabVMGuacamoleServer.cs
deleted file mode 100644
index 71c1be0..0000000
--- a/CollabVM/Server/CollabVMGuacamoleServer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using System.Net;
-using System.Net.WebSockets;
-using System.Text;
-
-namespace CollabVM.Server
-{
- public class CollabVMGuacamoleServer
- {
- 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(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);
- break;
- default:
- throw new NotSupportedException();
- }
- }
- } finally
- {
- ws.Dispose();
- }
- }
- }
-}
diff --git a/CollabVM/Server/CollabVMHttpServer.cs b/CollabVM/Server/CollabVMHttpServer.cs
index da7df25..1901544 100644
--- a/CollabVM/Server/CollabVMHttpServer.cs
+++ b/CollabVM/Server/CollabVMHttpServer.cs
@@ -10,7 +10,7 @@ namespace CollabVM.Server
public class CollabVMHttpServer
{
private HttpListener _listener = new();
- private Dictionary _servers = new();
+ private Dictionary _servers = new();
private readonly IPEndPoint _serverEndPoint;
private readonly Boolean _allowList = false;
@@ -21,12 +21,12 @@ namespace CollabVM.Server
}
public CollabVMHttpServer(IPAddress address, UInt16 port = 6004, Boolean allowList = false) : this(new(address, port), allowList) { }
- public CollabVMHttpServer(CollabVMGuacamoleServer server, IPEndPoint endPoint)
+ public CollabVMHttpServer(CollabVMv1_2GuacamoleServer server, IPEndPoint endPoint)
{
this._serverEndPoint = endPoint;
this._addServer("/", server);
}
- public CollabVMHttpServer(CollabVMGuacamoleServer server, IPAddress address, UInt16 port = 6004) : this(server, new(address, port)) { }
+ public CollabVMHttpServer(CollabVMv1_2GuacamoleServer server, IPAddress address, UInt16 port = 6004) : this(server, new(address, port)) { }
private void ListenPath(String path)
{
@@ -36,13 +36,13 @@ namespace CollabVM.Server
this._listener.Prefixes.Add(tmp);
}
- private void _addServer(String path, CollabVMGuacamoleServer server)
+ private void _addServer(String path, CollabVMv1_2GuacamoleServer server)
{
this._servers[path] = server;
//this.ListenPath(path);
}
- public void AddServer(String name, CollabVMGuacamoleServer server)
+ public void AddServer(String name, CollabVMv1_2GuacamoleServer server)
{
Regex nameRegex = new Regex(@"^[a-zA-Z0-9_-]+$");
if (this._servers.ContainsKey("/"))
@@ -68,7 +68,7 @@ namespace CollabVM.Server
{
if (context.Request.IsWebSocketRequest)
{
- if (this._servers.TryGetValue(context.Request.RawUrl, out CollabVMGuacamoleServer? server))
+ if (this._servers.TryGetValue(context.Request.RawUrl, out CollabVMv1_2GuacamoleServer? server))
{
WebSocketContext wsc;
try
@@ -101,7 +101,7 @@ namespace CollabVM.Server
}
}
- private async void HandleWebSocket(WebSocketContext wsc, CollabVMGuacamoleServer server, IPEndPoint remote)
+ private async void HandleWebSocket(WebSocketContext wsc, CollabVMv1_2GuacamoleServer server, IPEndPoint remote)
{
server.HandleSocket(wsc.WebSocket, remote);
}
diff --git a/CollabVM/Server/CollabVMv1_2GuacamoleServer.cs b/CollabVM/Server/CollabVMv1_2GuacamoleServer.cs
new file mode 100644
index 0000000..71e0e44
--- /dev/null
+++ b/CollabVM/Server/CollabVMv1_2GuacamoleServer.cs
@@ -0,0 +1,116 @@
+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 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(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(buf, 0, buf.Length), WebSocketMessageType.Text, true, CancellationToken.None);
+ }
+ }
+}
diff --git a/ImageConverter/ImageConverter.csproj b/ImageConverter/ImageConverter.csproj
new file mode 100644
index 0000000..b760144
--- /dev/null
+++ b/ImageConverter/ImageConverter.csproj
@@ -0,0 +1,9 @@
+
+
+
+ net10.0
+ enable
+ enable
+
+
+
diff --git a/ImageConverter/Magick.cs b/ImageConverter/Magick.cs
new file mode 100644
index 0000000..2a5aecb
--- /dev/null
+++ b/ImageConverter/Magick.cs
@@ -0,0 +1,34 @@
+using System.Diagnostics;
+
+namespace ImageConverter
+{
+ public static class Magick
+ {
+ public static void FileConvert(String infile, String outfile)
+ {
+ ProcessStartInfo psi = new ProcessStartInfo("magick");
+ psi.ArgumentList.Add(infile);
+ psi.ArgumentList.Add(outfile);
+ Process? p = Process.Start(psi);
+ if (p==null)
+ {
+ throw new Exception("Could not launch magick");
+ }
+ p.WaitForExit();
+ }
+
+ public static Byte[] BmpToJpg(this Byte[] bmpbuf)
+ {
+ String path = Path.GetTempFileName();
+ String bmppath = Path.Combine(path, "magicktmp.bmp");
+ String jpgpath = Path.Combine(path, "magicktmp.jpg");
+ File.Delete(path);
+ Directory.CreateDirectory(path);
+ File.WriteAllBytes(bmppath, bmpbuf);
+ FileConvert(bmppath, jpgpath);
+ Byte[] buf = File.ReadAllBytes(jpgpath);
+ Directory.Delete(path, true);
+ return buf;
+ }
+ }
+}
diff --git a/PVHelpers/Base64Helpers.cs b/PVHelpers/Base64Helpers.cs
new file mode 100644
index 0000000..3d496c9
--- /dev/null
+++ b/PVHelpers/Base64Helpers.cs
@@ -0,0 +1,20 @@
+using System.Buffers.Text;
+using System.Text;
+
+namespace PVHelpers
+{
+ public static class Base64Helpers
+ {
+ public static String EncodeBase64String(this Byte[] data)
+ {
+ Byte[] buf = new Byte[data.Length * 2];
+ if (Base64.EncodeToUtf8(data, buf, out _, out Int32 written) == System.Buffers.OperationStatus.Done)
+ {
+ return Encoding.UTF8.GetString(buf, 0, written);
+ } else
+ {
+ throw new Exception("Shit went south");
+ }
+ }
+ }
+}
diff --git a/PVabel2026.slnx b/PVabel2026.slnx
index edadf63..33e7528 100644
--- a/PVabel2026.slnx
+++ b/PVabel2026.slnx
@@ -4,6 +4,7 @@
+
diff --git a/RemoteFrameBuffer/Client/RemoteFrameBufferClientProtocol.cs b/RemoteFrameBuffer/Client/RemoteFrameBufferClientProtocol.cs
index 1f5c9e5..f329fa2 100644
--- a/RemoteFrameBuffer/Client/RemoteFrameBufferClientProtocol.cs
+++ b/RemoteFrameBuffer/Client/RemoteFrameBufferClientProtocol.cs
@@ -29,6 +29,9 @@ namespace RemoteFrameBuffer.Client
private RgbFrameBuffer? _frameBuffer;
+ public delegate void BitmapUpdateCallback(Byte[] bitmap);
+ public event BitmapUpdateCallback? FrameUpdate;
+
public RemoteFrameBufferClientProtocol(Stream s)
{
this.vncStream = s;
@@ -213,7 +216,8 @@ namespace RemoteFrameBuffer.Client
throw new NotImplementedException();
}
}
- this._frameBuffer!.SaveBitmap($"{DateTime.Now:yyyyMMdd-HHmmss}.bmp");
+ this.FrameUpdate?.Invoke(this._frameBuffer!.ToBitmap());
+ //this._frameBuffer!.SaveBitmap($"{DateTime.Now:yyyyMMdd-HHmmss}.bmp");
}
protected void ServerMsg_SetColourMapEntries()
diff --git a/RemoteFrameBuffer/Client/RemoteFramebufferClient.cs b/RemoteFrameBuffer/Client/RemoteFramebufferClient.cs
index 736a60d..448a9bf 100644
--- a/RemoteFrameBuffer/Client/RemoteFramebufferClient.cs
+++ b/RemoteFrameBuffer/Client/RemoteFramebufferClient.cs
@@ -20,6 +20,8 @@ namespace RemoteFrameBuffer
};
}
+ public Byte[] BitMap { get; protected set; } = [];
+
public RemoteFramebufferClient(IRemoteFrameBufferClientStreamProvider socketProvider)
{
this._socketProvider = socketProvider;
@@ -95,6 +97,10 @@ namespace RemoteFrameBuffer
// TODO: register auth callback and the like
proto.Handshake(this.cancellationTokenSource.Token);
proto.Initialization(this.cancellationTokenSource.Token);
+ proto.FrameUpdate += (bitmap) => {
+ Console.Error.WriteLine("####################################### CB hit");
+ this.BitMap = bitmap;
+ };
proto.StartListener(this.cancellationTokenSource.Token).Wait();
}
#warning REMOVE THIS
diff --git a/RemoteFrameBuffer/Common/RgbFrameBuffer.cs b/RemoteFrameBuffer/Common/RgbFrameBuffer.cs
index 20f285f..0259ce2 100644
--- a/RemoteFrameBuffer/Common/RgbFrameBuffer.cs
+++ b/RemoteFrameBuffer/Common/RgbFrameBuffer.cs
@@ -44,7 +44,7 @@
public void CopyRegion(UInt16 source_x, UInt16 source_y, UInt16 width, UInt16 height, UInt16 target_x, UInt16 target_y) => this.SetRegion(this._frame, source_x, source_y, width, height, target_x, target_y);
- public void SaveBitmap(String filename)
+ public Byte[] ToBitmap()
{
#warning Endianness is straight up ignored
Int32 rowBytes = (this.Width * 3) + 3;
@@ -72,7 +72,12 @@
buf[pos + 2] = this._frame[this.Height - j - 1][i].Red;
}
}
- File.WriteAllBytes(filename, buf);
+ return buf;
+ }
+
+ public void SaveBitmap(String filename)
+ {
+ File.WriteAllBytes(filename, this.ToBitmap());
}
}
}
diff --git a/YetAnotherDummy/Program.cs b/YetAnotherDummy/Program.cs
index 2e94cfe..77315db 100644
--- a/YetAnotherDummy/Program.cs
+++ b/YetAnotherDummy/Program.cs
@@ -4,16 +4,13 @@ using RemoteFrameBuffer;
using RemoteFrameBuffer.Client;
using System.Net;
-/*IPAddress tessia = new([192,168,16,253]);
+IPAddress tessia = new([192,168,16,253]);
IRemoteFrameBufferClientStreamProvider tessia6001vnc = new RemoteFrameBufferTcpClientStreamProvider(tessia, 5901);
RemoteFramebufferClient client = new(tessia6001vnc);
-client.Start();
-Console.ReadLine();
-client.Stop();*/
-
CollabVMHttpServer httpServer = new(new([100,65,0,14]), 6004, true);
-httpServer.AddServer("vmx", new());
+httpServer.AddServer("vmx", new(client));
httpServer.Start();
Console.ReadLine();
+client.Stop();