Quellcode durchsuchen

Merge branch 'misc-optimizations'

* misc-optimizations:
  * Remove core_hourly() / not used.
  * Move socket code out of the main loop into socket_run()
  * Use findanysnum() in more places
  * Use findanyidx() in more places
  * Implement likely()/unlikely() blocks from ratbox/linux

Conflicts:
	src/mod/irc.mod/chan.c
	src/mod/server.mod/servmsg.c
Bryan Drewery vor 16 Jahren
Ursprung
Commit
e7c77f81b7
17 geänderte Dateien mit 283 neuen und 263 gelöschten Zeilen
  1. 31 0
      src/common.h
  2. 2 2
      src/crypt.c
  3. 8 8
      src/dcc.c
  4. 8 8
      src/dccutil.c
  5. 1 1
      src/enclink.c
  6. 6 87
      src/main.c
  7. 9 7
      src/mod/irc.mod/chan.c
  8. 23 22
      src/mod/irc.mod/irc.c
  9. 3 3
      src/mod/irc.mod/mode.c
  10. 1 1
      src/mod/server.mod/server.c
  11. 1 1
      src/mod/server.mod/servmsg.c
  12. 169 103
      src/net.c
  13. 2 0
      src/net.h
  14. 2 2
      src/shell.c
  15. 6 7
      src/socket.c
  16. 4 4
      src/sprintf.c
  17. 7 7
      src/users.c

+ 31 - 0
src/common.h

@@ -77,5 +77,36 @@
 #define BIT30   (uint32_t) 0x040000000
 #define BIT31   (uint32_t) 0x080000000
 
+/* Thanks libratbox */
+#ifdef __GNUC__
+
+#ifdef likely
+#undef likely
+#endif
+#ifdef unlikely
+#undef unlikely
+#endif
+
+#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
+# define __builtin_expect(x, expected_value) (x)
+#endif
+
+#define likely(x)       __builtin_expect(!!(x), 1)
+#define unlikely(x)     __builtin_expect(!!(x), 0)
+
+#else /* !__GNUC__ */
+
+#define UNUSED(x) x
+
+#ifdef likely
+#undef likely
+#endif
+#ifdef unlikely
+#undef unlikely
+#endif
+#define likely(x)    (x)
+#define unlikely(x)  (x)
+#endif
+
 
 #endif				/* _COMMON_H */

+ 2 - 2
src/crypt.c

@@ -25,7 +25,7 @@ char *encrypt_string(const char *keydata, char *in)
 
   len = strlen(in);
   bdata = aes_encrypt_ecb_binary(keydata, (unsigned char *) in, &len);
-  if (keydata && *keydata) {
+  if (likely(keydata && *keydata)) {
     res = b64enc(bdata, len);
     OPENSSL_cleanse(bdata, len);
     free(bdata);
@@ -88,7 +88,7 @@ char *decrypt_string(const char *keydata, char *in)
   size_t len = strlen(in);
   char *buf = NULL, *res = NULL;
 
-  if (keydata && *keydata) {
+  if (likely(keydata && *keydata)) {
     buf = b64dec((const unsigned char *) in, &len);
     res = (char *) aes_decrypt_ecb_binary(keydata, (unsigned char *) buf, &len);
     OPENSSL_cleanse(buf, len);

+ 8 - 8
src/dcc.c

@@ -370,7 +370,7 @@ cont_link(int idx, char *buf, int ii)
 {
   /* If we're already connected somewhere, unlink and idle a sec */
   for (int i = 0; i < dcc_total; i++) {
-    if (dcc[i].type && (dcc[i].type == &DCC_BOT) && (!bot_aggressive_to(dcc[i].user))) {
+    if (unlikely(dcc[i].type && (dcc[i].type == &DCC_BOT) && (!bot_aggressive_to(dcc[i].user)))) {
       putlog(LOG_BOTS, "*", "Unlinking %s - restructure", dcc[i].nick);
       botnet_send_unlinked(i, dcc[i].nick, "Restructure");
       killsock(dcc[i].sock);
@@ -1222,16 +1222,16 @@ dcc_chat(int idx, char *buf, int len)
     else
       *d = 0;
 
-    if (u_pass_match(dcc[idx].user, buf)) {     /* user said their password :) */
+    if (unlikely(u_pass_match(dcc[idx].user, buf))) {     /* user said their password :) */
       dprintf(idx, "Sure you want that going to the partyline? ;) (msg to partyline halted.)\n");
-    } else if (!strncmp(buf, STR("+Auth "), 6)) {    /* ignore extra +Auth lines */
+    } else if (unlikely(!strncmp(buf, STR("+Auth "), 6))) {    /* ignore extra +Auth lines */
     } else if ((!strncmp(buf, settings.dcc_prefix, strlen(settings.dcc_prefix))) || (dcc[idx].u.chat->channel < 0)) {
       if (!strncmp(buf, settings.dcc_prefix, strlen(settings.dcc_prefix)) && (dcc[idx].u.chat->channel >= 0))        /* strip '.' out */
         buf++;
       v = newsplit(&buf);
       rmspace(buf);
       check_bind_dcc(v, idx, buf);
-    } else if (buf[0] == ',') {
+    } else if (unlikely(buf[0] == ',')) {
       int me = 0;
 
       if ((buf[1] == 'm') && (buf[2] == 'e') && buf[3] == ' ')
@@ -1257,7 +1257,7 @@ dcc_chat(int idx, char *buf, int len)
         }
        }
       }
-    } else if (buf[0] == '\'') {
+    } else if (unlikely(buf[0] == '\'')) {
       int me = 0;
 
       if ((buf[1] == 'm') && (buf[2] == 'e') && ((buf[3] == ' ') || (buf[3] == '\'') || (buf[3] == ',')))
@@ -1377,7 +1377,7 @@ dcc_telnet(int idx, char *buf, int ii)
   int i;
   char x[1024] = "";
 
-  if (dcc_total + 1 > max_dcc) {
+  if (unlikely(dcc_total + 1 > max_dcc)) {
     int j;
 
     j = answer(dcc[idx].sock, s, &ip, &port, 0);
@@ -1392,7 +1392,7 @@ dcc_telnet(int idx, char *buf, int ii)
 
   while ((sock == -1) && (errno == EAGAIN))
     sock = answer(dcc[idx].sock, s, &ip, &port, 0);
-  if (sock < 0) {
+  if (unlikely(sock < 0)) {
     putlog(LOG_MISC, "*", "Failed TELNET incoming (%s)", strerror(errno));
 //    killsock(dcc[idx].sock);
     return;
@@ -1433,7 +1433,7 @@ dcc_telnet(int idx, char *buf, int ii)
   // Are they ignored by IP?
   simple_snprintf(x, sizeof(x), "-telnet!telnet@%s", iptostr(htonl(ip)));
 
-  if (match_ignore(x) || detect_telnet_flood(x)) {
+  if (unlikely(match_ignore(x) || detect_telnet_flood(x))) {
     putlog(LOG_DEBUG, "*", "Ignored telnet connection from: %s", x);
     killsock(sock);
     return;

+ 8 - 8
src/dccutil.c

@@ -211,7 +211,7 @@ colorbuf(char *buf, size_t len, int idx, size_t bufsiz)
  */
 void dumplots(int idx, const char *prefix, const char *data)
 {
-  if (!*data) {
+  if (unlikely(!*data)) {
     dprintf(idx, "%s\n", prefix);
     return;
   }
@@ -268,7 +268,7 @@ dprintf(int idx, const char *format, ...)
   int vlen = egg_vsnprintf(buf, sizeof(buf), format, va);
   va_end(va);
 
-  if (vlen < 0) {
+  if (unlikely(vlen < 0)) {
     // Error parsing format..
     return;
   }
@@ -282,10 +282,10 @@ dprintf(int idx, const char *format, ...)
 
 /* this is for color on dcc :P */
 
-  if (idx < 0) {
+  if (unlikely(idx < 0)) {
     tputs(-idx, buf, len);
   } else if (idx > 0x7FF0) {
-    if (idx == DP_STDOUT || idx == DP_STDOUT) {
+    if (unlikely(idx == DP_STDOUT || idx == DP_STDOUT)) {
       len = colorbuf(buf, len, -1, sizeof(buf));
     }
 
@@ -311,7 +311,7 @@ dprintf(int idx, const char *format, ...)
           break;
         len -= remove_crlf_r(buf);
 
-        if ((idx == DP_DUMP || (floodless && idx != DP_CACHE))) {
+        if (unlikely((idx == DP_DUMP || (floodless && idx != DP_CACHE)))) {
          if (serv != -1) {
            if (debug_output)
              putlog(LOG_SRVOUT, "@", "[d->] %s", buf);
@@ -330,9 +330,9 @@ dprintf(int idx, const char *format, ...)
       buf[len - 1] = '\n';
       buf[len] = 0;
     }
-    if (dcc[idx].simul >= 0 && !dcc[idx].irc) {
+    if (unlikely(dcc[idx].simul >= 0 && !dcc[idx].irc)) {
       bounce_simul(idx, buf);
-    } else if (dcc[idx].irc) {
+    } else if (unlikely(dcc[idx].irc)) {
 //      size_t size = strlen(dcc[idx].simulbot) + strlen(buf) + 20;
 //      char *ircbuf = (char *) my_calloc(1, size);
 
@@ -709,7 +709,7 @@ new_dcc(struct dcc_table *type, int xtra_size)
       break;
 
   /* we managed to get to the end of the list! */
-  if (i == dcc_total) {
+  if (unlikely(i == dcc_total)) {
     i = dcc_total;
     dcc_total++;
   }

+ 1 - 1
src/enclink.c

@@ -35,7 +35,7 @@ static void ghost_link_case(int idx, direction_t direction)
 {
   int snum = findanysnum(dcc[idx].sock);
 
-  if (snum >= 0) {
+  if (likely(snum >= 0)) {
     char initkey[33] = "", *tmp2 = NULL;
     char *keyp = NULL, *nick1 = NULL, *nick2 = NULL;
     port_t port = 0;

+ 6 - 87
src/main.c

@@ -596,10 +596,6 @@ static void core_minutely()
 /*     flushlogs(); */
 }
 
-static void core_hourly()
-{
-}
-
 static void core_halfhourly()
 {
   if (conf.bot->hub) {
@@ -882,7 +878,6 @@ int main(int argc, char **argv)
   timer_create_secs(60, STR("core_minutely"), (Function) core_minutely);
   timer_create_secs(60, STR("check_botnet_pings"), (Function) check_botnet_pings);
   timer_create_secs(60, STR("check_expired_ignores"), (Function) check_expired_ignores);
-  timer_create_secs(3600, STR("core_hourly"), (Function) core_hourly);
   timer_create_secs(1800, STR("core_halfhourly"), (Function) core_halfhourly);
 
   if (socksfile)
@@ -890,9 +885,6 @@ int main(int argc, char **argv)
 
   debug0(STR("main: entering loop"));
 
-  int socket_cleanup = 0, xx, i = 0, idx = 0;
-  char buf[SGRAB + 10] = "";
-
   while (1) {
 
     /* Lets move some of this here, reducing the numer of actual
@@ -903,87 +895,14 @@ int main(int argc, char **argv)
     random();			/* jumble things up o_O */
     timer_run();
 
-    /* Only do this every so often. */
-    if (!socket_cleanup) {
-      socket_cleanup = 5;
-
-      /* Check for server or dcc activity. */
-      dequeue_sockets();		
-    } else
-      socket_cleanup--;
-
-    xx = sockgets(buf, &i);
-
-    if (xx >= 0) {		/* Non-error */
-      for (idx = 0; idx < dcc_total; idx++) {
-	if (dcc[idx].type && dcc[idx].sock == xx) {
-	  if (dcc[idx].type && dcc[idx].type->activity) {
-	    /* Traffic stats */
-	    if (dcc[idx].type->name) {
-	      if (!strncmp(dcc[idx].type->name, "BOT", 3))
-		traffic.in_today.bn += strlen(buf) + 1;
-	      else if (!strcmp(dcc[idx].type->name, "SERVER"))
-		traffic.in_today.irc += strlen(buf) + 1;
-	      else if (!strncmp(dcc[idx].type->name, "CHAT", 4))
-		traffic.in_today.dcc += strlen(buf) + 1;
-	      else if (!strncmp(dcc[idx].type->name, "FILES", 5))
-		traffic.in_today.dcc += strlen(buf) + 1;
-	      else if (!strcmp(dcc[idx].type->name, "SEND"))
-		traffic.in_today.trans += strlen(buf) + 1;
-	      else if (!strncmp(dcc[idx].type->name, "GET", 3))
-		traffic.in_today.trans += strlen(buf) + 1;
-	      else
-		traffic.in_today.unknown += strlen(buf) + 1;
-	    }
-	    dcc[idx].type->activity(idx, buf, (size_t) i);
-	  } else
-	    putlog(LOG_MISC, "*",
-		   STR("!!! untrapped dcc activity: type %s, sock %d"),
-		   dcc[idx].type->name, dcc[idx].sock);
-	  break;
-	}
-      }
-    } else if (xx == -1) {	/* EOF from someone */
-      if (i == STDOUT && !backgrd)
-	fatal(STR("END OF FILE ON TERMINAL"), 0);
-      for (idx = 0; idx < dcc_total; idx++) {
-	if (dcc[idx].type && dcc[idx].sock == i) {
-          sdprintf(STR("EOF on '%s' idx: %d"), dcc[idx].type ? dcc[idx].type->name : "unknown", idx);
-	  if (dcc[idx].type->eof)
-	    dcc[idx].type->eof(idx);
-	  else {
-	    putlog(LOG_MISC, "*",
-		   STR("*** ATTENTION: DEAD SOCKET (%d) OF TYPE %s UNTRAPPED"),
-		   i, dcc[idx].type ? dcc[idx].type->name : "*UNKNOWN*");
-	    killsock(i);
-	    lostdcc(idx);
-	  }
-	  idx = dcc_total + 1;
-	}
-      }
-      if (idx == dcc_total) {
-	putlog(LOG_MISC, "*", STR("(@) EOF socket %d, not a dcc socket, not anything."), i);
-	close(i);
-	killsock(i);
-      }
-    } else if (xx == -2 && errno != EINTR) {	/* select() error */
-      putlog(LOG_MISC, "*", STR("* Socket error #%d; recovering."), errno);
-      for (i = 0; i < dcc_total; i++) {
-	if (dcc[i].type && dcc[i].sock != -1 && (fcntl(dcc[i].sock, F_GETFD, 0) == -1) && (errno = EBADF)) {
-	  putlog(LOG_MISC, "*",
-		 STR("DCC socket %d (type %s, name '%s') expired -- pfft"),
-		 dcc[i].sock, dcc[i].type->name, dcc[i].nick);
-	  killsock(dcc[i].sock);
-	  lostdcc(i);
-	  i--;
-	}
-      }
-    } else if (xx == -3) {
-      if (!conf.bot->hub)
+    if (socket_run() == 1) {
+       /* Idle calls */
+      if (!conf.bot->hub) {
         flush_modes();
-      socket_cleanup = 0;	/* If we've been idle, cleanup & flush */
+      }
     }
-    if (do_restart) {
+
+    if (unlikely(do_restart)) {
       if (do_restart == 1)
         restart(-1);
       else { //rehash()

+ 9 - 7
src/mod/irc.mod/chan.c

@@ -256,7 +256,7 @@ static memberlist *newmember(struct chanset_t *chan, char *nick)
   n->hops = -1;
   if (!lx) {
     // Free the pseudo-member created in init_channel()
-    if (!chan->channel.member->nick[0]) {
+    if (unlikely(!chan->channel.member->nick[0])) {
       free(chan->channel.member);
       chan->channel.member = NULL;
     }
@@ -1435,7 +1435,7 @@ void recheck_channel(struct chanset_t *chan, int dobans)
 
 
   /* don't do much if i'm lonely bot. Maybe they won't notice me? :P */
-  if (botops == 1 && !botnonops) {
+  if (unlikely(botops == 1 && !botnonops)) {
     if (chan_bitch(chan) || channel_closed(chan))
       putlog(LOG_MISC, "*", "Opped in %s, not checking +closed/+bitch until more bots arrive.", chan->dname);
   } else {
@@ -1908,7 +1908,7 @@ static int got352or4(struct chanset_t *chan, char *user, char *host, char *nick,
   me = match_my_nick(nick);
 
 
-  if (me) {			/* Is it me? */
+  if (unlikely(me)) {			/* Is it me? */
 //    strcpy(botuserhost, m->userhost);		/* Yes, save my own userhost */
     m->joined = now;				/* set this to keep the whining masses happy */
   }
@@ -1919,10 +1919,12 @@ static int got352or4(struct chanset_t *chan, char *user, char *host, char *nick,
   }
 
   //This bot is set +r, so resolve.
-  if (!m->userip[0] && doresolv(chan))
-    resolve_to_member(chan, nick, host);
-  else if (!me && !m->user && m->userip[0] && doresolv(chan) && channel_rbl(chan))
-    resolve_to_rbl(chan, m->userip);
+  if (unlikely(doresolv(chan))) {
+    if (!m->userip[0])
+      resolve_to_member(chan, nick, host);
+    else if (!me && !m->user && m->userip[0] && channel_rbl(chan))
+      resolve_to_rbl(chan, m->userip);
+  }
 
 
   get_user_flagrec(m->user, &fr, chan->dname, chan);

+ 23 - 22
src/mod/irc.mod/irc.c

@@ -540,20 +540,20 @@ sdprintf("hash: %s", hash);
 void
 getin_request(char *botnick, char *code, char *par)
 {
-  if (!server_online)
+  if (unlikely(!server_online))
     return;
 
-  if (!par[0] || !par)
+  if (unlikely(!par[0] || !par))
     return;
 
   char *what = newsplit(&par), *chname = newsplit(&par);
 
-  if (!chname[0] || !chname)
+  if (unlikely(!chname[0] || !chname))
     return;
 
   char *tmp = newsplit(&par);		/* nick */
 
-  if (!tmp[0])
+  if (unlikely(!tmp[0]))
     return;
 
   char nick[NICKLEN] = "";
@@ -562,13 +562,13 @@ getin_request(char *botnick, char *code, char *par)
   const char *type = what[0] == 'o' ? "op" : "in", *desc = what[0] == 'o' ? "on" : "for";
 
   struct chanset_t *chan = findchan_by_dname(chname);
-  if (!chan) {
+  if (unlikely(!chan)) {
     putlog(LOG_GETIN, "*", "%sreq from %s/%s %s %s which is not a valid channel!", type, botnick, nick, desc, chname);
     return;
   }
 
   struct userrec *u = get_user_by_handle(userlist, botnick);
-  if (!u) {
+  if (unlikely(!u)) {
     putlog(LOG_GETIN, "*", "%sreq from %s/%s %s %s - No user called %s in userlist", type, botnick, nick, desc, 
                            chan->dname, botnick);
     return;
@@ -596,7 +596,7 @@ getin_request(char *botnick, char *code, char *par)
   }
 
   if (what[0] == 'K') {
-    if (!shouldjoin(chan)) {
+    if (unlikely(!shouldjoin(chan))) {
       putlog(LOG_GETIN, "*", "Got key for %s from %s - I shouldn't be on that chan?!?", chan->dname, botnick);
     } else {
       if (!(channel_pending(chan) || channel_active(chan))) {
@@ -657,7 +657,7 @@ getin_request(char *botnick, char *code, char *par)
       return;
     }
 
-    if (glob_kick(fr) || chan_kick(fr)) {
+    if (unlikely(glob_kick(fr) || chan_kick(fr))) {
       putlog(LOG_GETIN, "*", "opreq from %s/%s on %s - %s is currently being autokicked.", botnick, nick, chan->dname, botnick);
       return;
     }
@@ -679,7 +679,7 @@ getin_request(char *botnick, char *code, char *par)
 
     get_user_flagrec(u, &fr, chan->dname, chan);
 
-    if (!chk_op(fr, chan) || chan_kick(fr) || glob_kick(fr)) {
+    if (unlikely(!chk_op(fr, chan) || chan_kick(fr) || glob_kick(fr))) {
       putlog(LOG_GETIN, "*", "inreq from %s/%s for %s - %s doesn't have acces for chan.", botnick, nick, chan->dname, botnick);
       return;
     }
@@ -723,9 +723,9 @@ getin_request(char *botnick, char *code, char *par)
     /* Check internal global bans */
     mr = &global_bans;
     while (*mr) {
-      if (wild_match((*mr)->mask, uhost) || 
-          wild_match((*mr)->mask, uip) || 
-          match_cidr((*mr)->mask, uip)) {
+      if (unlikely(wild_match((*mr)->mask, uhost) ||
+          wild_match((*mr)->mask, uip) ||
+          match_cidr((*mr)->mask, uip))) {
 
         if (!noshare)
           shareout("-m b %s\n", (*mr)->mask);
@@ -748,9 +748,9 @@ getin_request(char *botnick, char *code, char *par)
     /* Check internal channel bans */
     mr = &chan->bans;
     while (*mr) {
-      if (wild_match((*mr)->mask, uhost) || 
-          wild_match((*mr)->mask, uip) || 
-          match_cidr((*mr)->mask, uip)) {
+      if (unlikely(wild_match((*mr)->mask, uhost) ||
+          wild_match((*mr)->mask, uip) ||
+          match_cidr((*mr)->mask, uip))) {
         if (!noshare)
           shareout("-mc b %s %s\n", chan->dname, (*mr)->mask);
         putlog(LOG_GETIN, "*", "inreq from %s/%s for %s - Removed permanent channel ban %s", botnick, nick,
@@ -770,9 +770,9 @@ getin_request(char *botnick, char *code, char *par)
 
     /* Check bans active in channel */
     for (struct maskstruct *b = chan->channel.ban; b->mask[0]; b = b->next) {
-      if (wild_match(b->mask, uhost) || 
-          wild_match(b->mask, uip) || 
-          match_cidr(b->mask, uip)) {
+      if (unlikely(wild_match(b->mask, uhost) ||
+          wild_match(b->mask, uip) ||
+          match_cidr(b->mask, uip))) {
         add_mode(chan, '-', 'b', b->mask);
         putlog(LOG_GETIN, "*", "inreq from %s/%s for %s - Removed active ban %s", botnick, nick, chan->dname,
                b->mask);
@@ -894,6 +894,7 @@ request_op(struct chanset_t *chan)
       --cnt;
       break;
     }
+    //FIXME: Also prefer our localhub or child bots
   }
 
   /* Pick random op and ask for ops */
@@ -1008,7 +1009,7 @@ want_to_revenge(struct chanset_t *chan, struct userrec *u,
       get_user_flagrec(u2, &fr2, chan->dname, chan);
       /* Protecting friends? */
       /* Protecting ops? */
-      if ((channel_protectops(chan) && chk_op(fr2, chan))
+      if ((channel_protectops(chan) && chk_op(fr2, chan)))
         return 1;
     }
   }
@@ -1203,7 +1204,7 @@ killmember(struct chanset_t *chan, char *nick)
   for (x = chan->channel.member; x && x->nick[0]; old = x, x = x->next)
     if (!rfc_casecmp(x->nick, nick))
       break;
-  if (!x || !x->nick[0]) {
+  if (unlikely(!x || !x->nick[0])) {
     if (!channel_pending(chan))
       putlog(LOG_MISC, "*", "(!) killmember(%s, %s) -> nonexistent", chan->dname, nick);
     return 0;
@@ -1218,13 +1219,13 @@ killmember(struct chanset_t *chan, char *nick)
   /* The following two errors should NEVER happen. We will try to correct
    * them though, to keep the bot from crashing.
    */
-  if (chan->channel.members < 0) {
+  if (unlikely(chan->channel.members < 0)) {
     chan->channel.members = 0;
     for (x = chan->channel.member; x && x->nick[0]; x = x->next)
       chan->channel.members++;
     putlog(LOG_MISC, "*", "(!) actually I know of %d members.", chan->channel.members);
   }
-  if (!chan->channel.member) {
+  if (unlikely(!chan->channel.member)) {
     chan->channel.member = (memberlist *) my_calloc(1, sizeof(memberlist));
     chan->channel.member->nick[0] = 0;
     chan->channel.member->next = NULL;

+ 3 - 3
src/mod/irc.mod/mode.c

@@ -957,12 +957,12 @@ gotmode(char *from, char *msg)
   if (msg[0] && (strchr(CHANMETA, msg[0]) != NULL)) {
     char *ch = newsplit(&msg);
 
-    if (match_my_nick(ch))
+    if (unlikely(match_my_nick(ch)))
       return 0;
 
     struct chanset_t *chan = findchan(ch);
 
-    if (!chan) {
+    if (unlikely(!chan)) {
       putlog(LOG_MISC, "*", "Oops.   Someone made me join %s... leaving...", ch);
       dprintf(DP_SERVER, "PART %s\n", ch);
       return 0;
@@ -1148,7 +1148,7 @@ gotmode(char *from, char *msg)
               }
             }
 
-            if (failure) { /* One of the hashes failed! */
+            if (unlikely(failure)) { /* One of the hashes failed! */
               /* Did *I* do this heinous act? */
               if (match_my_nick(m->nick)) {
                 detected(DETECT_HIJACK, "Possible Hijack: bad cookie");

+ 1 - 1
src/mod/server.mod/server.c

@@ -589,7 +589,7 @@ void queue_server(int which, char *buf, int len)
     return;
   }
 
-  if (h->tot < maxqmsg) {
+  if (likely(h->tot < maxqmsg)) {
     /* Don't queue msg if it's already queued?  */
     if (!doublemsg) {
       struct msgq *tq = NULL, *tqq = NULL;

+ 1 - 1
src/mod/server.mod/servmsg.c

@@ -1318,7 +1318,7 @@ static void server_activity(int idx, char *msg, int len)
 {
   char *from = NULL, *code = NULL;
 
-  if (trying_server) {
+  if (unlikely(trying_server)) {
     strlcpy(dcc[idx].nick, "(server)", sizeof(dcc[idx].nick));
     putlog(LOG_SERV, "*", "Connected to %s", dcc[idx].host);
 

+ 169 - 103
src/net.c

@@ -260,16 +260,15 @@ void cache_my_ip()
  */
 int sockoptions(int sock, int operation, int sock_options)
 {
-  for (int i = 0; i < MAXSOCKS; i++) {
-    if ((socklist[i].sock == sock) && !(socklist[i].flags & SOCK_UNUSED)) {
-      if (operation == EGG_OPTION_SET)
-	      socklist[i].flags |= sock_options;
-      else if (operation == EGG_OPTION_UNSET)
-	      socklist[i].flags &= ~sock_options;
-      else
-	      return -2;
-      return 0;
-    }
+  int i = -1;
+  if ((i = findanysnum(sock)) != -1) {
+    if (operation == EGG_OPTION_SET)
+      socklist[i].flags |= sock_options;
+    else if (operation == EGG_OPTION_UNSET)
+      socklist[i].flags &= ~sock_options;
+    else
+      return -2;
+    return 0;
   }
   return -1;
 }
@@ -406,25 +405,24 @@ void real_killsock(register int sock, const char *file, int line)
     return;
   }
 
-  for (register int i = 0; i < MAXSOCKS; i++) {
-    if ((socklist[i].sock == sock) && !(socklist[i].flags & SOCK_UNUSED)) {
-      close(socklist[i].sock);
-      if (socklist[i].inbuf != NULL) {
-	delete socklist[i].inbuf;
-	socklist[i].inbuf = NULL;
-      }
-      if (socklist[i].outbuf != NULL) {
-	delete socklist[i].outbuf;
-	socklist[i].outbuf = NULL;
-      }
-      if (socklist[i].host)
-        free(socklist[i].host);
-      bzero(&socklist[i], sizeof(socklist[i]));
-      socklist[i].flags = SOCK_UNUSED;
-      socks_total--;
-      sdprintf("killsock(%d, %s, %d) (socklist: %d)", sock, file, line, i);
-      return;
+  int i = -1;
+  if ((i = findanysnum(sock)) != -1) {
+    close(socklist[i].sock);
+    if (socklist[i].inbuf != NULL) {
+      delete socklist[i].inbuf;
+      socklist[i].inbuf = NULL;
+    }
+    if (socklist[i].outbuf != NULL) {
+      delete socklist[i].outbuf;
+      socklist[i].outbuf = NULL;
     }
+    if (socklist[i].host)
+      free(socklist[i].host);
+    bzero(&socklist[i], sizeof(socklist[i]));
+    socklist[i].flags = SOCK_UNUSED;
+    socks_total--;
+    sdprintf("killsock(%d, %s, %d) (socklist: %d)", sock, file, line, i);
+    return;
   }
   putlog(LOG_MISC, "*", "Attempt to kill un-allocated socket %d %s:%d !!", sock, file, line);
 }
@@ -451,9 +449,9 @@ static int proxy_connect(int sock, const char *ip, port_t port, int proxy_type)
     } else {	/* if not resolved, resolve it with blocking calls.. (shouldn't happen ever) */
       return -1;
     }
-    for (int i = 0; i < MAXSOCKS; i++)
-      if (!(socklist[i].flags & SOCK_UNUSED) && socklist[i].sock == sock)
-        socklist[i].flags |= SOCK_PROXYWAIT;
+    int i = -1;
+    if ((i = findanysnum(sock)) != -1)
+      socklist[i].flags |= SOCK_PROXYWAIT;
 #ifdef USE_IPV6
     if (af_ty == AF_INET6)
       simple_snprintf(s, sizeof s,
@@ -574,13 +572,11 @@ int open_telnet_raw(int sock, const char *ipIn, port_t sport, bool proxy_on, int
     socklen = SUN_LEN(&so.sock_un);
   }
 
-  for (int i = 0; i < MAXSOCKS; i++) {
-    if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == sock)) {
-      socklist[i].flags = (socklist[i].flags & ~SOCK_VIRTUAL) | SOCK_CONNECT;
-      socklist[i].host = strdup(ipIn);
-      socklist[i].port = port;
-      break;
-    }
+  int i = -1;
+  if ((i = findanysnum(sock)) != -1) {
+    socklist[i].flags = (socklist[i].flags & ~SOCK_VIRTUAL) | SOCK_CONNECT;
+    socklist[i].host = strdup(ipIn);
+    socklist[i].port = port;
   }
 
   if (identd && sport) //Only open identd if not a unix domain socket
@@ -941,7 +937,7 @@ static int sockread(char *s, int *len)
   int grab = SGRAB + 1;
   egg_timeval_t howlong;
 
-  if (timer_get_shortest(&howlong)) {
+  if (unlikely(timer_get_shortest(&howlong))) {
     /* No timer, default to 1 second. */
     t.tv_sec = 1;
     t.tv_usec = 0;
@@ -955,7 +951,7 @@ static int sockread(char *s, int *len)
   
   for (i = 0; i < MAXSOCKS; i++) {
     if (!(socklist[i].flags & (SOCK_UNUSED | SOCK_VIRTUAL))) {
-      if ((socklist[i].sock == STDOUT) && !backgrd)
+      if (unlikely((socklist[i].sock == STDOUT) && !backgrd))
 	fdtmp = STDIN;
       else
 	fdtmp = socklist[i].sock;
@@ -994,7 +990,7 @@ static int sockread(char *s, int *len)
 	  return i;
 	}
 	errno = 0;
-	if ((socklist[i].sock == STDOUT) && !backgrd)
+	if (unlikely((socklist[i].sock == STDOUT) && !backgrd))
 	  x = read(STDIN, s, grab);
 	else
           x = read(socklist[i].sock, s, grab);
@@ -1245,65 +1241,61 @@ void tputs(register int z, const char *s, size_t len)
 
   register int x, idx;
 
-  for (register int i = 0; i < MAXSOCKS; i++) {
-    if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == z)) {
-      for (idx = 0; idx < dcc_total; idx++) {
-        if (dcc[idx].type && (dcc[idx].sock == z) && dcc[idx].type->name) {
-          if (!strncmp(dcc[idx].type->name, "BOT", 3))
-                traffic.out_today.bn += len;
-          else if (!strcmp(dcc[idx].type->name, "SERVER"))
-                traffic.out_today.irc += len;
-          else if (!strncmp(dcc[idx].type->name, "CHAT", 4))
-                traffic.out_today.dcc += len;
-          else if (!strncmp(dcc[idx].type->name, "FILES", 5))
-                traffic.out_today.filesys += len;
-          else if (!strcmp(dcc[idx].type->name, "SEND"))
-                traffic.out_today.trans += len;
-          else if (!strncmp(dcc[idx].type->name, "GET", 3))
-                traffic.out_today.trans += len;
-          else
-                traffic.out_today.unknown += len;
-          break;
-        }
-      }
+  int i = -1;
+  if ((i = findanysnum(z)) != -1) {
+    if ((idx = findanyidx(z)) != -1 && dcc[idx].type->name) {
+      if (!strncmp(dcc[idx].type->name, "BOT", 3))
+        traffic.out_today.bn += len;
+      else if (!strcmp(dcc[idx].type->name, "SERVER"))
+        traffic.out_today.irc += len;
+      else if (!strncmp(dcc[idx].type->name, "CHAT", 4))
+        traffic.out_today.dcc += len;
+      else if (!strncmp(dcc[idx].type->name, "FILES", 5))
+        traffic.out_today.filesys += len;
+      else if (!strcmp(dcc[idx].type->name, "SEND"))
+        traffic.out_today.trans += len;
+      else if (!strncmp(dcc[idx].type->name, "GET", 3))
+        traffic.out_today.trans += len;
+      else
+        traffic.out_today.unknown += len;
+    }
 
-      if (len && socklist[i].encstatus)
-        s = link_write(i, s, &len);
+    if (len && socklist[i].encstatus)
+      s = link_write(i, s, &len);
 
 #ifdef HAVE_ZLIB_H
-/*
-      if (socklist[i].gz) { 		
-        FILE *fp;
-        fp = gzdopen(z, "wb0");
-        x = gzwrite(fp, s, len);
-        
-      } else
-*/
+    /*
+       if (socklist[i].gz) {
+       FILE *fp;
+       fp = gzdopen(z, "wb0");
+       x = gzwrite(fp, s, len);
+
+       } else
+       */
 #endif /* HAVE_ZLIB_H */
 
-      if (socklist[i].outbuf != NULL) {
-	/* Already queueing: just add it */
-        *(socklist[i].outbuf) += bd::String(s, len);
-	return;
-      }
-      /* Try. */
-        x = write(z, s, len);
-      if (x == -1)
-	x = 0;
-      if ((size_t) x < len) {
-	/* Socket is full, queue it */
-	socklist[i].outbuf = new bd::String(&s[x], len - x);
-      }
-//      if (socklist[i].encstatus && s)
-//        free(s);
+    if (socklist[i].outbuf != NULL) {
+      /* Already queueing: just add it */
+      *(socklist[i].outbuf) += bd::String(s, len);
       return;
     }
+    /* Try. */
+    x = write(z, s, len);
+    if (x == -1)
+      x = 0;
+    if ((size_t) x < len) {
+      /* Socket is full, queue it */
+      socklist[i].outbuf = new bd::String(&s[x], len - x);
+    }
+    //      if (socklist[i].encstatus && s)
+    //        free(s);
+    return;
   }
 
   /* Make sure we don't cause a crash by looping here */
   static int inhere = 0;
 
-  if (!inhere) {
+  if (unlikely(!inhere)) {
     inhere = 1;
 
     putlog(LOG_MISC, "*", "!!! writing to nonexistent socket: %d", z);
@@ -1333,14 +1325,12 @@ int findanysnum(register int sock)
   return -1;
 }
 
-static int findanyidx(register int sock)
+int findanyidx(int sock)
 {
-  register int j;
-
   if (sock != -1)
-    for (j = 0; j < dcc_total; j++)
-      if (dcc[j].type && dcc[j].sock == sock)
-        return j;
+    for (int idx = 0; idx < dcc_total; ++idx)
+      if (dcc[idx].type && dcc[idx].sock == sock)
+        return idx;
 
   return -1;
 }
@@ -1459,22 +1449,98 @@ void tell_netdebug(int idx)
 bool sock_has_data(int type, int sock)
 {
   bool ret = 0;
-  int i;
+  int i = -1;
 
-  for (i = 0; i < MAXSOCKS; i++)
-    if (!(socklist[i].flags & SOCK_UNUSED) && socklist[i].sock == sock)
-      break;
-  if (i < MAXSOCKS) {
+  if ((i = findanysnum(sock)) != -1) {
     switch (type) {
       case SOCK_DATA_OUTGOING:
-	ret = (socklist[i].outbuf != NULL);
-	break;
+        ret = (socklist[i].outbuf != NULL);
+        break;
       case SOCK_DATA_INCOMING:
-	ret = (socklist[i].inbuf != NULL);
-	break;
+        ret = (socklist[i].inbuf != NULL);
+        break;
     }
   } else
     debug1("sock_has_data: could not find socket #%d, returning false.", sock);
   return ret;
 }
 
+bool socket_run() {
+  static int socket_cleanup = 0;
+  char buf[SGRAB + 10] = "";
+  int i = 0, idx = 0;
+
+  /* Only do this every so often. */
+  if (!socket_cleanup) {
+    socket_cleanup = 5;
+
+    /* Check for server or dcc activity. */
+    dequeue_sockets();
+  } else
+    --socket_cleanup;
+
+  int xx = sockgets(buf, &i);
+
+  if (xx >= 0) {		/* Non-error */
+    if ((idx = findanyidx(xx)) != -1) {
+      if (likely(dcc[idx].type->activity)) {
+        /* Traffic stats */
+        if (dcc[idx].type->name) {
+          if (!strncmp(dcc[idx].type->name, "BOT", 3))
+            traffic.in_today.bn += strlen(buf) + 1;
+          else if (!strcmp(dcc[idx].type->name, "SERVER"))
+            traffic.in_today.irc += strlen(buf) + 1;
+          else if (!strncmp(dcc[idx].type->name, "CHAT", 4))
+            traffic.in_today.dcc += strlen(buf) + 1;
+          else if (!strncmp(dcc[idx].type->name, "FILES", 5))
+            traffic.in_today.dcc += strlen(buf) + 1;
+          else if (!strcmp(dcc[idx].type->name, "SEND"))
+            traffic.in_today.trans += strlen(buf) + 1;
+          else if (!strncmp(dcc[idx].type->name, "GET", 3))
+            traffic.in_today.trans += strlen(buf) + 1;
+          else
+            traffic.in_today.unknown += strlen(buf) + 1;
+        }
+        dcc[idx].type->activity(idx, buf, (size_t) i);
+      } else
+        putlog(LOG_MISC, "*",
+            STR("!!! untrapped dcc activity: type %s, sock %d"),
+            dcc[idx].type->name, dcc[idx].sock);
+    }
+  } else if (unlikely(xx == -1)) {	/* EOF from someone */
+    if (unlikely(i == STDOUT && !backgrd))
+      fatal(STR("END OF FILE ON TERMINAL"), 0);
+    if ((idx = findanyidx(i)) != -1) {
+      sdprintf(STR("EOF on '%s' idx: %d"), dcc[idx].type ? dcc[idx].type->name : "unknown", idx);
+      if (likely(dcc[idx].type->eof))
+        dcc[idx].type->eof(idx);
+      else {
+        putlog(LOG_MISC, "*",
+            STR("*** ATTENTION: DEAD SOCKET (%d) OF TYPE %s UNTRAPPED"),
+            i, dcc[idx].type ? dcc[idx].type->name : "*UNKNOWN*");
+        killsock(i);
+        lostdcc(idx);
+      }
+    } else if (unlikely(idx == -1)) {
+      putlog(LOG_MISC, "*", STR("(@) EOF socket %d, not a dcc socket, not anything."), i);
+      close(i);
+      killsock(i);
+    }
+  } else if (unlikely(xx == -2 && errno != EINTR)) {	/* select() error */
+    putlog(LOG_MISC, "*", STR("* Socket error #%d; recovering."), errno);
+    for (i = 0; i < dcc_total; i++) {
+      if (dcc[i].type && dcc[i].sock != -1 && (fcntl(dcc[i].sock, F_GETFD, 0) == -1) && (errno = EBADF)) {
+        putlog(LOG_MISC, "*",
+            STR("DCC socket %d (type %s, name '%s') expired -- pfft"),
+            dcc[i].sock, dcc[i].type->name, dcc[i].nick);
+        killsock(dcc[i].sock);
+        lostdcc(i);
+        i--;
+      }
+    }
+  } else if (xx == -3) {                      /* Idle */
+    socket_cleanup = 0;	/* If we've been idle, cleanup & flush */
+    return 1;
+  }
+  return 0;
+}

+ 2 - 0
src/net.h

@@ -116,6 +116,7 @@ int sockprotocol(int);
 void real_killsock(int, const char *, int);
 int answer(int, char *, in_addr_t *, port_t *, int);
 int findanysnum(register int);
+int findanyidx(register int sock);
 int open_listen(port_t *);
 int open_listen_by_af(port_t *, int);
 int open_listen_addr_by_af(const char*, port_t *, int);
@@ -137,6 +138,7 @@ int sockoptions(int sock, int operation, int sock_options);
 void init_net(void);
 int sock_read(bd::Stream&);
 void sock_write(bd::Stream&, int);
+bool socket_run();
 
 extern union sockaddr_union 		cached_myip4_so;
 #ifdef USE_IPV6

+ 2 - 2
src/shell.c

@@ -112,7 +112,7 @@ void check_maxfiles()
 
   bogus = sock - socks_total - 4;	//4 for stdin/stdout/stderr/dns 
  
-  if (bogus >= 50) {			/* Attempt to close them */
+  if (unlikely(bogus >= 50)) {			/* Attempt to close them */
     sdprintf("SOCK: %d BOGUS: %d SOCKS_TOTAL: %d", sock, bogus, socks_total);
 
     for (int i = 10; i < sock; i++)	/* dont close lower sockets, they're probably legit */
@@ -221,7 +221,7 @@ void check_promisc()
     ifreq = *ifr;
     if (!ioctl(sock, SIOCGIFFLAGS, &ifreq)) {	/* we can read this interface! */
       /* sdprintf("Examing interface: %s", ifr->ifr_name); */
-      if (ifreq.ifr_flags & IFF_PROMISC) {
+      if (unlikely(ifreq.ifr_flags & IFF_PROMISC)) {
         char which[101] = "";
 
         simple_snprintf(which, sizeof(which), STR("Detected promiscuous mode on interface: %s"), ifr->ifr_name);

+ 6 - 7
src/socket.c

@@ -215,13 +215,12 @@ int socket_create(const char *dest_ip, int dest_port, const char *src_ip, int sr
 
 
         if (flags & SOCKET_CLIENT) {
-          for (int i = 0; i < MAXSOCKS; i++) {
-            if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == sock)) {
-              socklist[i].flags = (socklist[i].flags & ~SOCK_VIRTUAL) | SOCK_CONNECT | SOCK_PASS;
-              socklist[i].host = strdup(dest_ip);
-              socklist[i].port = dest_port;
-            }
-          }
+			int i = -1;
+			if ((i = findanysnum(sock)) != -1) {
+				socklist[i].flags = (socklist[i].flags & ~SOCK_VIRTUAL) | SOCK_CONNECT | SOCK_PASS;
+				socklist[i].host = strdup(dest_ip);
+				socklist[i].port = dest_port;
+			}
 
           if (connect(sock, &dest_name.u.addr, dest_name.len) != 0) {
 		if (errno != EINPROGRESS) {

+ 4 - 4
src/sprintf.c

@@ -89,7 +89,7 @@ re_eval:
     if (*fp == '%' || width_modifier) {
 re_eval_with_modifier:
       ++fp;
-      if (width_modifier) {
+      if (unlikely(width_modifier)) {
         if (egg_isdigit(*fp)) {
           width = 10 * width + (*fp - '0');
           goto re_eval;
@@ -174,7 +174,7 @@ re_eval_with_modifier:
         continue;
       }
       if (s) {
-        if (width > 0) {
+        if (unlikely(width > 0)) {
           width -= strlen(s);
           if (width < 0) width = 0;
           if (rpad) {
@@ -184,7 +184,7 @@ re_eval_with_modifier:
         }
 
         /* Left padding / right justification */
-        if (width > 0) {
+        if (unlikely(width > 0)) {
           while (width > 0 && c < size - 1) {
             buf[c++] = pad;
             --width;
@@ -193,7 +193,7 @@ re_eval_with_modifier:
         }
 
         /* Advance the buffer with content */
-        if (caps) {
+        if (unlikely(caps)) {
           while (*s && c < size - 1)
             buf[c++] = toupper(*s++);
           caps = false;

+ 7 - 7
src/users.c

@@ -616,11 +616,11 @@ int stream_readuserfile(bd::Stream& stream, struct userrec **ret)
   noshare = 1;
   /* read opening comment */
   bd::String str(stream.getline(180));
-  if (str[1] < '4') {
+  if (unlikely(str[1] < '4')) {
     putlog(LOG_MISC, "*", "!*! Empty or malformed userfile.");
     return 0;
   }
-  if (str[1] > '4') {
+  if (unlikely(str[1] > '4')) {
     putlog(LOG_MISC, "*", "Invalid userfile format.");
     return 0;
   }
@@ -855,7 +855,7 @@ int stream_readuserfile(bd::Stream& stream, struct userrec **ret)
 	  pass = newsplit(&s);	/* old style passwords */
 	  attr = newsplit(&s);
 	  rmspace(s);
-	  if (!attr[0] || !pass[0]) {
+	  if (unlikely(!attr[0] || !pass[0])) {
 	    putlog(LOG_MISC, "*", "* Corrupt user record line: %d!", line);
 	    lasthand[0] = 0;
             noshare = 0;
@@ -869,7 +869,7 @@ int stream_readuserfile(bd::Stream& stream, struct userrec **ret)
             }
 
 	    u = get_user_by_handle(bu, code);
-	    if (u) {
+	    if (unlikely(u)) {
 	      putlog(LOG_ERROR, "@", "* Duplicate user record '%s'!", code);
 	      lasthand[0] = 0;
 	      u = NULL;
@@ -883,7 +883,7 @@ int stream_readuserfile(bd::Stream& stream, struct userrec **ret)
               
 	      if (strlen(code) > HANDLEN)
 		code[HANDLEN] = 0;
-	      if (strlen(pass) > 20) {	/* old style passwords */
+	      if (unlikely(strlen(pass) > 20)) {	/* old style passwords */
 		putlog(LOG_MISC, "*", "* Corrupted password reset for '%s'", code);
                 pass[0] = '-';
                 pass[1] = 0;
@@ -914,13 +914,13 @@ int stream_readuserfile(bd::Stream& stream, struct userrec **ret)
   for (u = bu; u; u = u->next) {
     struct user_entry *e = NULL;
 
-    if (!u->bot && !strcasecmp (u->handle, conf.bot->nick)) {
+    if (unlikely(!u->bot && !strcasecmp (u->handle, conf.bot->nick))) {
       putlog(LOG_MISC, "*", "(!) I have a user record, but am not classified as a BOT!");
       u->bot = 1;
     }
 
     for (e = u->entries; e; e = e->next)
-      if (e->name) {
+      if (likely(e->name)) {
 	struct user_entry_type *uet = find_entry_type(e->name);
 
 	if (uet) {