diff --git a/source/ircd/connection.d b/source/ircd/connection.d index dfb6dc0..6825f31 100644 --- a/source/ircd/connection.d +++ b/source/ircd/connection.d @@ -181,6 +181,10 @@ class Connection if(!registered) sendErrNotRegistered(); else onLusers(message); break; + case "ISON": + if(!registered) sendErrNotRegistered(); + else onIson(message); + break; default: writeln("unknown command '", message.command, "'"); send(Message(_server.name, "421", [nick, message.command, "Unknown command"])); @@ -207,11 +211,11 @@ class Connection return; } - if(!_server.isValidNick(newNick)) - { - send(Message(_server.name, "432", [nick, newNick, "Erroneous nickname"])); - return; - } + if(!_server.isValidNick(newNick)) + { + send(Message(_server.name, "432", [nick, newNick, "Erroneous nickname"])); + return; + } if(nick !is null) { @@ -641,6 +645,22 @@ class Connection _server.sendLusers(this); } + void onIson(Message message) + { + if(message.parameters.length < 1) + { + sendErrNeedMoreParams(message.command); + return; + } + + //NOTE: The RFCs are ambiguous about the parameter(s). + // It specifies one allowed parameter type, a space-separated list of nicknames (i.e. prefixed with ':'). + // However, the nicknames in the example are sent as separate parameters, not as a single string prefixed with ':'. + // For this implementation, we assume the example is wrong, like most clients seem to assume as well. + // (Other server implementations usually seem to support both interpretations.) + _server.ison(this, message.parameters[0].split); + } + void sendWhoReply(string channel, Connection user, uint hopCount) { auto flags = user.modes.canFind('a') ? "G" : "H"; diff --git a/source/ircd/server.d b/source/ircd/server.d index 43617dd..e6f0b02 100644 --- a/source/ircd/server.d +++ b/source/ircd/server.d @@ -314,7 +314,7 @@ class Server void sendLusers(Connection connection) { - //TODO: If RFC-strictness is off, use '1 server' instead of '1 servers' of the network (or the part of the network of the query) has only one server + //TODO: If RFC-strictness is off, use '1 server' instead of '1 servers' if the network (or the part of the network of the query) has only one server //TODO: Support services and multiple servers connection.send(Message(name, "251", [connection.nick, "There are " ~ connections.filter!(c => c.registered).count.to!string ~ " users and 0 services on 1 servers"], true)); @@ -337,6 +337,13 @@ class Server connection.send(Message(name, "255", [connection.nick, "I have " ~ connections.length.to!string ~ " clients and 1 servers"], true)); } + void ison(Connection connection, string[] nicks) + { + auto reply = nicks.filter!(n => connections.canFind!(u => u.nick == n)).join(' '); + + connection.send(Message(name, "303", [connection.nick, reply], true)); + } + void listen(ushort port = 6667) { listenTCP(port, &acceptConnection);