2022-04-11 15:38:02 -07:00
|
|
|
|
// <copyright file="WebSocketListener.cs" company="Scratch Foundation">
|
|
|
|
|
// Copyright (c) Scratch Foundation. All rights reserved.
|
|
|
|
|
// </copyright>
|
|
|
|
|
|
|
|
|
|
namespace ScratchLink;
|
|
|
|
|
|
2022-07-07 17:40:49 -07:00
|
|
|
|
using System;
|
|
|
|
|
using System.Threading;
|
2022-07-11 14:58:08 -07:00
|
|
|
|
using Fleck;
|
2022-04-11 15:38:02 -07:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Listen for WebSocket connections and direct them to service handlers.
|
|
|
|
|
/// </summary>
|
|
|
|
|
internal class WebSocketListener
|
|
|
|
|
{
|
2022-04-12 12:48:59 -07:00
|
|
|
|
private readonly CancellationTokenSource cts = new ();
|
2022-04-11 15:38:02 -07:00
|
|
|
|
|
2022-07-11 14:58:08 -07:00
|
|
|
|
private WebSocketServer server;
|
2022-04-11 15:38:02 -07:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
2022-04-12 14:22:05 -07:00
|
|
|
|
/// Gets or sets the action which will be called when the listener receives a WebSocket connection.
|
2022-04-11 15:38:02 -07:00
|
|
|
|
/// </summary>
|
2022-07-11 14:58:08 -07:00
|
|
|
|
public Action<IWebSocketConnection> OnWebSocketConnection { get; set; }
|
2022-04-11 15:38:02 -07:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Start listening for connections. If already listening, stop and restart with the new prefix list.
|
|
|
|
|
/// </summary>
|
2022-07-11 14:58:08 -07:00
|
|
|
|
/// <param name="location">
|
|
|
|
|
/// The list of WS URL to listen on.
|
2022-04-11 15:38:02 -07:00
|
|
|
|
/// <example><code>
|
2022-07-11 14:58:08 -07:00
|
|
|
|
/// ws://0.0.0.0:1234/
|
|
|
|
|
/// ws://127.0.0.1/
|
2022-04-11 15:38:02 -07:00
|
|
|
|
/// </code></example>
|
|
|
|
|
/// </param>
|
2022-07-11 14:58:08 -07:00
|
|
|
|
public void Start(string location)
|
2022-04-11 15:38:02 -07:00
|
|
|
|
{
|
2022-07-11 14:58:08 -07:00
|
|
|
|
if (this.server != null)
|
2022-04-11 15:38:02 -07:00
|
|
|
|
{
|
2022-07-11 14:58:08 -07:00
|
|
|
|
this.server.ListenerSocket.Close();
|
|
|
|
|
this.server.Dispose();
|
2022-04-11 15:38:02 -07:00
|
|
|
|
}
|
|
|
|
|
|
2022-07-11 14:58:08 -07:00
|
|
|
|
this.server = new WebSocketServer(location);
|
|
|
|
|
this.server.ListenerSocket.NoDelay = true; // disable Nagle's algorithm
|
2022-04-11 15:38:02 -07:00
|
|
|
|
|
2022-07-11 14:58:08 -07:00
|
|
|
|
this.server.Start(socket =>
|
2022-04-11 15:38:02 -07:00
|
|
|
|
{
|
2022-07-11 14:58:08 -07:00
|
|
|
|
if (this.cts.IsCancellationRequested)
|
2022-04-11 15:38:02 -07:00
|
|
|
|
{
|
2022-07-11 14:58:08 -07:00
|
|
|
|
socket.Close(503); // Service Unavailable: the server is stopping
|
|
|
|
|
return;
|
2022-04-11 15:38:02 -07:00
|
|
|
|
}
|
2022-07-11 14:58:08 -07:00
|
|
|
|
|
2022-08-11 17:28:12 -07:00
|
|
|
|
this.OnWebSocketConnection(socket);
|
2022-04-11 15:38:02 -07:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-12 14:22:05 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Stop listening for connections and terminate processing of all ongoing requests.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void Stop()
|
2022-04-11 15:38:02 -07:00
|
|
|
|
{
|
2022-04-12 14:22:05 -07:00
|
|
|
|
this.cts.Cancel();
|
2022-07-11 14:58:08 -07:00
|
|
|
|
this.server.RestartAfterListenError = false; // work around statianzo/Fleck#325
|
|
|
|
|
this.server.ListenerSocket.Close();
|
|
|
|
|
this.server.Dispose();
|
2022-04-11 15:38:02 -07:00
|
|
|
|
}
|
|
|
|
|
}
|