From 7e1e361c21aabcf96d91fd31c690611762a09325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20=F0=9F=85=B1=2E=20Kildaire?= <21629986@sun.ac.za> Date: Wed, 23 Sep 2020 18:52:11 +0200 Subject: [PATCH] Added 'join' command --- source/dnetd/dchannel.d | 41 ++++++++++++++++++++++ source/dnetd/dconnection.d | 70 +++++++++++++++++++++++++++++++------- source/dnetd/dserver.d | 52 +++++++++++++++++++++++++++- 3 files changed, 150 insertions(+), 13 deletions(-) create mode 100644 source/dnetd/dchannel.d diff --git a/source/dnetd/dchannel.d b/source/dnetd/dchannel.d new file mode 100644 index 0000000..7581aaf --- /dev/null +++ b/source/dnetd/dchannel.d @@ -0,0 +1,41 @@ +/** +* DChannel +* +* Represents a channel and its +* associated information such +* as its name, topic, members +*/ + +module dnetd.dchannel; + +import dnetd.dconnection : DConnection; + +public class DChannel +{ + /** + * Channel information + */ + private string name; + //private string topic; + + /** + * Users in this channel + */ + private DConnection[] members; + + this(string name) + { + + } + + public string getName() + { + return name; + } + + public void join(DConnection client) + { + + } + +} \ No newline at end of file diff --git a/source/dnetd/dconnection.d b/source/dnetd/dconnection.d index e8b410c..b93dcdf 100644 --- a/source/dnetd/dconnection.d +++ b/source/dnetd/dconnection.d @@ -15,12 +15,16 @@ import std.socket : Socket; import bmessage; import tristanable.encoding : DataMessage; import core.sync.mutex : Mutex; +import dnetd.dserver : DServer; +import std.string : split; +import dnetd.dchannel : DChannel; public class DConnection : Thread { /** * Connection information */ + private DServer server; private Socket socket; private bool hasAuthed; @@ -34,11 +38,14 @@ public class DConnection : Thread /* Reserved tag for push notifications */ private long notificationTag = 0; - this(Socket socket) + this(DServer server, Socket socket) { /* Set the function to be called on thread start */ super(&worker); + /* Set the associated server */ + this.server = server; + /* Set the socket */ this.socket = socket; @@ -94,12 +101,19 @@ public class DConnection : Thread /** * Write to socket + * + * Encodes the byte array as a tristanable tagged + * message and then encodes that as a bformat + * message + * + * Locks the writeLock mutex, sends it over the + * socket to the client/server, and unlocks the + * mutex */ - private void writeSocket(long tag, byte[] data) + private bool writeSocket(long tag, byte[] data) { - /* TODO: Implement me */ - - + /* Send status */ + bool status; /* Create the tagged message */ DataMessage message = new DataMessage(tag, data); @@ -107,14 +121,13 @@ public class DConnection : Thread /* Lock the write mutex */ writeLock.lock(); - /* TODO: Do send */ - - bool status = sendMessage(socket, message.encode()); - - /* TODO: use status */ + /* Send the message */ + status = sendMessage(socket, message.encode()); /* Unlock the write mutex */ writeLock.unlock(); + + return status; } @@ -144,15 +157,48 @@ public class DConnection : Thread bool status = authenticate(username, password); /* Encode the reply */ - byte[] reply = [1, status]; + byte[] reply = [status]; - /* TODO: Implement me */ + /* TODO: Implement me, use return value */ writeSocket(tag, reply); } /* If `link` command (requires: unauthed) */ else if(commandByte == 1 && !hasAuthed) { + } + /* */ + else if(commandByte == 2 && !hasAuthed) + { + + } + /* If `join` command (requires: authed) */ + else if(commandByte == 3 && !hasAuthed) + { + /* Get the channel names */ + string channelList = cast(string)message.data[1..message.data.length]; + string[] channels = split(channelList, ","); + + /** + * Loop through each channel, check if it + * exists, if so join it, else create it + * and then join it + */ + foreach(string channelName; channels) + { + /* Attempt to find the channel */ + DChannel channel = server.getChannelByName(channelName); + + /* Create the channel if it doesn't exist */ + if(channel is null) + { + /* TODO: Thread safety for name choice */ + channel = new DChannel(channelName); + } + + /* Join the channel */ + channel.join(this); + } } /* TODO: Handle this case */ else diff --git a/source/dnetd/dserver.d b/source/dnetd/dserver.d index 4c55fa2..02dedce 100644 --- a/source/dnetd/dserver.d +++ b/source/dnetd/dserver.d @@ -13,6 +13,9 @@ module dnetd.dserver; import core.thread : Thread; import std.socket : Address, Socket; import dnetd.dconnection; +import dnetd.dchannel; +import std.string : cmp; +import core.sync.mutex : Mutex; public class DServer : Thread { @@ -27,6 +30,12 @@ public class DServer : Thread * Connection queue */ private DConnection[] connectionQueue; + + /** + * Channels + */ + private DChannel[] channels; + private Mutex channelLock; this(Address sockAddress) { @@ -50,6 +59,9 @@ public class DServer : Thread /* Setup queues */ initQueues(); + + /* Setup locks */ + initLocks(); } /** @@ -73,6 +85,12 @@ public class DServer : Thread { /* TODO: Implement me */ } + + private void initLocks() + { + /* Initialioze the channel lock */ + channelLock = new Mutex(); + } private void startServer() { @@ -91,10 +109,42 @@ public class DServer : Thread Socket socket = serverSocket.accept(); /* Spawn a connection handler */ - DConnection connection = new DConnection(socket); + DConnection connection = new DConnection(this, socket); /* Add to the connection queue */ connectionQueue ~= connection; } } + + public void addChannel(DConnection causer, DChannel channel) + { + /* Lock the channels list */ + channelLock.lock(); + + channels ~= channel; + + /* TODO: Use causer */ + + /* Unlock the channels list */ + channelLock.unlock(); + } + + public DChannel getChannelByName(string channelName) + { + /* Lock the channels list */ + channelLock.lock(); + + foreach(DChannel currentChannel; channels) + { + if(cmp(currentChannel.getName(), channelName) == 0) + { + return currentChannel; + } + } + + /* Unlock the channels list */ + channelLock.unlock(); + + return null; + } } \ No newline at end of file