瀏覽代碼

Merge branch '320-monitor'

* 320-monitor:
  * Fix compile warning
  * Prevent double logging on QUIT/NICK+MONITOR, and DUMP the NICK change.
  * Fix regression in ISON processing
  * Disable monitor on server disconnect
  * Make note in help for 'set' that notify-time is only used when server does not support MONITOR
  * When a nick is available, send NICK before logging the fact so that the ircd receives our request quicker.
  * Also rehash MONITOR list when done restarting.
  * Rehash MONITOR List on server when jupenick/nick change, and on connect.
  * Update Docs and make note that this fixes #320
  * Use nicks_available() when on NICK and our own nick just changed unexpectedly
  * Remove redundant check against current nick
  * Also use nicks_available() on NICK
  * Use nicks_available() where appropriate. (Fixes jupenick not being grabbed on QUIT)
  * Support RPL_MONOFFLINE (MONITOR response that nick is available)
  * Don't send ISON if using monitor
  * Move ison timer to server_secondly
  * Detect MONITOR on connect and set use_monitor if available
Bryan Drewery 16 年之前
父節點
當前提交
994c2001d9
共有 9 個文件被更改,包括 142 次插入81 次删除
  1. 1 0
      doc/UPDATES
  2. 2 1
      doc/help.txt
  3. 1 11
      src/main.c
  4. 2 6
      src/mod/irc.mod/chan.c
  5. 16 1
      src/mod/server.mod/server.c
  6. 6 4
      src/mod/server.mod/server.h
  7. 102 56
      src/mod/server.mod/servmsg.c
  8. 3 1
      src/mod/share.mod/share.c
  9. 9 1
      src/set.c

+ 1 - 0
doc/UPDATES

@@ -67,6 +67,7 @@
   * Fix +botbitch being very slow and inefficient
   * Better +bitch/+botbitch/+closed handling when in floodless mode.
 * Misc changes
+  * Add MONITOR support. This speeds up NICK grabbing. (fixes #320)
   * Add set 'deaf' to run bot in DEAF mode on supporting IRCDs. This prevents channel conversations coming to the bot. On by default.
   * Add set 'callerid' to run bot in CALLERID mode (+g). +c bots will automatically accept messages from known users. (fixes #45)
   * Rename set 'flood-g' to 'flood-callerid', which only takes effect if the server supports CALLERID.

+ 2 - 1
doc/help.txt

@@ -1616,7 +1616,8 @@ See also: reload, backup
                          of jupenick.
 [S]  $bnick$b            The bot's preferred nickname on IRC. It will auto rotate and append
                          'altchars' on the end if taken.
-[N]  $bnotify-time$b     The number of seconds between server notify checks for nick.
+[N]  $bnotify-time$b     The number of seconds between server notify checks for nick, if
+                          the server does not support MONITOR.
  
 [B]  $birc-autoaway$b    Should the bot go away auto?
  

+ 1 - 11
src/main.c

@@ -514,7 +514,7 @@ static void event_resettraffic()
 
 static void core_secondly()
 {
-  static int cnt = 0, ison_cnt = 0;
+  static int cnt = 0;
   time_t miltime;
 
   if (fork_interval && backgrd && ((now - lastfork) > fork_interval))
@@ -526,16 +526,6 @@ static void core_secondly()
     cnt = 0;
   }
 
-  if (!conf.bot->hub) {
-    if (ison_time == 0) //If someone sets this to 0, all hell will break loose!
-      ison_time = 10;
-    if (ison_cnt >= ison_time) {
-      server_send_ison();
-      ison_cnt = 0;
-    } else
-      ++ison_cnt;
-  }
-
   memcpy(&nowtm, gmtime(&now), sizeof(struct tm));
   if (nowtm.tm_min != lastmin) {
     int i = 0;

+ 2 - 6
src/mod/irc.mod/chan.c

@@ -3050,12 +3050,8 @@ static int gotquit(char *from, char *msg)
   }
   /* Our nick quit? if so, grab it.
    */
-  if (keepnick && !match_my_nick(nick)) {
-    if (!rfc_casecmp(nick, origbotname)) {
-      putlog(LOG_MISC, "*", "Switching back to nick %s", origbotname);
-      dprintf(DP_SERVER, "NICK %s\n", origbotname);
-    }
-  }
+  if (keepnick && !match_my_nick(nick))
+    nicks_available(nick);
 #ifdef CACHE
   /* see if they were in our cache at all */
   cache_t *cache = cache_find(nick);

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

@@ -74,7 +74,9 @@ bool keepnick = 1;		/* keep trying to regain my intended
 				   nickname? */
 static bool nick_juped = 0;	/* True if origbotname is juped(RPL437) (dw) */
 static bool jnick_juped = 0;    /* True if jupenick is juped */
-bool tried_jupenick = 0;
+time_t tried_jupenick = 0;
+time_t tried_nick = 0;
+bool use_monitor = 0;
 static bool waiting_for_awake;	/* set when i unidle myself, cleared when I get the response */
 time_t server_online;	/* server connection time */
 char botrealname[121] = "A deranged product of evil coders.";	/* realname of bot */
@@ -987,6 +989,19 @@ static void server_secondly()
   deq_msg();
   if (!resolvserv && serv < 0 && !trying_server)
     connect_server();
+
+  if (!conf.bot->hub) {
+    static int ison_cnt = 0;
+
+    if (ison_time == 0) //If someone sets this to 0, all hell will break loose!
+      ison_time = 10;
+    if (ison_cnt >= ison_time) {
+      server_send_ison();
+      ison_cnt = 0;
+    } else
+      ++ison_cnt;
+  }
+
 }
 
 static void server_check_lag()

+ 6 - 4
src/mod/server.mod/server.h

@@ -44,15 +44,13 @@ enum {
 	NETT_HYBRID_EFNET	= 4	/* new +e/+I Efnet hybrid.	  */
 };
 
-#endif		/* _EGG_MOD_SERVER_SERVER_H */
-
 extern bind_table_t	*BT_ctcp, *BT_ctcr, *BT_msgc;
 extern size_t		nick_len;
-extern bool		trigger_on_ignore, floodless, tried_jupenick, keepnick;
+extern bool		trigger_on_ignore, floodless, keepnick;
 extern int 		servidx, ctcp_mode, answer_ctcp, serv, curserv, default_alines;
 extern unsigned int     rolls;
 extern port_t		default_port, newserverport, curservport;
-extern time_t		server_online;
+extern time_t		server_online, tried_jupenick, tried_nick;
 extern interval_t	cycle_time;
 extern char		cursrvname[], botrealname[121], botuserhost[], ctcp_reply[1024],
 			newserver[], newserverpass[], curnetwork[], botuserip[], altnick_char, deaf_char, callerid_char;
@@ -61,6 +59,7 @@ extern struct dcc_table SERVER_SOCKET;
 extern rate_t		flood_msg, flood_ctcp, flood_callerid;
 
 int check_bind_ctcpr(char *, char *, struct userrec *, char *, char *, char *, bind_table_t *);
+void nicks_available(char* buf, char delim = 0, bool buf_contains_available = 1);
 
 #define check_bind_ctcp(a, b, c, d, e, f) check_bind_ctcpr(a, b, c, d, e, f, BT_ctcp)
 #define check_bind_ctcr(a, b, c, d, e, f) check_bind_ctcpr(a, b, c, d, e, f, BT_ctcr)
@@ -75,8 +74,11 @@ void clearq(struct server_list *);
 void nuke_server(const char *);
 bool match_my_nick(char *);
 void rehash_server(const char *, const char *);
+void rehash_monitor_list();
 void replay_cache(int, bd::Stream*);
 void join_chans();
 void check_hostmask();
 void next_server(int *, char *, port_t *, char *);
 void server_send_ison();
+
+#endif		/* _EGG_MOD_SERVER_SERVER_H */

+ 102 - 56
src/mod/server.mod/servmsg.c

@@ -174,6 +174,15 @@ bool match_my_nick(char *nick)
   return (!rfc_casecmp(nick, botname));
 }
 
+void rehash_monitor_list() {
+  if (!use_monitor) return;
+  dprintf(DP_SERVER, "MONITOR C\n");
+  if (jupenick[0])
+    dprintf(DP_SERVER, "MONITOR + %s,%s\n", jupenick, origbotname);
+  else
+    dprintf(DP_SERVER, "MONITOR + %s", origbotname);
+}
+
 void rehash_server(const char *servname, const char *nick)
 {
   server_online = now;
@@ -188,6 +197,7 @@ void rehash_server(const char *servname, const char *nick)
     dprintf(DP_SERVER, "WHOIS %s\n", botname); /* get user@host */
     dprintf(DP_SERVER, "USERHOST %s\n", botname); /* get user@ip */
     dprintf(DP_SERVER, "MODE %s %s\n", botname, var_get_str_by_name("usermode"));
+    rehash_monitor_list();
   }
 }
 
@@ -288,6 +298,14 @@ got005(char *from, char *msg)
         modesperline = MODES_PER_LINE_MAX;
     } else if (!strcasecmp(tmp, "NICKLEN"))
       nick_len = atoi(p);
+    else if (!strcasecmp(tmp, "MONITOR")) {
+      bool need_to_rehash_monitor = 0;
+      if (!use_monitor && !replaying_cache) // Don't rehash if restarting. No need.
+        need_to_rehash_monitor = 1;
+      use_monitor = 1;
+      if (need_to_rehash_monitor)
+        rehash_monitor_list();
+    }
     else if (!strcasecmp(tmp, "NETWORK"))
       strlcpy(curnetwork, p, 120);
     else if (!strcasecmp(tmp, "PENALTY"))
@@ -772,7 +790,7 @@ static int gotwall(char *from, char *msg)
 
 void server_send_ison()
 {
-  if (server_online && keepnick) {
+  if (server_online && keepnick && !use_monitor) {
     // Only check if we're not on jupenick, or there is no jupenick and we're not on the preferred nick
     bool have_jupenick = jupenick[0] ? match_my_nick(jupenick) : 0;
     if (!have_jupenick) {
@@ -826,46 +844,85 @@ static int gotpong(char *from, char *msg)
   return 0;
 }
 
-/* This is a reply on ISON :<orig> [<jupenick>]
- */
-static void got303(char *from, char *msg)
-{
-  if (!keepnick)
-    return;
-
-  char *tmp = NULL;
-
-  tmp = newsplit(&msg);
-  fixcolon(msg);
-  if (tmp[0] && match_my_nick(tmp)) {
-    bool ison_jupe = 0, ison_orig = 0;
-
-    while ((tmp = newsplit(&msg))[0]) {
-      if (jupenick[0] && !rfc_casecmp(tmp, jupenick)) {
-        ison_jupe = 1;
-        // If some stupid reason they have the same jupenick/nick, make sure to mark it as on
-        if (!rfc_casecmp(tmp, origbotname)) {
-          ison_orig = 1;
-          break;
-        }
-      } else if (!rfc_casecmp(tmp, origbotname)) {
-        ison_orig = 1;
-      }
-    }
+static int nick_which(const char* nick, bool& is_jupe, bool& is_orig) {
+  if (jupenick[0] && !rfc_casecmp(nick, jupenick)) {
+    is_jupe = 1;
+    // If some stupid reason they have the same jupenick/nick, make sure to mark it as on
+    if (!rfc_casecmp(nick, origbotname))
+      is_orig = 1;
+    return 1;
+  } else if (!rfc_casecmp(nick, origbotname)) {
+    is_orig = 1;
+  }
+  return 0;
+}
 
-    if (jupenick[0] && !ison_jupe && rfc_casecmp(botname, jupenick)) {
+static void nick_available(bool is_jupe, bool is_orig) {
+  if (jupenick[0] && is_jupe && !match_my_nick((jupenick))) {
+    /* Ensure we aren't processing a QUIT/NICK and a MONITOR, or just some screw up */
+    if (!tried_jupenick || ((now - tried_jupenick) > 1)) {
+      tried_jupenick = now;
+      dprintf(DP_DUMP, "NICK %s\n", jupenick);
       if (!jnick_juped)
-        putlog(LOG_MISC, "*", "Switching back to jupenick %s", jupenick);
-      tried_jupenick = 1;
-      dprintf(DP_SERVER, "NICK %s\n", jupenick);
+        putlog(LOG_MISC, "*", "Switching back to jupenick '%s'", jupenick);
+    }
     // Don't switch to the nick if already on jupenick
-    } else if (!ison_orig && rfc_casecmp(botname, origbotname) && (!jupenick[0] || !match_my_nick(jupenick))) {
-      if (!nick_juped)
-        putlog(LOG_MISC, "*", "Switching back to nick %s", origbotname);
+  } else if (is_orig && !match_my_nick(origbotname) && (!jupenick[0] || !match_my_nick(jupenick))) {
+    if (!tried_nick || ((now - tried_nick) > 1)) {
       altnick_char = rolls = 0;
-      dprintf(DP_SERVER, "NICK %s\n", origbotname);
+      tried_nick = now;
+      dprintf(DP_DUMP, "NICK %s\n", origbotname);
+      if (!nick_juped)
+        putlog(LOG_MISC, "*", "Switching back to nick '%s'", origbotname);
+    }
+  }
+}
+
+void nicks_available(char* buf, char delim, bool buf_contains_available) {
+  if (!buf[0] || !keepnick) return;
+  bool is_jupe = 0, is_orig = 0;
+
+  char *nick = NULL;
+  if (delim) {
+    while ((nick = newsplit(&buf, delim))[0]) {
+      if (nick_which(nick, is_jupe, is_orig))
+        break;
     }
+  } else {
+    nick = buf;
+    nick_which(nick, is_jupe, is_orig);
+  }
+
+  if (buf_contains_available == 0) {
+    is_jupe = !is_jupe;
+    is_orig = !is_orig;
   }
+
+  nick_available(is_jupe, is_orig);
+}
+
+/* This is a reply to MONITOR: Offline
+ * RPL_MONOFFLINE
+ * :<server> 731 <nick> :nick[,nick1]*
+ */
+static void got731(char* from, char* msg)
+{
+  char *tmp = newsplit(&msg);
+  fixcolon(msg);
+
+  //msg now contains the nick(s) available
+  if (tmp[0] && (!strcmp(tmp, "*") || match_my_nick(tmp)))
+    nicks_available(msg, ',');
+}
+
+/* This is a reply on ISON :<orig> [<jupenick>]
+*/
+static void got303(char *from, char *msg)
+{
+  char *tmp = newsplit(&msg);
+  fixcolon(msg);
+  if (tmp[0] && match_my_nick(tmp))
+    nicks_available(msg, ' ', 0);
 }
 
 /* 432 : Bad nickname (RESV)
@@ -922,7 +979,9 @@ static int got433(char *from, char *msg)
     else if (!rfc_casecmp(tmp, origbotname))
       nick_juped = 0;
 
-    sdprintf("433: botname: %s tmp: %s rolls: %d altnick_char: %c tried_jupenick: %d", botname, tmp, rolls, altnick_char, tried_jupenick);
+    tried_nick = 0;
+
+    sdprintf("433: botname: %s tmp: %s rolls: %d altnick_char: %c tried_jupenick: %li", botname, tmp, rolls, altnick_char, (long)tried_jupenick);
     // Tried jupenick, but already on origbotname (or a rolled nick), stay on it.
     if (tried_jupenick && (match_my_nick(origbotname) || rolls || altnick_char != 0)) {
       putlog(LOG_MISC, "*", "%sNICK IN USE: '%s' (keeping '%s').", tried_jupenick ? "JUPE" : "", tmp, botname);
@@ -1052,6 +1111,7 @@ static int gotnick(char *from, char *msg)
     strlcpy(botname, msg, NICKLEN);
 
     tried_jupenick = 0;
+    tried_nick = 0;
 
     if (jupenick[0] && !rfc_casecmp(msg, jupenick)) {
       altnick_char = rolls = 0;
@@ -1068,30 +1128,12 @@ static int gotnick(char *from, char *msg)
         putlog(LOG_MISC, "*", "Nickname changed to '%s'", msg);
       } else {
         putlog(LOG_SERV | LOG_MISC, "*", "Nickname changed to '%s'???", msg);
-    
-        if (jupenick[0] && !rfc_casecmp(nick, jupenick)) {
-          putlog(LOG_MISC, "*", "Switching back to jupenick %s", jupenick);
-          tried_jupenick = 1;
-          dprintf(DP_SERVER, "NICK %s\n", jupenick);
-        } else if (!rfc_casecmp(nick, origbotname)) {
-          putlog(LOG_MISC, "*", "Switching back to nick %s", origbotname);
-          dprintf(DP_SERVER, "NICK %s\n", origbotname);
-          altnick_char = rolls = 0;
-        }
+        nicks_available(nick);
       }
     } else
       putlog(LOG_SERV | LOG_MISC, "*", "Nickname changed to '%s'???", msg);
   } else if ((keepnick) && (rfc_casecmp(nick, msg))) { //Ignore case changes
-    //Another client changed nick
-    if (jupenick[0] && !rfc_casecmp(nick, jupenick)) {
-      putlog(LOG_MISC, "*", "Switching back to jupenick %s", jupenick);
-      tried_jupenick = 1;
-      dprintf(DP_SERVER, "NICK %s\n", jupenick);
-    } else if (!rfc_casecmp(nick, origbotname)) {
-      putlog(LOG_MISC, "*", "Switching back to nick %s", origbotname);
-      dprintf(DP_SERVER, "NICK %s\n", origbotname);
-      altnick_char = rolls = 0;
-    }
+    nicks_available(nick);
   }
   free(buf_ptr);
   return 0;
@@ -1131,6 +1173,7 @@ static void disconnect_server(int idx, int dolost)
   serv = -1;
   servidx = -1;
   server_online = 0;
+  use_monitor = 0;
   cookies_disabled = false;
   floodless = 0;
   botuserhost[0] = 0;
@@ -1655,6 +1698,7 @@ static cmd_t my_raw_binds[] =
   {"318",	"",	(Function) whoispenalty,	NULL, LEAF},	/* :End of /WHOIS */
   {"369",	"",	(Function) got369,		NULL, LEAF},	/* :End of /WHOWAS */
   {"718",	"",	(Function) got718,		NULL, LEAF},
+  {"731",	"",	(Function) got731,		NULL, LEAF},	/* RPL_MONOFFLINE */
   {NULL,	NULL,	NULL,				NULL, 0}
 };
 
@@ -1708,8 +1752,10 @@ static void connect_server(void)
     nick_juped = 0;
     jnick_juped = 0;
     tried_jupenick = 0;
+    tried_nick = 0;
     rolls = 0;
     altnick_char = 0;
+    use_monitor = 0;
 
     for (chan = chanset; chan; chan = chan->next)
       chan->status &= ~CHAN_JUPED;

+ 3 - 1
src/mod/share.mod/share.c

@@ -1442,8 +1442,10 @@ static void share_read_stream(int idx, bd::Stream& stream) {
   updatebot(-1, dcc[idx].nick, '+', 0, 0, 0, NULL);
   send_sysinfo();
 
-  if (restarting && !keepnick)
+  if (restarting && !keepnick) {
     keepnick = 1;
+    rehash_monitor_list();
+  }
 
   /* Prevents the server connect from dumping JOIN #chan */
   restarting = 0;

+ 9 - 1
src/set.c

@@ -298,6 +298,8 @@ sdprintf("var (mem): %s -> %s", var->name, datain ? datain : "(NULL)");
       ((char *) var->mem)[0] = 0;
 
     if (!conf.bot->hub) {
+      bool should_reset_monitor = 0;
+
       if (var->flags & VAR_JUPENICK) {
         //Don't allow setting to the same as origbotname
         if (data && !rfc_casecmp(jupenick, origbotname)) {
@@ -313,15 +315,18 @@ sdprintf("var (mem): %s -> %s", var->name, datain ? datain : "(NULL)");
           if (data && (!olddata || (olddata && strcmp(olddata, jupenick)))) {
             // If not on the new nick, jump to it
             if (!match_my_nick(jupenick)) {
-              tried_jupenick = 1;
+              tried_jupenick = now;
               dprintf(DP_SERVER, "NICK %s\n", jupenick);
+              should_reset_monitor = 1;
             }
           // Unset and there was an old value
           } else if (!data && olddata) { 
             // Unset jupenick, try for 'nick' now if we were on jupenick
             if (match_my_nick(olddata)) {
               altnick_char = rolls = 0;
+              tried_nick = now;
               dprintf(DP_SERVER, "NICK %s\n", origbotname);
+              should_reset_monitor = 1;
             }
           }
         }
@@ -340,9 +345,12 @@ sdprintf("var (mem): %s -> %s", var->name, datain ? datain : "(NULL)");
             // Unset the rolls/altnick stuff as we're starting over from scratch.
             altnick_char = rolls = 0;
             dprintf(DP_SERVER, "NICK %s\n", (char *) var->mem);
+            should_reset_monitor = 1;
           }
         }
       }
+      if (server_online && should_reset_monitor)
+        rehash_monitor_list();
     }
     if (olddata)
       free(olddata);