From: Paul Date: Sun, 29 Jun 2008 10:28:02 +0000 (+0100) Subject: initial commit - patricia nick index X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/commitdiff_plain/84ca44e7b697aee25f5bfa6e015471a98dbc1451 initial commit - patricia nick index --- diff --git a/core/nsmalloc.h b/core/nsmalloc.h index 657a5828..94b68ce6 100644 --- a/core/nsmalloc.h +++ b/core/nsmalloc.h @@ -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 index 00000000..05b9b7b1 --- /dev/null +++ b/patricianick/Makefile.in @@ -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 index 00000000..5227a109 --- /dev/null +++ b/patricianick/patricianick.c @@ -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 +#include + +#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;inext; + 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;inp; + + 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 "); + 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 index 00000000..b168e5cd --- /dev/null +++ b/patricianick/patricianick.h @@ -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