mirror of
https://github.com/deavmi/birchwood
synced 2024-09-20 14:23:38 +02:00
Merge branch 'master' into bugfix/stripper
This commit is contained in:
commit
4fbe10adca
@ -23,9 +23,9 @@ dub add birchwood
|
|||||||
|
|
||||||
Birchwood depends on the following D libraries:
|
Birchwood depends on the following D libraries:
|
||||||
|
|
||||||
* `libsnooze` (atleast 1.0.0-beta)
|
* `libsnooze` (at least 1.2.0-beta)
|
||||||
* `eventy` (atleast 0.4.0)
|
* `eventy` (at least 0.4.0)
|
||||||
* `dlog` (atleast 0.3.19)
|
* `dlog` (at least 0.3.19)
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
2
dub.json
2
dub.json
@ -7,7 +7,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dlog": ">=0.3.19",
|
"dlog": ">=0.3.19",
|
||||||
"eventy": ">=0.4.0",
|
"eventy": ">=0.4.0",
|
||||||
"libsnooze": ">=1.0.0-beta"
|
"libsnooze": ">=1.2.0-beta"
|
||||||
},
|
},
|
||||||
"description": "A sane IRC framework for the D language",
|
"description": "A sane IRC framework for the D language",
|
||||||
"license": "LGPL-3.0",
|
"license": "LGPL-3.0",
|
||||||
|
@ -10,7 +10,7 @@ import std.container.slist : SList;
|
|||||||
import core.sync.mutex : Mutex;
|
import core.sync.mutex : Mutex;
|
||||||
import core.thread : Thread, dur;
|
import core.thread : Thread, dur;
|
||||||
import std.string;
|
import std.string;
|
||||||
import eventy : EventyEvent = Event, Engine, EventType, Signal;
|
import eventy : EventyEvent = Event, Engine, EventType, Signal, EventyException;
|
||||||
import birchwood.config;
|
import birchwood.config;
|
||||||
import birchwood.client.exceptions : BirchwoodException, ErrorType;
|
import birchwood.client.exceptions : BirchwoodException, ErrorType;
|
||||||
import birchwood.protocol.messages : Message, encodeMessage, decodeMessage, isValidText;
|
import birchwood.protocol.messages : Message, encodeMessage, decodeMessage, isValidText;
|
||||||
@ -19,6 +19,8 @@ import birchwood.client.receiver : ReceiverThread;
|
|||||||
import birchwood.client.sender : SenderThread;
|
import birchwood.client.sender : SenderThread;
|
||||||
import birchwood.client.events;
|
import birchwood.client.events;
|
||||||
|
|
||||||
|
import libsnooze.exceptions : SnoozeError;
|
||||||
|
|
||||||
import dlog;
|
import dlog;
|
||||||
|
|
||||||
package __gshared Logger logger;
|
package __gshared Logger logger;
|
||||||
@ -209,7 +211,7 @@ public class Client : Thread
|
|||||||
* Params:
|
* Params:
|
||||||
* nickname = the nickname to request
|
* nickname = the nickname to request
|
||||||
* Throws:
|
* Throws:
|
||||||
* BirchwoodException on invalid nickname
|
* `BirchwoodException` on invalid nickname
|
||||||
*/
|
*/
|
||||||
public void nick(string nickname)
|
public void nick(string nickname)
|
||||||
{
|
{
|
||||||
@ -244,7 +246,7 @@ public class Client : Thread
|
|||||||
* Params:
|
* Params:
|
||||||
* channel = the channel to join
|
* channel = the channel to join
|
||||||
* Throws:
|
* Throws:
|
||||||
* BirchwoodException on invalid channel name
|
* `BirchwoodException` on invalid channel name
|
||||||
*/
|
*/
|
||||||
public void joinChannel(string channel)
|
public void joinChannel(string channel)
|
||||||
{
|
{
|
||||||
@ -275,7 +277,8 @@ public class Client : Thread
|
|||||||
* Params:
|
* Params:
|
||||||
* channels = the channels to join
|
* channels = the channels to join
|
||||||
* Throws:
|
* Throws:
|
||||||
* BirchwoodException on invalid channel name
|
* `BirchwoodException` on invalid channel name or
|
||||||
|
* if the list is empty
|
||||||
*/
|
*/
|
||||||
public void joinChannel(string[] channels)
|
public void joinChannel(string[] channels)
|
||||||
{
|
{
|
||||||
@ -344,7 +347,8 @@ public class Client : Thread
|
|||||||
* Params:
|
* Params:
|
||||||
* channels = the list of channels to part from
|
* channels = the list of channels to part from
|
||||||
* Throws:
|
* Throws:
|
||||||
* BirchwoodException if the channels list is empty
|
* `BirchwoodException` if the channels list is empty
|
||||||
|
* or there are illegal characters present
|
||||||
*/
|
*/
|
||||||
public void leaveChannel(string[] channels)
|
public void leaveChannel(string[] channels)
|
||||||
{
|
{
|
||||||
@ -414,14 +418,24 @@ public class Client : Thread
|
|||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* channel = the channel to leave
|
* channel = the channel to leave
|
||||||
|
* Throws:
|
||||||
|
* `BirchwoodException` if the channel name
|
||||||
|
* is invalid
|
||||||
*/
|
*/
|
||||||
public void leaveChannel(string channel)
|
public void leaveChannel(string channel)
|
||||||
{
|
{
|
||||||
// TODO: Add check for valid and non-empty channel names
|
/* Ensure the channel name contains only valid characters */
|
||||||
|
if(isValidText(channel))
|
||||||
/* Leave the channel */
|
{
|
||||||
Message leaveMessage = new Message("", "PART", channel);
|
/* Leave the channel */
|
||||||
sendMessage(leaveMessage);
|
Message leaveMessage = new Message("", "PART", channel);
|
||||||
|
sendMessage(leaveMessage);
|
||||||
|
}
|
||||||
|
/* If invalid characters were present */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new BirchwoodException(ErrorType.ILLEGAL_CHARACTERS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -431,7 +445,8 @@ public class Client : Thread
|
|||||||
* message = The message to send
|
* message = The message to send
|
||||||
* recipients = The receipients of the message
|
* recipients = The receipients of the message
|
||||||
* Throws:
|
* Throws:
|
||||||
* BirchwoodException if the recipients list is empty
|
* `BirchwoodException` if the recipients list is empty
|
||||||
|
* or illegal characters are present
|
||||||
*/
|
*/
|
||||||
public void directMessage(string message, string[] recipients)
|
public void directMessage(string message, string[] recipients)
|
||||||
{
|
{
|
||||||
@ -504,6 +519,9 @@ public class Client : Thread
|
|||||||
* Params:
|
* Params:
|
||||||
* message = The message to send
|
* message = The message to send
|
||||||
* recipients = The receipient of the message
|
* recipients = The receipient of the message
|
||||||
|
* Throws:
|
||||||
|
* `BirchwoodException` if the receipient's nickname
|
||||||
|
* is invalid or there are illegal characters present
|
||||||
*/
|
*/
|
||||||
public void directMessage(string message, string recipient)
|
public void directMessage(string message, string recipient)
|
||||||
{
|
{
|
||||||
@ -537,7 +555,7 @@ public class Client : Thread
|
|||||||
* message = The message to send
|
* message = The message to send
|
||||||
* recipients = The receipients of the message
|
* recipients = The receipients of the message
|
||||||
* Throws:
|
* Throws:
|
||||||
* BirchwoodException if the channels list is empty
|
* `BirchwoodException` if the channels list is empty
|
||||||
*/
|
*/
|
||||||
public void channelMessage(string message, string[] channels)
|
public void channelMessage(string message, string[] channels)
|
||||||
{
|
{
|
||||||
@ -610,6 +628,9 @@ public class Client : Thread
|
|||||||
* Params:
|
* Params:
|
||||||
* message = The message to send
|
* message = The message to send
|
||||||
* channel = The channel to send the message to
|
* channel = The channel to send the message to
|
||||||
|
* Throws:
|
||||||
|
* `BirchwoodException` if the message or channel name
|
||||||
|
* contains illegal characters
|
||||||
*/
|
*/
|
||||||
public void channelMessage(string message, string channel)
|
public void channelMessage(string message, string channel)
|
||||||
{
|
{
|
||||||
@ -625,13 +646,11 @@ public class Client : Thread
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//TODO: Invalid channel name
|
|
||||||
throw new BirchwoodException(ErrorType.INVALID_CHANNEL_NAME);
|
throw new BirchwoodException(ErrorType.INVALID_CHANNEL_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//TODO: Illegal characters
|
|
||||||
throw new BirchwoodException(ErrorType.ILLEGAL_CHARACTERS);
|
throw new BirchwoodException(ErrorType.ILLEGAL_CHARACTERS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -649,8 +668,12 @@ public class Client : Thread
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the event handlers
|
* Initialize the event handlers
|
||||||
*/
|
*
|
||||||
|
* Throws:
|
||||||
|
* `EventyException` on error registering
|
||||||
|
* the signals and event types
|
||||||
|
*/
|
||||||
private void initEvents()
|
private void initEvents()
|
||||||
{
|
{
|
||||||
/* TODO: For now we just register one signal type for all messages */
|
/* TODO: For now we just register one signal type for all messages */
|
||||||
@ -775,7 +798,8 @@ public class Client : Thread
|
|||||||
* Connects to the server
|
* Connects to the server
|
||||||
*
|
*
|
||||||
* Throws:
|
* Throws:
|
||||||
* BirchwoodException if there is an error connecting
|
* `BirchwoodException` if there is an error connecting
|
||||||
|
* or something failed internally
|
||||||
*/
|
*/
|
||||||
public void connect()
|
public void connect()
|
||||||
{
|
{
|
||||||
@ -793,22 +817,12 @@ public class Client : Thread
|
|||||||
/* Register default handler */
|
/* Register default handler */
|
||||||
initEvents();
|
initEvents();
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Initialize the ready events for both the
|
|
||||||
// * receive and send queue managers, then after
|
|
||||||
// * doing so start both managers and spin for
|
|
||||||
// * both of them to enter a ready state (i.e.
|
|
||||||
// * they have ensured a waiting-pipe pair for
|
|
||||||
// * libsnooze exists)
|
|
||||||
// */
|
|
||||||
|
|
||||||
/* Set the running status to true */
|
/* Set the running status to true */
|
||||||
running = true;
|
running = true;
|
||||||
|
|
||||||
/* Start the receive queue and send queue managers */
|
/* Start the receive queue and send queue managers */
|
||||||
this.receiver.start();
|
this.receiver.start();
|
||||||
this.sender.start();
|
this.sender.start();
|
||||||
// while(!receiver.isReady() || !sender.isReady()) {}
|
|
||||||
|
|
||||||
/* Start the socket read-decode loop */
|
/* Start the socket read-decode loop */
|
||||||
this.start();
|
this.start();
|
||||||
@ -820,6 +834,14 @@ public class Client : Thread
|
|||||||
{
|
{
|
||||||
throw new BirchwoodException(ErrorType.CONNECT_ERROR);
|
throw new BirchwoodException(ErrorType.CONNECT_ERROR);
|
||||||
}
|
}
|
||||||
|
catch(EventyException e)
|
||||||
|
{
|
||||||
|
throw new BirchwoodException(ErrorType.INTERNAL_FAILURE, e.toString());
|
||||||
|
}
|
||||||
|
catch(SnoozeError e)
|
||||||
|
{
|
||||||
|
throw new BirchwoodException(ErrorType.INTERNAL_FAILURE, e.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// TODO: Do actual liveliness check here
|
// TODO: Do actual liveliness check here
|
||||||
else
|
else
|
||||||
|
@ -15,6 +15,16 @@ import std.conv : to;
|
|||||||
*/
|
*/
|
||||||
public enum ErrorType
|
public enum ErrorType
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* This could occur from errors with `Eventy`
|
||||||
|
* when setting up the signal handlers and
|
||||||
|
* event types. It can also occur if `libsnooze`
|
||||||
|
* has an error which would occur when calling
|
||||||
|
* `ensure(Thread)` for the `Receiver` and `Sender`
|
||||||
|
* threads
|
||||||
|
*/
|
||||||
|
INTERNAL_FAILURE,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the provided connection information
|
* If the provided connection information
|
||||||
* is invalid, such as incorrect hostname,
|
* is invalid, such as incorrect hostname,
|
||||||
|
@ -48,7 +48,6 @@ public final class ReceiverThread : Thread
|
|||||||
* to be processed and received
|
* to be processed and received
|
||||||
*/
|
*/
|
||||||
private Event receiveEvent;
|
private Event receiveEvent;
|
||||||
// private bool hasEnsured;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The associated IRC client
|
* The associated IRC client
|
||||||
@ -61,16 +60,19 @@ public final class ReceiverThread : Thread
|
|||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* client = the Client to associate with
|
* client = the Client to associate with
|
||||||
|
* Throws:
|
||||||
|
* `SnoozeError` on failure to construct an
|
||||||
|
* `Event` or ensure ourselves
|
||||||
*/
|
*/
|
||||||
this(Client client)
|
this(Client client)
|
||||||
{
|
{
|
||||||
super(&recvHandlerFunc);
|
super(&recvHandlerFunc);
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.receiveEvent = new Event(); // TODO: Catch any libsnooze error here
|
this.receiveEvent = new Event();
|
||||||
this.recvQueueLock = new Mutex();
|
this.recvQueueLock = new Mutex();
|
||||||
|
this.receiveEvent.ensure(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Rename to `receiveQ`
|
|
||||||
/**
|
/**
|
||||||
* Enqueues the raw message into the receieve queue
|
* Enqueues the raw message into the receieve queue
|
||||||
* for eventual processing
|
* for eventual processing
|
||||||
@ -89,10 +91,6 @@ public final class ReceiverThread : Thread
|
|||||||
/* Unlock queue */
|
/* Unlock queue */
|
||||||
recvQueueLock.unlock();
|
recvQueueLock.unlock();
|
||||||
|
|
||||||
// TODO: Add a "register" function which can initialize pipes
|
|
||||||
// ... without needing a wait, we'd need a ready flag though
|
|
||||||
// ... for receiver's thread start
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wake up all threads waiting on this event
|
* Wake up all threads waiting on this event
|
||||||
* (if any, and if so it would only be the receiver)
|
* (if any, and if so it would only be the receiver)
|
||||||
@ -116,21 +114,6 @@ public final class ReceiverThread : Thread
|
|||||||
{
|
{
|
||||||
// TODO: We could look at libsnooze wait starvation or mutex racing (future thought)
|
// TODO: We could look at libsnooze wait starvation or mutex racing (future thought)
|
||||||
|
|
||||||
|
|
||||||
// // Do a once-off call to `ensure()` here which then only runs once and
|
|
||||||
// // ... sets a `ready` flag for the Client to spin on. This ensures that
|
|
||||||
// // ... when the first received messages will be able to cause a wait
|
|
||||||
// // ... to immediately unblock rather than letting wait() register itself
|
|
||||||
// // ... and then require another receiveQ call to wake it up and process
|
|
||||||
// // ... the initial n messages + m new ones resulting in the second call
|
|
||||||
// if(hasEnsured == false)
|
|
||||||
// {
|
|
||||||
// receiveEvent.ensure();
|
|
||||||
// hasEnsured = true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// TODO: See above notes about libsnooze behaviour due
|
|
||||||
// ... to usage in our context
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
receiveEvent.wait();
|
receiveEvent.wait();
|
||||||
@ -154,8 +137,6 @@ public final class ReceiverThread : Thread
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Lock the receieve queue */
|
/* Lock the receieve queue */
|
||||||
recvQueueLock.lock();
|
recvQueueLock.lock();
|
||||||
|
|
||||||
|
@ -40,7 +40,6 @@ public final class SenderThread : Thread
|
|||||||
* to be processed and sent
|
* to be processed and sent
|
||||||
*/
|
*/
|
||||||
private Event sendEvent;
|
private Event sendEvent;
|
||||||
// private bool hasEnsured;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The associated IRC client
|
* The associated IRC client
|
||||||
@ -53,16 +52,19 @@ public final class SenderThread : Thread
|
|||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* client = the Client to associate with
|
* client = the Client to associate with
|
||||||
|
* Throws:
|
||||||
|
* `SnoozeError` on failure to construct an
|
||||||
|
* `Event` or ensure ourselves
|
||||||
*/
|
*/
|
||||||
this(Client client)
|
this(Client client)
|
||||||
{
|
{
|
||||||
super(&sendHandlerFunc);
|
super(&sendHandlerFunc);
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.sendEvent = new Event(); // TODO: Catch any libsnooze error here
|
this.sendEvent = new Event();
|
||||||
this.sendQueueLock = new Mutex();
|
this.sendQueueLock = new Mutex();
|
||||||
|
this.sendEvent.ensure(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Rename to `sendQ`
|
|
||||||
/**
|
/**
|
||||||
* Enqueues the raw message into the send queue
|
* Enqueues the raw message into the send queue
|
||||||
* for eventual sending
|
* for eventual sending
|
||||||
@ -81,10 +83,6 @@ public final class SenderThread : Thread
|
|||||||
/* Unlock queue */
|
/* Unlock queue */
|
||||||
sendQueueLock.unlock();
|
sendQueueLock.unlock();
|
||||||
|
|
||||||
// TODO: Add a "register" function which can initialize pipes
|
|
||||||
// ... without needing a wait, we'd need a ready flag though
|
|
||||||
// ... for sender's thread start
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wake up all threads waiting on this event
|
* Wake up all threads waiting on this event
|
||||||
* (if any, and if so it would only be the sender)
|
* (if any, and if so it would only be the sender)
|
||||||
@ -92,7 +90,6 @@ public final class SenderThread : Thread
|
|||||||
sendEvent.notifyAll();
|
sendEvent.notifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The send queue worker function
|
* The send queue worker function
|
||||||
*/
|
*/
|
||||||
@ -100,24 +97,10 @@ public final class SenderThread : Thread
|
|||||||
{
|
{
|
||||||
while(client.running)
|
while(client.running)
|
||||||
{
|
{
|
||||||
// // Do a once-off call to `ensure()` here which then only runs once and
|
|
||||||
// // ... sets a `ready` flag for the Client to spin on. This ensures that
|
|
||||||
// // ... when the first sent messages will be able to cause a wait
|
|
||||||
// // ... to immediately unblock rather than letting wait() register itself
|
|
||||||
// // ... and then require another sendQ call to wake it up and process
|
|
||||||
// // ... the initial n messages + m new ones resulting in the second call
|
|
||||||
// if(hasEnsured == false)
|
|
||||||
// {
|
|
||||||
// sendEvent.ensure();
|
|
||||||
// hasEnsured = true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// TODO: We could look at libsnooze wait starvation or mutex racing (future thought)
|
// TODO: We could look at libsnooze wait starvation or mutex racing (future thought)
|
||||||
|
|
||||||
/* TODO: handle normal messages (xCount with fakeLagInBetween) */
|
/* TODO: handle normal messages (xCount with fakeLagInBetween) */
|
||||||
|
|
||||||
// TODO: See above notes about libsnooze behaviour due
|
|
||||||
// ... to usage in our context
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
sendEvent.wait();
|
sendEvent.wait();
|
||||||
@ -141,13 +124,6 @@ public final class SenderThread : Thread
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: After the above call have a once-off call to `ensure()` here
|
|
||||||
// ... which then only runs once and sets a `ready` flag for the Client
|
|
||||||
// ... to spin on
|
|
||||||
|
|
||||||
|
|
||||||
/* Lock queue */
|
/* Lock queue */
|
||||||
sendQueueLock.lock();
|
sendQueueLock.lock();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user