Implement STATS commands usage and server uptime querying

This commit is contained in:
Les De Ridder 2017-05-19 01:19:23 +02:00
parent 18271e9f49
commit f7edfa9e8f
No known key found for this signature in database
GPG Key ID: 5EC132DFA85DB372
3 changed files with 80 additions and 2 deletions

View File

@ -226,11 +226,16 @@ class Connection
case "MODE":
onMode(message);
break;
case "STATS":
onStats(message);
break;
default:
writeln("unknown command '", message.command, "'");
send(Message(_server.name, "421", [nick, message.command, "Unknown command"]));
break;
continue;
}
_server.updateCommandStatistics(message);
}
onDisconnect();
@ -1097,6 +1102,37 @@ Lforeach:
}
}
void onStats(Message message)
{
if(message.parameters.length > 1)
{
notImplemented("forwarding STATS to another other server");
return;
}
char statsLetter = message.parameters.length > 0 ? message.parameters[0][0] : '*';
switch(statsLetter)
{
case 'l':
notImplemented("STATS server link information");
break;
case 'm':
_server.sendCommandUsage(this);
break;
case 'o':
notImplemented("O-lines and O-line querying");
break;
case 'u':
_server.sendUptime(this);
break;
default:
break;
}
send(Message(_server.name, "219", [nick, [statsLetter].idup, "End of STATS report"], true));
}
void sendWhoReply(string channel, Connection user, string nickPrefix, uint hopCount)
{
auto flags = user.modes.canFind('a') ? "G" : "H";

View File

@ -14,6 +14,9 @@ struct Message
string[] parameters;
bool prefixedParameter;
//NOTE: The RFCs don't state what this is exactly, but common implementations use the byte count of the message parameters
ulong bytes;
static Message fromString(string line)
{
string prefix = null;
@ -32,6 +35,7 @@ struct Message
auto command = line[0 .. line.indexOf(' ')];
line = line[command.length + 1 .. $];
auto bytes = line.length;
string[] params = [];
bool prefixedParam;
while(true)
@ -55,7 +59,7 @@ struct Message
}
}
return Message(prefix, command, params, prefixedParam);
return Message(prefix, command, params, prefixedParam, bytes);
}
string toString()

View File

@ -32,12 +32,19 @@ class Server
Channel[] channels;
private uint[string] _commandUsage;
private ulong[string] _commandBytes;
private SysTime _startTime;
this()
{
name = Socket.hostName;
readMotd();
_startTime = Clock.currTime;
runTask(&pingLoop);
}
@ -399,6 +406,37 @@ class Server
channel.kick(kicker, user, comment);
}
void updateCommandStatistics(Message message)
{
auto command = message.command.toUpper;
if(command !in _commandUsage)
{
_commandUsage[command] = 0;
_commandBytes[command] = 0;
}
_commandUsage[command]++;
_commandBytes[command] += message.bytes;
}
void sendCommandUsage(Connection connection)
{
foreach(command, count; _commandUsage)
{
//TODO: Implement remote count
connection.send(Message(name, "212", [connection.nick, command, count.to!string, _commandBytes[command].to!string, "0"], false));
}
}
void sendUptime(Connection connection)
{
import std.format : format;
auto uptime = (Clock.currTime - _startTime).split!("days", "hours", "minutes", "seconds");
auto uptimeString = format!"Server Up %d days %d:%02d:%02d"(uptime.days, uptime.hours, uptime.minutes, uptime.seconds);
connection.send(Message(name, "242", [connection.nick, uptimeString], true));
}
void listen(ushort port = 6667)
{
listenTCP(port, &acceptConnection);