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

Merge branch 'deavmi:master' into master

This commit is contained in:
supremestdoggo 2023-03-15 12:16:44 -04:00 committed by GitHub
commit e785fbf8b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 117 additions and 43 deletions

View File

@ -71,6 +71,10 @@ public class Client : Thread
//TODO: Do something here, tare downs //TODO: Do something here, tare downs
} }
public ConnectionInfo getConnInfo()
{
return connInfo;
}
/** /**
@ -101,6 +105,8 @@ public class Client : Thread
* User operations (request-response type) * User operations (request-response type)
*/ */
// TODO: Add joinChannels(strung[])
/** /**
* Joins the requested channel * Joins the requested channel
* *
@ -118,7 +124,8 @@ public class Client : Thread
if(channel[0] == '#') if(channel[0] == '#')
{ {
/* Join the channel */ /* Join the channel */
sendMessage("JOIN "~channel); Message joinMessage = new Message("", "JOIN", channel);
sendMessage(joinMessage);
} }
else else
{ {
@ -187,7 +194,8 @@ public class Client : Thread
} }
/* Leave multiple channels */ /* Leave multiple channels */
sendMessage("PART "~channelLine); Message leaveMessage = new Message("", "PART", channelLine);
sendMessage(leaveMessage);
} }
else else
{ {
@ -212,7 +220,8 @@ public class Client : Thread
// TODO: Add check for valid and non-empty channel names // TODO: Add check for valid and non-empty channel names
/* Leave the channel */ /* Leave the channel */
sendMessage("PART "~channel); Message leaveMessage = new Message("", "PART", channel);
sendMessage(leaveMessage);
} }
/** /**
@ -269,7 +278,8 @@ public class Client : Thread
} }
/* Send the message */ /* Send the message */
sendMessage("PRIVMSG "~recipientLine~" "~message); Message privMessage = new Message("", "PRIVMSG", recipientLine~" "~message);
sendMessage(privMessage);
} }
else else
{ {
@ -306,7 +316,8 @@ public class Client : Thread
if(recipient[0] != '#') if(recipient[0] != '#')
{ {
/* Send the message */ /* Send the message */
sendMessage("PRIVMSG "~recipient~" "~message); Message privMessage = new Message("", "PRIVMSG", recipient~" "~message);
sendMessage(privMessage);
} }
else else
{ {
@ -373,7 +384,8 @@ public class Client : Thread
} }
/* Send to multiple channels */ /* Send to multiple channels */
sendMessage("PRIVMSG "~channelLine~" "~message); Message privMessage = new Message("", "PRIVMSG", channelLine~" "~message);
sendMessage(privMessage);
} }
else else
{ {
@ -408,7 +420,8 @@ public class Client : Thread
if(channel[0] == '#') if(channel[0] == '#')
{ {
/* Send the channel message */ /* Send the channel message */
sendMessage("PRIVMSG "~channel~" "~message); Message privMessage = new Message("", "PRIVMSG", channel~" "~message);
sendMessage(privMessage);
} }
else else
{ {
@ -431,13 +444,8 @@ public class Client : Thread
*/ */
public void command(Message message) public void command(Message message)
{ {
/* Encode according to EBNF format */
// TODO: Validty check
// TODO: Make `Message.encode()` actually encode instead of empty string
string stringToSend = message.encode();
/* Send the message */ /* Send the message */
sendMessage(stringToSend); sendMessage(message);
} }
@ -544,8 +552,9 @@ public class Client : Thread
PongEvent pongEvent = cast(PongEvent)e; PongEvent pongEvent = cast(PongEvent)e;
assert(pongEvent); assert(pongEvent);
string messageToSend = "PONG "~pongEvent.getID(); // string messageToSend = "PONG "~pongEvent.getID();
client.sendMessage(messageToSend); Message pongMessage = new Message("", "PONG", pongEvent.getID());
client.sendMessage(pongMessage);
logger.log("Ponged back with "~pongEvent.getID()); logger.log("Ponged back with "~pongEvent.getID());
} }
} }
@ -623,28 +632,54 @@ public class Client : Thread
receiver.rq(message); receiver.rq(message);
} }
/** // /**
* TODO: Make send queue which is used on another thread to send messages // * Sends a message to the server by enqueuing it on
* // * the client-side send queue
* This allows us to intrpoduce fakelag and also prioritse pongs (we should // *
* send them via here) // * Params:
*/ // * messageOut = the message to send
// */
// private void sendMessage(string messageOut)
// {
// // TODO: Do message splits here
// /* Encode the mesage */
// ubyte[] encodedMessage = encodeMessage(messageOut);
// /* Enqueue the message to the send queue */
// sender.sq(encodedMessage);
// }
/** /**
* Sends a message to the server by enqueuing it on * Sends a message to the server by enqueuing it on
* the client-side send queue * the client-side send queue.
*
* A BirchwoodException is thrown if the messages
* final length exceeds 512 bytes
* *
* Params: * Params:
* messageOut = the message to send * message = the message to send
*/ */
private void sendMessage(string messageOut) private void sendMessage(Message message)
{ {
/* Encode the mesage */ // TODO: Do message splits here
ubyte[] encodedMessage = encodeMessage(messageOut);
/* Encode the message */
ubyte[] encodedMessage = encodeMessage(message.encode());
/* If the message is 512 bytes or less then send */
if(encodedMessage.length <= 512)
{
/* Enqueue the message to the send queue */ /* Enqueue the message to the send queue */
sender.sq(encodedMessage); sender.sq(encodedMessage);
} }
/* If above then throw an exception */
else
{
throw new BirchwoodException(BirchwoodException.ErrorType.COMMAND_TOO_LONG);
}
}
/** /**
* Disconnect from the IRC server gracefully * Disconnect from the IRC server gracefully
@ -653,7 +688,7 @@ public class Client : Thread
{ {
/* Generate the quit command using the custom quit message */ /* Generate the quit command using the custom quit message */
Message quitCommand = new Message("", "QUIT", connInfo.quitMessage); Message quitCommand = new Message("", "QUIT", connInfo.quitMessage);
sendMessage(quitCommand.encode()); sendMessage(quitCommand);
/* TODO: I don't know how long we should wait here */ /* TODO: I don't know how long we should wait here */
Thread.sleep(dur!("seconds")(1)); Thread.sleep(dur!("seconds")(1));
@ -830,6 +865,12 @@ public class Client : Thread
} }
} }
version(unittest)
{
import core.thread;
}
unittest unittest
{ {
/* FIXME: Get domaina name resolution support */ /* FIXME: Get domaina name resolution support */
@ -837,15 +878,19 @@ public class Client : Thread
//freenode: 149.28.246.185 //freenode: 149.28.246.185
//snootnet: 178.62.125.123 //snootnet: 178.62.125.123
//bonobonet: fd08:8441:e254::5 //bonobonet: fd08:8441:e254::5
ConnectionInfo connInfo = ConnectionInfo.newConnection("worcester.community.deavmi.crxn", 6667, "testBirchwood"); ConnectionInfo connInfo = ConnectionInfo.newConnection("worcester.community.networks.deavmi.assigned.network", 6667, "testBirchwood");
// // Set the fakelag to 1 second
// connInfo.setFakeLag(1);
// Create a new Client
Client client = new Client(connInfo); Client client = new Client(connInfo);
client.connect(); client.connect();
import core.thread;
Thread.sleep(dur!("seconds")(2)); Thread.sleep(dur!("seconds")(2));
client.command(new Message("", "NICK", "birchwood")); client.command(new Message("", "NICK", "birchwood")); // TODO: add nickcommand
Thread.sleep(dur!("seconds")(2)); Thread.sleep(dur!("seconds")(2));
client.command(new Message("", "USER", "doggie doggie irc.frdeenode.net :Tristan B. Kildaire")); client.command(new Message("", "USER", "doggie doggie irc.frdeenode.net :Tristan B. Kildaire"));
@ -860,13 +905,13 @@ public class Client : Thread
client.joinChannel("#birchwoodLeave3"); client.joinChannel("#birchwoodLeave3");
Thread.sleep(dur!("seconds")(2)); Thread.sleep(dur!("seconds")(2));
client.command(new Message("", "NAMES", "")); client.command(new Message("", "NAMES", "")); // TODO: add names commdn
Thread.sleep(dur!("seconds")(2)); Thread.sleep(dur!("seconds")(2));
client.command(new Message("", "PRIVMSG", "#birchwood naai")); client.channelMessage("naai", "#birchwood");
Thread.sleep(dur!("seconds")(2)); Thread.sleep(dur!("seconds")(2));
client.command(new Message("", "PRIVMSG", "deavmi naai")); client.directMessage("naai", "deavmi");
/** /**

View File

@ -13,7 +13,8 @@ public class BirchwoodException : Exception
EMPTY_PARAMS, EMPTY_PARAMS,
INVALID_CHANNEL_NAME, INVALID_CHANNEL_NAME,
INVALID_NICK_NAME, INVALID_NICK_NAME,
ILLEGAL_CHARACTERS ILLEGAL_CHARACTERS,
COMMAND_TOO_LONG
} }
private ErrorType errType; private ErrorType errType;

View File

@ -126,10 +126,14 @@ public final class ReceiverThread : Thread
ulong pos = 0; ulong pos = 0;
foreach(ubyte[] message; recvQueue[]) foreach(ubyte[] message; recvQueue[])
{ {
// FIXME: Holy shit this is funny (see https://github.com/deavmi/birchwood/issues/13)
if(indexOf(cast(string)message, "PING") > -1) if(indexOf(cast(string)message, "PING") > -1)
{ {
pingMessage = message; pingMessage = message;
recvQueue.linearRemoveElement(message); recvQueue.linearRemoveElement(message);
import std.stdio;
writeln("\n\nHOLY SHIT\n: "~cast(string)(message)~"\n\n");
break; break;
} }

View File

@ -79,9 +79,6 @@ public final class SenderThread : Thread
*/ */
private void sendHandlerFunc() private void sendHandlerFunc()
{ {
/* TODO: Hoist up into ConnInfo */
ulong fakeLagInBetween = 1;
while(client.running) while(client.running)
{ {
// // Do a once-off call to `ensure()` here which then only runs once and // // Do a once-off call to `ensure()` here which then only runs once and
@ -115,7 +112,7 @@ public final class SenderThread : Thread
foreach(ubyte[] message; sendQueue[]) foreach(ubyte[] message; sendQueue[])
{ {
client.socket.send(message); client.socket.send(message);
Thread.sleep(dur!("seconds")(fakeLagInBetween)); Thread.sleep(dur!("seconds")(client.getConnInfo().getFakeLag()));
} }
/* Empty the send queue */ /* Empty the send queue */

View File

@ -14,7 +14,7 @@ public struct ConnectionInfo
private ulong bulkReadSize; private ulong bulkReadSize;
/* Client behaviour (TODO: what is sleep(0), like nothing) */ /* Client behaviour (TODO: what is sleep(0), like nothing) */
private ulong fakeLag = 0; private ulong fakeLag;
/* The quit message */ /* The quit message */
public const string quitMessage; public const string quitMessage;
@ -26,6 +26,9 @@ public struct ConnectionInfo
this.nickname = nickname; this.nickname = nickname;
this.bulkReadSize = bulkReadSize; this.bulkReadSize = bulkReadSize;
this.quitMessage = quitMessage; this.quitMessage = quitMessage;
// Set the default fakelag to 1
this.fakeLag = 1;
} }
public ulong getBulkReadSize() public ulong getBulkReadSize()
@ -38,6 +41,16 @@ public struct ConnectionInfo
return addrInfo; return addrInfo;
} }
public ulong getFakeLag()
{
return fakeLag;
}
public void setFakeLag(ulong fakeLag)
{
this.fakeLag = fakeLag;
}
/** /**
* Creates a ConnectionInfo struct representing a client configuration which * Creates a ConnectionInfo struct representing a client configuration which
* can be provided to the Client class to create a new connection based on its * can be provided to the Client class to create a new connection based on its

View File

@ -0,0 +1,2 @@
module birchwood.protocol.formatting;

View File

@ -30,7 +30,16 @@ __gshared static this()
/** /**
* Encoding/decoding primitives * Encoding/decoding primitives
*/ */
public static ubyte[] encodeMessage(string messageIn)
/**
* Encodes the provided message into a CRLF
* terminated byte array
*
* Params:
* messageIn = the message to encode
* Returns: the encoded message
*/
public ubyte[] encodeMessage(string messageIn)
{ {
ubyte[] messageOut = cast(ubyte[])messageIn; ubyte[] messageOut = cast(ubyte[])messageIn;
messageOut~=[cast(ubyte)13, cast(ubyte)10]; messageOut~=[cast(ubyte)13, cast(ubyte)10];

View File

@ -1,3 +1,6 @@
module birchwood.protocol; module birchwood.protocol;
public import birchwood.protocol.messages : Message; public import birchwood.protocol.messages : Message;
// TODO: Look how to neaten up (if any)
public import birchwood.protocol.formatting;