From 5801b29f22e4a9489e10a8a396d098228a809673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Feh=C3=A9r=20Roland?= Date: Thu, 12 Feb 2026 15:43:03 +0100 Subject: [PATCH] guacamole in progress --- CollabVM/CollabVM.csproj | 9 ++ CollabVM/Server/CollabVMGuacamoleServer.cs | 40 ++++++++ CollabVM/Server/CollabVMHttpServer.cs | 109 +++++++++++++++++++++ PVabel2026.slnx | 1 + YetAnotherDummy/Program.cs | 10 +- YetAnotherDummy/YetAnotherDummy.csproj | 1 + 6 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 CollabVM/CollabVM.csproj create mode 100644 CollabVM/Server/CollabVMGuacamoleServer.cs create mode 100644 CollabVM/Server/CollabVMHttpServer.cs 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 @@ +