Просмотр исходного кода

Merge branch 'irc-fixes'

* irc-fixes: (31 commits)
  * Avoid tputs() in mode processing
  * Add a dprintf_real() to avoid vsprintf() if the length is already known and buffer already formatted
  * Fix bots never timing out when connecting to servers sometimes.
  * Move the stackable commands into 005:NETWORK
  * Move use_fastdeq determination to 005:NETWORK
  * Remove include_lk nettype hacks. include_lk defaults to 1 but is unset on hybrid type servers
  * Cache deaf/callerid state when restarting
  * Rework IRCnet +r hack
  * Fix case of using wrong channel name type
  * Another place to not set/unset callerid/deaf unless already set/unset
  * Rename deaf_set -> in_deaf
  * Only set deaf/callerid if not already in them
  * Fix cases where callerid was not tracked as being set
  * Clear out flags and force a join when confused or kicked/parted a chan
  * Fix join_chan() not properly checking the ircnet status flags
  * Fix WHO getting updated while the channel is still pending
  * Further optimize WHO parsing by avoiding match_my_nick() and just processing that need at got315 (End of WHO)
  * Further optimize WHO parsing
  * Remove redundant clear_channel
  * Remove redundant flag clearing / joining code
  ...

Conflicts:
	src/dccutil.c
	src/mod/irc.mod/chan.c
	src/mod/irc.mod/mode.c
Bryan Drewery 16 лет назад
Родитель
Сommit
f83eb68d7d

+ 1 - 0
doc/UPDATES

@@ -78,6 +78,7 @@
   * Fix case where bot would not get the +e and +I lists when getting opped.
   * If a bot devoices a user in a +voice channel, the +y bot will no longer enforce this.
   * Fix cmd_botjoin not properly setting up addedby/addedts for the channel.
+  * Fix bots never timing out when connecting to servers sometimes.
 * Misc changes
   * Cleanup DCC/Telnet listening so bot only listens on IPV6 if it was specifically given an IPV6 IP.
   * CTCP bot CHAT will no longer work if the bot does not have an IPV4 IP set.

+ 4 - 2
src/chanprog.c

@@ -109,7 +109,7 @@ struct chanset_t *findchan(const char *name)
   register struct chanset_t	*chan = NULL;
 
   for (chan = chanset; chan; chan = chan->next)
-    if (!rfc_casecmp(chan->name, name))
+    if (chan->name[0] && !rfc_casecmp(chan->name, name))
       return chan;
   return NULL;
 }
@@ -847,7 +847,9 @@ bool bot_shouldjoin(struct userrec* u, struct flag_record* fr, struct chanset_t*
   }
 #endif
   // Ignore +inactive during cmd_slowjoin to ensure that +backup bots join
-  return ((ignore_inactive || !channel_inactive(chan)) && (channel_backup(chan) || (!glob_backup(*fr) && !chan_backup(*fr))));
+  return (!glob_kick(*fr) && !chan_kick(*fr) &&
+      ((ignore_inactive || !channel_inactive(chan)) &&
+       (channel_backup(chan) || (!glob_backup(*fr) && !chan_backup(*fr)))));
 }
 
 bool shouldjoin(struct chanset_t *chan)

+ 7 - 2
src/dccutil.c

@@ -279,14 +279,19 @@ dprintf(int idx, const char *format, ...)
   } else {
     len = size_t(vlen);
   }
+  dprintf_real(idx, buf, len, sizeof(buf));
+}
 
+void
+dprintf_real(int idx, char* buf, size_t len, size_t bufsiz)
+{
 /* this is for color on dcc :P */
 
   if (unlikely(idx < 0)) {
     tputs(-idx, buf, len);
   } else if (idx > 0x7FF0) {
     if (unlikely(idx == DP_STDOUT || idx == DP_STDOUT)) {
-      len = colorbuf(buf, len, -1, sizeof(buf));
+      len = colorbuf(buf, len, -1, bufsiz);
     }
 
     switch (idx) {
@@ -323,7 +328,7 @@ dprintf(int idx, const char *format, ...)
     }
     return;
   } else {                      /* normal chat text */
-    len = colorbuf(buf, len, idx, sizeof(buf));
+    len = colorbuf(buf, len, idx, bufsiz);
 
     if (len > 1000) {           /* Truncate to fit */
       len = 1000;

+ 1 - 0
src/dccutil.h

@@ -38,6 +38,7 @@ namespace bd {
 void init_dcc(void);
 void dumplots(int, const char *, const char *);
 void dprintf(int, const char *, ...) __attribute__((format(printf, 2, 3)));
+void dprintf_real(int, char*, size_t, size_t);
 void chatout(const char *, ...) __attribute__((format(printf, 1, 2)));
 void chanout_but(int, int, const char *, ...) __attribute__((format(printf, 3, 4)));
 void dcc_chatter(int);

+ 8 - 0
src/misc.c

@@ -651,6 +651,10 @@ readsocks(const char *fname)
       server_online = strtol(str.c_str(), NULL, 10);
     else if (type == STR("+server_floodless"))
       floodless = 1;
+    else if (type == STR("+in_deaf"))
+      in_deaf = 1;
+    else if (type == STR("+in_callerid"))
+      in_callerid = 1;
     else if (type == STR("+buildts"))
       old_buildts = strtol(str.c_str(), NULL, 10);
     else if (type == STR("+botname"))
@@ -757,6 +761,10 @@ restart(int idx)
   stream << buf.printf(STR("+online_since %li\n"), online_since);
   if (floodless)
     stream << buf.printf(STR("+server_floodless %d\n"), floodless);
+  if (in_deaf)
+    stream << buf.printf(STR("+in_deaf\n"));
+  if (in_callerid)
+    stream << buf.printf(STR("+in_callerid\n"));
   stream << buf.printf(STR("+buildts %li\n"), buildts);
   stream << buf.printf(STR("+ip4 %s\n"), myipstr(AF_INET));
   stream << buf.printf(STR("+ip6 %s\n"), myipstr(AF_INET6));

+ 4 - 8
src/mod/channels.mod/channels.c

@@ -388,10 +388,8 @@ check_slowjoinpart(struct chanset_t *chan)
   } else if ((chan->channel.jointime) && (chan->channel.jointime < now)) {
       chan->status &= ~CHAN_INACTIVE;
       chan->channel.jointime = 0;
-    if (shouldjoin(chan) && !channel_active(chan) && !channel_joining(chan)) {
-      dprintf(DP_MODE, "JOIN %s %s\n", chan->dname, chan->key_prot);
-      chan->ircnet_status |= CHAN_JOINING;
-    }
+    if (shouldjoin(chan))
+      join_chan(chan);
   } else if (channel_closed(chan)) {
     enforce_closed(chan);
   }
@@ -483,10 +481,8 @@ static void got_jn(int idx, char *code, char *par)
   if (chan->channel.jointime && channel_inactive(chan)) {
     chan->status &= ~CHAN_INACTIVE;
     chan->channel.jointime = 0;
-    if (!conf.bot->hub && shouldjoin(chan) && !channel_active(chan) && !channel_joining(chan)) {
-      dprintf(DP_MODE, "JOIN %s %s\n", chan->name, chan->key_prot);
-      chan->ircnet_status |= CHAN_JOINING;
-    }
+    if (!conf.bot->hub && shouldjoin(chan))
+      join_chan(chan);
   }
 }
 #endif

+ 2 - 4
src/mod/channels.mod/cmdschan.c

@@ -605,10 +605,8 @@ static void cmd_slowjoin(int idx, char *par)
 
   dprintf(idx, "%i bots joining %s during the next %i seconds\n", count, chan->dname, delay);
 
-  if (!conf.bot->hub && shouldjoin(chan) && !channel_joining(chan)) {
-    dprintf(DP_MODE, "JOIN %s %s\n", chan->name, chan->key_prot);
-    chan->ircnet_status |= CHAN_JOINING;
-  }
+  if (!conf.bot->hub && shouldjoin(chan))
+    join_chan(chan);
 }
 
 static void cmd_slowpart(int idx, char *par)

+ 6 - 10
src/mod/channels.mod/tclchan.c

@@ -816,14 +816,9 @@ int channel_modify(char *result, struct chanset_t *chan, int items, char **item,
   if (!conf.bot->hub && (chan != chanset_default)) {
     if ((old_status ^ chan->status) & (CHAN_INACTIVE | CHAN_BACKUP)) {
       if (!shouldjoin(chan) && (chan->ircnet_status & (CHAN_ACTIVE | CHAN_PEND)))
-        dprintf(DP_SERVER, "PART %s\n", chan->name);
-      if (shouldjoin(chan) && !(chan->ircnet_status & (CHAN_ACTIVE | CHAN_PEND | CHAN_JOINING))) {
-        dprintf(DP_SERVER, "JOIN %s %s\n", (chan->name[0]) ?
-  			   chan->name : chan->dname,
-  			   chan->channel.key[0] ?
-    			   chan->channel.key : chan->key_prot);
-        chan->ircnet_status |= CHAN_JOINING;
-      }
+        dprintf(DP_SERVER, "PART %s\n", chan->name[0] ? chan->name : chan->dname);
+      else if (shouldjoin(chan))
+        join_chan(chan);
     }
     if (me_op(chan)) {
       if ((old_status ^ chan->status) & (CHAN_ENFORCEBANS|CHAN_NOUSERBANS|CHAN_DYNAMICBANS|CHAN_NOUSEREXEMPTS|CHAN_NOUSERINVITES|CHAN_DYNAMICEXEMPTS|CHAN_DYNAMICINVITES)) {
@@ -916,7 +911,8 @@ void clear_channel(struct chanset_t *chan, bool reset)
 
   chan->channel.last_eI = 0;
 
-  chan->ircnet_status &= ~CHAN_HAVEBANS;
+  chan->ircnet_status = 0;
+//  chan->ircnet_status &= ~CHAN_HAVEBANS;
 
   if (reset)
     init_channel(chan, 1);
@@ -1051,6 +1047,6 @@ int channel_add(char *result, char *newname, char *options, bool isdefault)
 
   free(item);
   if (join && shouldjoin(chan))
-    dprintf(DP_SERVER, "JOIN %s %s\n", chan->dname, chan->key_prot);
+    join_chan(chan);
   return ret;
 }

+ 76 - 125
src/mod/irc.mod/chan.c

@@ -219,6 +219,14 @@ void resolve_to_rbl(struct chanset_t *chan, const char *host, resolv_member *r)
   free(ip);
 }
 
+// Just got a part event (KICK, PART) on me
+static void check_rejoin(struct chanset_t* chan) {
+  if (shouldjoin(chan))
+    force_join_chan(chan);
+  else // Out of chan, not rejoining, just clear it
+    clear_channel(chan, 1);
+}
+
 /* ID length for !channels.
  */
 #define CHANNEL_ID_LEN 5
@@ -247,12 +255,15 @@ static memberlist *newmember(struct chanset_t *chan, char *nick)
     lx = x;
     x = x->next;
   }
+  /*
+   * redundant as calloc is used
+   n->next = NULL;
+   n->split = 0L;
+   n->last = 0L;
+   n->delay = 0L;
+   */
 
-  n->next = NULL;
   strlcpy(n->nick, nick, sizeof(n->nick));
-  n->split = 0L;
-  n->last = 0L;
-  n->delay = 0L;
   n->hops = -1;
   if (!lx) {
     // Free the pseudo-member created in init_channel()
@@ -268,7 +279,7 @@ static memberlist *newmember(struct chanset_t *chan, char *nick)
     lx->next = n;
   }
 
-  chan->channel.members++;
+  ++(chan->channel.members);
   return n;
 }
 
@@ -1201,25 +1212,48 @@ static void check_this_member(struct chanset_t *chan, char *nick, struct flag_re
 }
 
 
-//del=1 -user, del=2 -host
+//1 -user
+//2 -host
 void check_this_user(char *hand, int del, char *host)
 {
-  char s[UHOSTLEN] = "";
   memberlist *m = NULL;
-  struct userrec *u = NULL;
   struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };
 
-  for (struct chanset_t *chan = chanset; chan; chan = chan->next)
+  for (struct chanset_t *chan = chanset; chan; chan = chan->next) {
     for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
-      simple_snprintf(s, sizeof(s), "%s!%s", m->nick, m->userhost);
-      u = m->user ? m->user : get_user_by_host(s);
-      if ((u && !strcasecmp(u->handle, hand) && del < 2) ||
-	  (!u && del == 2 && wild_match(host, s))) {
-	u = del ? NULL : u;
-	get_user_flagrec(u, &fr, chan->dname, chan);
-	check_this_member(chan, m->nick, &fr);
+      bool check_member = 0;
+      bool had_user = m->user ? 1 : 0;
+      member_getuser(m);
+      struct userrec* u = m->user;
+      if (m->user && !had_user) // If a member is newly recognized, act on it
+        check_member = 1;
+      else if (del != 2 && m->user && !strcasecmp(m->user->handle, hand)) { //general check / -user, match specified user
+        check_member = 1;
+        if (del == 1)
+          u = NULL; // Pretend user doesn't exist when checking
+      } else if (0 && del == 2) { //-host, may now match on a diff user and need to act on them
+        /*
+        for (int i = 0; i < (m->userip[0] ? 2 : 1); ++i) {
+          if (i == 0 && m->userip[0]) // Check userip first in case userhost is already an ip
+            simple_snprintf(s, sizeof(s), "%s!%s", m->nick, m->userip);
+          else
+            simple_snprintf(s, sizeof(s), "%s!%s", m->nick, m->userhost);
+          if (wild_match(host, s) ||
+              (i == 0 && m->userip[0] && match_cidr(host, s))) {
+            check_member = 1;
+            break;
+          }
+        }
+        */
+        if (m->user && !had_user)
+          check_member = 1;
+      }
+      if (check_member) {
+        get_user_flagrec(u, &fr, chan->dname, chan);
+        check_this_member(chan, m->nick, &fr);
       }
     }
+  }
 }
 
 static void enforce_bitch(struct chanset_t *chan, bool flush = 1) {
@@ -1461,9 +1495,9 @@ void recheck_channel(struct chanset_t *chan, int dobans)
       get_channel_masks(chan);
     }
 
-  //Check +d/+O/+k
-  for (m = chan->channel.member; m && m->nick[0]; m = m->next) { 
-    member_getuser(m);
+    //Check +d/+O/+k
+    for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
+      member_getuser(m);
       get_user_flagrec(m->user, &fr, chan->dname, chan);
       //Already a bot opped, dont bother resetting masks
       if (glob_bot(fr) && chan_hasop(m) && !match_my_nick(m->nick))
@@ -1845,23 +1879,19 @@ static void memberlist_reposition(struct chanset_t *chan, memberlist *target) {
 
 static int got352or4(struct chanset_t *chan, char *user, char *host, char *nick, char *flags, int hops, char* realname, char* ip)
 {
-  struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0 };
-  char userhost[UHOSTLEN] = "";
   memberlist *m = ismember(chan, nick);	/* in my channel list copy? */
 //  bool waschanop = 0;
-  bool me = 0;
 //  struct chanset_t *ch = NULL;
 //  memberlist *ml = NULL;
 
   if (!m) {			/* Nope, so update */
     m = newmember(chan, nick);	/* Get a new channel entry */
-    m->joined = m->split = m->delay = 0L;	/* Don't know when he joined */
-    m->flags = 0;		/* No flags for now */
     m->last = now;		/* Last time I saw him */
-    m->user = NULL;
+
+    /* Store the userhost */
+    simple_snprintf(m->userhost, sizeof(m->userhost), "%s@%s", user, host);
   }
-  if (!m->nick[0])
-    strlcpy(m->nick, nick, sizeof(m->nick));	/* Store the nick in list */
+
 
   m->hops = hops;
 
@@ -1896,10 +1926,6 @@ static int got352or4(struct chanset_t *chan, char *user, char *host, char *nick,
 //  if (!(m->flags & (CHANVOICE | CHANOP)))
 //    m->flags |= STOPWHO;
 
-  /* Store the userhost */
-  if (!m->userhost[0])
-    simple_snprintf(m->userhost, sizeof(m->userhost), "%s@%s", user, host);
-
   if (!m->userip[0]) {
     if (ip)
       simple_snprintf(m->userip, sizeof(m->userip), "%s@%s", user, ip);
@@ -1907,64 +1933,16 @@ static int got352or4(struct chanset_t *chan, char *user, char *host, char *nick,
       simple_snprintf(m->userip, sizeof(m->userip), "%s@%s", user, host);
   }
 
-  simple_snprintf(userhost, sizeof(userhost), "%s!%s", nick, m->userhost);
-
-  me = match_my_nick(nick);
-
-
-  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 */
-  }
-
-  if (!m->user && !m->tried_getuser) {
-    m->user = get_user_by_host(userhost);
-    m->tried_getuser = 1;
-  }
+  member_getuser(m);
 
   //This bot is set +r, so resolve.
   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))
+    else if (!m->user && m->userip[0] && channel_rbl(chan))
       resolve_to_rbl(chan, m->userip);
   }
 
-
-  get_user_flagrec(m->user, &fr, chan->dname, chan);
-  
-  if (me_op(chan)) {
-    /* are they a chanop, and me too */
-        /* are they a channel or global de-op */
-    if (chan_hasop(m) && chk_deop(fr, chan) && !me)
-        /* && target_priority(chan, m, 1) */
-      add_mode(chan, '-', 'o', nick);
-
-    /* if channel is enforce bans */
-    if (channel_enforcebans(chan) &&
-        !chan_sentkick(m) && 
-        /* and user matches a ban */
-        (u_match_mask(global_bans, userhost) || u_match_mask(chan->bans, userhost)) &&
-        /* and it's not me, and i'm an op */
-        !me) {
-      /*  && target_priority(chan, m, 0) */
-      dprintf(DP_SERVER, "KICK %s %s :%s%s\n", chan->name, nick, bankickprefix, r_banned(chan));
-      m->flags |= SENTKICK;
-    }
-    /* if the user is a +k */
-    else if ((chan_kick(fr) || glob_kick(fr)) &&
-           !chan_sentkick(m) &&
-           /* and it's not me :) who'd set me +k anyway, a sicko? */
-           /* and if im an op */
-           !me) {
-           /* && target_priority(chan, m, 0) */
-      /* cya later! */
-      quickban(chan, userhost);
-      dprintf(DP_SERVER, "KICK %s %s :%s%s\n", chan->name, nick, bankickprefix, response(RES_KICKBAN));
-      m->flags |= SENTKICK;
-    }
-  }
-
   return 0;
 }
 
@@ -2046,16 +2024,13 @@ static int got315(char *from, char *msg)
   /* Finished getting who list, can now be considered officially ON CHANNEL */
   chan->ircnet_status |= CHAN_ACTIVE;
   chan->ircnet_status &= ~(CHAN_PEND | CHAN_JOINING);
+  memberlist* me = ismember(chan, botname);
   /* Am *I* on the channel now? if not, well d0h. */
-  if (shouldjoin(chan) && !ismember(chan, botname)) {
+  if (shouldjoin(chan) && !me) {
     putlog(LOG_MISC | LOG_JOIN, chan->dname, "Oops, I'm not really on %s.", chan->dname);
-    clear_channel(chan, 1);
-    chan->ircnet_status &= ~CHAN_ACTIVE;
-    chan->ircnet_status |= CHAN_JOINING;
-    dprintf(DP_MODE, "JOIN %s %s\n",
-	    (chan->name[0]) ? chan->name : chan->dname,
-	    chan->channel.key[0] ? chan->channel.key : chan->key_prot);
+    force_join_chan(chan);
   } else {
+    me->joined = now;				/* set this to keep the whining masses happy */
     if (me_op(chan))
       recheck_channel(chan, 2);
     else if (chan->channel.members == 1)
@@ -2281,8 +2256,8 @@ static int got403(char *from, char *msg)
       putlog(LOG_MISC, "*",
              "Unique channel %s does not exist... Attempting to join with "
              "short name.", chname);
-      dprintf(DP_SERVER, "JOIN %s\n", chan->dname);
-      chan->ircnet_status |= CHAN_JOINING;
+      chan->name[0] = 0;
+      join_chan(chan);
     } else {
       /* We have found the channel, so the server has given us the short
        * name. Prefix another '!' to it, and attempt the join again...
@@ -2420,7 +2395,7 @@ static int got475(char *from, char *msg)
     if (chan->channel.key[0]) {
       free(chan->channel.key);
       chan->channel.key = (char *) my_calloc(1, 1);
-      dprintf(DP_MODE, "JOIN %s %s\n", chan->dname, chan->key_prot);
+      join_chan(chan);
     } else {
       request_in(chan);
 /* need: key */
@@ -2458,8 +2433,7 @@ static int gotinvite(char *from, char *msg)
     if (channel_pending(chan) || channel_active(chan))
       dprintf(DP_HELP, "NOTICE %s :I'm already here.\n", nick);
     else if (shouldjoin(chan))
-      dprintf(DP_MODE, "JOIN %s %s\n", (chan->name[0]) ? chan->name : chan->dname,
-              chan->channel.key[0] ? chan->channel.key : chan->key_prot);
+      join_chan(chan);
   }
   return 0;
 }
@@ -2642,11 +2616,7 @@ static int gotjoin(char *from, char *chname)
 	if (m)
 	  killmember(chan, nick);
 	m = newmember(chan, nick);
-	m->joined = now;
-	m->split = 0L;
-	m->flags = 0;
-	m->last = now;
-	m->delay = 0L;
+	m->joined = m->last = now;
 	strlcpy(m->userhost, uhost, sizeof(m->userhost));
         if (is_dotted_ip(host))
           strlcpy(m->userip, uhost, sizeof(m->userip));
@@ -2815,7 +2785,6 @@ static int gotpart(char *from, char *msg)
   if (chan && !shouldjoin(chan) && match_my_nick(nick)) {
     irc_log(chan, "Parting");    
     clear_channel(chan, 1);
-    chan->ircnet_status = 0;
     return 0;
   }
   if (chan && !channel_pending(chan)) {
@@ -2841,14 +2810,7 @@ static int gotpart(char *from, char *msg)
       irc_log(chan, "Part: %s (%s)", nick, uhost);
     /* If it was me, all hell breaks loose... */
     if (match_my_nick(nick)) {
-      clear_channel(chan, 1);
-      chan->ircnet_status = 0;
-      if (shouldjoin(chan)) {
-	dprintf(DP_MODE, "JOIN %s %s\n",
-	        (chan->name[0]) ? chan->name : chan->dname,
-	        chan->channel.key[0] ? chan->channel.key : chan->key_prot);
-        chan->ircnet_status |= CHAN_JOINING;
-      }
+      check_rejoin(chan);
     } else
       check_lonely_channel(chan);
   }
@@ -2871,13 +2833,8 @@ static int gotkick(char *from, char *origmsg)
 
   char *nick = newsplit(&msg);
 
-  if (match_my_nick(nick) && channel_pending(chan) && shouldjoin(chan) && !channel_joining(chan)) {
-    chan->ircnet_status = 0;
-    chan->ircnet_status |= CHAN_JOINING;
-    dprintf(DP_MODE, "JOIN %s %s\n",
-            (chan->name[0]) ? chan->name : chan->dname,
-            chan->channel.key[0] ? chan->channel.key : chan->key_prot);
-    clear_channel(chan, 1);
+  if (match_my_nick(nick) && channel_pending(chan)) {
+    check_rejoin(chan);
     return 0; /* rejoin if kicked before getting needed info <Wcc[08/08/02]> */
   }
   if (channel_active(chan)) {
@@ -2919,13 +2876,8 @@ static int gotkick(char *from, char *origmsg)
     }
     irc_log(chan, "%s was kicked by %s (%s)", s1, from, msg);
     /* Kicked ME?!? the sods! */
-    if (match_my_nick(nick) && shouldjoin(chan) && !channel_joining(chan)) {
-      chan->ircnet_status = 0;
-      dprintf(DP_MODE, "JOIN %s %s\n",
-              (chan->name[0]) ? chan->name : chan->dname,
-              chan->channel.key[0] ? chan->channel.key : chan->key_prot);
-      chan->ircnet_status |= CHAN_JOINING;
-      clear_channel(chan, 1);
+    if (match_my_nick(nick)) {
+      check_rejoin(chan);
     } else {
       killmember(chan, nick);
       check_lonely_channel(chan);
@@ -3036,11 +2988,10 @@ void check_should_cycle(struct chanset_t *chan)
     /* I'm only one opped here... and other side has some ops... so i'm cycling */
     if (localnonops) {
       /* need to unset any +kil first */
-      dprintf(DP_MODE, "MODE %s -ilk %s\nPART %s\nJOIN %s\n", chan->name,
-                            (chan->channel.key && chan->channel.key[0]) ? chan->channel.key : "",
-                             chan->name, chan->name);
+      dprintf(DP_MODE, "MODE %s -ilk %s\n", chan->name[0] ? chan->name : chan->dname, (chan->channel.key && chan->channel.key[0]) ? chan->channel.key : "");
+      dprintf(DP_MODE, "PART %s\n", chan->name[0] ? chan->name : chan->dname);
     } else
-      dprintf(DP_MODE, "PART %s\nJOIN %s\n", chan->name, chan->name);
+      dprintf(DP_MODE, "PART %s\n", chan->name[0] ? chan->name : chan->dname);
   }
 }
 

+ 24 - 41
src/mod/irc.mod/irc.c

@@ -69,7 +69,6 @@ static cache_t *irccache = NULL;
 
 #define do_eI (((now - chan->channel.last_eI) > 30) ? 1 : 0)
 
-static int net_type = 0;
 static time_t wait_split = 900;    /* Time to wait for user to return from
                                  * net-split. */
 int max_bans;                   /* Modified by net-type 1-4 */
@@ -87,7 +86,7 @@ bool use_354 = 0;                /* Use ircu's short 354 /who
 static bool kick_fun = 0;
 static bool ban_fun = 1;
 static bool prevent_mixing = 1;  /* To prevent mixing old/new modes */
-static bool include_lk = 1;      /* For correct calculation
+bool include_lk = 1;      /* For correct calculation
                                  * in real_add_mode. */
 bd::HashTable<bd::String, unsigned long> bot_counters;
 static unsigned long my_counter = 0;
@@ -605,8 +604,7 @@ getin_request(char *botnick, char *code, char *par)
         chan->channel.key = strdup(nick);
 
         putlog(LOG_GETIN, "*", "Got key for %s from %s (%s) - Joining", chan->dname, botnick, chan->channel.key);
-        dprintf(DP_MODE, "JOIN %s %s\n", chan->name[0] ? chan->name : chan->dname, chan->channel.key);
-        chan->ircnet_status |= CHAN_JOINING;
+        join_chan(chan);
       } else {
         putlog(LOG_GETIN, "*", "Got key for %s from %s - I'm already in the channel", chan->dname, botnick);
       }
@@ -1347,6 +1345,21 @@ static void send_chan_who(int queue, struct chanset_t *chan) {
       dprintf(queue, "WHO %s\n", chan->name);
 }
 
+void force_join_chan(struct chanset_t* chan, int idx) {
+  chan->ircnet_status = 0;
+  join_chan(chan, idx);
+}
+
+void join_chan(struct chanset_t* chan, int idx) {
+  if (shouldjoin(chan) && !(chan->ircnet_status & (CHAN_ACTIVE | CHAN_PEND | CHAN_JOINING))) {
+    dprintf(idx, "JOIN %s %s\n",
+        (chan->name[0]) ? chan->name : chan->dname,
+        chan->channel.key[0] ? chan->channel.key : chan->key_prot);
+    clear_channel(chan, 1);
+    chan->ircnet_status |= CHAN_JOINING;
+  }
+}
+
 /* If i'm the only person on the channel, and i'm not op'd,
  * might as well leave and rejoin. If i'm NOT the only person
  * on the channel, but i'm still not op'd, demand ops.
@@ -1371,9 +1384,7 @@ check_lonely_channel(struct chanset_t *chan)
     if (chan->name[0] != '+') { /* Its pointless to cycle + chans for ops */
       putlog(LOG_MISC, "*", "Trying to cycle %s to regain ops.", chan->dname);
       dprintf(DP_MODE, "PART %s\n", chan->name);
-      /* If it's a !chan, we need to recreate the channel with !!chan <cybah> */
-      dprintf(DP_MODE, "JOIN %s%s %s\n", (chan->dname[0] == '!') ? "!" : "", chan->dname, chan->key_prot);
-      chan->ircnet_status |= CHAN_JOINING;
+      // Will auto rejoin once the bot PARTs
       whined = 0;
     }
   } else if (any_ops(chan)) {
@@ -1604,12 +1615,8 @@ check_expired_chanstuff(struct chanset_t *chan)
       m = n;
     }
     check_lonely_channel(chan);
-  } else if (shouldjoin(chan) && !channel_pending(chan)) {
-    dprintf(DP_MODE, "JOIN %s %s\n",
-            (chan->name[0]) ? chan->name : chan->dname,
-            chan->channel.key[0] ? chan->channel.key : chan->key_prot);
-    chan->ircnet_status |= CHAN_JOINING;
-  }
+  } else if (shouldjoin(chan))
+    join_chan(chan);
 }
 
 void
@@ -1618,8 +1625,10 @@ irc_minutely()
   for (register struct chanset_t *chan = chanset; chan; chan = chan->next) {
     warn_pls_take(chan);
     if (server_online) {
-      check_netfight(chan);
-      check_servers(chan);
+      if (!channel_pending(chan)) {
+        check_netfight(chan);
+        check_servers(chan);
+      }
       check_expired_chanstuff(chan);
     }
   }
@@ -1720,30 +1729,6 @@ irc_report(int idx, int details)
   }
 }
 
-static void
-do_nettype()
-{
-  switch (net_type) {
-    case 0:                    /* Efnet */
-      include_lk = 0;
-      break;
-    case 1:                    /* Ircnet */
-      include_lk = 1;
-      break;
-    case 2:                    /* Undernet */
-      include_lk = 1;
-      break;
-    case 3:                    /* Dalnet */
-      include_lk = 1;
-      break;
-    case 4:                    /* hybrid-6+ */
-      include_lk = 0;
-      break;
-    default:
-      break;
-  }
-}
-
 static void bot_release_nick (char *botnick, char *code, char *par) {
   release_nick(par);
 }
@@ -1779,6 +1764,4 @@ irc_init()
   add_builtins("raw", irc_raw);
   add_builtins("msg", C_msg);
   add_builtins("msgc", C_msgc);
-
-  do_nettype();
 }

+ 4 - 1
src/mod/irc.mod/irc.h

@@ -110,6 +110,9 @@ static void get_channel_masks(struct chanset_t* chan);
 
 #endif /* MAKING_IRC */
 
+void force_join_chan(struct chanset_t* chan, int idx = DP_MODE);
+void join_chan(struct chanset_t* chan, int idx = DP_MODE);
+
 int check_bind_authc(char *, Auth *, char *, char *);
 void notice_invite(struct chanset_t *, char *, char *, char *, bool);
 void real_add_mode(struct chanset_t *, const char, const char, const char *, bool);
@@ -144,7 +147,7 @@ void reset_chan_info(struct chanset_t *);
 char *getnick(const char *, struct chanset_t *);
 
 extern int		max_bans, max_exempts, max_invites, max_modes;
-extern bool		use_354;
+extern bool		use_354, include_lk;
 extern unsigned int	modesperline;
 #endif				/* _EGG_MOD_IRC_IRC_H */
 

+ 8 - 14
src/mod/irc.mod/mode.c

@@ -179,7 +179,7 @@ flush_cookies(struct chanset_t *chan, int pri)
       char outbuf[201] = "";
 
       const size_t len = simple_snprintf(outbuf, sizeof(outbuf), "MODE %s %s\r\n", chan->name, out);
-      tputs(serv, outbuf, len);
+      dprintf_real(DP_MODE, outbuf, len, sizeof(outbuf));
       /* dprintf(DP_MODE, "MODE %s %s\n", chan->name, out); */
     } else
       dprintf(DP_MODE, "MODE %s %s\n", chan->name, out);
@@ -588,7 +588,7 @@ got_op(struct chanset_t *chan, memberlist *m, memberlist *mv)
         add_mode(chan, '-', 'o', mv->nick);
 
       if (len)
-        tputs(serv, outbuf, len);
+        dprintf_real(DP_MODE_NEXT, outbuf, len, sizeof(outbuf));
     }
 
 
@@ -1076,10 +1076,7 @@ gotmode(char *from, char *msg)
               if (role < 5 && !chan_sentkick(m)) {
                 m->flags |= SENTKICK;
                 const size_t len = simple_snprintf(tmp, sizeof(tmp), "KICK %s %s :%s%s\r\n", chan->name, m->nick, kickprefix, response(RES_MASSDEOP));
-                if (role <= 2)
-                  tputs(serv, tmp, len);
-                else
-                  dprintf(DP_MODE, "%s", tmp);
+                dprintf_real(DP_MODE_NEXT, tmp, len, sizeof(tmp));
               } else {
                 if (u) {
                   simple_snprintf(tmp, sizeof(tmp), "Mass deop on %s by %s", chan->dname, m->nick);
@@ -1098,10 +1095,7 @@ gotmode(char *from, char *msg)
                 if (role < 5) {
                   m->flags |= SENTKICK;
                   const size_t len = simple_snprintf(tmp, sizeof(tmp), "KICK %s %s :%s%s\r\n", chan->name, m->nick, kickprefix, response(RES_MANUALOP));
-                  if (role <= 2)
-                    tputs(serv, tmp, len);
-                  else
-                    dprintf(DP_MODE, "%s", tmp);
+                  dprintf_real(DP_MODE_NEXT, tmp, len, sizeof(tmp));
                 } else { 
                   if (u) {
                     simple_snprintf(tmp, sizeof(tmp), "Mass op on %s by %s", chan->dname, m->nick);
@@ -1148,7 +1142,7 @@ gotmode(char *from, char *msg)
                         if (mv)
                           mv->flags |= SENTKICK;
                         const size_t len = simple_snprintf(tmp, sizeof(tmp), "KICK %s %s :%s%s\r\n", chan->name, mparam, kickprefix, response(RES_BADOPPED));
-                        tputs(serv, tmp, len);
+                        dprintf_real(DP_MODE_NEXT, tmp, len, sizeof(tmp));
                       }
                     }
                   }
@@ -1166,7 +1160,7 @@ gotmode(char *from, char *msg)
                 if (!chan_sentkick(m)) {
                   m->flags |= SENTKICK;
                   const size_t len = simple_snprintf(tmp, sizeof(tmp), "KICK %s %s :%s%s\r\n", chan->name, m->nick, kickprefix, response(RES_BADOP));
-                  tputs(serv, tmp, len);
+                  dprintf_real(DP_MODE_NEXT, tmp, len, sizeof(tmp));
                 }
                 simple_snprintf(tmp, sizeof(tmp), "%s!%s MODE %s %s", m->nick, m->userhost, chan->dname, modes[modecnt - 1]);
                 deflag_user(u, DEFLAG_BADCOOKIE, tmp, chan);
@@ -1204,7 +1198,7 @@ gotmode(char *from, char *msg)
                   /* Kick opper */
                   if (!chan_sentkick(m)) {
                     const size_t len = simple_snprintf(tmp, sizeof(tmp), "KICK %s %s :%s%s\r\n", chan->name, m->nick, kickprefix, response(RES_MANUALOP));
-                    tputs(serv, tmp, len);
+                    dprintf_real(DP_MODE_NEXT, tmp, len, sizeof(tmp));
                     m->flags |= SENTKICK;
                   }
                   simple_snprintf(tmp, sizeof(tmp), "%s!%s MODE %s %s", m->nick, m->userhost, chan->dname, modes[modecnt - 1]);
@@ -1229,7 +1223,7 @@ gotmode(char *from, char *msg)
                         if (mv)
                           mv->flags |= SENTKICK;
                         const size_t len = simple_snprintf(tmp, sizeof(tmp), "KICK %s %s :%s%s\r\n", chan->name, mparam, kickprefix, response(RES_MANUALOPPED));
-                        tputs(serv, tmp, len);
+                        dprintf_real(DP_MODE_NEXT, tmp, len, sizeof(tmp));
                       }
                     }
                   }

+ 11 - 50
src/mod/server.mod/server.c

@@ -82,13 +82,13 @@ static bool waiting_for_awake;	/* set when i unidle myself, cleared when I get t
 time_t server_online = 0;	/* server connection time */
 char botrealname[121] = "A deranged product of evil coders.";	/* realname of bot */
 static interval_t server_timeout = 15;	/* server timeout for connecting */
+static const interval_t stoned_timeout = 500;
 struct server_list *serverlist = NULL;	/* old-style queue, still used by
 					   server list */
 interval_t cycle_time;			/* cycle time till next server connect */
 port_t default_port = 6667;		/* default IRC port */
 bool trigger_on_ignore;	/* trigger bindings if user is ignored ? */
 int answer_ctcp = 1;		/* answer how many stacked ctcp's ? */
-static bool check_mode_r;	/* check for IRCNET +r modes */
 static int net_type = NETT_EFNET;
 static bool resolvserv;		/* in the process of resolving a server host */
 static time_t lastpingtime;	/* IRCNet LAGmeter support -- drummer */
@@ -99,8 +99,9 @@ static bool use_penalties = 0;
 static int use_fastdeq;
 size_t nick_len = 9;			/* Maximal nick length allowed on the network. */
 char deaf_char = 0;
-bool deaf_set = 0;
+bool in_deaf = 0;
 char callerid_char = 0;
+bool in_callerid = 0;
 
 static bool double_mode = 0;		/* allow a msgs to be twice in a queue? */
 static bool double_server = 0;
@@ -815,35 +816,6 @@ void next_server(int *ptr, char *servname, port_t *port, char *pass)
     pass[0] = 0;
 }
 
-static void do_nettype(void)
-{
-  switch (net_type) {
-  case NETT_EFNET:
-    check_mode_r = 0;
-    break;
-  case NETT_IRCNET:
-    check_mode_r = 1;
-    use_fastdeq = 3;
-    simple_snprintf(stackablecmds, sizeof(stackablecmds), "INVITE AWAY VERSION NICK");
-    break;
-  case NETT_UNDERNET:
-    check_mode_r = 0;
-    use_fastdeq = 2;
-    simple_snprintf(stackablecmds, sizeof(stackablecmds), "PRIVMSG NOTICE TOPIC PART WHOIS USERHOST USERIP ISON");
-    simple_snprintf(stackable2cmds, sizeof(stackable2cmds), "USERHOST USERIP ISON");
-    break;
-  case NETT_DALNET:
-    check_mode_r = 0;
-    use_fastdeq = 2;
-    simple_snprintf(stackablecmds, sizeof(stackablecmds), "PRIVMSG NOTICE PART WHOIS WHOWAS USERHOST ISON WATCH DCCALLOW");
-    simple_snprintf(stackable2cmds, sizeof(stackable2cmds), "USERHOST ISON WATCH");
-    break;
-  case NETT_HYBRID_EFNET:
-    check_mode_r = 0;
-    break;
-  }
-}
-
 /*
  *     CTCP DCC CHAT functions
  */
@@ -1021,13 +993,13 @@ static void server_secondly()
           bool need_chatter = doflood(NULL) || (Auth::ht_host.size() && auth_chan && strlen(auth_prefix));
 
           // In +D but am +f, need to -D
-          if (deaf_set && (need_chatter || !use_deaf)) {
+          if (in_deaf && (need_chatter || !use_deaf)) {
             dprintf(DP_SERVER, "MODE %s -%c\n", botname, deaf_char);
-            deaf_set = 0;
-          } else if (!deaf_set && use_deaf && !need_chatter) {
+            in_deaf = 0;
+          } else if (!in_deaf && use_deaf && !need_chatter) {
             // Not +D but should be, probably had +f removed.
             dprintf(DP_SERVER, "MODE %s +%c\n", botname, deaf_char);
-            deaf_set = 1;
+            in_deaf = 1;
           }
         }
 
@@ -1044,17 +1016,10 @@ static void server_check_lag()
     dprintf(DP_DUMP, "PING :%li\n", (long)now);
     lastpingtime = now;
     waiting_for_awake = 1;
-  }
-}
-
-static void server_5minutely()
-{
-  if (server_online && waiting_for_awake && ((now - lastpingtime) >= 300)) {
-      /* Uh oh!  Never got pong from last time, five minutes ago!
-       * Server is probably stoned.
-       */
-      disconnect_server(servidx, DO_LOST);
-      putlog(LOG_SERV, "*", "Server got stoned; jumping...");
+  } else if (servidx != -1 && waiting_for_awake && ((now - lastpingtime) >= stoned_timeout)) {
+    // Not checking server_online as this will handle connect timeouts as well where the connect() works, but the server gets stoned afterwards
+    disconnect_server(servidx, DO_LOST);
+    putlog(LOG_SERV, "*", "Server got stoned; jumping...");
   }
 }
 
@@ -1137,7 +1102,6 @@ static cmd_t my_ctcps[] =
 void server_init()
 {
   strlcpy(botrealname, "A deranged product of evil coders", sizeof(botrealname));
-  strlcpy(stackable2cmds, "USERHOST ISON", sizeof(stackable2cmds));
 
   mq.head = hq.head = modeq.head = NULL;
   mq.last = hq.last = modeq.last = NULL;
@@ -1161,8 +1125,5 @@ void server_init()
 
   timer_create_secs(1, "server_secondly", (Function) server_secondly);
   timer_create_secs(30, "server_check_lag", (Function) server_check_lag);
-  timer_create_secs(300, "server_5minutely", (Function) server_5minutely);
 //  timer_create_secs(60, "minutely_checks", (Function) minutely_checks);
-
-  do_nettype();
 }

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

@@ -46,7 +46,7 @@ enum {
 
 extern bind_table_t	*BT_ctcp, *BT_ctcr, *BT_msgc;
 extern size_t		nick_len;
-extern bool		trigger_on_ignore, floodless, keepnick, deaf_set;
+extern bool		trigger_on_ignore, floodless, keepnick, in_deaf, in_callerid;
 extern int 		servidx, ctcp_mode, answer_ctcp, serv, curserv, default_alines;
 extern unsigned int     rolls;
 extern port_t		default_port, newserverport, curservport;

+ 54 - 35
src/mod/server.mod/servmsg.c

@@ -209,13 +209,8 @@ void
 join_chans()
 {
   for (register struct chanset_t *chan = chanset; chan; chan = chan->next) {
-    if (shouldjoin(chan)) {
-      // Clear out all channel status flags
-      chan->ircnet_status = 0;
-      dprintf(DP_SERVER, "JOIN %s %s\n", (chan->name[0]) ? chan->name : chan->dname,
-                                         chan->channel.key[0] ? chan->channel.key : chan->key_prot);
-      chan->ircnet_status |= CHAN_JOINING;
-    }
+    if (shouldjoin(chan))
+      force_join_chan(chan, DP_SERVER);
   }
 }
 
@@ -226,6 +221,7 @@ static int got001(char *from, char *msg)
 
   fixcolon(msg);
   server_online = now;
+  waiting_for_awake = 0;
   rehash_server(from, msg);
   /* Ok...param #1 of 001 = what server thinks my nick is */
 
@@ -271,6 +267,8 @@ got004(char *from, char *msg)
   if (strstr(tmp, "u2.") || strstr(tmp, "Unreal") || strstr(tmp, "snircd")) {
     putlog(LOG_DEBUG, "*", "Disabling cookies as they are not supported on %s", cursrvname);
     cookies_disabled = true;
+  } else if (strstr(tmp, "hybrid") || strstr(tmp, "ratbox") || strstr(tmp, "Charybdis") || strstr(tmp, "ircd-seven")) {
+    include_lk = 0;
   }
 
   return 0;
@@ -312,22 +310,41 @@ got005(char *from, char *msg)
       if (need_to_rehash_monitor)
         rehash_monitor_list();
     }
-    else if (!strcasecmp(tmp, "NETWORK"))
+    else if (!strcasecmp(tmp, "NETWORK")) {
       strlcpy(curnetwork, p, 120);
-    else if (!strcasecmp(tmp, "PENALTY"))
+      if (!strcasecmp(tmp, "IRCnet")) {
+        simple_snprintf(stackablecmds, sizeof(stackablecmds), "INVITE AWAY VERSION NICK");
+        simple_snprintf(stackable2cmds, sizeof(stackable2cmds), "USERHOST ISON");
+        use_fastdeq = 3;
+      } else if (!strcasecmp(tmp, "DALnet")) {
+        simple_snprintf(stackablecmds, sizeof(stackablecmds), "PRIVMSG NOTICE PART WHOIS WHOWAS USERHOST ISON WATCH DCCALLOW");
+        simple_snprintf(stackable2cmds, sizeof(stackable2cmds), "USERHOST ISON WATCH");
+        use_fastdeq = 2;
+      } else if (!strcasecmp(tmp, "UnderNet")) {
+        simple_snprintf(stackablecmds, sizeof(stackablecmds), "PRIVMSG NOTICE TOPIC PART WHOIS USERHOST USERIP ISON");
+        simple_snprintf(stackable2cmds, sizeof(stackable2cmds), "USERHOST USERIP ISON");
+        use_fastdeq = 2;
+      } else {
+        stackablecmds[0] = 0;
+        simple_snprintf(stackable2cmds, sizeof(stackable2cmds), "USERHOST ISON");
+        use_fastdeq = 0;
+      }
+    } else if (!strcasecmp(tmp, "PENALTY"))
       use_penalties = 1;
     else if (!strcasecmp(tmp, "WHOX"))
       use_354 = 1;
     else if (!strcasecmp(tmp, "DEAF")) {
       deaf_char = p ? p[0] : 'D';
-      if (use_deaf) {
+      if (use_deaf && !in_deaf) {
         dprintf(DP_SERVER, "MODE %s +%c\n", botname, deaf_char);
-        deaf_set = 1;
+        in_deaf = 1;
       }
     } else if (!strcasecmp(tmp, "CALLERID")) {
       callerid_char = p ? p[0] : 'g';
-      if (use_callerid)
+      if (use_callerid && !in_callerid) {
         dprintf(DP_SERVER, "MODE %s +%c\n", botname, callerid_char);
+        in_callerid = 1;
+      }
     } else if (!strcasecmp(tmp, "EXCEPTS"))
       use_exempts = 1;
     else if (!strcasecmp(tmp, "INVEX"))
@@ -382,15 +399,10 @@ static int got442(char *from, char *msg)
   newsplit(&msg);
   chname = newsplit(&msg);
   chan = findchan(chname);
-  if (chan)
-    if (shouldjoin(chan) && !channel_joining(chan)) {
-      putlog(LOG_MISC, chname, "Server says I'm not on channel: %s", chname);
-      clear_channel(chan, 1);
-      chan->ircnet_status = 0;
-      chan->ircnet_status |= CHAN_JOINING;
-      dprintf(DP_MODE, "JOIN %s %s\n", chan->name,
-	      chan->channel.key[0] ? chan->channel.key : chan->key_prot);
-    }
+  if (chan && shouldjoin(chan) && !channel_joining(chan)) {
+    putlog(LOG_MISC, chname, "Server says I'm not on channel: %s", chname);
+    force_join_chan(chan);
+  }
 
   return 0;
 }
@@ -415,15 +427,16 @@ static char lastmsghost[FLOOD_GLOBAL_MAX][128];
 static time_t lastmsgtime[FLOOD_GLOBAL_MAX];
 static int dronemsgs;
 static time_t dronemsgtime;
-static bool in_callerid = 0;
 static interval_t flood_callerid_time = 60;
 
 rate_t flood_callerid = { 6, 2 };
 
 void unset_callerid(int data)
 {
-  dprintf(DP_MODE, "MODE %s :-%c\n", botname, callerid_char);
-  in_callerid = 0;
+  if (in_callerid) {
+    dprintf(DP_MODE, "MODE %s :-%c\n", botname, callerid_char);
+    in_callerid = 0;
+  }
 }
 
 /* Do on NICK, PRIVMSG, NOTICE and JOIN.
@@ -1213,8 +1226,8 @@ static int gotmode(char *from, char *msg)
   ch = newsplit(&buf);
   /* Usermode changes? */
   if (strchr(CHANMETA, ch[0]) == NULL) {
-    if (match_my_nick(ch) && check_mode_r) {
-      /* umode +r? - D0H dalnet uses it to mean something different */
+    if (match_my_nick(ch) && !strcmp(curnetwork, "IRCnet")) {
+      // Umode +r is restricted on IRCnet, can only chat.
       fixcolon(buf);
       if ((buf[0] == '+') && strchr(buf, 'r')) {
 	putlog(LOG_SERV, "*", "%s has me i-lined (jumping)", dcc[servidx].host);
@@ -1246,7 +1259,7 @@ static void disconnect_server(int idx, int dolost)
   use_penalties = 0;
   use_354 = 0;
   deaf_char = 0;
-  deaf_set = 0;
+  in_deaf = 0;
   callerid_char = 0;
   in_callerid = 0;
   use_exempts = 0;
@@ -1283,11 +1296,11 @@ static void kill_server(int idx, void *x)
 {
   disconnect_server(idx, NO_LOST);	/* eof_server will lostdcc() it. */
 
-  if (!segfaulted)		// don't bother if we've segfaulted, too many memory calls in this loop
-    for (struct chanset_t *chan = chanset; chan; chan = chan->next) {
-      chan->ircnet_status = 0;
-      clear_channel(chan, 1);
-    }
+  if (segfaulted)		// don't bother if we've segfaulted, too many memory calls in this loop
+    return;
+
+  for (struct chanset_t *chan = chanset; chan; chan = chan->next)
+    clear_channel(chan, 1);
   /* A new server connection will be automatically initiated in
      about 2 seconds. */
 }
@@ -1328,8 +1341,13 @@ static void server_activity(int idx, char *msg, int len)
     serv = dcc[idx].sosck;
     */
     SERVER_SOCKET.timeout_val = 0;
-  }
-  waiting_for_awake = 0;
+
+    // Setup timer for conecting
+    waiting_for_awake = 1;
+    lastpingtime = now - (stoned_timeout + 30); //30 seconds to reach 001
+  } else if (server_online) // Only set once 001 has been received
+    waiting_for_awake = 0;
+
   if (msg[0] == ':') {
     msg++;
     from = newsplit(&msg);
@@ -1503,7 +1521,7 @@ hide_chans(const char *nick, struct userrec *u, char *_channels, bool publicOnly
         if (!(p = strchr(chname, '!')))
           continue;
 
-    chan = findchan_by_dname(p);
+    chan = findchan(p);
 
     if (chan && !publicOnly)
      get_user_flagrec(u, &fr, chan->dname, chan);
@@ -1845,6 +1863,7 @@ static void connect_server(void)
     rolls = 0;
     altnick_char = 0;
     use_monitor = 0;
+    include_lk = 1;
 
     for (chan = chanset; chan; chan = chan->next)
       chan->ircnet_status &= ~CHAN_JUPED;

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

@@ -407,7 +407,7 @@ share_chattr(int idx, char *par)
             if (!(dcc[idx].status & STAT_GETTING))
               putlog(LOG_CMDS, "@", "%s: chattr %s %s %s", dcc[idx].nick, hand, s, par);
           } else
-            recheck_channel(cst, 0);
+            check_this_user(u->handle, 0, NULL);
         } else {
           fr.match = FR_GLOBAL;
           get_user_flagrec(dcc[idx].user, &fr, 0);
@@ -426,8 +426,7 @@ share_chattr(int idx, char *par)
             if (!(dcc[idx].status & STAT_GETTING))
               putlog(LOG_CMDS, "@", "%s: chattr %s %s", dcc[idx].nick, hand, s);
           } else {
-            for (cst = chanset; cst; cst = cst->next)
-              recheck_channel(cst, 0);
+            check_this_user(u->handle, 0, NULL);
           }
         }
         noshare = 0;

+ 7 - 3
src/set.c

@@ -287,9 +287,13 @@ sdprintf("var (mem): %s -> %s", var->name, datain ? datain : "(NULL)");
           which = '-';
         if (which) {
           char mode_char = strcmp(var->name, "deaf") == 0 ? deaf_char : callerid_char;
-          if (mode_char == deaf_char)
-            deaf_set = num;
-          dprintf(DP_SERVER, "MODE %s %c%c\n", botname, which, mode_char);
+          if ((mode_char == deaf_char && in_deaf != num) || (mode_char == callerid_char && in_callerid != num)) {
+            if (mode_char == deaf_char)
+              in_deaf = num;
+            else if (mode_char == callerid_char)
+              in_callerid = num;
+            dprintf(DP_SERVER, "MODE %s %c%c\n", botname, which, mode_char);
+          }
         }
       }
     }