From: Chris Porter Date: Mon, 20 Feb 2012 00:51:09 +0000 (+0000) Subject: NUMERICTRACKER: initial import. X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/commitdiff_plain/ec2650e16fe27b7731bc0c2ffa6e64384eb07187 NUMERICTRACKER: initial import. --- diff --git a/numerictracker/Makefile.in b/numerictracker/Makefile.in new file mode 100644 index 00000000..56c92670 --- /dev/null +++ b/numerictracker/Makefile.in @@ -0,0 +1,9 @@ +@include@ @includel@../build.mk@includel@ + +CFLAGS+=$(INCDBAPI) +LDFLAGS+=$(LIBDBAPI) + +.PHONY: all +all: numerictracker.so + +numerictracker.so: numerictracker.o diff --git a/numerictracker/numerictracker.c b/numerictracker/numerictracker.c new file mode 100644 index 00000000..cfedea42 --- /dev/null +++ b/numerictracker/numerictracker.c @@ -0,0 +1,127 @@ +#include +#include +#include "../lib/version.h" +#include "../dbapi2/dbapi2.h" +#include "../core/error.h" +#include "../core/hooks.h" +#include "../core/schedule.h" +#include "../server/server.h" +#include "../control/control.h" + +MODULE_VERSION("") + +static DBAPIConn *db; + +static void hook_server(int hook, void *arg); +static void create_entry(unsigned long servernum, int start_transaction); +static int list_numerics(void *source, int cargc, char **cargv); +static void rescan_network(void); +static void rescan_network_s(void *arg); + +void _init(void) { + db = dbapi2open(NULL, "numerictracker"); + if(!db) { + Error("numerictracker", ERR_WARNING, "Unable to connect to db -- not loaded."); + return; + } + + db->createtable(db, NULL, NULL, "CREATE TABLE ? (numeric VARCHAR(2) NOT NULL, server_name VARCHAR(?), last_seen INT, PRIMARY KEY (numeric, server_name));", "Td", "numerics", HOSTLEN); + + registerhook(HOOK_SERVER_NEWSERVER, &hook_server); + registerhook(HOOK_SERVER_LOSTSERVER, &hook_server); + rescan_network(); + schedulerecurring(time(NULL)+60*5, 0, 60*5, rescan_network_s, NULL); + + registercontrolhelpcmd("listnumerics", NO_OPER, 0, list_numerics, "Usage: listnumerics\nLists all numeric-servername pairs ever seen by the service."); +} + +void _fini(void) { + if(!db) + return; + + deregisterhook(HOOK_SERVER_NEWSERVER, &hook_server); + deregisterhook(HOOK_SERVER_LOSTSERVER, &hook_server); + deregistercontrolcmd("listnumerics", list_numerics); + deleteallschedules(rescan_network_s); +} + +static void rescan_network() { + int i; + + db->squery(db, "BEGIN TRANSACTION;", ""); + + for(i=0;isquery(db, "COMMIT;", ""); +} + +static void rescan_network_s(void *arg) { + rescan_network(); +} + +static void hook_server(int hook, void *arg) { + unsigned long servernum = (unsigned long)arg; + + create_entry(servernum, 1); +} + +static void create_entry(unsigned long servernum, int start_transaction) { + char *server_name = serverlist[servernum].name->content; + char *numeric = longtonumeric(servernum, 2); + + if(start_transaction) + db->squery(db, "BEGIN TRANSACTION;", ""); + + db->squery(db, "DELETE FROM ? WHERE numeric = ? AND server_name = ?;", "Tss", "numerics", numeric, server_name); + db->squery(db, "INSERT INTO ? (numeric, server_name, last_seen) VALUES (?, ?, ?);", "Tsst", "numerics", numeric, server_name, time(NULL)); + + if(start_transaction) + db->squery(db, "COMMIT;", ""); +} + +static void list_numerics_callback(const DBAPIResult *result, void *tag) { + nick *sender = getnickbynumeric((unsigned long)tag); + + if(!result) { + if(sender) + controlreply(sender, "DB query error 1."); + return; + } + + if(!sender || !result->success || (result->fields != 3)) { + if(sender) + controlreply(sender, "DB query error 2."); + + result->clear(result); + return; + } + + controlreply(sender, "%s %-50s %s", "NN", "Server name", "Last seen"); + while(result->next(result)) { + char *numeric; + char *server_name; + time_t last_seen; + char timebuf[50]; + + numeric = result->get(result, 0); + server_name = result->get(result, 1); + last_seen = strtoul(result->get(result, 2), NULL, 10); + + strftime(timebuf, sizeof(timebuf), "%d/%m/%y %H:%M GMT", gmtime(&last_seen)); + controlreply(sender, " %s %-50s %s", numeric, server_name, timebuf); + } + result->clear(result); + + controlreply(sender, "End of listing."); +} + +static int list_numerics(void *source, int cargc, char **cargv) { + nick *sender = (nick *)source; + + rescan_network(); + db->query(db, list_numerics_callback, (void *)sender->numeric, "SELECT numeric, server_name, last_seen FROM ? ORDER BY last_seen ASC, numeric, server_name", "T", "numerics"); + + return CMD_OK; +}