From 3bd59840fda66562c7533a639127e822b68c8fb1 Mon Sep 17 00:00:00 2001 From: "Tristan B. Kildaire" Date: Tue, 24 May 2022 23:04:49 +0200 Subject: [PATCH] Upgraded to new Tasky, now using fixed descriptor classes --- dub.json | 3 +- source/libdnet/libdnet.d | 186 +++++++++++++++++++++++++++++++-------- 2 files changed, 151 insertions(+), 38 deletions(-) diff --git a/dub.json b/dub.json index 406a2c7..21c6acd 100644 --- a/dub.json +++ b/dub.json @@ -5,8 +5,9 @@ "copyright": "Copyright © 2021, Tristan B. Kildaire", "dependencies": { "bformat": "3.1.3", + "dlog": "~>0.0.6", "msgpack-d": "1.0.3", - "tasky": "1.0.3" + "tasky": "1.2.0" }, "description": "Client-side DNET API", "license": "LGPLv2", diff --git a/source/libdnet/libdnet.d b/source/libdnet/libdnet.d index 8dab864..2d4e9dd 100644 --- a/source/libdnet/libdnet.d +++ b/source/libdnet/libdnet.d @@ -5,10 +5,34 @@ module libdnet.libdnet; import std.socket : Address, Socket; -import tasky.engine : Engine; +import tasky.engine : Engine, TaskyEvent; +import tasky.jobs : Descriptor; + + +import libdnet.messages.types; + +import msgpack; + +/* TODO: Remove this when we use the newer version of tasky (which uses TaskyEvent) */ +import eventy.event : Event; + +import dlog; public class Client { + /** + * Without __gshared, this would cause us to have a `logger` per-thread + * and statically init a new DefaultLogger() for each respective `logger` field + * + * This makes sure we have one `logger` field for ALL threads and therefore + * only one static initialization. + * + * Funnily enough if you wanted the opposite behaviour, omitting the `__gshared` + * will not help, DMD complains. One must make it explicit I guess with a + * static initialization block `static this()`. + */ + private __gshared static Logger logger = new DefaultLogger(); + private Engine engine; @@ -16,7 +40,7 @@ public class Client - + private Socket sock; @@ -33,53 +57,141 @@ public class Client this.endpoint = endpoint; /* Open socket here */ - Socket sock = new Socket(); - sock.connect(endpoint); + this.sock = new Socket(); + /* Initialize a new Tasky engine */ engine = new Engine(sock); + + /* Register handlers */ + registerHandlers(); + } + + + public enum SpecProtocolID : byte + { + NEWMESSAGE + } + + /** + * Protocols + */ + private ulong[SpecProtocolID] ids; + + + /** + * Registers all of the handlers + */ + private final void registerHandlers() + { + /* Register the message handler */ + Descriptor messageHandlerDesc = new class Descriptor + { + this() + { + super(0); + } + + public override void handler_TaskyEvent(TaskyEvent e) + { + /* Call the entry point handler */ + messageHandler_entry(e); + } + }; + ids[SpecProtocolID.NEWMESSAGE] = messageHandlerDesc.getDescriptorClass(); + + /* TODO: Handler IDs must match the specifition so these should be set in sequence */ + + + + /** + * TODO: Only output when in debug mode + */ + logger.log("<<< Protocol specification breakdown >>>"); + import std.conv : to; + foreach(SpecProtocolID specID; ids.keys()) + { + logger.log("["~to!(string)(specID)~"] = "~to!(string)(ids[specID])); + } + } + + unittest + { + logger.log("unittesting with null address family (no connect() call)"); + Client c = new Client(null); + + } + + + /** + * New message handler + * + * This is called whenever a new message arrives + * + * TODO: Switch to `TaskyEvent e` + */ + private final void messageHandler_entry(TaskyEvent e) + { + /* Get the payload */ + ubyte[] eventPayload = cast(ubyte[])e.getPayload(); + + /* TODO: Check for msgpack errors */ + + /* Unpack the message */ + EntityMessage message = unpack!(EntityMessage)(eventPayload); + + /* Call the handler */ + messageHandler(message); + + + } + + /** + * Override this to provide your handler for new messages + */ + public void messageHandler(EntityMessage message) + { + import std.stdio; + writeln(message); + } + + + /** + * Authenicate with the server + * + * This is a handler that will get a unique descriptor + * for this given authentication attempt such that it + * matches up the reply, you want to ovveride authResponseHandler + */ + public void auth(string[] credentials) + { + /* TODO: Do auth */ + + /* TODO: Set the handler to `authResponseHandler` */ + Descriptor desc; + + /* TODO: Check if descriptor IDs available */ + + /* Get the descriptor ID */ + desc.getDescriptorClass(); + } + + public void authResponseHandler() + { + } /** * Connect to the server */ - public void connect() + public final void start() { + /* TODO: Catch errors: Connect the socket to the endpoint host */ + sock.connect(endpoint); + /* Start the Tasky engine */ engine.start(); } - - /** - * Login - */ - public void login(string[] credentials) - { - - } - - /** - * Shutsdown the client - */ - public void shutdown() - { - /* TODO: Logout if not already logged out */ - - /* TODO: Get tasky to shutdown */ - } - - - /* TODO: Hook ~this() onto shutdown() */ - - /** - * When the next cycle of the garbage collector - * runs and realises there is a zero-refcount - * to this object then shutdown the client - */ - ~this() - { - /* Shutdown the client */ - shutdown(); - } }