]> jfr.im git - irc/quakenet/newserv.git/commitdiff
NUMERICTRACKER: initial import.
authorChris Porter <redacted>
Mon, 20 Feb 2012 00:51:09 +0000 (00:51 +0000)
committerChris Porter <redacted>
Mon, 20 Feb 2012 00:51:09 +0000 (00:51 +0000)
numerictracker/Makefile.in [new file with mode: 0644]
numerictracker/numerictracker.c [new file with mode: 0644]

diff --git a/numerictracker/Makefile.in b/numerictracker/Makefile.in
new file mode 100644 (file)
index 0000000..56c9267
--- /dev/null
@@ -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 (file)
index 0000000..cfedea4
--- /dev/null
@@ -0,0 +1,127 @@
+#include <stdio.h>
+#include <time.h>
+#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;i<MAXSERVERS;i++)
+    if(serverlist[i].linkstate != LS_INVALID)
+      create_entry(i, 0);
+
+  db->squery(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;
+}