]> jfr.im git - irc/quakenet/newserv.git/blobdiff - authext/authext.c
Add MODULE_VERSION to all default modules.
[irc/quakenet/newserv.git] / authext / authext.c
index e4eef2a538afc3e111fb763c0bd79ef2738ba4d3..e1939e38605ffc051903a09fa5b4f49cbb029600 100644 (file)
@@ -3,28 +3,47 @@
 #include "../core/error.h"
 #include "../lib/sstring.h"
 #include "../lib/irc_string.h"
+#include "../nick/nick.h"
+#include "../core/hooks.h"
+#include "../lib/strlfunc.h"
+#include "../lib/version.h"
 
 #include <string.h>
+#include <stdio.h>
+
+MODULE_VERSION("")
 
 #define ALLOCUNIT 100
 
 #define authnamehash(x)   ((x)%AUTHNAMEHASHSIZE)
+#define authnamehashbyname(x) (crc32i(x)%AUTHNAMEHASHSIZE)
 
 authname *freeauthnames;
 authname *authnametable[AUTHNAMEHASHSIZE];
 
-sstring *authnameextnames[MAXAUTHNAMEEXTS];
+/* internal access only */
+static authname *authnametablebyname[AUTHNAMEHASHSIZE];
+
+static struct {
+  sstring *name;
+  int persistant;
+} authnameexts[MAXAUTHNAMEEXTS];
+
+static void authextstats(int hooknum, void *arg);
 
-void _init() {
+void _init(void) {
   freeauthnames=NULL;
   memset(authnametable,0,sizeof(authnametable));
+  memset(authnametablebyname,0,sizeof(authnametablebyname));
+  registerhook(HOOK_CORE_STATSREQUEST, &authextstats);
 }
 
-void _fini() {
+void _fini(void) {
+  deregisterhook(HOOK_CORE_STATSREQUEST, &authextstats);
   nsfreeall(POOL_AUTHEXT);
 }
 
-authname *newauthname() {
+authname *newauthname(void) {
   authname *anp;
   int i;
 
@@ -47,7 +66,7 @@ void freeauthname (authname *anp) {
   freeauthnames=anp;
 }
 
-int registerauthnameext(const char *name) {
+int registerauthnameext(const char *name, int persistant) {
   int i;
 
   if (findauthnameext(name)!=-1) {
@@ -56,8 +75,9 @@ int registerauthnameext(const char *name) {
   }
 
   for (i=0;i<MAXAUTHNAMEEXTS;i++) {
-    if (authnameextnames[i]==NULL) {
-      authnameextnames[i]=getsstring(name,100);
+    if (authnameexts[i].name==NULL) {
+      authnameexts[i].name=getsstring(name,100);
+      authnameexts[i].persistant=persistant;
       return i;
     }
   }
@@ -70,7 +90,7 @@ int findauthnameext(const char *name) {
   int i;
 
   for (i=0;i<MAXAUTHNAMEEXTS;i++) {
-    if (authnameextnames[i]!=NULL && !ircd_strcmp(name,authnameextnames[i]->content)) {
+    if (authnameexts[i].name!=NULL && !ircd_strcmp(name,authnameexts[i].name->content)) {
       return i;
     }
   }
@@ -82,14 +102,16 @@ void releaseauthnameext(int index) {
   int i;
   authname *anp;
 
-  freesstring(authnameextnames[index]);
-  authnameextnames[index]=NULL;
+  freesstring(authnameexts[index].name);
+  authnameexts[index].name=NULL;
 
   for (i=0;i<AUTHNAMEHASHSIZE;i++) {
     for (anp=authnametable[i];anp;anp=anp->next) {
       anp->exts[index]=NULL;
     }
   }
+
+  /* the contents of authnametablebyname should be identical */
 }
 
 authname *findauthname(unsigned long userid) {
@@ -105,11 +127,24 @@ authname *findauthname(unsigned long userid) {
   return NULL;
 }
 
-authname *findorcreateauthname(unsigned long userid) {
+authname *findauthnamebyname(const char *name) {
   authname *anp;
-  unsigned int thehash=authnamehash(userid);
 
-  if(!userid)
+  if(!name)
+    return NULL;
+
+  for (anp=authnametablebyname[authnamehashbyname(name)];anp;anp=(authname *)anp->nextbyname)
+    if (!ircd_strcmp(anp->name, name))
+      return anp;
+
+  return NULL;
+}
+
+authname *findorcreateauthname(unsigned long userid, const char *name) {
+  authname *anp;
+  unsigned int thehash=authnamehash(userid), secondhash = authnamehashbyname(name);
+
+  if(!userid || !name)
     return NULL;
 
   for (anp=authnametable[thehash];anp;anp=(authname *)anp->next)
@@ -118,36 +153,59 @@ authname *findorcreateauthname(unsigned long userid) {
 
   anp=newauthname();
   anp->userid=userid;
+  strlcpy(anp->name, name, sizeof(anp->name));
   anp->usercount=0;
   anp->marker=0;
+  anp->flags=0;
   anp->nicks=NULL;
   memset(anp->exts, 0, MAXAUTHNAMEEXTS * sizeof(void *));
   anp->next=(struct authname *)authnametable[thehash];
   authnametable[thehash]=anp;
 
+  anp->namebucket=secondhash;
+  anp->nextbyname=(struct authname *)authnametablebyname[secondhash];
+  authnametablebyname[secondhash]=anp;
+
   return anp;
 }
 
 void releaseauthname(authname *anp) {
   authname **manp;
-  int i;
+  int i, found;
   if (anp->usercount==0) {
+    anp->nicks = NULL;
+
     for(i=0;i<MAXAUTHNAMEEXTS;i++)
-      if(anp->exts[i]!=NULL)
+      if(authnameexts[i].persistant && anp->exts[i]!=NULL)
         return;
 
+    triggerhook(HOOK_AUTH_LOSTAUTHNAME, (void *)anp);
+    found = 0;
     for(manp=&(authnametable[authnamehash(anp->userid)]);*manp;manp=(authname **)&((*manp)->next)) {
       if ((*manp)==anp) {
         (*manp)=(authname *)anp->next;
+        found = 1;
+        break;
+      }
+    }
+    if(!found) {
+      Error("nick",ERR_ERROR,"Unable to remove authname %lu from hashtable",anp->userid);
+      return;
+    }
+
+    for(manp=&(authnametablebyname[anp->namebucket]);*manp;manp=(authname **)&((*manp)->nextbyname)) {
+      if ((*manp)==anp) {
+        (*manp)=(authname *)anp->nextbyname;
         freeauthname(anp);
         return;
       }
     }
-    Error("nick",ERR_ERROR,"Unable to remove authname %lu from hashtable",anp->userid);
+
+    Error("nick",ERR_STOP,"Unable to remove authname %lu from byname hashtable, TABLES ARE INCONSISTENT -- DYING",anp->userid);
   }
 }
 
-unsigned int nextauthnamemarker() {
+unsigned int nextauthnamemarker(void) {
   int i;
   authname *anp;
   static unsigned int authnamemarker=0;
@@ -163,3 +221,57 @@ unsigned int nextauthnamemarker() {
 
   return authnamemarker;
 }
+
+authname *getauthbyname(const char *name) {
+  authname *a = findauthnamebyname(name);
+  if(!a || !a->nicks)
+    return NULL;
+
+  return a;
+}
+
+static char *genstats(authname **hashtable, authname *(nextfn)(authname *)) {
+  int i,curchain,maxchain=0,total=0,buckets=0;
+  authname *ap;
+  static char buf[100];
+
+  for (i=0;i<AUTHNAMEHASHSIZE;i++) {
+    if (hashtable[i]!=NULL) {
+      buckets++;
+      curchain=0;
+      for (ap=hashtable[i];ap;ap=nextfn(ap)) {
+        total++;
+        curchain++;
+      }
+      if (curchain>maxchain) {
+        maxchain=curchain;
+      }
+    }
+  }
+
+  snprintf(buf, sizeof(buf), "%6d authexts (HASH: %6d/%6d, chain %3d)",total,buckets,AUTHNAMEHASHSIZE,maxchain);
+  return buf;
+}
+
+static authname *nextbynext(authname *in) {
+  return in->next;
+}
+
+static authname *nextbyname(authname *in) {
+  return in->nextbyname;
+}
+
+static void authextstats(int hooknum, void *arg) {
+  long level=(long)arg;
+  char buf[100];
+
+  if (level>5) {
+    /* Full stats */
+    snprintf(buf,sizeof(buf),"Authext : by id:   %s", genstats(authnametable, nextbynext));
+    triggerhook(HOOK_CORE_STATSREPLY,buf);
+
+    snprintf(buf,sizeof(buf),"Authext : by name: %s", genstats(authnametablebyname, nextbyname));
+    triggerhook(HOOK_CORE_STATSREPLY,buf);
+  }
+}
+