feat: serve planning snapshots on loopback
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading;
|
||||
|
||||
namespace TrajectoryPlanningVisualization;
|
||||
|
||||
public sealed class PlanningVisualizationSessionInfo
|
||||
{
|
||||
public PlanningVisualizationSessionInfo(Uri uri, string token)
|
||||
{
|
||||
Uri = uri ?? throw new ArgumentNullException(nameof(uri));
|
||||
Token = token ?? throw new ArgumentNullException(nameof(token));
|
||||
}
|
||||
|
||||
public Uri Uri { get; }
|
||||
public string Token { get; }
|
||||
}
|
||||
|
||||
public sealed class PlanningVisualizationSession : IDisposable
|
||||
{
|
||||
private readonly object lifecycleLock = new object();
|
||||
private readonly PlanningVisualizationOptions options;
|
||||
private LoopbackVisualizationServer server;
|
||||
private PlanningVisualizationSessionInfo sessionInfo;
|
||||
|
||||
public PlanningVisualizationSession(PlanningVisualizationOptions options)
|
||||
{
|
||||
this.options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
public bool IsRunning
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (lifecycleLock)
|
||||
{
|
||||
return server != null && server.IsRunning;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PlanningVisualizationSessionInfo Start(PlanningVisualizationStaticSnapshot staticSnapshot)
|
||||
{
|
||||
if (staticSnapshot == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(staticSnapshot));
|
||||
}
|
||||
|
||||
lock (lifecycleLock)
|
||||
{
|
||||
if (server != null)
|
||||
{
|
||||
return sessionInfo;
|
||||
}
|
||||
|
||||
PlanningVisualizationOptionsSnapshot validated = options.CreateValidatedSnapshot();
|
||||
string token = CreateToken();
|
||||
var created = new LoopbackVisualizationServer(validated, staticSnapshot, token);
|
||||
try
|
||||
{
|
||||
created.Start();
|
||||
server = created;
|
||||
sessionInfo = new PlanningVisualizationSessionInfo(
|
||||
new Uri("http://127.0.0.1:" + created.Port + "/?token=" + token), token);
|
||||
return sessionInfo;
|
||||
}
|
||||
catch
|
||||
{
|
||||
created.Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Publish(PlanningVisualizationDynamicSnapshot snapshot)
|
||||
{
|
||||
if (snapshot == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(snapshot));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Volatile.Read(ref server)?.Publish(snapshot);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
LoopbackVisualizationServer current;
|
||||
lock (lifecycleLock)
|
||||
{
|
||||
current = server;
|
||||
server = null;
|
||||
sessionInfo = null;
|
||||
}
|
||||
|
||||
current?.Dispose();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
private static string CreateToken()
|
||||
{
|
||||
byte[] tokenBytes = new byte[32];
|
||||
using (RandomNumberGenerator random = RandomNumberGenerator.Create())
|
||||
{
|
||||
random.GetBytes(tokenBytes);
|
||||
}
|
||||
|
||||
return BitConverter.ToString(tokenBytes).Replace("-", string.Empty).ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user