Implement basic config loading and PASS message

This commit is contained in:
Les De Ridder 2017-12-29 14:38:13 +01:00
parent 4407a7419b
commit b7868a87c5
7 changed files with 123 additions and 3 deletions

1
.gitignore vendored
View File

@ -7,3 +7,4 @@ __test__*__
/salty-ircd
source/ircd/packageVersion.d
motd
config.sdl

10
config.template.sdl Normal file
View File

@ -0,0 +1,10 @@
listen {
type "plaintext"
address "::"
port 6667
}
# No password set
pass "";
# vim:ft=

View File

@ -6,5 +6,6 @@ license "NCSA"
targetType "executable"
dependency "vibe-d:core" version="~>0.7.30"
dependency "gen-package-version" version="~>1.0.5"
dependency "sdlang-d" version="~>0.10.1"
preGenerateCommands "dub run gen-package-version -- ircd --src=source/"
versions "VibeDefaultMain"

View File

@ -6,10 +6,13 @@
"gen-package-version": "1.0.5",
"libasync": "0.8.3",
"libevent": "2.0.2+2.0.16",
"libinputvisitor": "1.2.2",
"memutils": "0.4.9",
"openssl": "1.1.5+1.0.1g",
"scriptlike": "0.9.7",
"sdlang-d": "0.10.1",
"taggedalgebraic": "0.10.5",
"unit-threaded": "0.6.36",
"vibe-d": "0.7.31"
}
}

View File

@ -1,10 +1,73 @@
module ircd.app;
import std.algorithm;
import std.traits;
import std.string;
import sdlang;
import ircd.server;
static T tagValueOrNull(T)(Tag tag, string childName)
{
if(childName !in tag.tags)
{
return null;
}
else
{
return tagValue!T(tag, childName);
}
}
static T tagValue(T)(Tag tag, string childName)
{
static if(isArray!T && !isSomeString!T)
{
template U(T : T[])
{
alias U = T;
}
T array = [];
foreach(value; tag.tags[childName][0].values)
{
array ~= value.get!(U!T);
}
return array;
}
else static if(isIntegral!T && !is(T == int))
{
return cast(T)tagValue!int(tag, childName);
}
else
{
return tag.tags[childName][0].values[0].get!T;
}
}
shared static this()
{
auto server = new Server();
server.listen();
auto config = parseFile("config.sdl");
auto pass = config.tagValue!string("pass");
server.setPass(pass.empty ? null : pass);
foreach(listenBlock; config.tags.filter!(t => t.getFullName.toString == "listen"))
{
assert(listenBlock.tagValue!string("type") == "plaintext");
auto addresses = listenBlock.tagValue!(string[])("address");
auto port = listenBlock.tagValue!ushort("port");
foreach(address; addresses)
{
server.listen(port, address);
}
}
}

View File

@ -34,10 +34,12 @@ class Connection
bool connected;
string pass = null;
@property auto channels() { return _server.channels.filter!(c => c.members.canFind(this)); }
@property string prefix() { return nick ~ "!" ~ user ~ "@" ~ hostname; }
@property bool registered() { return nick !is null && user !is null; }
@property bool registered() { return nick !is null && user !is null && _server.isPassCorrect(pass); }
@property bool isOperator() { return modes.canFind('o') || modes.canFind('O'); }
@property string servername() { return _server.name; } //TODO: Support server linking
@ -145,7 +147,7 @@ class Connection
writeln("C> " ~ message.toString);
if(!registered && !["NICK", "USER", "PING", "PONG", "QUIT"].canFind(message.command))
if(!registered && !["NICK", "USER", "PASS", "PING", "PONG", "QUIT"].canFind(message.command))
{
sendErrNotRegistered();
continue;
@ -159,6 +161,9 @@ class Connection
case "USER":
onUser(message);
break;
case "PASS":
onPass(message);
break;
case "PING":
//TODO: Connection timeout when we don't get a PONG
send(Message(_server.name, "PONG", [_server.name, message.parameters[0]], true));
@ -307,6 +312,31 @@ class Connection
}
}
void onPass(Message message)
{
//TODO: Make sure PASS is sent before the NICK/USER combination
if(message.parameters.length < 1)
{
sendErrNeedMoreParams(message.command);
return;
}
if(registered)
{
send(Message(_server.name, "462", [nick, "Unauthorized command (already registered)"], true));
return;
}
pass = message.parameters[0];
if(!_server.isPassCorrect(pass))
{
//NOTE: The RFCs don't allow ERR_PASSWDMISMATCH as a response to PASS
//TODO: If RFC-strictness is off, do send ERR_PASSWDMISMATCH
}
}
void onQuit(Message message)
{
connected = false;

View File

@ -35,6 +35,8 @@ class Server
private uint[string] _commandUsage;
private ulong[string] _commandBytes;
private string _pass = null;
private SysTime _startTime;
this()
@ -441,6 +443,16 @@ class Server
connection.send(Message(name, "242", [connection.nick, uptimeString], true));
}
void setPass(string pass)
{
_pass = pass;
}
bool isPassCorrect(string pass)
{
return pass == _pass;
}
void listen(ushort port = 6667)
{
listenTCP(port, &acceptConnection);