-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #102 from dennis/webwidgets
Webwidgets
- Loading branch information
Showing
47 changed files
with
1,137 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<html> | ||
<head> | ||
<title>Slipstream Actice WebWidget Instances</title> | ||
</head> | ||
<body> | ||
<h1>Slipstream Actice WebWidget Instances</h1> | ||
|
||
{{CONTENT}} | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
var INSTANCE_ID | ||
var WEB_WIDGET_TYPE | ||
var ASSETS | ||
|
||
function connect() { | ||
let socket = a = new WebSocket("ws://" + document.location.host + "/events/" + INSTANCE_ID) | ||
|
||
socket.onopen = function (e) { | ||
console.log("[slipstream ws] [open] Connection established") | ||
|
||
if (typeof(onConnect) === "function") { | ||
onConnect() | ||
} | ||
} | ||
|
||
socket.onmessage = function (event) { | ||
if (typeof (onData) !== "function") { | ||
console.log("[slipstream ws] [onmessage] got data, but no onData() function defined. Ignored", event.data) | ||
} | ||
else { | ||
console.log("[slipstream ws] [onmessage] got data", event.data) | ||
onData(JSON.parse(event.data)) | ||
} | ||
} | ||
|
||
socket.onclose = function (event) { | ||
if (event.wasClean) { | ||
console.log("[slipstream ws] [close] Connection closed cleanly, code=" + event.code + " reason=" + event.reason) | ||
} else { | ||
console.log('[slipstream ws] [close] Connection died') | ||
} | ||
|
||
if (typeof (onDisconnect) === "function") { | ||
onDisconnect() | ||
} | ||
|
||
setTimeout(connect, 1000); | ||
} | ||
|
||
socket.onerror = function (error) { | ||
console.log("[slipstream ws] [error] " + error.message) | ||
socket.close() | ||
} | ||
} | ||
|
||
window.addEventListener('load', function () { | ||
INSTANCE_ID = document.body.getAttribute("data-instance-id") | ||
WEB_WIDGET_TYPE = document.body.getAttribute("data-web-widget-type") | ||
ASSETS = document.body.getAttribute("data-assets") | ||
|
||
connect() | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
Components/WebWidget/EventFactory/WebWidgetEventFactory.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using Slipstream.Components.WebWidget; | ||
using Slipstream.Components.WebWidget.Events; | ||
using Slipstream.Shared; | ||
|
||
#nullable enable | ||
|
||
namespace Slipstream.Components.Internal.EventFactory | ||
{ | ||
public class WebWidgetEventFactory : IWebWidgetEventFactory | ||
{ | ||
public WebWidgetCommandEvent CreateWebWidgetCommandEvent(IEventEnvelope envelope, string data) | ||
{ | ||
return new WebWidgetCommandEvent { Envelope = envelope, Data = data }; | ||
} | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
Components/WebWidget/EventHandler/WebWidgetEventHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
#nullable enable | ||
|
||
using Slipstream.Components.WebWidget.Events; | ||
using Slipstream.Shared; | ||
using System; | ||
|
||
namespace Slipstream.Components.WebWidget.EventHandler | ||
{ | ||
internal class WebWidgetEventHandler : IEventHandler | ||
{ | ||
public event EventHandler<WebWidgetCommandEvent>? OnWebWidgetCommandEvent; | ||
|
||
public IEventHandler.HandledStatus HandleEvent(IEvent @event) | ||
{ | ||
return @event switch | ||
{ | ||
WebWidgetCommandEvent tev => OnEvent(OnWebWidgetCommandEvent, tev), | ||
_ => IEventHandler.HandledStatus.NotMine, | ||
}; | ||
} | ||
|
||
private IEventHandler.HandledStatus OnEvent<TEvent>(EventHandler<TEvent>? onEvent, TEvent args) | ||
{ | ||
if (onEvent != null) | ||
{ | ||
onEvent.Invoke(this, args); | ||
return IEventHandler.HandledStatus.Handled; | ||
} | ||
return IEventHandler.HandledStatus.UseDefault; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#nullable enable | ||
|
||
using Slipstream.Shared; | ||
|
||
namespace Slipstream.Components.WebWidget.Events | ||
{ | ||
public class WebWidgetCommandEvent : IEvent | ||
{ | ||
public string EventType => typeof(WebWidgetCommandEvent).Name; | ||
public IEventEnvelope Envelope { get; set; } = new EventEnvelope(); | ||
public string Data { get; set; } = string.Empty; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
#nullable enable | ||
|
||
using System; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using EmbedIO; | ||
using Serilog; | ||
using Slipstream.Components.WebWidget.EventHandler; | ||
using Slipstream.Shared; | ||
|
||
namespace Slipstream.Components.WebWidget | ||
{ | ||
public class HttpServer : IHttpServer, IHttpServerApi | ||
{ | ||
private const string WEB_WIDGET_ROOT_DIRECTORY = "WebWidgets/"; | ||
|
||
private readonly Object Lock = new object(); | ||
private Thread? ServiceThread; | ||
private readonly ILogger Logger; | ||
private readonly IEventBusSubscription Subscription; | ||
private readonly WebSocketsEventsServer EventsServerModule; | ||
private readonly IEventHandlerController EventHandlerController; | ||
private readonly IWebWidgetInstances Instances = new WebWidgetInstances(); | ||
private const string Url = "http://127.0.0.1:1919"; // Must NOT end with slash | ||
|
||
public HttpServer(ILogger logger, IEventBusSubscription subscription, IEventHandlerController eventHandlerController) | ||
{ | ||
Logger = logger; | ||
Subscription = subscription; | ||
EventHandlerController = eventHandlerController; | ||
|
||
EventsServerModule = new WebSocketsEventsServer(Logger, Instances); | ||
|
||
System.IO.Directory.CreateDirectory(WEB_WIDGET_ROOT_DIRECTORY); | ||
} | ||
|
||
public void AddInstance(string instanceId, string webWidgetType, string? data) | ||
{ | ||
lock (Lock) | ||
{ | ||
if (ServiceThread == null) | ||
{ | ||
ServiceThread = new Thread(new ThreadStart(ThreadMain)) | ||
{ | ||
Name = GetType().Name, | ||
}; | ||
ServiceThread.Start(); | ||
} | ||
} | ||
|
||
// Crude sanity check | ||
var indexFile = WEB_WIDGET_ROOT_DIRECTORY + webWidgetType + "/index.html"; | ||
if (System.IO.File.Exists(indexFile)) | ||
{ | ||
Instances.Add(instanceId, webWidgetType, data); | ||
Subscription.AddImpersonate(instanceId); | ||
|
||
Logger.Information($"HttpServer: {Url}/instances/{instanceId} added"); | ||
} | ||
else | ||
{ | ||
Logger.Error($"HttpServer: {Url}/instances/{instanceId} not added, as {indexFile} does not exist"); | ||
} | ||
} | ||
|
||
private void ThreadMain() | ||
{ | ||
Logger.Information("HttpServer started"); | ||
|
||
using (var server = CreateWebServer(Url)) | ||
{ | ||
Task serverTask = server.RunAsync(); | ||
bool stopping = false; | ||
|
||
var internalHandler = EventHandlerController.Get<Internal.EventHandler.Internal>(); | ||
var webWidgetHandler = EventHandlerController.Get<WebWidgetEventHandler>(); | ||
|
||
internalHandler.OnInternalCommandShutdown += (_, e) => stopping = true; | ||
webWidgetHandler.OnWebWidgetCommandEvent += (_, e) => | ||
{ | ||
if (e.Envelope.Recipients == null) | ||
return; | ||
foreach (var recipient in e.Envelope.Recipients) | ||
{ | ||
EventsServerModule.Broadcast(recipient, e.Data); | ||
} | ||
}; | ||
|
||
while (!stopping) | ||
{ | ||
IEvent? @event = Subscription.NextEvent(100); | ||
EventHandlerController.HandleEvent(@event); | ||
|
||
stopping = stopping || serverTask.IsCompleted; | ||
} | ||
} | ||
|
||
Logger.Information("HttpServer stopped"); | ||
} | ||
|
||
public void RemoveInstance(string instanceId) | ||
{ | ||
Instances.Remove(instanceId); | ||
Subscription.DeleteImpersonation(instanceId); | ||
Logger.Information($"HttpServer: {Url}/instances/{instanceId} removed"); | ||
} | ||
|
||
private WebServer CreateWebServer(string url) | ||
{ | ||
// endpoints: | ||
// / | ||
// /ss.js | ||
// /instances/<instanceid>/ | ||
// /webwidgets/<webwidgettype>/ | ||
// /events/<instanceid>/ | ||
|
||
var server = new WebServer(o => o | ||
.WithUrlPrefix(url)) | ||
.WithStaticFolder("/webwidgets/", WEB_WIDGET_ROOT_DIRECTORY, false) | ||
.WithModule(EventsServerModule) | ||
.WithModule(new JavascriptWebModule()) | ||
.WithModule(new InstanceWebModule(Instances, WEB_WIDGET_ROOT_DIRECTORY, Logger)) | ||
.WithModule(new InstanceIndexWebModule(Instances, Logger)); | ||
|
||
return server; | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#nullable enable | ||
|
||
using System; | ||
|
||
namespace Slipstream.Components.WebWidget | ||
{ | ||
public interface IHttpServer : IDisposable | ||
{ | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#nullable enable | ||
|
||
namespace Slipstream.Components.WebWidget | ||
{ | ||
public interface IHttpServerApi | ||
{ | ||
// These needs to be threadsafe! | ||
void AddInstance(string instanceId, string instanceType, string? data); | ||
void RemoveInstance(string instanceId); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using Slipstream.Components.WebWidget.Events; | ||
using Slipstream.Shared; | ||
|
||
#nullable enable | ||
|
||
namespace Slipstream.Components.WebWidget | ||
{ | ||
public interface IWebWidgetEventFactory | ||
{ | ||
WebWidgetCommandEvent CreateWebWidgetCommandEvent(IEventEnvelope envelope, string data); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#nullable enable | ||
|
||
|
||
using System.Collections.Generic; | ||
|
||
namespace Slipstream.Components.WebWidget | ||
{ | ||
public interface IWebWidgetInstances | ||
{ | ||
void Add(string id, string type, string? data); | ||
void Remove(string id); | ||
string this[string id] {get;} | ||
ICollection<string> GetIds(); | ||
string? InitData(string id); | ||
} | ||
} |
Oops, something went wrong.