diff --git a/dub.json b/dub.json index fb1300e..5473acc 100644 --- a/dub.json +++ b/dub.json @@ -1,4 +1,5 @@ { + "homepage": "https://deavmi.assigned.network/projects/birchwood", "authors": [ "Tristan B. Velloza Kildaire" ], diff --git a/source/birchwood/client/client.d b/source/birchwood/client/client.d index 403ef5a..32c789c 100644 --- a/source/birchwood/client/client.d +++ b/source/birchwood/client/client.d @@ -9,7 +9,7 @@ import core.thread : Thread, dur; import std.string; import eventy : EventyEvent = Event, Engine, EventType, Signal; import birchwood.config : ConnectionInfo; -import birchwood.client.exceptions : BirchwoodException; +import birchwood.client.exceptions : BirchwoodException, ErrorType; import birchwood.protocol.messages : Message, encodeMessage, decodeMessage, isValidText; import birchwood.client.receiver : ReceiverThread; @@ -190,12 +190,12 @@ public class Client : Thread } else { - throw new BirchwoodException(BirchwoodException.ErrorType.INVALID_CHANNEL_NAME); + throw new BirchwoodException(ErrorType.INVALID_CHANNEL_NAME); } } else { - throw new BirchwoodException(BirchwoodException.ErrorType.ILLEGAL_CHARACTERS); + throw new BirchwoodException(ErrorType.ILLEGAL_CHARACTERS); } } @@ -248,7 +248,7 @@ public class Client : Thread } else { - throw new BirchwoodException(BirchwoodException.ErrorType.ILLEGAL_CHARACTERS); + throw new BirchwoodException(ErrorType.ILLEGAL_CHARACTERS); } } @@ -258,13 +258,13 @@ public class Client : Thread } else { - throw new BirchwoodException(BirchwoodException.ErrorType.ILLEGAL_CHARACTERS); + throw new BirchwoodException(ErrorType.ILLEGAL_CHARACTERS); } } /* If no channels provided at all (error) */ else { - throw new BirchwoodException(BirchwoodException.ErrorType.EMPTY_PARAMS); + throw new BirchwoodException(ErrorType.EMPTY_PARAMS); } } @@ -319,7 +319,7 @@ public class Client : Thread } else { - throw new BirchwoodException(BirchwoodException.ErrorType.ILLEGAL_CHARACTERS); + throw new BirchwoodException(ErrorType.ILLEGAL_CHARACTERS); } } @@ -329,13 +329,13 @@ public class Client : Thread } else { - throw new BirchwoodException(BirchwoodException.ErrorType.ILLEGAL_CHARACTERS); + throw new BirchwoodException(ErrorType.ILLEGAL_CHARACTERS); } } /* If no channels provided at all (error) */ else { - throw new BirchwoodException(BirchwoodException.ErrorType.EMPTY_PARAMS); + throw new BirchwoodException(ErrorType.EMPTY_PARAMS); } } @@ -403,7 +403,7 @@ public class Client : Thread } else { - throw new BirchwoodException(BirchwoodException.ErrorType.ILLEGAL_CHARACTERS); + throw new BirchwoodException(ErrorType.ILLEGAL_CHARACTERS); } } @@ -413,18 +413,18 @@ public class Client : Thread } else { - throw new BirchwoodException(BirchwoodException.ErrorType.ILLEGAL_CHARACTERS); + throw new BirchwoodException(ErrorType.ILLEGAL_CHARACTERS); } } else { - throw new BirchwoodException(BirchwoodException.ErrorType.ILLEGAL_CHARACTERS); + throw new BirchwoodException(ErrorType.ILLEGAL_CHARACTERS); } } /* If no recipients provided at all (error) */ else { - throw new BirchwoodException(BirchwoodException.ErrorType.EMPTY_PARAMS); + throw new BirchwoodException(ErrorType.EMPTY_PARAMS); } } @@ -451,12 +451,12 @@ public class Client : Thread } else { - throw new BirchwoodException(BirchwoodException.ErrorType.INVALID_NICK_NAME); + throw new BirchwoodException(ErrorType.INVALID_NICK_NAME); } } else { - throw new BirchwoodException(BirchwoodException.ErrorType.ILLEGAL_CHARACTERS); + throw new BirchwoodException(ErrorType.ILLEGAL_CHARACTERS); } } @@ -509,7 +509,7 @@ public class Client : Thread } else { - throw new BirchwoodException(BirchwoodException.ErrorType.ILLEGAL_CHARACTERS); + throw new BirchwoodException(ErrorType.ILLEGAL_CHARACTERS); } } @@ -519,18 +519,18 @@ public class Client : Thread } else { - throw new BirchwoodException(BirchwoodException.ErrorType.ILLEGAL_CHARACTERS); + throw new BirchwoodException(ErrorType.ILLEGAL_CHARACTERS); } } else { - throw new BirchwoodException(BirchwoodException.ErrorType.ILLEGAL_CHARACTERS); + throw new BirchwoodException(ErrorType.ILLEGAL_CHARACTERS); } } /* If no channels provided at all (error) */ else { - throw new BirchwoodException(BirchwoodException.ErrorType.EMPTY_PARAMS); + throw new BirchwoodException(ErrorType.EMPTY_PARAMS); } } @@ -556,13 +556,13 @@ public class Client : Thread else { //TODO: Invalid channel name - throw new BirchwoodException(BirchwoodException.ErrorType.INVALID_CHANNEL_NAME); + throw new BirchwoodException(ErrorType.INVALID_CHANNEL_NAME); } } else { //TODO: Illegal characters - throw new BirchwoodException(BirchwoodException.ErrorType.ILLEGAL_CHARACTERS); + throw new BirchwoodException(ErrorType.ILLEGAL_CHARACTERS); } } @@ -749,13 +749,13 @@ public class Client : Thread } catch(SocketOSException e) { - throw new BirchwoodException(BirchwoodException.ErrorType.CONNECT_ERROR); + throw new BirchwoodException(ErrorType.CONNECT_ERROR); } } // TODO: Do actual liveliness check here else { - throw new BirchwoodException(BirchwoodException.ErrorType.ALREADY_CONNECTED); + throw new BirchwoodException(ErrorType.ALREADY_CONNECTED); } } @@ -799,7 +799,7 @@ public class Client : Thread /* If above then throw an exception */ else { - throw new BirchwoodException(BirchwoodException.ErrorType.COMMAND_TOO_LONG); + throw new BirchwoodException(ErrorType.COMMAND_TOO_LONG); } } @@ -1011,6 +1011,8 @@ public class Client : Thread client.connect(); + // TODO: The below should all be automatic, maybe once IRCV3 is done + // ... we should automate sending in NICK and USER stuff Thread.sleep(dur!("seconds")(2)); client.command(new Message("", "NICK", "birchwood")); // TODO: add nickcommand diff --git a/source/birchwood/client/exceptions.d b/source/birchwood/client/exceptions.d index 4aaac53..ae5a1a6 100644 --- a/source/birchwood/client/exceptions.d +++ b/source/birchwood/client/exceptions.d @@ -1,40 +1,112 @@ +/** + * Exception handling + */ module birchwood.client.exceptions; import std.conv : to; +/** + * The type of error to be used + * with BirchwoodException + */ +public enum ErrorType +{ + /** + * If the provided connection information + * is invalid, such as incorrect hostname, + * invalid nick + */ + INVALID_CONN_INFO, + + /** + * If an attempt to call connect() is made + * when already connected + */ + ALREADY_CONNECTED, + + /** + * If there is an erroring opening a connection + * to the endpoint server + */ + CONNECT_ERROR, + + /** + * If invalid parameter information is provided + * to an IRC command method + */ + EMPTY_PARAMS, + + /** + * If an invalid channel name is provided + */ + INVALID_CHANNEL_NAME, + + /** + * If an invalid nickname is provided + */ + INVALID_NICK_NAME, + + /** + * If illegal characters exist within the + * message + */ + ILLEGAL_CHARACTERS, + + /** + * If the final encoded IRC message + * is too long to send to the server + */ + COMMAND_TOO_LONG +} + +/** + * A runtime exception in the Birchwood library + */ public class BirchwoodException : Exception { - // TODO: Move outside one level - public enum ErrorType - { - INVALID_CONN_INFO, - ALREADY_CONNECTED, - CONNECT_ERROR, - EMPTY_PARAMS, - INVALID_CHANNEL_NAME, - INVALID_NICK_NAME, - ILLEGAL_CHARACTERS, - COMMAND_TOO_LONG - } - + /** + * The specific type of error occurred + */ private ErrorType errType; - /* Auxillary error information */ - /* TODO: Make these actually Object */ + /** + * Auxillary information + */ private string auxInfo; + /** + * Constructs a new exception with the given sub-error type + * and infers the auxillary information based on said sub-error + * type + * + * Params: + * errType = the sub-error type + */ this(ErrorType errType) { super("BirchwoodError("~to!(string)(errType)~")"~(auxInfo.length == 0 ? "" : " "~auxInfo)); this.errType = errType; } - + + /** + * Constructs a new exception with the given sub-error type + * and auxillary information + * + * Params: + * errType = the sub-error type + * auxInfo = the auxillary information + */ this(ErrorType errType, string auxInfo) { this(errType); this.auxInfo = auxInfo; } + /** + * Retrieve the specific error which occurred + * + * Returns: the ErrorType of the error + */ public ErrorType getType() { return errType; diff --git a/source/birchwood/client/package.d b/source/birchwood/client/package.d index 0745f2b..7f0d958 100644 --- a/source/birchwood/client/package.d +++ b/source/birchwood/client/package.d @@ -1,4 +1,14 @@ +/** + * IRC client and runtime related + */ module birchwood.client; +/** + * IRC client + */ public import birchwood.client.client; -public import birchwood.client.exceptions : BirchwoodException; \ No newline at end of file + +/** + * Error handling + */ +public import birchwood.client.exceptions; \ No newline at end of file diff --git a/source/birchwood/client/receiver.d b/source/birchwood/client/receiver.d index 2b73c16..3b964ab 100644 --- a/source/birchwood/client/receiver.d +++ b/source/birchwood/client/receiver.d @@ -1,3 +1,6 @@ +/** + * Receive queue management + */ module birchwood.client.receiver; import core.thread : Thread, dur; @@ -15,13 +18,23 @@ import birchwood.client; import birchwood.protocol.messages : Message, decodeMessage; import std.string : indexOf; import birchwood.client.events : PongEvent, IRCEvent; +import std.string : cmp; +/** + * Manages the receive queue and performs + * message parsing and event triggering + * based on said messages + */ public final class ReceiverThread : Thread { /** - * The receive queue and its lock + * The receive queue */ private SList!(ubyte[]) recvQueue; + + /** + * The receive queue's lock + */ private Mutex recvQueueLock; /** @@ -151,7 +164,6 @@ public final class ReceiverThread : Thread Message pingMessage; foreach(Message curMsg; currentMessageQueue[]) { - import std.string : cmp; if(cmp(curMsg.getCommand(), "PING") == 0) { currentMessageQueue.linearRemoveElement(curMsg); @@ -221,15 +233,13 @@ public final class ReceiverThread : Thread } } + /** + * Stops the receive queue manager + */ public void end() { // TODO: See above notes about libsnooze behaviour due // ... to usage in our context receiveEvent.notifyAll(); } - - // public bool isReady() - // { - // return hasEnsured; - // } } \ No newline at end of file diff --git a/source/birchwood/client/sender.d b/source/birchwood/client/sender.d index 3e70f90..5d7fbc0 100644 --- a/source/birchwood/client/sender.d +++ b/source/birchwood/client/sender.d @@ -1,3 +1,6 @@ +/** + * Send queue management + */ module birchwood.client.sender; import core.thread : Thread, dur; @@ -11,12 +14,19 @@ import libsnooze; import birchwood.client; +/** + * Manages the send queue + */ public final class SenderThread : Thread { /** - * The send queue and its lock + * The send queue */ private SList!(ubyte[]) sendQueue; + + /** + * The send queue's lock + */ private Mutex sendQueueLock; /** @@ -130,15 +140,13 @@ public final class SenderThread : Thread } } + /** + * Stops the send queue manager + */ public void end() { // TODO: See above notes about libsnooze behaviour due // ... to usage in our context sendEvent.notifyAll(); } - - // public bool isReady() - // { - // return hasEnsured; - // } } \ No newline at end of file diff --git a/source/birchwood/config/conninfo.d b/source/birchwood/config/conninfo.d index 2eebd76..5181e8f 100644 --- a/source/birchwood/config/conninfo.d +++ b/source/birchwood/config/conninfo.d @@ -1,10 +1,10 @@ /** - * COnfiguration-related types + * Configuration-related types */ module birchwood.config.conninfo; import std.socket : SocketException, Address, getAddress; -import birchwood.client.exceptions : BirchwoodException; +import birchwood.client.exceptions; /** * Represents the connection details for a server @@ -12,21 +12,46 @@ import birchwood.client.exceptions : BirchwoodException; */ public struct ConnectionInfo { - /* Server address information */ + /** + * Server address + */ private Address addrInfo; + + /** + * Nickname to use + */ private string nickname; - /* Misc. */ - /* TODO: Make final/const (find out difference) */ + /** + * Size to use to dequeue bytes + * from socket in read-loop + */ private ulong bulkReadSize; - /* Client behaviour (TODO: what is sleep(0), like nothing) */ + //TODO: Make this a Duration + /** + * Time to wait (in seconds) between + * sending messages + */ private ulong fakeLag; - /* The quit message */ + /** + * Quit message + */ public const string quitMessage; /* TODO: before publishing change this bulk size */ + + /** + * Constructs a new ConnectionInfo instance with the + * provided details + * + * Params: + * addrInfo = the server's endpoint + * nickname = the nickname to use + * bulkReadSize = the dequeue read size + * quitMessage = the message to use when quitting + */ private this(Address addrInfo, string nickname, ulong bulkReadSize = 20, string quitMessage = "birchwood client disconnecting...") { this.addrInfo = addrInfo; @@ -38,6 +63,11 @@ public struct ConnectionInfo this.fakeLag = 1; } + /** + * Retrieve the read-dequeue size + * + * Returns: the number of bytes + */ public ulong getBulkReadSize() { return this.bulkReadSize; @@ -83,6 +113,7 @@ public struct ConnectionInfo * hostname = hostname of the server * port = server port * nickname = nickname to use + * * Returns: ConnectionInfo for this server */ public static ConnectionInfo newConnection(string hostname, ushort port, string nickname) @@ -95,7 +126,7 @@ public struct ConnectionInfo /* Username check */ if(!nickname.length) { - throw new BirchwoodException(BirchwoodException.ErrorType.INVALID_CONN_INFO); + throw new BirchwoodException(ErrorType.INVALID_CONN_INFO); } /* TODO: Add feature to choose which address to use, prefer v4 or v6 type of thing */ @@ -105,7 +136,7 @@ public struct ConnectionInfo } catch(SocketException e) { - throw new BirchwoodException(BirchwoodException.ErrorType.INVALID_CONN_INFO); + throw new BirchwoodException(ErrorType.INVALID_CONN_INFO); } } @@ -124,7 +155,7 @@ public struct ConnectionInfo } catch(BirchwoodException e) { - assert(e.getType() == BirchwoodException.ErrorType.INVALID_CONN_INFO); + assert(e.getType() == ErrorType.INVALID_CONN_INFO); } try @@ -134,7 +165,7 @@ public struct ConnectionInfo } catch(BirchwoodException e) { - assert(e.getType() == BirchwoodException.ErrorType.INVALID_CONN_INFO); + assert(e.getType() == ErrorType.INVALID_CONN_INFO); } } diff --git a/source/birchwood/config/package.d b/source/birchwood/config/package.d index 808ee27..1bb8dfd 100644 --- a/source/birchwood/config/package.d +++ b/source/birchwood/config/package.d @@ -1,3 +1,9 @@ +/** + * Configuration system + */ module birchwood.config; +/** + * Connection information + */ public import birchwood.config.conninfo : ConnectionInfo; \ No newline at end of file diff --git a/source/birchwood/package.d b/source/birchwood/package.d index d9018f1..4925ed1 100644 --- a/source/birchwood/package.d +++ b/source/birchwood/package.d @@ -1,5 +1,19 @@ +/** + * A sane IRC framework for the D language + */ module birchwood; +/** + * Client + */ public import birchwood.client; + +/** + * Configuration + */ public import birchwood.config; + +/** + * Encoding and decoding + */ public import birchwood.protocol; \ No newline at end of file diff --git a/source/birchwood/protocol/package.d b/source/birchwood/protocol/package.d index 733ce7a..64e0468 100644 --- a/source/birchwood/protocol/package.d +++ b/source/birchwood/protocol/package.d @@ -1,7 +1,19 @@ +/** + * IRC protocol decoding and encoding + */ module birchwood.protocol; +/** + * Message type and parsing + */ public import birchwood.protocol.messages : Message; + +/** + * Numeric response codes + */ public import birchwood.protocol.constants : ReplyType; -// TODO: Look how to neaten up (if any) +/** + * Message formatting utilities + */ public import birchwood.protocol.formatting; \ No newline at end of file