2017-11-10 05:00:15 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Concurrent;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Microsoft.AspNetCore.Http;
|
|
|
|
|
|
|
|
|
|
namespace Ooui.AspNetCore
|
|
|
|
|
{
|
|
|
|
|
public static class WebSocketHandler
|
|
|
|
|
{
|
|
|
|
|
public static string WebSocketPath { get; set; } = "/ooui.ws";
|
|
|
|
|
|
2018-02-21 23:40:12 +00:00
|
|
|
|
public static TimeSpan SessionTimeout { get; set; } = TimeSpan.FromMinutes (1);
|
2017-11-10 05:00:15 +00:00
|
|
|
|
|
2018-02-21 23:40:12 +00:00
|
|
|
|
static readonly ConcurrentDictionary<string, PendingSession> pendingSessions =
|
|
|
|
|
new ConcurrentDictionary<string, PendingSession> ();
|
2017-11-10 05:00:15 +00:00
|
|
|
|
|
2018-04-15 23:30:08 +00:00
|
|
|
|
public static string BeginSession (HttpContext context, Element element, bool disposeElementWhenDone)
|
2017-11-10 05:00:15 +00:00
|
|
|
|
{
|
|
|
|
|
var id = Guid.NewGuid ().ToString ("N");
|
|
|
|
|
|
2018-02-21 23:40:12 +00:00
|
|
|
|
var s = new PendingSession {
|
2017-11-10 05:00:15 +00:00
|
|
|
|
Element = element,
|
2018-02-21 23:40:12 +00:00
|
|
|
|
CreateTimeUtc = DateTime.UtcNow,
|
2018-04-15 23:30:08 +00:00
|
|
|
|
DisposeElementWhenDone = disposeElementWhenDone,
|
2017-11-10 05:00:15 +00:00
|
|
|
|
};
|
|
|
|
|
|
2018-02-21 23:40:12 +00:00
|
|
|
|
if (!pendingSessions.TryAdd (id, s)) {
|
2017-11-10 05:00:15 +00:00
|
|
|
|
throw new Exception ("Failed to schedule pending session");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return id;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-19 20:19:44 +00:00
|
|
|
|
|
|
|
|
|
|
2017-11-10 05:00:15 +00:00
|
|
|
|
public static async Task HandleWebSocketRequestAsync (HttpContext context)
|
|
|
|
|
{
|
2017-11-19 20:19:44 +00:00
|
|
|
|
void BadRequest (string message)
|
|
|
|
|
{
|
|
|
|
|
context.Response.StatusCode = StatusCodes.Status400BadRequest;
|
|
|
|
|
context.Response.ContentType = "text/plain; charset=utf-8";
|
|
|
|
|
using (var sw = new System.IO.StreamWriter (context.Response.Body)) {
|
|
|
|
|
sw.WriteLine (message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-10 05:00:15 +00:00
|
|
|
|
//
|
|
|
|
|
// Make sure we get a good ID
|
|
|
|
|
//
|
|
|
|
|
if (!context.Request.Query.TryGetValue ("id", out var idValues)) {
|
2017-11-19 20:19:44 +00:00
|
|
|
|
BadRequest ("Missing `id`");
|
2017-11-10 05:00:15 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-19 20:19:44 +00:00
|
|
|
|
var id = idValues.LastOrDefault ();
|
2017-11-10 05:00:15 +00:00
|
|
|
|
if (id == null || id.Length != 32) {
|
2017-11-19 20:19:44 +00:00
|
|
|
|
BadRequest ("Invalid `id`");
|
2017-11-10 05:00:15 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
2018-02-01 23:09:37 +00:00
|
|
|
|
// Clear old sessions
|
2017-11-10 05:00:15 +00:00
|
|
|
|
//
|
2018-02-21 23:40:12 +00:00
|
|
|
|
var toClear = pendingSessions.Where (x => (DateTime.UtcNow - x.Value.CreateTimeUtc) > SessionTimeout).ToList ();
|
2018-02-01 23:09:37 +00:00
|
|
|
|
foreach (var c in toClear) {
|
2018-02-21 23:40:12 +00:00
|
|
|
|
pendingSessions.TryRemove (c.Key, out var _);
|
2017-11-10 05:00:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
2018-02-01 23:09:37 +00:00
|
|
|
|
// Find the pending session
|
2017-11-10 05:00:15 +00:00
|
|
|
|
//
|
2018-02-21 23:40:12 +00:00
|
|
|
|
if (!pendingSessions.TryRemove (id, out var activeSession)) {
|
2018-02-01 23:09:37 +00:00
|
|
|
|
BadRequest ("Unknown `id`");
|
2017-11-19 20:19:44 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Set the element's dimensions
|
|
|
|
|
//
|
|
|
|
|
if (!context.Request.Query.TryGetValue ("w", out var wValues) || wValues.Count < 1) {
|
|
|
|
|
BadRequest ("Missing `w`");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!context.Request.Query.TryGetValue ("h", out var hValues) || hValues.Count < 1) {
|
|
|
|
|
BadRequest ("Missing `h`");
|
2017-11-10 05:00:15 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2017-12-09 23:34:48 +00:00
|
|
|
|
var icult = System.Globalization.CultureInfo.InvariantCulture;
|
|
|
|
|
if (!double.TryParse (wValues.Last (), System.Globalization.NumberStyles.Any, icult, out var w))
|
2017-11-19 20:19:44 +00:00
|
|
|
|
w = 640;
|
2017-12-09 23:34:48 +00:00
|
|
|
|
if (!double.TryParse (hValues.Last (), System.Globalization.NumberStyles.Any, icult, out var h))
|
2017-11-19 20:19:44 +00:00
|
|
|
|
h = 480;
|
2017-11-10 05:00:15 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// OK, Run
|
|
|
|
|
//
|
|
|
|
|
var token = CancellationToken.None;
|
|
|
|
|
var webSocket = await context.WebSockets.AcceptWebSocketAsync ("ooui");
|
2018-04-15 23:30:08 +00:00
|
|
|
|
var session = new Ooui.WebSocketSession (webSocket, activeSession.Element, activeSession.DisposeElementWhenDone, w, h, token);
|
2017-11-10 05:00:15 +00:00
|
|
|
|
await session.RunAsync ().ConfigureAwait (false);
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-21 23:40:12 +00:00
|
|
|
|
class PendingSession
|
2017-11-10 05:00:15 +00:00
|
|
|
|
{
|
|
|
|
|
public Element Element;
|
2018-02-21 23:40:12 +00:00
|
|
|
|
public DateTime CreateTimeUtc;
|
2018-04-15 23:30:08 +00:00
|
|
|
|
public bool DisposeElementWhenDone;
|
2017-11-10 05:00:15 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|