diff --git a/CollabVM/CollabVM.csproj b/CollabVM/CollabVM.csproj
new file mode 100644
index 0000000..b760144
--- /dev/null
+++ b/CollabVM/CollabVM.csproj
@@ -0,0 +1,9 @@
+
+
+
+ net10.0
+ enable
+ enable
+
+
+
diff --git a/CollabVM/Server/CollabVMGuacamoleServer.cs b/CollabVM/Server/CollabVMGuacamoleServer.cs
new file mode 100644
index 0000000..71c1be0
--- /dev/null
+++ b/CollabVM/Server/CollabVMGuacamoleServer.cs
@@ -0,0 +1,40 @@
+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
new file mode 100644
index 0000000..da7df25
--- /dev/null
+++ b/CollabVM/Server/CollabVMHttpServer.cs
@@ -0,0 +1,109 @@
+using System.Net;
+using System.Net.WebSockets;
+using System.Text;
+using System.Text.Json;
+using System.Text.RegularExpressions;
+
+namespace CollabVM.Server
+{
+ // https://github.com/paulbatum/WebSocket-Samples/blob/master/HttpListenerWebSocketEcho/Server/Server.cs
+ public class CollabVMHttpServer
+ {
+ private HttpListener _listener = new();
+ private Dictionary _servers = new();
+ private readonly IPEndPoint _serverEndPoint;
+ private readonly Boolean _allowList = false;
+
+ public CollabVMHttpServer(IPEndPoint endPoint, Boolean allowServerList = false)
+ {
+ this._serverEndPoint = endPoint;
+ this._allowList = allowServerList;
+ }
+ public CollabVMHttpServer(IPAddress address, UInt16 port = 6004, Boolean allowList = false) : this(new(address, port), allowList) { }
+
+ public CollabVMHttpServer(CollabVMGuacamoleServer server, IPEndPoint endPoint)
+ {
+ this._serverEndPoint = endPoint;
+ this._addServer("/", server);
+ }
+ public CollabVMHttpServer(CollabVMGuacamoleServer server, IPAddress address, UInt16 port = 6004) : this(server, new(address, port)) { }
+
+ private void ListenPath(String path)
+ {
+ String tmp = $"http://{this._serverEndPoint.Address}:{this._serverEndPoint.Port}{path}";
+ //String tmp = $"http://+:{this._serverEndPoint.Port}/{path}";
+ Console.Error.WriteLine($"Listen: {tmp}");
+ this._listener.Prefixes.Add(tmp);
+ }
+
+ private void _addServer(String path, CollabVMGuacamoleServer server)
+ {
+ this._servers[path] = server;
+ //this.ListenPath(path);
+ }
+
+ public void AddServer(String name, CollabVMGuacamoleServer server)
+ {
+ Regex nameRegex = new Regex(@"^[a-zA-Z0-9_-]+$");
+ if (this._servers.ContainsKey("/"))
+ {
+ throw new InvalidOperationException("Cannot add servers to a single-server instance");
+ }
+ if (name.Contains("/"))
+ {
+ throw new ArgumentException("Server name must only include latin letters, numbers, underscores and hyphens", nameof(name));
+ }
+ this._addServer($"/{name}", server);
+ }
+
+ public async void Start()
+ {
+ this.ListenPath("/");
+ this._listener.Start();
+ while (true)
+ {
+ HttpListenerContext context = await this._listener.GetContextAsync();
+ Console.Error.WriteLine($"<< {context.Request.HttpMethod} {context.Request.UserHostAddress} {context.Request.UserHostName} {context.Request.RawUrl}");
+ if (context.Request.RawUrl is not null)
+ {
+ if (context.Request.IsWebSocketRequest)
+ {
+ if (this._servers.TryGetValue(context.Request.RawUrl, out CollabVMGuacamoleServer? server))
+ {
+ WebSocketContext wsc;
+ try
+ {
+ wsc = await context.AcceptWebSocketAsync(subProtocol: "guacamole");
+ } catch (Exception)
+ {
+ context.Response.StatusCode = (Int32)HttpStatusCode.InternalServerError;
+ context.Response.Close();
+ continue;
+ }
+ this.HandleWebSocket(wsc, server, context.Request.RemoteEndPoint);
+ continue;
+ } else
+ {
+ context.Response.StatusCode = (Int32)HttpStatusCode.NotFound;
+ context.Response.Close();
+ continue;
+ }
+ } else if (this._allowList && context.Request.RawUrl == "/")
+ {
+ context.Response.StatusCode = (Int32)HttpStatusCode.OK;
+ context.Response.ContentType = "application/json";
+ context.Response.Close(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(this._servers.Keys.Select((path) => $"ws://{context.Request.UserHostAddress}{path}").ToList())), false);
+ continue;
+ }
+ }
+ context.Response.StatusCode = (Int32)HttpStatusCode.BadRequest;
+ context.Response.Close();
+ }
+ }
+
+ private async void HandleWebSocket(WebSocketContext wsc, CollabVMGuacamoleServer server, IPEndPoint remote)
+ {
+ server.HandleSocket(wsc.WebSocket, remote);
+ }
+ }
+}
diff --git a/PVabel2026.slnx b/PVabel2026.slnx
index bb5fa7a..edadf63 100644
--- a/PVabel2026.slnx
+++ b/PVabel2026.slnx
@@ -1,4 +1,5 @@
+
diff --git a/YetAnotherDummy/Program.cs b/YetAnotherDummy/Program.cs
index 5ed75f1..2e94cfe 100644
--- a/YetAnotherDummy/Program.cs
+++ b/YetAnotherDummy/Program.cs
@@ -1,13 +1,19 @@
// See https://aka.ms/new-console-template for more information
+using CollabVM.Server;
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();
+client.Stop();*/
+
+CollabVMHttpServer httpServer = new(new([100,65,0,14]), 6004, true);
+httpServer.AddServer("vmx", new());
+httpServer.Start();
+Console.ReadLine();
diff --git a/YetAnotherDummy/YetAnotherDummy.csproj b/YetAnotherDummy/YetAnotherDummy.csproj
index 5dd89bf..cc91429 100644
--- a/YetAnotherDummy/YetAnotherDummy.csproj
+++ b/YetAnotherDummy/YetAnotherDummy.csproj
@@ -8,6 +8,7 @@
+