mirror of
https://github.com/deavmi/birchwood
synced 2024-09-20 16:23:39 +02:00
Merge branch 'deavmi:master' into master
This commit is contained in:
commit
e785fbf8b6
@ -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");
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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
|
||||||
|
2
source/birchwood/protocol/formatting.d
Normal file
2
source/birchwood/protocol/formatting.d
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
module birchwood.protocol.formatting;
|
||||||
|
|
@ -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];
|
||||||
|
@ -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;
|
Loading…
Reference in New Issue
Block a user