]> jfr.im git - irc/quakenet/newserv.git/commitdiff
initial commit - patricia nick index
authorPaul <redacted>
Sun, 29 Jun 2008 10:28:02 +0000 (11:28 +0100)
committerPaul <redacted>
Sun, 29 Jun 2008 10:28:02 +0000 (11:28 +0100)
core/nsmalloc.h
patricianick/Makefile.in [new file with mode: 0644]
patricianick/patricianick.c [new file with mode: 0644]
patricianick/patricianick.h [new file with mode: 0644]

index 657a582804aea3cf3019b4b6baa0f16140aef55f..94b68ce6c5cc88ef502b8eecc8f25912b6485fea 100644 (file)
@@ -60,6 +60,7 @@ beginpools() {
   pool(SQLITE),
   pool(PQSQL),
   pool(PATRICIA),
+  pool(PATRICIANICK),
 } endpools()
 
 #undef pool
diff --git a/patricianick/Makefile.in b/patricianick/Makefile.in
new file mode 100644 (file)
index 0000000..05b9b7b
--- /dev/null
@@ -0,0 +1,6 @@
+@include@ @includel@../build.mk@includel@
+
+.PHONY: all
+all: patricianick.so
+
+patricianick.so: patricianick.o
diff --git a/patricianick/patricianick.c b/patricianick/patricianick.c
new file mode 100644 (file)
index 0000000..5227a10
--- /dev/null
@@ -0,0 +1,178 @@
+/* patricianick.c */
+
+#include "patricianick.h"
+#include "../irc/irc_config.h"
+#include "../lib/irc_string.h"
+#include "../core/error.h"
+#include "../core/nsmalloc.h"
+#include "../control/control.h"
+#include "../core/schedule.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#define ALLOCUNIT      1000
+
+patricianick_t *freepatricianicks;
+int pnode_ext;
+int pnick_ext;
+
+int pn_cmd_dumpnodenicks(void *source, int cargc, char **cargv);
+
+void _init() {
+  nick *np, *nnp;
+  int i;
+
+  pnode_ext = registernodeext("patricianick");
+  if ( pnode_ext == -1 ) {
+    Error("patricianick", ERR_FATAL, "Could not register a required node extension");
+    return;
+  }
+
+  pnick_ext = registernickext("patricianick");
+  if ( pnick_ext == -1) { 
+    Error("patricianick", ERR_FATAL, "Could not register a required nick extension");
+    return;
+  }
+
+  for (i=0;i<NICKHASHSIZE;i++)
+    for (np=nicktable[i];np;np=nnp) {
+      nnp=np->next;
+      addnicktonode(np->ipnode, np);
+    }
+
+  registerhook(HOOK_NICK_NEWNICK, &pn_hook_newuser);
+  registerhook(HOOK_NICK_LOSTNICK, &pn_hook_lostuser);
+
+  registercontrolcmd("dumpnodenicks", NO_DEVELOPER, 1, &pn_cmd_dumpnodenicks);
+}
+
+void _fini() {
+  nsfreeall(POOL_PATRICIANICK);
+  if (pnode_ext != -1) {
+    releasenodeext(pnode_ext);
+  }
+
+  if (pnick_ext != -1) {
+    releasenickext(pnick_ext);
+  }
+
+  deregisterhook(HOOK_NICK_NEWNICK, &pn_hook_newuser);
+  deregisterhook(HOOK_NICK_LOSTNICK, &pn_hook_lostuser);
+
+  deregistercontrolcmd("dumpnodenicks", &pn_cmd_dumpnodenicks);
+}
+
+patricianick_t *getpatricianick() {
+  int i;
+  patricianick_t *pnp;
+
+  if (freepatricianicks==NULL) {
+    freepatricianicks=(patricianick_t *)nsmalloc(POOL_PATRICIANICK, ALLOCUNIT*sizeof(patricianick_t));
+    for(i=0;i<ALLOCUNIT-1;i++) {
+      freepatricianicks[i].np=(nick *)&(freepatricianicks[i+1]);
+    }
+    freepatricianicks[ALLOCUNIT-1].np=NULL;
+  }
+
+  pnp=freepatricianicks;
+  freepatricianicks=(patricianick_t *)pnp->np;
+
+  pnp->marker = 0;
+  pnp->np = NULL;
+  return pnp;
+}
+
+void addnicktonode(patricia_node_t *node, nick *np) {
+  if ( !(node->exts[pnode_ext]) ) {
+    node->exts[pnode_ext] = getpatricianick();
+  }
+  np->exts[pnick_ext] = ((patricianick_t *)node->exts[pnode_ext])->np;
+  ((patricianick_t *)node->exts[pnode_ext])->np = np;
+}
+
+void deletenickfromnode(patricia_node_t *node, nick *np) {
+  nick **tnp;
+  int found =0; 
+
+  for ( tnp = &(((patricianick_t *)node->exts[pnode_ext])->np); *tnp; tnp = (nick **)(&((*tnp)->exts[pnick_ext])) ) {
+    if ( *tnp == np ) { 
+      *tnp = np->exts[pnick_ext];
+      found = 1;
+      break;
+    }
+  }
+
+  if (!found) {
+    return; /* err */
+  }
+
+  if (!(((patricianick_t *)node->exts[pnode_ext])->np)) {
+    freepatricianick(node->exts[pnode_ext]);
+    node->exts[pnode_ext]= NULL;
+  }
+
+}
+
+void freepatricianick(patricianick_t *pnp) {
+  pnp->np=(nick *)freepatricianicks;
+  freepatricianicks=pnp;
+}
+
+void pn_hook_newuser(int hook, void *arg) {
+  nick *np = (nick *)arg;
+
+  addnicktonode(np->ipnode, np);
+}
+
+void pn_hook_lostuser(int hook, void *arg) {
+  nick *np = (nick *)arg;
+
+  deletenickfromnode(np->ipnode, np);
+}
+
+int pn_cmd_dumpnodenicks(void *source, int cargc, char **cargv) {
+  nick *np=(nick *)source;
+  struct irc_in_addr sin;
+  unsigned char bits;
+  patricia_node_t *head, *node;
+  patricianick_t *pnp;
+  nick *npp;
+  int limit = 0;
+
+  if (cargc < 1) {
+    controlreply(np, "Syntax: dumpnodenicks <ipv4|ipv6|cidr4|cidr6>");
+    return CMD_OK;
+  }
+
+  if (ipmask_parse(cargv[0], &sin, &bits) == 0) {
+    controlreply(np, "Invalid mask.");
+    return CMD_OK;
+  }
+
+  head = refnode(iptree, &sin, bits);
+
+  PATRICIA_WALK(head, node)
+  {
+    pnp = node->exts[pnode_ext];
+    if (pnp ) {
+      npp = pnp->np;
+      while(npp) {
+        limit++;
+
+        if ( limit < PATRICIANICK_MAXRESULTS )
+          controlreply(np, "%s!%s@%s%s%s (%s)", npp->nick, npp->ident, npp->host->name->content, IsAccount(npp) ? "/" : "", npp->authname, IPtostr(node->prefix->sin));
+        else if ( limit == PATRICIANICK_MAXRESULTS )
+          controlreply(np, "Too many Results, truncated..");
+        npp=npp->exts[pnick_ext];
+      }    
+    }
+  }
+  PATRICIA_WALK_END;
+  controlreply(np, "Nick Count: %d", limit);
+
+  return CMD_OK;
+}
+
diff --git a/patricianick/patricianick.h b/patricianick/patricianick.h
new file mode 100644 (file)
index 0000000..b168e5c
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef __PATRICIANICKS_H
+#define __PATRICIANICKS_H
+
+#include "../nick/nick.h"
+
+#define  PNHASHSIZE              1000
+#define  PATRICIANICK_MAXRESULTS 1000
+
+typedef struct patricianick_s {  
+  nick *np;
+  unsigned int marker; /* todo */
+} patricianick_t;
+
+extern int pnode_ext;
+extern int pnick_ext;
+
+void pn_hook_newuser(int hook, void *arg);
+void pn_hook_lostuser(int hook, void *arg);
+
+void addnicktonode(patricia_node_t *node, nick *nick);
+void deletenickfromnode(patricia_node_t *node, nick *nick) ;
+void freepatricianick(patricianick_t *pnp);
+#endif