Improve the clean-up of outdated IAuth instances on rehash (SF bug #2789656).
[ircu2.10.12-pk.git] / ircd / class.c
index 9c00e848bc145f9c615eac23744c1c0308f1c0d1..216960534d2df75d48bd0e3e55173f4e7a40771a 100644 (file)
@@ -27,6 +27,7 @@
 #include "ircd.h"
 #include "ircd_alloc.h"
 #include "ircd_features.h"
+#include "ircd_log.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
 #include "list.h"
 #include "s_debug.h"
 #include "send.h"
 
-#include <assert.h>
+/* #include <assert.h> -- Now using assert in ircd_log.h */
 
 /** List of all connection classes. */
-static struct ConnectionClass* connClassList = 0;
+static struct ConnectionClass* connClassList;
 /** Number of allocated connection classes. */
 static unsigned int connClassAllocCount;
 
@@ -49,15 +50,21 @@ const struct ConnectionClass* get_class_list(void)
 }
 
 /** Allocate a new connection class.
+ * If #connClassList is not null, insert the new class just after it.
  * @return Newly allocated connection class structure.
  */
 struct ConnectionClass* make_class(void)
 {
   struct ConnectionClass *tmp;
 
-  tmp = (struct ConnectionClass*) MyMalloc(sizeof(struct ConnectionClass));
-  tmp->ref_count = 1;
+  tmp = (struct ConnectionClass*) MyCalloc(1, sizeof(struct ConnectionClass));
   assert(0 != tmp);
+  tmp->ref_count = 1;
+  if (connClassList)
+  {
+    tmp->next = connClassList->next;
+    connClassList->next = tmp;
+  }
   ++connClassAllocCount;
   return tmp;
 }
@@ -70,8 +77,8 @@ void free_class(struct ConnectionClass* p)
   if (p)
   {
     assert(0 == p->valid);
-    if (p->cc_name)
-      MyFree(p->cc_name);
+    MyFree(p->cc_name);
+    MyFree(p->default_umode);
     MyFree(p);
     --connClassAllocCount;
   }
@@ -84,8 +91,10 @@ void free_class(struct ConnectionClass* p)
  */
 void init_class(void)
 {
-  if (!connClassList)
+  if (!connClassList) {
     connClassList = (struct ConnectionClass*) make_class();
+    connClassList->next   = 0;
+  }
 
   /* We had better not try and free this... */
   ConClass(connClassList) = "default";
@@ -94,8 +103,7 @@ void init_class(void)
   MaxLinks(connClassList) = feature_int(FEAT_MAXIMUM_LINKS);
   MaxSendq(connClassList) = feature_int(FEAT_DEFAULTMAXSENDQLENGTH);
   connClassList->valid    = 1;
-  Links(connClassList)    = 0;
-  connClassList->next     = 0;
+  Links(connClassList)    = 1;
 }
 
 /** Mark current connection classes as invalid.
@@ -128,13 +136,12 @@ void class_delete_marked(void)
     /*
      * unlink marked classes, delete unreferenced ones
      */
-    if (cl->valid)
+    if (cl->valid || Links(cl) > 1)
       prev = cl;
     else
     {
       prev->next = cl->next;
-      if (0 == --cl->ref_count)
-        free_class(cl);
+      free_class(cl);
     }
   }
 }
@@ -189,19 +196,6 @@ get_client_class(struct Client *acptr)
   return "(null-class)";
 }
 
-/** Get connection interval for a connection class.
- * @param[in] clptr Connection class to check (or NULL).
- * @return If \a clptr != NULL, its connection frequency; else default
- * connection frequency.
- */
-unsigned int get_con_freq(struct ConnectionClass * clptr)
-{
-  if (clptr)
-    return (ConFreq(clptr));
-  else
-    return feature_int(FEAT_CONNECTFREQUENCY);
-}
-
 /** Make sure we have a connection class named \a name.
  * If one does not exist, create it.  Then set its ping frequency,
  * connection frequency, maximum link count, and max SendQ according
@@ -215,24 +209,16 @@ unsigned int get_con_freq(struct ConnectionClass * clptr)
 void add_class(char *name, unsigned int ping, unsigned int confreq,
                unsigned int maxli, unsigned int sendq)
 {
-  struct ConnectionClass* t;
   struct ConnectionClass* p;
 
-  t = find_class(name);
-  if ((t == connClassList) && (name != NULL))
-  {
-    p = (struct ConnectionClass *) make_class();
-    p->next = t->next;
-    t->next = p;
-  }
-  else
-  {
-    if (ConClass(t) != NULL)
-      MyFree(ConClass(t));
-    p = t;
-  }
   Debug((DEBUG_DEBUG, "Add Class %s: cf: %u pf: %u ml: %u sq: %d",
          name, confreq, ping, maxli, sendq));
+  assert(name != NULL);
+  p = do_find_class(name, 1);
+  if (!p)
+    p = make_class();
+  else
+    MyFree(ConClass(p));
   ConClass(p) = name;
   ConFreq(p) = confreq;
   PingFreq(p) = ping;
@@ -240,23 +226,24 @@ void add_class(char *name, unsigned int ping, unsigned int confreq,
   MaxSendq(p) = (sendq > 0) ?
      sendq : feature_int(FEAT_DEFAULTMAXSENDQLENGTH);
   p->valid = 1;
-  if (p != t)
-    Links(p) = 0;
 }
 
 /** Find a connection class by name.
  * @param[in] name Name of connection class to search for.
+ * @param[in] extras If non-zero, include unreferenced classes.
  * @return Pointer to connection class structure (or NULL if none match).
  */
-struct ConnectionClass* find_class(const char *name)
+struct ConnectionClass* do_find_class(const char *name, int extras)
 {
   struct ConnectionClass *cltmp;
 
   for (cltmp = connClassList; cltmp; cltmp = cltmp->next) {
+    if (!cltmp->valid && !extras)
+      continue;
     if (!ircd_strcmp(ConClass(cltmp), name))
       return cltmp;
   }
-  return connClassList;
+  return NULL;
 }
 
 /** Report connection classes to a client.
@@ -271,9 +258,9 @@ report_classes(struct Client *sptr, const struct StatDesc *sd,
   struct ConnectionClass *cltmp;
 
   for (cltmp = connClassList; cltmp; cltmp = cltmp->next)
-    send_reply(sptr, RPL_STATSYLINE, 'Y', ConClass(cltmp), PingFreq(cltmp),
-              ConFreq(cltmp), MaxLinks(cltmp), MaxSendq(cltmp),
-              Links(cltmp));
+    send_reply(sptr, RPL_STATSYLINE, (cltmp->valid ? 'Y' : 'y'),
+               ConClass(cltmp), PingFreq(cltmp), ConFreq(cltmp),
+               MaxLinks(cltmp), MaxSendq(cltmp), Links(cltmp) - 1);
 }
 
 /** Return maximum SendQ length for a client.