This commit is contained in:
Les De Ridder 2017-03-11 06:14:48 +01:00
parent 945a6907ff
commit ee1e8ff950
No known key found for this signature in database
GPG Key ID: 5EC132DFA85DB372
5 changed files with 177 additions and 130 deletions

2
.gitignore vendored
View File

@ -4,4 +4,4 @@ __dummy.html
*.o
*.obj
__test__*__
ircd
/ircd

View File

@ -1,129 +0,0 @@
import vibe.d;
import std.stdio;
import std.functional;
import std.array;
import std.algorithm;
import std.conv;
shared static this()
{
listenTCP(6667, toDelegate(&handleConnection), "127.0.0.1");
}
struct Message
{
string prefix;
string command;
string[] parameters;
bool prefixedParameter;
static Message fromString(string line)
{
string prefix = null;
if(line.startsWith(':'))
{
line = line[1 .. $];
prefix = line[0 .. line.indexOf(' ')];
line = line[prefix.length + 1 .. $];
}
auto command = line[0 .. line.indexOf(' ')];
line = line[command.length + 1 .. $];
string[] params = [];
bool prefixedParam;
while(true)
{
if(line.startsWith(':'))
{
params ~= line[1 .. $];
prefixedParam = true;
break;
}
else if(line.canFind(' '))
{
auto param = line[0 .. line.indexOf(' ')];
line = line[param.length + 1 .. $];
params ~= param;
}
else
{
params ~= line;
break;
}
}
return Message(prefix, command, params, prefixedParam);
}
string toString()
{
auto message = "";
if(prefix != null)
{
message = ":" ~ prefix ~ " ";
}
message ~= command ~ " ";
if(parameters.length > 1)
{
message ~= parameters[0 .. $-1].join(' ') ~ " ";
}
if(parameters[$-1].canFind(' ') || prefixedParameter)
{
message ~= ":";
}
message ~= parameters[$-1];
return message;
}
}
void send(TCPConnection connection, Message message)
{
string messageString = message.toString;
writeln("S> " ~ messageString);
connection.write(messageString ~ "\r\n");
}
void handleConnection(TCPConnection connection)
{
string nick;
string user;
string realname;
while(connection.connected)
{
auto message = Message.fromString((cast(string)connection.readLine()).chomp);
writeln("C> " ~ message.toString);
switch(message.command)
{
case "NICK":
nick = message.parameters[0];
writeln("nick: " ~ nick);
break;
case "USER":
user = message.parameters[0];
realname = message.parameters[3];
writeln("user: " ~ user);
writeln("mode: " ~ message.parameters[1]);
writeln("unused: " ~ message.parameters[2]);
writeln("realname: " ~ realname);
connection.send(Message("localhost", "001", [nick, "Welcome to the Internet Relay Network " ~ nick ~ "!" ~ user ~ "@hostname"], true));
connection.send(Message("localhost", "002", [nick, "Your host is ircd, running version 0.01"], true));
connection.send(Message("localhost", "003", [nick, "This server was created 2017-03-11"], true));
connection.send(Message("localhost", "004", [nick, "ircd", "0.01", "w", "snt"]));
break;
case "PING":
connection.send(Message(null, "PONG", [message.parameters[0]]));
break;
default:
writeln("unknown command '", message.command, "'");
break;
}
}
}

24
source/ircd/app.d Normal file
View File

@ -0,0 +1,24 @@
module ircd.app;
import std.stdio;
import std.algorithm;
import core.time;
import vibe.d;
import ircd.message;
import ircd.connection;
shared static this()
{
Connection[] connections = [];
listenTCP(6667, delegate(TCPConnection connection)
{
auto c = new Connection(connection);
connections ~= c;
c.handle();
connections = connections.filter!(a => a != c).array;
},"127.0.0.1");
}

76
source/ircd/connection.d Normal file
View File

@ -0,0 +1,76 @@
module ircd.connection;
import std.stdio;
import vibe.d;
import ircd.message;
class Connection
{
private TCPConnection _connection;
//TODO: Make into auto-properties (via template)
string nick;
string user;
string realname;
bool connected;
this(TCPConnection connection)
{
_connection = connection;
}
void send(Message message)
{
string messageString = message.toString;
writeln("S> " ~ messageString);
_connection.write(messageString ~ "\r\n");
}
void handle()
{
connected = true;
while(connected)
{
auto message = Message.fromString((cast(string)_connection.readLine()).chomp);
writeln("C> " ~ message.toString);
switch(message.command)
{
case "NICK":
//TODO: Check availablity and validity etc.
nick = message.parameters[0];
writeln("nick: " ~ nick);
break;
case "USER":
user = message.parameters[0];
realname = message.parameters[3];
writeln("user: " ~ user);
writeln("mode: " ~ message.parameters[1]);
writeln("unused: " ~ message.parameters[2]);
writeln("realname: " ~ realname);
send(Message("localhost", "001", [nick, "Welcome to the Internet Relay Network " ~ nick ~ "!" ~ user ~ "@hostname"], true));
send(Message("localhost", "002", [nick, "Your host is ircd, running version 0.01"], true));
send(Message("localhost", "003", [nick, "This server was created 2017-03-11"], true));
send(Message("localhost", "004", [nick, "ircd", "0.01", "w", "snt"]));
break;
case "PING":
send(Message(null, "PONG", [message.parameters[0]]));
break;
case "QUIT":
send(Message(null, "ERROR", ["Bye!"]));
connected = false;
break;
default:
writeln("unknown command '", message.command, "'");
break;
}
}
}
}

76
source/ircd/message.d Normal file
View File

@ -0,0 +1,76 @@
module ircd.message;
import std.string;
import std.functional;
import std.array;
import std.algorithm;
import std.conv;
struct Message
{
string prefix;
string command;
string[] parameters;
bool prefixedParameter;
static Message fromString(string line)
{
string prefix = null;
if(line.startsWith(':'))
{
line = line[1 .. $];
prefix = line[0 .. line.indexOf(' ')];
line = line[prefix.length + 1 .. $];
}
auto command = line[0 .. line.indexOf(' ')];
line = line[command.length + 1 .. $];
string[] params = [];
bool prefixedParam;
while(true)
{
if(line.startsWith(':'))
{
params ~= line[1 .. $];
prefixedParam = true;
break;
}
else if(line.canFind(' '))
{
auto param = line[0 .. line.indexOf(' ')];
line = line[param.length + 1 .. $];
params ~= param;
}
else
{
params ~= line;
break;
}
}
return Message(prefix, command, params, prefixedParam);
}
string toString()
{
auto message = "";
if(prefix != null)
{
message = ":" ~ prefix ~ " ";
}
message ~= command ~ " ";
if(parameters.length > 1)
{
message ~= parameters[0 .. $-1].join(' ') ~ " ";
}
if(parameters[$-1].canFind(' ') || prefixedParameter)
{
message ~= ":";
}
message ~= parameters[$-1];
return message;
}
}