From f8b226bae577298297075ad3eb34e593c910540f Mon Sep 17 00:00:00 2001 From: Djeeberjr Date: Sun, 4 Jun 2023 16:28:26 +0200 Subject: [PATCH] added SRSC --- src/bin/srsc/CLI.hx | 92 +++++++++++++++++++++ src/bin/srsc/PackageTypes.hx | 32 ++++++++ src/bin/srsc/SiteRessourceController.hx | 104 ++++++++++++++++++++++++ src/kernel/DCEHack.hx | 2 + src/kernel/binstore/BinStore.hx | 6 +- src/lib/RessourceNames.hx | 66 +++++++++++++++ 6 files changed, 301 insertions(+), 1 deletion(-) create mode 100644 src/bin/srsc/CLI.hx create mode 100644 src/bin/srsc/PackageTypes.hx create mode 100644 src/bin/srsc/SiteRessourceController.hx create mode 100644 src/lib/RessourceNames.hx diff --git a/src/bin/srsc/CLI.hx b/src/bin/srsc/CLI.hx new file mode 100644 index 0000000..3a74bb7 --- /dev/null +++ b/src/bin/srsc/CLI.hx @@ -0,0 +1,92 @@ +package bin.srsc; + +import kernel.net.Package.NetworkID; +import lib.RessourceNames; +import lib.CLIAppBase; + +using tink.CoreApi; + +class CLI extends CLIAppBase { + public function new() { + registerAsyncSubcommand("get", (args) -> { + if (args.length < 2) { + handle.writeLine("Not enough arguments"); + return Future.sync(false); + } + + var id:NetworkID = Std.parseInt(args[0]); + if (id == null) { + handle.writeLine("Invalid id"); + return Future.sync(false); + } + + return RessourceNames.get(args[1], id).map((res) -> { + switch (res) { + case Success(data): + if (data == null) { + handle.writeLine("Not found"); + } else { + handle.writeLine("Found: " + data); + } + case Failure(error): + handle.writeLine("Error: " + error); + } + return true; + }); + }, " "); + + registerAsyncSubcommand("register", (args) -> { + if (args.length < 3) { + handle.writeLine("Not enough arguments"); + return Future.sync(false); + } + + var id:NetworkID = Std.parseInt(args[0]); + if (id == null) { + handle.writeLine("Invalid id"); + return Future.sync(false); + } + + var id2:NetworkID = Std.parseInt(args[2]); + if (id2 == null) { + handle.writeLine("Invalid id"); + return Future.sync(false); + } + + return RessourceNames.register(args[1], id2, id).map((res) -> { + switch (res) { + case Success(data): + handle.writeLine("Success"); + case Failure(error): + handle.writeLine("Error: " + error); + } + + return true; + }); + }, " "); + + registerAsyncSubcommand("unregister", (args) -> { + if (args.length < 2) { + handle.writeLine("Not enough arguments"); + return Future.sync(false); + } + + var id:NetworkID = Std.parseInt(args[0]); + if (id == null) { + handle.writeLine("Invalid id"); + return Future.sync(false); + } + + return RessourceNames.unregister(args[1], id).map((res) -> { + switch (res) { + case Success(data): + handle.writeLine("Success"); + case Failure(error): + handle.writeLine("Error: " + error); + } + + return true; + }); + }, " "); + } +} diff --git a/src/bin/srsc/PackageTypes.hx b/src/bin/srsc/PackageTypes.hx new file mode 100644 index 0000000..dddbd14 --- /dev/null +++ b/src/bin/srsc/PackageTypes.hx @@ -0,0 +1,32 @@ +package bin.srsc; + +import kernel.net.Package.NetworkID; + +typedef GetRequest = { + public var ?type:String; + public var name:String; +} + +typedef GetResponse = { + public var success:Bool; + public var netID:NetworkID; +} + +typedef RegisterRequest = { + public var ?type:String; + public var name:String; + public var netID:NetworkID; +} + +typedef RegisterResponse = { + public var success:Bool; +} + +typedef UnregisterRequest = { + public var ?type:String; + public var name:String; +} + +typedef UnregisterResponse = { + public var success:Bool; +} diff --git a/src/bin/srsc/SiteRessourceController.hx b/src/bin/srsc/SiteRessourceController.hx new file mode 100644 index 0000000..747a2dc --- /dev/null +++ b/src/bin/srsc/SiteRessourceController.hx @@ -0,0 +1,104 @@ +package bin.srsc; + +import kernel.log.Log; +import lib.KVStore; +import bin.srsc.PackageTypes; +import kernel.net.Package; +import kernel.ps.ProcessHandle; +import kernel.ps.Process; + +/** + The SiteRessourceController is responsible for the management of ressources on the site. + It makes sure that ressources are have a unique id and that they are not duplicated. + It also keeps track of the responsible NetID for each ressource. Kinda like a DNS. +**/ +class SiteRessourceController implements Process { + public static inline final SITE_CONTROLLER_RESSOURCE_MANAGER_PROTO:String = "srsc"; + + private var handle:ProcessHandle; + private var ressources:Map; + + public function new() {} + + public function run(handle:ProcessHandle) { + this.handle = handle; + + load(); + + // Register proto + kernel.net.Net.instance.registerProto(SITE_CONTROLLER_RESSOURCE_MANAGER_PROTO, this.handleMsg); + } + + private function handleMsg(pkg:Package) { + /* + There are 3 types of messages: + - Register a new ressource name + - Unregister a ressource name + - Get the responsible NetID for a ressource name + */ + + switch (pkg.data.type) { + case "register": + pkg.respond(handleRegister(pkg.data)); + case "unregister": + pkg.respond(handleUnregister(pkg.data)); + case "get": + pkg.respond(handleGet(pkg.data)); + default: + handle.writeLine("Unknown message type: " + pkg.data.type); + } + } + + private function handleGet(data:GetRequest):GetResponse { + var res = get(data.name); + return {success: res != null, netID: res}; + } + + private function handleRegister(data:RegisterRequest):RegisterResponse { + var res = register(data.name, data.netID); + return {success: res}; + } + + private function handleUnregister(data:UnregisterRequest):UnregisterResponse { + unregister(data.name); + return {success: true}; + } + + public function register(name:String, netID:NetworkID):Bool { + if (ressources.exists(name) && ressources.get(name) != netID) { + return false; + } + + ressources.set(name, netID); + save(); + return true; + } + + public function unregister(name:String) { + if (ressources.exists(name)) { + ressources.remove(name); + } + save(); + } + + public function get(name:String):Null { + return ressources.get(name); + } + + private function load() { + var store = KVStore.getStoreForClass(); + var data:Null> = store.get("ressources"); + + if (data != null) { + this.ressources = data; + } else { + this.ressources = new Map(); + } + } + + private function save() { + var store = KVStore.getStoreForClass(); + store.set("ressources", this.ressources); + store.save(); + } +} diff --git a/src/kernel/DCEHack.hx b/src/kernel/DCEHack.hx index 7582ed5..6d1b25a 100644 --- a/src/kernel/DCEHack.hx +++ b/src/kernel/DCEHack.hx @@ -16,6 +16,8 @@ class DCEHack { new bin.Terminal(), new bin.Turtle(), new bin.HelloWorldService(), + new bin.srsc.SiteRessourceController(), + new bin.srsc.CLI(), ]; } } diff --git a/src/kernel/binstore/BinStore.hx b/src/kernel/binstore/BinStore.hx index 942b5de..a3810b3 100644 --- a/src/kernel/binstore/BinStore.hx +++ b/src/kernel/binstore/BinStore.hx @@ -1,5 +1,7 @@ package kernel.binstore; +import bin.srsc.CLI; +import bin.srsc.SiteRessourceController; import bin.HelloWorldService; import bin.Service; import bin.LSPS; @@ -27,7 +29,9 @@ class BinStore { {c: Turtle, name: "Turtle", aliases: ["turtle"]}, {c: LSPS, name: "PM", aliases: ["lsps"]}, {c: Service, name: "Service", aliases: ["service","srv"]}, - {c: HelloWorldService, name: "HelloWorldService", aliases: ["hello-service"] } + {c: HelloWorldService, name: "HelloWorldService", aliases: ["hello-service"] }, + {c: SiteRessourceController, name: "SiteRessourceController", aliases: ["srsc"]}, + {c: CLI, name: "SRSC CLI", aliases: ["srsc-cli"]} ]; @:allow(kernel.Init) diff --git a/src/lib/RessourceNames.hx b/src/lib/RessourceNames.hx new file mode 100644 index 0000000..bb1481e --- /dev/null +++ b/src/lib/RessourceNames.hx @@ -0,0 +1,66 @@ +package lib; + +import bin.srsc.PackageTypes.UnregisterRequest; +import kernel.log.Log; +import bin.srsc.PackageTypes.RegisterRequest; +import bin.srsc.PackageTypes.GetRequest; +import bin.srsc.SiteRessourceController; +import kernel.net.Net; +import kernel.net.Package.NetworkID; + +using tink.CoreApi; + +class RessourceNames { + private static final SITE_CONTROLLER:NetworkID = 0; // Temporary TODO: Change to real ID + + public static function get(name: String, controllerID: NetworkID = -1): Promise> { + if (controllerID == -1) controllerID = SITE_CONTROLLER; + + var payload: GetRequest = {name: name, type: "get"}; + + return Net.instance.sendAndAwait( + SITE_CONTROLLER, + SiteRessourceController.SITE_CONTROLLER_RESSOURCE_MANAGER_PROTO, + payload + ).map((res)->{ + switch (res){ + case Success(pkg): + return Success(pkg.data.netID); + case Failure(error): + return Failure(error); + } + }); + } + + public static function register(name: String, netID: NetworkID, controllerID: NetworkID = -1): Promise { + if (controllerID == -1) controllerID = SITE_CONTROLLER; + + var payload: RegisterRequest = {name: name, netID: netID, type: "register"}; + + return Net.instance.sendAndAwait( + SITE_CONTROLLER, + SiteRessourceController.SITE_CONTROLLER_RESSOURCE_MANAGER_PROTO, + payload + ).map((res)->{ + switch (res){ + case Success(pkg): + return Success(pkg.data.success); + case Failure(error): + return Failure(error); + + } + }); + } + + public static function unregister(name: String, controllerID: NetworkID = -1): Promise { + if (controllerID == -1) controllerID = SITE_CONTROLLER; + + var payload: UnregisterRequest = {name: name, type: "unregister"}; + + return Net.instance.sendAndAwait( + SITE_CONTROLLER, + SiteRessourceController.SITE_CONTROLLER_RESSOURCE_MANAGER_PROTO, + payload + ); + } +} \ No newline at end of file