mirror of
https://github.com/cadmium-im/zirconium-sharp.git
synced 2024-12-22 08:51:51 +00:00
Implement config parsing, implement removing c2s/core event handlers in router, slightly change C2S/Core Event Handler API, Host Module API
This commit is contained in:
parent
fc609869eb
commit
1996546a73
@ -6,17 +6,19 @@ namespace Zirconium.Core
|
||||
{
|
||||
public class App
|
||||
{
|
||||
public Config Config;
|
||||
public SessionManager SessionManager { get; }
|
||||
public Router Router { get; }
|
||||
public ModuleManager ModuleManager { get; }
|
||||
public IHostModuleAPI HostModuleAPI { get; }
|
||||
public AuthManager AuthManager { get; }
|
||||
|
||||
public App()
|
||||
public App(Config config)
|
||||
{
|
||||
Config = config;
|
||||
SessionManager = new SessionManager();
|
||||
Router = new Router(this);
|
||||
HostModuleAPI = new HostModuleAPI(Router);
|
||||
HostModuleAPI = new HostModuleAPI(this, Router);
|
||||
AuthManager = new AuthManager(this);
|
||||
Log.Info("Zirconium is initialized successfully");
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ namespace Zirconium.Core
|
||||
{
|
||||
private App _app;
|
||||
private string _secretString;
|
||||
private const int TOKEN_EXPIRATION_TIME_HOURS = 24;
|
||||
private const long DEFAULT_TOKEN_EXPIRATION_TIME_HOURS = 24 * 3600000;
|
||||
|
||||
public AuthManager(App app)
|
||||
{
|
||||
@ -18,7 +18,7 @@ namespace Zirconium.Core
|
||||
_secretString = Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
public string CreateToken(string entityID, string deviceID)
|
||||
public string CreateToken(string entityID, string deviceID, long tokenExpirationMillis)
|
||||
{
|
||||
JWTPayload payload = new JWTPayload();
|
||||
payload.DeviceID = deviceID;
|
||||
@ -26,11 +26,15 @@ namespace Zirconium.Core
|
||||
return new JwtBuilder()
|
||||
.WithAlgorithm(new HMACSHA256Algorithm()) // symmetric
|
||||
.WithSecret(_secretString)
|
||||
.AddClaim("exp", DateTimeOffset.UtcNow.AddHours(TOKEN_EXPIRATION_TIME_HOURS).ToUnixTimeSeconds())
|
||||
.AddClaim("exp", DateTimeOffset.UtcNow.AddMilliseconds(tokenExpirationMillis).ToUnixTimeSeconds())
|
||||
.AddClaims(payload.ToDictionary())
|
||||
.Encode();
|
||||
}
|
||||
|
||||
public string CreateToken(string entityID, string deviceID) {
|
||||
return CreateToken(entityID, deviceID, DEFAULT_TOKEN_EXPIRATION_TIME_HOURS);
|
||||
}
|
||||
|
||||
public JWTPayload ValidateToken(string token)
|
||||
{
|
||||
var jsonPayload = new JwtBuilder()
|
||||
|
@ -1,23 +1,17 @@
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace Zirconium.Core
|
||||
{
|
||||
public class Config
|
||||
{
|
||||
// A list of enabled plugins (or extensions) in server
|
||||
[YamlMember(Alias = "enabledPlugins")]
|
||||
public string[] EnabledPlugins {get; set;}
|
||||
|
||||
// Server domain names (e.g. example.com)
|
||||
[YamlMember(Alias = "serverDomains")]
|
||||
public string[] ServerDomains {get; set;}
|
||||
|
||||
// Path to directory with plugin assemblies
|
||||
[YamlMember(Alias = "pluginsDirPath")]
|
||||
public string PluginsDirPath {get; set;}
|
||||
|
||||
// ID of this server in terms of Cadmium federation network
|
||||
[YamlMember(Alias = "serverID")]
|
||||
public string ServerID {get; set;}
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using WebSocketSharp.Server;
|
||||
using WebSocketSharp;
|
||||
@ -42,8 +43,9 @@ namespace Zirconium.Core
|
||||
Console.WriteLine($"Connection {ID} was created"); // TODO implement normal logging
|
||||
}
|
||||
|
||||
public void SendMessage(string message) {
|
||||
public Task SendMessage(string message) {
|
||||
this.Send(message.ToByteArray());
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,43 @@
|
||||
using System;
|
||||
using CommandLine;
|
||||
using Nett;
|
||||
using Zirconium.Core.Logging;
|
||||
|
||||
namespace Zirconium.Core
|
||||
{
|
||||
public class RunOptions
|
||||
{
|
||||
[Option('c', "config", Required = true, HelpText = "Set config path")]
|
||||
public string ConfigPath { get; set; }
|
||||
}
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
App app = new App();
|
||||
string configPath = null;
|
||||
Parser.Default.ParseArguments<RunOptions>(args)
|
||||
.WithParsed<RunOptions>(o =>
|
||||
{
|
||||
configPath = o.ConfigPath;
|
||||
})
|
||||
.WithNotParsed(errs =>
|
||||
{
|
||||
foreach (var err in errs)
|
||||
{
|
||||
Log.Error($"Error occured when parsing run options - {err.Tag}");
|
||||
}
|
||||
Environment.Exit(1);
|
||||
});
|
||||
Config config = null;
|
||||
try
|
||||
{
|
||||
config = Toml.ReadFile<Config>(configPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Fatal($"Error occured when parsing config - {e.Message}");
|
||||
}
|
||||
App app = new App(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Zirconium.Core.Models;
|
||||
using Zirconium.Core.Modules.Interfaces;
|
||||
|
||||
@ -6,56 +7,58 @@ namespace Zirconium.Core.Modules
|
||||
{
|
||||
public class HostModuleAPI : IHostModuleAPI
|
||||
{
|
||||
private App _app;
|
||||
private Router _router;
|
||||
|
||||
public HostModuleAPI(Router router)
|
||||
public HostModuleAPI(App app, Router router)
|
||||
{
|
||||
_router = router;
|
||||
_app = app;
|
||||
}
|
||||
|
||||
public void FireEvent(CoreEvent coreEvent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_router.RouteCoreEvent(coreEvent);
|
||||
}
|
||||
|
||||
public string GenerateAuthToken(string entityID, string deviceID, int tokenExpirationMillis)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _app.AuthManager.CreateToken(entityID, deviceID, tokenExpirationMillis);
|
||||
}
|
||||
|
||||
public string[] GetServerDomains()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _app.Config.ServerDomains;
|
||||
}
|
||||
|
||||
public string GetServerID()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _app.Config.ServerID;
|
||||
}
|
||||
|
||||
public void Hook(IC2SMessageHandler handler)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_router.AddC2SHandler(handler.GetHandlingMessageType(), handler);
|
||||
}
|
||||
|
||||
public void HookCoreEvent(ICoreEventHandler handler)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_router.AddCoreEventHandler(handler.GetHandlingEventType(), handler);
|
||||
}
|
||||
|
||||
public void SendMessage(string connID, BaseMessage message)
|
||||
public void SendMessage(ConnectionInfo connInfo, BaseMessage message)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
connInfo.ConnectionHandler.SendMessage(JsonConvert.SerializeObject(message));
|
||||
}
|
||||
|
||||
public void Unhook(IC2SMessageHandler handler)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_router.RemoveC2SHandler(handler.GetHandlingMessageType(), handler);
|
||||
}
|
||||
|
||||
public void UnhookCoreEvent(ICoreEventHandler handler)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_router.RemoveCoreEventHandler(handler.GetHandlingEventType(), handler);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,8 @@ using Zirconium.Core.Models;
|
||||
namespace Zirconium.Core.Modules.Interfaces
|
||||
{
|
||||
public interface IC2SMessageHandler {
|
||||
void HandleMessage(BaseMessage message);
|
||||
string GetHandlingMessageType();
|
||||
void HandleMessage(ConnectionInfo connInfo, BaseMessage message);
|
||||
bool IsAuthorizationRequired();
|
||||
string GetHandlerUniqueID();
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ namespace Zirconium.Core.Modules.Interfaces
|
||||
{
|
||||
public interface ICoreEventHandler
|
||||
{
|
||||
string GetHandlingEventType();
|
||||
void HandleEvent(CoreEvent coreEvent);
|
||||
string GetHandlerUniqueID();
|
||||
}
|
||||
|
@ -12,6 +12,6 @@ namespace Zirconium.Core.Modules.Interfaces
|
||||
string GenerateAuthToken(string entityID, string deviceID, int tokenExpirationMillis);
|
||||
string[] GetServerDomains();
|
||||
string GetServerID();
|
||||
void SendMessage(string connID, BaseMessage message);
|
||||
void SendMessage(ConnectionInfo connInfo, BaseMessage message);
|
||||
}
|
||||
}
|
@ -44,46 +44,43 @@ namespace Zirconium.Core
|
||||
{
|
||||
if (h.IsAuthorizationRequired())
|
||||
{
|
||||
JWTPayload tokenPayload;
|
||||
try
|
||||
string hash;
|
||||
using (SHA512 shaM = new SHA512Managed())
|
||||
{
|
||||
tokenPayload = _app.AuthManager.ValidateToken(message.AuthToken);
|
||||
hash = shaM.ComputeHash(message.AuthToken.ToByteArray()).ConvertToString();
|
||||
}
|
||||
catch (Exception e)
|
||||
if (connInfo.LastTokenHash != hash)
|
||||
{
|
||||
Log.Warning(e.Message);
|
||||
|
||||
var serializedMsg = JsonConvert.SerializeObject(
|
||||
OtherUtils.GenerateProtocolError(
|
||||
message,
|
||||
"unauthorized",
|
||||
"Unauthorized access",
|
||||
new Dictionary<string, object>()
|
||||
)
|
||||
);
|
||||
connInfo.ConnectionHandler.SendMessage(serializedMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (connInfo.LastTokenHash == "" || connInfo.LastTokenHash == null)
|
||||
{
|
||||
string hash;
|
||||
using (SHA512 shaM = new SHA512Managed())
|
||||
JWTPayload tokenPayload;
|
||||
try
|
||||
{
|
||||
hash = shaM.ComputeHash(message.AuthToken.ToByteArray()).ConvertToString();
|
||||
tokenPayload = _app.AuthManager.ValidateToken(message.AuthToken);
|
||||
}
|
||||
connInfo.LastTokenHash = hash;
|
||||
// TODO implement comparing last token hash and if hash isn't changed then check payload
|
||||
// if payload already exists - then skip validating auth token
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Warning(e.Message);
|
||||
|
||||
connInfo.LastTokenPayload = tokenPayload;
|
||||
var serializedMsg = JsonConvert.SerializeObject(
|
||||
OtherUtils.GenerateProtocolError(
|
||||
message,
|
||||
"unauthorized",
|
||||
"Unauthorized access",
|
||||
new Dictionary<string, object>()
|
||||
)
|
||||
);
|
||||
connInfo.ConnectionHandler.SendMessage(serializedMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
connInfo.LastTokenHash = hash;
|
||||
connInfo.LastTokenPayload = tokenPayload;
|
||||
}
|
||||
}
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
{
|
||||
// probably need to wrap whole foreach body, not only HandleMessage call - need to investigate
|
||||
h.HandleMessage(message);
|
||||
h.HandleMessage(connInfo, message);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -91,11 +88,13 @@ namespace Zirconium.Core
|
||||
public void RouteCoreEvent(CoreEvent coreEvent)
|
||||
{
|
||||
var handlers = _coreEventsHandlers[coreEvent.Name];
|
||||
if (handlers == null) {
|
||||
if (handlers == null)
|
||||
{
|
||||
Log.Warning($"Drop core event {coreEvent.Name} because server hasn't proper handlers");
|
||||
return;
|
||||
}
|
||||
foreach (var h in handlers) {
|
||||
foreach (var h in handlers)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
h.HandleEvent(coreEvent);
|
||||
@ -112,6 +111,13 @@ namespace Zirconium.Core
|
||||
this._c2sMessageHandlers[messageType].Add(handler);
|
||||
}
|
||||
|
||||
public void RemoveC2SHandler(string messageType, IC2SMessageHandler handler)
|
||||
{
|
||||
if (!this._c2sMessageHandlers[messageType].Remove(handler)) {
|
||||
Log.Warning("attempt to remove c2s handler which doesn't exist in router");
|
||||
}
|
||||
}
|
||||
|
||||
public void AddCoreEventHandler(string eventType, ICoreEventHandler handler)
|
||||
{
|
||||
if (_coreEventsHandlers.GetValueOrDefault(eventType, null) == null)
|
||||
@ -120,5 +126,12 @@ namespace Zirconium.Core
|
||||
}
|
||||
this._coreEventsHandlers[eventType].Add(handler);
|
||||
}
|
||||
|
||||
public void RemoveCoreEventHandler(string eventType, ICoreEventHandler handler)
|
||||
{
|
||||
if (!this._coreEventsHandlers[eventType].Remove(handler)) {
|
||||
Log.Warning("attempt to remove core handler which doesn't exist in router");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -5,10 +5,11 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Colorful.Console" Version="1.2.10" />
|
||||
<PackageReference Include="CommandLineParser" Version="2.8.0" />
|
||||
<PackageReference Include="websocketsharp.core" Version="1.0.0" />
|
||||
<PackageReference Include="YamlDotNet" Version="8.1.2" />
|
||||
<PackageReference Include="JWT" Version="7.2.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="McMaster.NETCore.Plugins" Version="1.3.0" />
|
||||
<PackageReference Include="Nett" Version="0.15.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user