1
0
mirror of https://github.com/deavmi/birchwood synced 2024-09-20 07:43:55 +02:00

Eventy integration

- Fully integrated eventy
- PongEvent and IRCEvent along with respective GenericSignal and PingSignal handlers added
- Moved parsing of messages into Message class

Debugging

- Added dlog which always logs (for now, we should add a debug clause that enables it)
This commit is contained in:
Tristan B. Velloza Kildaire 2022-11-01 13:41:39 +02:00
parent ce8dbd7f5e
commit cbe41bff80
3 changed files with 235 additions and 115 deletions

View File

@ -4,6 +4,7 @@
], ],
"copyright": "Copyright © 2022, Tristan B. Kildaire", "copyright": "Copyright © 2022, Tristan B. Kildaire",
"dependencies": { "dependencies": {
"dlog": "~>0.0.6",
"eventy": "0.2.5" "eventy": "0.2.5"
}, },
"description": "A sane IRC framework for the D language", "description": "A sane IRC framework for the D language",

View File

@ -12,6 +12,14 @@ import birchwood.messages : Message;
// TODO: Remove this import // TODO: Remove this import
import std.stdio : writeln; import std.stdio : writeln;
import dlog;
__gshared Logger logger;
__gshared static this()
{
logger = new DefaultLogger();
}
public class BirchwoodException : Exception public class BirchwoodException : Exception
{ {
@ -146,9 +154,6 @@ public class Client
this(ConnectionInfo connInfo) this(ConnectionInfo connInfo)
{ {
this.connInfo = connInfo; this.connInfo = connInfo;
/* Set the client inside IRCEvent so all can access it when handling events */
IRCEvent.client = this;
} }
~this() ~this()
@ -156,16 +161,21 @@ public class Client
//TODO: Do something here, tare downs //TODO: Do something here, tare downs
} }
private enum EventType : ulong
{
GENERIC_EVENT = 1,
PONG_EVENT
}
/* TODO: Move to an events.d class */
class IRCEvent : Event class IRCEvent : Event
{ {
/* The client itself */
private static __gshared Client client;
private Message msg; private Message msg;
this(ulong typeID, Message msg) this(Message msg)
{ {
super(typeID, null); super(EventType.GENERIC_EVENT, null);
this.msg = msg; this.msg = msg;
} }
@ -181,21 +191,52 @@ public class Client
} }
} }
/* TODO: make PongEvent (id 2 buit-in) */
class PongEvent : Event
{
private string pingID;
this(string pingID)
{
super(EventType.PONG_EVENT);
this.pingID = pingID;
}
public string getID()
{
return pingID;
}
}
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 */
ulong signalDefault = 1;
engine.addQueue(signalDefault);
/* Register all event types */
engine.addQueue(EventType.GENERIC_EVENT);
engine.addQueue(EventType.PONG_EVENT);
/* Base signal with IRC client in it */
abstract class BaseSignal : Signal
{
/* ICR client */
private Client client;
this(Client client, ulong[] eventIDs)
{
super(eventIDs);
this.client = client;
}
}
/* TODO: We also add default signal handler which will just print stuff out */ /* TODO: We also add default signal handler which will just print stuff out */
class SignalHandler1 : Signal class GenericSignal : BaseSignal
{ {
this() this(Client client)
{ {
super([1]); super(client, [EventType.GENERIC_EVENT]);
} }
public override void handler(Event e) public override void handler(Event e)
@ -204,16 +245,40 @@ public class Client
IRCEvent ircEvent = cast(IRCEvent)e; IRCEvent ircEvent = cast(IRCEvent)e;
assert(ircEvent); //Should never fail, unless some BOZO regged multiple handles for 1 - wait idk does eventy do that even mmm assert(ircEvent); //Should never fail, unless some BOZO regged multiple handles for 1 - wait idk does eventy do that even mmm
writeln("IRCEvent (id): "~to!(string)(ircEvent.id)); logger.log("IRCEvent (id): "~to!(string)(ircEvent.id));
writeln("IRCEvent "~ircEvent.getMessage().toString()); logger.log("IRCEvent "~ircEvent.getMessage().toString());
writeln(IRCEvent.client); logger.log(client);
} }
} }
Signal j = new SignalHandler1(); Signal j = new GenericSignal(this);
engine.addSignalHandler(j); engine.addSignalHandler(j);
/* TODO: Add Pong signal handler (make it id 2) */
class PongSignal : BaseSignal
{
this(Client client)
{
super(client, [EventType.PONG_EVENT]);
}
/* TODO: Implement me */
public override void handler(Event e)
{
PongEvent pongEvent = cast(PongEvent)e;
assert(pongEvent);
string messageToSend = "PONG "~pongEvent.getID();
client.sendMessage(messageToSend);
logger.log("Ponged");
}
}
engine.addSignalHandler(new PongSignal(this));
} }
/** /**
@ -298,92 +363,6 @@ public class Client
// return null; // return null;
} }
/* TODO: Implement me */
/* TODO: This should be a static method in `birchwood.messages.Message`
* which geneartes a Message object for us
*/
private void parseReceivedMessage(string message)
{
/* TODO: testing */
/* From */
string from;
/* Command */
string command;
/* Params */
string params;
/* Check if there is a PREFIX (according to RFC 1459) */
if(message[0] == ':')
{
/* prefix ends after first space (we fetch servername, host/user) */
//TODO: make sure not -1
long firstSpace = indexOf(message, ' ');
/* TODO: double check the condition */
if(firstSpace > 0)
{
from = message[1..firstSpace];
writeln("from: "~from);
/* TODO: Find next space (what follows `from` is `' ' { ' ' }`) */
ulong i = firstSpace;
for(; i < message.length; i++)
{
if(message[i] != ' ')
{
break;
}
}
// writeln("Yo");
string rem = message[i..message.length];
// writeln("Rem: "~rem);
long idx = indexOf(rem, " "); //TOOD: -1 check
/* Extract the command */
command = rem[0..idx];
writeln("command: "~command);
/* Params are everything till the end */
i = idx;
for(; i < rem.length; i++)
{
if(rem[i] != ' ')
{
break;
}
}
params = rem[i..rem.length];
writeln("params: "~params);
}
else
{
//TODO: handle
writeln("Malformed message start after :");
assert(false);
}
}
import birchwood.messages;
Message msg = new Message(from, command, message);
/* TODO: Set static in IRCEvent field for access to Client (and hence socket) */
/* TODO: This should be done in reeive handler me thinks, or rather
shouild return something not yet TRIGGER an event */
Event eTest = new IRCEvent(1, msg);
engine.push(eTest);
}
/* TODO: Spawn a thread worker that reacts */ /* TODO: Spawn a thread worker that reacts */
/** /**
@ -406,6 +385,8 @@ public class Client
/* Lock the receieve queue */ /* Lock the receieve queue */
recvQueueLock.lock(); recvQueueLock.lock();
/* Message being analysed */
Message curMsg;
/* Search for a PING */ /* Search for a PING */
ubyte[] pingMessage; ubyte[] pingMessage;
@ -443,24 +424,34 @@ public class Client
* - we can cache or remember stuff when we get 353 * - we can cache or remember stuff when we get 353
*/ */
/* If we found a PING */ /* If we found a PING */
if(pingMessage.length > 0) if(pingMessage.length > 0)
{ {
writeln("Found a ping: "~cast(string)pingMessage); /* Decode the message and parse it */
string ogMessage = cast(string)pingMessage; curMsg = Message.parseReceivedMessage(decodeMessage(pingMessage));
long idxSigStart = indexOf(ogMessage, ":")+1; logger.log("Found a ping: "~curMsg.toString());
long idxSigEnd = lastIndexOf(ogMessage, '\r');
string pingID = ogMessage[idxSigStart..idxSigEnd]; // string ogMessage = cast(string)pingMessage;
// long idxSigStart = indexOf(ogMessage, ":")+1;
// long idxSigEnd = lastIndexOf(ogMessage, '\r');
// string pingID = ogMessage[idxSigStart..idxSigEnd];
string pingID = curMsg.getMessage();
// this.socket.send(encodeMessage("PONG "~pingID)); // this.socket.send(encodeMessage("PONG "~pingID));
// string messageToSend = "PONG "~pingID;
string messageToSend = "PONG "~pingID; // sendMessage(messageToSend);
sendMessage(messageToSend); // logger.log("Ponged");
/* TODO: Implement */
Event pongEvent = new PongEvent(pingID);
engine.push(pongEvent);
} }
/* Now let's go message by message */ /* Now let's go message by message */
@ -473,12 +464,15 @@ public class Client
recvQueue.linearRemoveElement(recvQueue.front()); recvQueue.linearRemoveElement(recvQueue.front());
writeln("Normal message: "~messageNormal); // writeln("Normal message: "~messageNormal);
/* TODO: Parse message and call correct handler */ /* TODO: Parse message and call correct handler */
parseReceivedMessage(messageNormal); curMsg = Message.parseReceivedMessage(messageNormal);
Event ircEvent = new IRCEvent(curMsg);
engine.push(ircEvent);
} }
@ -553,8 +547,8 @@ public class Client
private void processMessage(ubyte[] message) private void processMessage(ubyte[] message)
{ {
// import std.stdio; // import std.stdio;
// writeln("Message length: "~to!(string)(message.length)); // logger.log("Message length: "~to!(string)(message.length));
// writeln("InterpAsString: "~cast(string)message); // logger.log("InterpAsString: "~cast(string)message);
receiveQ(message); receiveQ(message);

View File

@ -1,5 +1,31 @@
module birchwood.messages; module birchwood.messages;
import dlog;
import std.string;
// TODO: Before release we should remove this import
import std.stdio : writeln;
/* TODO: We could move these all to `package.d` */
/* Static is redundant as module is always static , gshared needed */
/* Apparebky works without gshared, that is kinda sus ngl */
__gshared Logger logger;
/**
* source/birchwood/messages.d(10,8): Error: variable `birchwood.messages.logger` is a thread-local class and cannot have a static initializer. Use `static this()` to initialize instead.
*
* It is complaining that it wopuld static init per thread, static this() for module is required but that would
* do a module init per thread, so __gshared static this() is needed, we want one global init - a single logger
* variable and also class init
*/
__gshared static this()
{
logger = new DefaultLogger();
}
/** /**
* Message types * Message types
*/ */
@ -16,8 +42,107 @@ public class Message
this.message = message; this.message = message;
} }
public static Message parseReceivedMessage(string message)
{
/* TODO: testing */
/* From */
string from;
/* Command */
string command;
/* Params */
string params;
/* Check if there is a PREFIX (according to RFC 1459) */
if(message[0] == ':')
{
/* prefix ends after first space (we fetch servername, host/user) */
//TODO: make sure not -1
long firstSpace = indexOf(message, ' ');
/* TODO: double check the condition */
if(firstSpace > 0)
{
from = message[1..firstSpace];
logger.log("from: "~from);
/* TODO: Find next space (what follows `from` is `' ' { ' ' }`) */
ulong i = firstSpace;
for(; i < message.length; i++)
{
if(message[i] != ' ')
{
break;
}
}
// writeln("Yo");
string rem = message[i..message.length];
// writeln("Rem: "~rem);
long idx = indexOf(rem, " "); //TOOD: -1 check
/* Extract the command */
command = rem[0..idx];
logger.log("command: "~command);
/* Params are everything till the end */
i = idx;
for(; i < rem.length; i++)
{
if(rem[i] != ' ')
{
break;
}
}
params = rem[i..rem.length];
logger.log("params: "~params);
}
else
{
//TODO: handle
logger.log("Malformed message start after :");
assert(false);
}
}
/* In this case it is only `<command> <params>` */
else
{
long firstSpace = indexOf(message, " "); //TODO: Not find check
command = message[0..firstSpace];
ulong pos = firstSpace;
for(; pos < message.length; pos++)
{
if(message[pos] != ' ')
{
break;
}
}
params = message[pos..message.length];
}
return new Message(from, command, params);
}
public override string toString() public override string toString()
{ {
return "(from: "~from~", command: "~command~", message: `"~message~"`)"; return "(from: "~from~", command: "~command~", message: `"~message~"`)";
} }
public string getMessage()
{
return message;
}
} }