mirror of
https://github.com/cadmium-im/zirconium-sharp.git
synced 2024-11-22 02:12:22 +00:00
Implement running websocket server and add handling messages in ConnectionHandler
This commit is contained in:
parent
f34b4e3596
commit
394f9ab908
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
@ -11,11 +11,11 @@
|
|||||||
"preLaunchTask": "build",
|
"preLaunchTask": "build",
|
||||||
// If you have changed target frameworks, make sure to update the program path.
|
// If you have changed target frameworks, make sure to update the program path.
|
||||||
"program": "${workspaceFolder}/src/Zirconium/bin/Debug/netcoreapp3.1/Zirconium.dll",
|
"program": "${workspaceFolder}/src/Zirconium/bin/Debug/netcoreapp3.1/Zirconium.dll",
|
||||||
"args": [],
|
"args": ["--config", "${workspaceFolder}/.config.toml"],
|
||||||
"cwd": "${workspaceFolder}/src/Zirconium",
|
"cwd": "${workspaceFolder}/src/Zirconium",
|
||||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||||
"console": "internalConsole",
|
"console": "internalConsole",
|
||||||
"stopAtEntry": false
|
"stopAtEntry": false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": ".NET Core Attach",
|
"name": ".NET Core Attach",
|
||||||
|
@ -8,4 +8,10 @@ ServerDomains = []
|
|||||||
PluginsDirPath = ""
|
PluginsDirPath = ""
|
||||||
|
|
||||||
# ID of this server in terms of Cadmium federation network. WARNING! This ID should be maximally unique.
|
# ID of this server in terms of Cadmium federation network. WARNING! This ID should be maximally unique.
|
||||||
ServerID = ""
|
ServerID = ""
|
||||||
|
|
||||||
|
# Websocket server settings
|
||||||
|
[Websocket]
|
||||||
|
Host = "localhost"
|
||||||
|
Port = 8000
|
||||||
|
Endpoint = ""
|
@ -1,6 +1,7 @@
|
|||||||
using Zirconium.Core.Modules;
|
using Zirconium.Core.Modules;
|
||||||
using Zirconium.Core.Modules.Interfaces;
|
using Zirconium.Core.Modules.Interfaces;
|
||||||
using Zirconium.Core.Logging;
|
using Zirconium.Core.Logging;
|
||||||
|
using WebSocketSharp.Server;
|
||||||
|
|
||||||
namespace Zirconium.Core
|
namespace Zirconium.Core
|
||||||
{
|
{
|
||||||
@ -12,15 +13,28 @@ namespace Zirconium.Core
|
|||||||
public ModuleManager ModuleManager { get; }
|
public ModuleManager ModuleManager { get; }
|
||||||
public IHostModuleAPI HostModuleAPI { get; }
|
public IHostModuleAPI HostModuleAPI { get; }
|
||||||
public AuthManager AuthManager { get; }
|
public AuthManager AuthManager { get; }
|
||||||
|
private WebSocketServer _websocketServer;
|
||||||
|
|
||||||
public App(Config config)
|
public App(Config config)
|
||||||
{
|
{
|
||||||
Config = config;
|
Config = config;
|
||||||
|
_websocketServer = new WebSocketServer($"ws://{config.Websocket.Host}:{config.Websocket.Port}");
|
||||||
|
_websocketServer.AddWebSocketService<ConnectionHandler>(config.Websocket.Endpoint, () => new ConnectionHandler(this));
|
||||||
SessionManager = new SessionManager();
|
SessionManager = new SessionManager();
|
||||||
Router = new Router(this);
|
Router = new Router(this);
|
||||||
HostModuleAPI = new HostModuleAPI(this, Router);
|
HostModuleAPI = new HostModuleAPI(this, Router);
|
||||||
AuthManager = new AuthManager(this);
|
AuthManager = new AuthManager(this);
|
||||||
Log.Info("Zirconium is initialized successfully");
|
Log.Info("Zirconium is initialized successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Run()
|
||||||
|
{
|
||||||
|
_websocketServer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Destroy() {
|
||||||
|
Log.Info("Shutting down Zirconium...");
|
||||||
|
_websocketServer.Stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,15 +3,25 @@ namespace Zirconium.Core
|
|||||||
public class Config
|
public class Config
|
||||||
{
|
{
|
||||||
// A list of enabled plugins (or extensions) in server
|
// A list of enabled plugins (or extensions) in server
|
||||||
public string[] EnabledPlugins {get; set;}
|
public string[] EnabledPlugins { get; set; }
|
||||||
|
|
||||||
// Server domain names (e.g. example.com)
|
// Server domain names (e.g. example.com)
|
||||||
public string[] ServerDomains {get; set;}
|
public string[] ServerDomains { get; set; }
|
||||||
|
|
||||||
// Path to directory with plugin assemblies
|
// Path to directory with plugin assemblies
|
||||||
public string PluginsDirPath {get; set;}
|
public string PluginsDirPath { get; set; }
|
||||||
|
|
||||||
// ID of this server in terms of Cadmium federation network
|
// ID of this server in terms of Cadmium federation network
|
||||||
public string ServerID {get; set;}
|
public string ServerID { get; set; }
|
||||||
|
|
||||||
|
// Websocket server settings
|
||||||
|
public Websocket Websocket { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Websocket
|
||||||
|
{
|
||||||
|
public string Host { get; set; }
|
||||||
|
public int Port { get; set; }
|
||||||
|
public string Endpoint { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,9 +1,11 @@
|
|||||||
using System.Threading.Tasks;
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using WebSocketSharp.Server;
|
using WebSocketSharp.Server;
|
||||||
using WebSocketSharp;
|
using WebSocketSharp;
|
||||||
using Zirconium.Core.Models;
|
using Zirconium.Core.Models;
|
||||||
using Zirconium.Utils;
|
using Zirconium.Utils;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Zirconium.Core
|
namespace Zirconium.Core
|
||||||
{
|
{
|
||||||
@ -19,18 +21,49 @@ namespace Zirconium.Core
|
|||||||
protected override void OnClose(CloseEventArgs e)
|
protected override void OnClose(CloseEventArgs e)
|
||||||
{
|
{
|
||||||
_app.SessionManager.DeleteSession(ID);
|
_app.SessionManager.DeleteSession(ID);
|
||||||
Console.WriteLine($"Connection {ID} was closed (reason: {e.Reason})"); // TODO implement normal logging
|
Logging.Log.Info($"Connection {ID} was closed (reason: {e.Reason})");
|
||||||
// TODO implement closing connection
|
// TODO implement closing connection
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnError(ErrorEventArgs e)
|
protected override void OnError(ErrorEventArgs e)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Error occurred: {e.Exception}"); // TODO implement normal logging
|
Logging.Log.Error($"Error occurred: {e.Exception}");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnMessage(MessageEventArgs e)
|
protected override void OnMessage(MessageEventArgs e)
|
||||||
{
|
{
|
||||||
// TODO implement message parsing and routing
|
try
|
||||||
|
{
|
||||||
|
if (e.IsText)
|
||||||
|
{
|
||||||
|
var msg = JsonConvert.DeserializeObject<BaseMessage>(e.Data);
|
||||||
|
_app.Router.RouteMessage(_app.SessionManager.GetConnectionInfo(ID), msg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var errMsg = OtherUtils.GenerateProtocolError(
|
||||||
|
null,
|
||||||
|
"parseError",
|
||||||
|
$"Server cannot parse this message yet because it is not JSON",
|
||||||
|
new Dictionary<string, object>()
|
||||||
|
);
|
||||||
|
errMsg.From = _app.Config.ServerID;
|
||||||
|
var msgStr = JsonConvert.SerializeObject(errMsg);
|
||||||
|
this.SendMessage(msgStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
var errMsg = OtherUtils.GenerateProtocolError(
|
||||||
|
null,
|
||||||
|
"parseError",
|
||||||
|
$"Server cannot parse this message! {ex.Message}",
|
||||||
|
new Dictionary<string, object>()
|
||||||
|
);
|
||||||
|
errMsg.From = _app.Config.ServerID;
|
||||||
|
var msgStr = JsonConvert.SerializeObject(errMsg);
|
||||||
|
this.SendMessage(msgStr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnOpen()
|
protected override void OnOpen()
|
||||||
@ -40,12 +73,12 @@ namespace Zirconium.Core
|
|||||||
connInfo.ClientAddress = ip;
|
connInfo.ClientAddress = ip;
|
||||||
connInfo.ConnectionHandler = this;
|
connInfo.ConnectionHandler = this;
|
||||||
_app.SessionManager.AddSession(ID, connInfo);
|
_app.SessionManager.AddSession(ID, connInfo);
|
||||||
Console.WriteLine($"Connection {ID} was created"); // TODO implement normal logging
|
Logging.Log.Info($"Connection {ID} was created");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task SendMessage(string message) {
|
public void SendMessage(string message)
|
||||||
this.Send(message.ToByteArray());
|
{
|
||||||
return Task.CompletedTask;
|
this.Send(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ namespace Zirconium.Core
|
|||||||
}
|
}
|
||||||
class Program
|
class Program
|
||||||
{
|
{
|
||||||
|
private static bool keepRunning = true;
|
||||||
|
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
string configPath = null;
|
string configPath = null;
|
||||||
@ -38,6 +40,14 @@ namespace Zirconium.Core
|
|||||||
Log.Fatal($"Error occured when parsing config - {e.Message}");
|
Log.Fatal($"Error occured when parsing config - {e.Message}");
|
||||||
}
|
}
|
||||||
App app = new App(config);
|
App app = new App(config);
|
||||||
|
app.Run();
|
||||||
|
Console.CancelKeyPress += delegate (object sender, ConsoleCancelEventArgs e)
|
||||||
|
{
|
||||||
|
e.Cancel = true;
|
||||||
|
app.Destroy();
|
||||||
|
keepRunning = false;
|
||||||
|
};
|
||||||
|
while(keepRunning) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,16 +11,16 @@ namespace Zirconium.Core.Models
|
|||||||
[JsonProperty("type")]
|
[JsonProperty("type")]
|
||||||
public string MessageType { get; set; }
|
public string MessageType { get; set; }
|
||||||
|
|
||||||
[JsonProperty("from")]
|
[JsonProperty("from", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string From { get; set; }
|
public string From { get; set; }
|
||||||
|
|
||||||
[JsonProperty("to")]
|
[JsonProperty("to", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string To { get; set; }
|
public string To { get; set; }
|
||||||
|
|
||||||
[JsonProperty("ok")]
|
[JsonProperty("ok")]
|
||||||
public bool Ok { get; set; }
|
public bool Ok { get; set; }
|
||||||
|
|
||||||
[JsonProperty("authToken")]
|
[JsonProperty("authToken", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string AuthToken { get; set; }
|
public string AuthToken { get; set; }
|
||||||
|
|
||||||
[JsonProperty("payload")]
|
[JsonProperty("payload")]
|
||||||
@ -30,22 +30,25 @@ namespace Zirconium.Core.Models
|
|||||||
|
|
||||||
public BaseMessage(BaseMessage message, bool reply)
|
public BaseMessage(BaseMessage message, bool reply)
|
||||||
{
|
{
|
||||||
ID = message.ID;
|
if (message != null)
|
||||||
MessageType = message.MessageType;
|
|
||||||
if (reply)
|
|
||||||
{
|
{
|
||||||
From = message.To;
|
ID = message.ID;
|
||||||
To = message.From;
|
MessageType = message.MessageType;
|
||||||
}
|
if (reply)
|
||||||
else
|
{
|
||||||
{
|
From = message.To;
|
||||||
From = message.From;
|
To = message.From;
|
||||||
To = message.To;
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
From = message.From;
|
||||||
|
To = message.To;
|
||||||
|
}
|
||||||
|
|
||||||
Ok = message.Ok;
|
Ok = message.Ok;
|
||||||
AuthToken = message.AuthToken;
|
AuthToken = message.AuthToken;
|
||||||
Payload = message.Payload;
|
Payload = message.Payload;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,18 +25,18 @@ namespace Zirconium.Core
|
|||||||
|
|
||||||
public void RouteMessage(ConnectionInfo connInfo, BaseMessage message)
|
public void RouteMessage(ConnectionInfo connInfo, BaseMessage message)
|
||||||
{
|
{
|
||||||
var handlers = _c2sMessageHandlers[message.MessageType];
|
var handlers = _c2sMessageHandlers.GetValueOrDefault(message.MessageType, null);
|
||||||
if (handlers == null)
|
if (handlers == null)
|
||||||
{
|
{
|
||||||
Log.Warning($"Drop message with type {message.MessageType} because server hasn't proper handlers");
|
Log.Warning($"Drop message with type \"{message.MessageType}\" because server hasn't proper handlers");
|
||||||
var serializedMsg = JsonConvert.SerializeObject(
|
var msg = OtherUtils.GenerateProtocolError(
|
||||||
OtherUtils.GenerateProtocolError(
|
message,
|
||||||
message,
|
"unhandled",
|
||||||
"unhandled",
|
$"Server doesn't implement message type \"{message.MessageType}\"",
|
||||||
$"Server doesn't implement message type {message.MessageType}",
|
new Dictionary<string, object>()
|
||||||
new Dictionary<string, object>()
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
msg.From = _app.Config.ServerID;
|
||||||
|
var serializedMsg = JsonConvert.SerializeObject(msg);
|
||||||
connInfo.ConnectionHandler.SendMessage(serializedMsg);
|
connInfo.ConnectionHandler.SendMessage(serializedMsg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -113,7 +113,8 @@ namespace Zirconium.Core
|
|||||||
|
|
||||||
public void RemoveC2SHandler(string messageType, IC2SMessageHandler handler)
|
public void RemoveC2SHandler(string messageType, IC2SMessageHandler handler)
|
||||||
{
|
{
|
||||||
if (!this._c2sMessageHandlers[messageType].Remove(handler)) {
|
if (!this._c2sMessageHandlers[messageType].Remove(handler))
|
||||||
|
{
|
||||||
Log.Warning("attempt to remove c2s handler which doesn't exist in router");
|
Log.Warning("attempt to remove c2s handler which doesn't exist in router");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,7 +130,8 @@ namespace Zirconium.Core
|
|||||||
|
|
||||||
public void RemoveCoreEventHandler(string eventType, ICoreEventHandler handler)
|
public void RemoveCoreEventHandler(string eventType, ICoreEventHandler handler)
|
||||||
{
|
{
|
||||||
if (!this._coreEventsHandlers[eventType].Remove(handler)) {
|
if (!this._coreEventsHandlers[eventType].Remove(handler))
|
||||||
|
{
|
||||||
Log.Warning("attempt to remove core handler which doesn't exist in router");
|
Log.Warning("attempt to remove core handler which doesn't exist in router");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Zirconium.Core.Models;
|
using Zirconium.Core.Models;
|
||||||
|
|
||||||
@ -13,6 +14,9 @@ namespace Zirconium.Utils
|
|||||||
err.ErrPayload = errPayload;
|
err.ErrPayload = errPayload;
|
||||||
|
|
||||||
BaseMessage msg = new BaseMessage(parentMessage, true);
|
BaseMessage msg = new BaseMessage(parentMessage, true);
|
||||||
|
if (parentMessage == null) {
|
||||||
|
msg.ID = Guid.NewGuid().ToString();
|
||||||
|
}
|
||||||
msg.Ok = false;
|
msg.Ok = false;
|
||||||
msg.Payload = err.ToDictionary();
|
msg.Payload = err.ToDictionary();
|
||||||
return msg;
|
return msg;
|
||||||
|
Loading…
Reference in New Issue
Block a user