Skip to content

Commit

Permalink
Unify windows WS and HTTP server
Browse files Browse the repository at this point in the history
  • Loading branch information
Levminer committed Jul 17, 2024
1 parent 2739582 commit e09ec2a
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 128 deletions.
2 changes: 1 addition & 1 deletion platforms/interface/app/layout/app.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
// Connect to local WebSocket server
const connectToWSServer = () => {
let ws = new WebSocket("ws://localhost:5391")
let ws = new WebSocket("ws://localhost:5390/ws")
ws.onopen = () => {
console.log("Local WS Connection established")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
using lib;
using Serilog;
using System.Collections.Concurrent;
using System.Net;
using System.Net.WebSockets;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;

namespace service;
public class HTTPServer {
public class Server {
static HttpListener listener;
static ConcurrentDictionary<WebSocket, Task> connectedClients = new ConcurrentDictionary<WebSocket, Task>();

// Start the server
public void Start(HardwareInfo hardwareInfo) {
string url = "http://localhost:5390/";

Expand All @@ -21,6 +26,7 @@ public void Start(HardwareInfo hardwareInfo) {
Task.Run(async () => await HandleRequests(hardwareInfo));
}

// Wait for a request
static async Task HandleRequests(HardwareInfo hardwareInfo) {
while (true) {
// Wait for a request to be received asynchronously
Expand All @@ -32,20 +38,30 @@ static async Task HandleRequests(HardwareInfo hardwareInfo) {
}

static async Task ProcessRequestAsync(HttpListenerContext context, HardwareInfo hardwareInfo) {
string path = context.Request.RawUrl;
string method = context.Request.HttpMethod;

if (method == "OPTIONS") {
if (context.Request.HttpMethod == "OPTIONS") {
await HandleOptionsRequest(context);
return;
}

switch (path) {
switch (context.Request.RawUrl) {
case "/":
await HandleRootRequest(context);
break;
case "/data":
await HandleDataRequest(context, hardwareInfo);
case "/ws":
if (context.Request.IsWebSocketRequest) {
WebSocketContext wsContext = await context.AcceptWebSocketAsync(null);
WebSocket socket = wsContext.WebSocket;
Task clientTask = HandleWSRequest(socket, hardwareInfo);
connectedClients.TryAdd(socket, clientTask);
} else {
byte[] responseBytes = Encoding.UTF8.GetBytes("Connection header did not include 'upgrade'");
context.Response.ContentLength64 = responseBytes.Length;
context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);
context.Response.OutputStream.Close();
}
break;
case "/rest":
await HandleRESTRequest(context, hardwareInfo);
break;
case "/post":
await HandlePostRequest(context, hardwareInfo);
Expand All @@ -71,7 +87,7 @@ static async Task HandleRootRequest(HttpListenerContext context) {
await SendResponse(context, buffer, "text/plain");
}

static async Task HandleDataRequest(HttpListenerContext context, HardwareInfo hardwareInfo) {
static async Task HandleRESTRequest(HttpListenerContext context, HardwareInfo hardwareInfo) {
string responseJson = JsonSerializer.Serialize(hardwareInfo.API, Program.SerializerOptions);
byte[] buffer = Encoding.UTF8.GetBytes(responseJson);
await SendResponse(context, buffer, "application/json");
Expand Down Expand Up @@ -131,6 +147,67 @@ static async Task SendResponse(HttpListenerContext context, byte[] buffer, strin
context.Response.Close();
}

static async Task HandleWSRequest(WebSocket socket, HardwareInfo hardwareInfo) {
// Send the initial data
byte[] initialBuffer = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(new GenericMessage<API>() { Type = "initialData", Data = hardwareInfo.API }, Program.CompressedSerializerOptions));
await socket.SendAsync(new ArraySegment<byte>(initialBuffer, 0, initialBuffer.Length), WebSocketMessageType.Text, true, CancellationToken.None);

var receiveBuffer = new ArraySegment<byte>(new byte[1024 * 4]);
WebSocketReceiveResult result;

// Send last 60s and last 60 minutes data
await Task.Run(async () => {
var secondsList = Program.HardwareStats.seconds.Where((x, i) => (i + 1) % 3 == 0).ToList();
for (int i = 0; i < secondsList.Count; i++) {
byte[] buffer = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(new GenericMessage<JsonNode>() { Type = "secondsData", Data = JsonNode.Parse(secondsList[i]) }, Program.CompressedSerializerOptions));
await socket.SendAsync(new ArraySegment<byte>(buffer, 0, buffer.Length), WebSocketMessageType.Text, true, CancellationToken.None);
}
var minutesList = Program.HardwareStats.minutes.Where((x, i) => (i + 1) % 3 == 0).ToList();
for (int i = 0; i < minutesList.Count; i++) {
byte[] buffer = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(new GenericMessage<JsonNode>() { Type = "minutesData", Data = JsonNode.Parse(minutesList[i]) }, Program.CompressedSerializerOptions));
await socket.SendAsync(new ArraySegment<byte>(buffer, 0, buffer.Length), WebSocketMessageType.Text, true, CancellationToken.None);
}
});

// Send updated data every 2s
Task sendTask = Task.Run(async () => {
while (socket.State == WebSocketState.Open) {
byte[] buffer = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(new GenericMessage<API>() { Type = "data", Data = hardwareInfo.API }, Program.CompressedSerializerOptions));
await socket.SendAsync(new ArraySegment<byte>(buffer, 0, buffer.Length), WebSocketMessageType.Text, true, CancellationToken.None);
await Task.Delay(2000);
}
});

try {
while (socket.State == WebSocketState.Open) {
result = await socket.ReceiveAsync(receiveBuffer, CancellationToken.None);

if (result.MessageType == WebSocketMessageType.Close) {
await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
connectedClients.TryRemove(socket, out _);
break;
} else if (result.MessageType == WebSocketMessageType.Text) {
string receivedText = Encoding.UTF8.GetString(receiveBuffer.Array, receiveBuffer.Offset, result.Count);
HandleWSMessage(receivedText);
}
}
}
catch (Exception) {
Log.Error("Failed to close WS connection");
connectedClients.TryRemove(socket, out _);
}

// Wait for the send task to complete
await sendTask;
}

static void HandleWSMessage(string message) {
Commands.HandleRemoteMessage(message);
}

public void Stop() {
listener.Stop();
}
Expand Down
112 changes: 0 additions & 112 deletions platforms/windows/service/WSServer.cs

This file was deleted.

9 changes: 3 additions & 6 deletions platforms/windows/service/WindowsBackgroundService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@
namespace service;
public sealed class WindowsBackgroundService : BackgroundService {
internal static HardwareInfo HardwareInfo = new();
internal static HTTPServer HTTPServer = new();
internal static WSServer WSServer = new();
internal static RTCServer RTCServer = new();
internal static Analytics Analytics = new();
internal static Server Server = new();

protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
Log.Information("Starting Cores service");
HardwareInfo.GetInfo();
HTTPServer.Start(HardwareInfo);
WSServer.Start(HardwareInfo);
Server.Start(HardwareInfo);

// Send analytics
_ = Task.Run(async () => {
Expand Down Expand Up @@ -60,8 +58,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
}
catch (OperationCanceledException) {
RTCServer.Stop();
HTTPServer.Stop();
WSServer.Stop();
Server.Stop();
HardwareInfo.Stop();
}
catch (Exception ex) {
Expand Down

0 comments on commit e09ec2a

Please sign in to comment.