getting there
This commit is contained in:
@@ -6,4 +6,10 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\ImageConverter\ImageConverter.csproj" />
|
||||||
|
<ProjectReference Include="..\PVHelpers\PVHelpers.csproj" />
|
||||||
|
<ProjectReference Include="..\RemoteFrameBuffer\RemoteFrameBuffer.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -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<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);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally
|
|
||||||
{
|
|
||||||
ws.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,7 @@ namespace CollabVM.Server
|
|||||||
public class CollabVMHttpServer
|
public class CollabVMHttpServer
|
||||||
{
|
{
|
||||||
private HttpListener _listener = new();
|
private HttpListener _listener = new();
|
||||||
private Dictionary<String, CollabVMGuacamoleServer> _servers = new();
|
private Dictionary<String, CollabVMv1_2GuacamoleServer> _servers = new();
|
||||||
private readonly IPEndPoint _serverEndPoint;
|
private readonly IPEndPoint _serverEndPoint;
|
||||||
private readonly Boolean _allowList = false;
|
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(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._serverEndPoint = endPoint;
|
||||||
this._addServer("/", server);
|
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)
|
private void ListenPath(String path)
|
||||||
{
|
{
|
||||||
@@ -36,13 +36,13 @@ namespace CollabVM.Server
|
|||||||
this._listener.Prefixes.Add(tmp);
|
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._servers[path] = server;
|
||||||
//this.ListenPath(path);
|
//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_-]+$");
|
Regex nameRegex = new Regex(@"^[a-zA-Z0-9_-]+$");
|
||||||
if (this._servers.ContainsKey("/"))
|
if (this._servers.ContainsKey("/"))
|
||||||
@@ -68,7 +68,7 @@ namespace CollabVM.Server
|
|||||||
{
|
{
|
||||||
if (context.Request.IsWebSocketRequest)
|
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;
|
WebSocketContext wsc;
|
||||||
try
|
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);
|
server.HandleSocket(wsc.WebSocket, remote);
|
||||||
}
|
}
|
||||||
|
|||||||
116
CollabVM/Server/CollabVMv1_2GuacamoleServer.cs
Normal file
116
CollabVM/Server/CollabVMv1_2GuacamoleServer.cs
Normal file
@@ -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<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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
ImageConverter/ImageConverter.csproj
Normal file
9
ImageConverter/ImageConverter.csproj
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
34
ImageConverter/Magick.cs
Normal file
34
ImageConverter/Magick.cs
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
PVHelpers/Base64Helpers.cs
Normal file
20
PVHelpers/Base64Helpers.cs
Normal file
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
<Platform Project="x64" />
|
<Platform Project="x64" />
|
||||||
<Deploy />
|
<Deploy />
|
||||||
</Project>
|
</Project>
|
||||||
|
<Project Path="ImageConverter/ImageConverter.csproj" Id="a00d66ff-239a-48b6-a8fc-b3ab517a39a5" />
|
||||||
<Project Path="PVHelpers/PVHelpers.csproj" Id="eec5debc-f993-42e0-9962-4744b18bd0c7" />
|
<Project Path="PVHelpers/PVHelpers.csproj" Id="eec5debc-f993-42e0-9962-4744b18bd0c7" />
|
||||||
<Project Path="RemoteFrameBuffer/RemoteFrameBuffer.csproj" Id="8e7296d6-c427-4a91-ae0b-131bd7b3ba1a" />
|
<Project Path="RemoteFrameBuffer/RemoteFrameBuffer.csproj" Id="8e7296d6-c427-4a91-ae0b-131bd7b3ba1a" />
|
||||||
<Project Path="YetAnotherDummy/YetAnotherDummy.csproj" />
|
<Project Path="YetAnotherDummy/YetAnotherDummy.csproj" />
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ namespace RemoteFrameBuffer.Client
|
|||||||
|
|
||||||
private RgbFrameBuffer? _frameBuffer;
|
private RgbFrameBuffer? _frameBuffer;
|
||||||
|
|
||||||
|
public delegate void BitmapUpdateCallback(Byte[] bitmap);
|
||||||
|
public event BitmapUpdateCallback? FrameUpdate;
|
||||||
|
|
||||||
public RemoteFrameBufferClientProtocol(Stream s)
|
public RemoteFrameBufferClientProtocol(Stream s)
|
||||||
{
|
{
|
||||||
this.vncStream = s;
|
this.vncStream = s;
|
||||||
@@ -213,7 +216,8 @@ namespace RemoteFrameBuffer.Client
|
|||||||
throw new NotImplementedException();
|
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()
|
protected void ServerMsg_SetColourMapEntries()
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ namespace RemoteFrameBuffer
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Byte[] BitMap { get; protected set; } = [];
|
||||||
|
|
||||||
public RemoteFramebufferClient(IRemoteFrameBufferClientStreamProvider socketProvider)
|
public RemoteFramebufferClient(IRemoteFrameBufferClientStreamProvider socketProvider)
|
||||||
{
|
{
|
||||||
this._socketProvider = socketProvider;
|
this._socketProvider = socketProvider;
|
||||||
@@ -95,6 +97,10 @@ namespace RemoteFrameBuffer
|
|||||||
// TODO: register auth callback and the like
|
// TODO: register auth callback and the like
|
||||||
proto.Handshake(this.cancellationTokenSource.Token);
|
proto.Handshake(this.cancellationTokenSource.Token);
|
||||||
proto.Initialization(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();
|
proto.StartListener(this.cancellationTokenSource.Token).Wait();
|
||||||
}
|
}
|
||||||
#warning REMOVE THIS
|
#warning REMOVE THIS
|
||||||
|
|||||||
@@ -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 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
|
#warning Endianness is straight up ignored
|
||||||
Int32 rowBytes = (this.Width * 3) + 3;
|
Int32 rowBytes = (this.Width * 3) + 3;
|
||||||
@@ -72,7 +72,12 @@
|
|||||||
buf[pos + 2] = this._frame[this.Height - j - 1][i].Red;
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,16 +4,13 @@ using RemoteFrameBuffer;
|
|||||||
using RemoteFrameBuffer.Client;
|
using RemoteFrameBuffer.Client;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
|
||||||
/*IPAddress tessia = new([192,168,16,253]);
|
IPAddress tessia = new([192,168,16,253]);
|
||||||
|
|
||||||
IRemoteFrameBufferClientStreamProvider tessia6001vnc = new RemoteFrameBufferTcpClientStreamProvider(tessia, 5901);
|
IRemoteFrameBufferClientStreamProvider tessia6001vnc = new RemoteFrameBufferTcpClientStreamProvider(tessia, 5901);
|
||||||
RemoteFramebufferClient client = new(tessia6001vnc);
|
RemoteFramebufferClient client = new(tessia6001vnc);
|
||||||
|
|
||||||
client.Start();
|
|
||||||
Console.ReadLine();
|
|
||||||
client.Stop();*/
|
|
||||||
|
|
||||||
CollabVMHttpServer httpServer = new(new([100,65,0,14]), 6004, true);
|
CollabVMHttpServer httpServer = new(new([100,65,0,14]), 6004, true);
|
||||||
httpServer.AddServer("vmx", new());
|
httpServer.AddServer("vmx", new(client));
|
||||||
httpServer.Start();
|
httpServer.Start();
|
||||||
Console.ReadLine();
|
Console.ReadLine();
|
||||||
|
client.Stop();
|
||||||
|
|||||||
Reference in New Issue
Block a user