]> jfr.im git - irc/rizon/plexus4.git/commitdiff
Add delay
authorAdam <redacted>
Sat, 24 Nov 2018 20:48:11 +0000 (15:48 -0500)
committerAdam <redacted>
Thu, 29 Nov 2018 00:49:31 +0000 (19:49 -0500)
18 files changed:
include/channel.h
include/client.h
include/conf.h
include/delay.h [new file with mode: 0644]
include/send.h
modules/core/m_message.c
modules/core/m_nick.c
src/Makefile.am
src/channel.c
src/client.c
src/conf.c
src/conf_lexer.l
src/conf_parser.y
src/delay.c [new file with mode: 0644]
src/ircd.c
src/parse.c
src/s_user.c
src/send.c

index b82818e7e0c85dd6fee931ddde08f3ff409e432b..9d06b86ef6aeea2f1b18a590e5c3fb25405ac765 100644 (file)
@@ -135,6 +135,7 @@ struct Ban
 extern dlink_list global_channel_list;
 
 extern int msg_is_ctcp(const char *msg);
+extern void channel_flags_to_prefix(unsigned int flags, char *c);
 extern int ban_matches(struct Client *who, struct Ban *bp);
 extern int find_bmask(struct Client *, const dlink_list *const, struct Extban *);
 extern int is_bwsave(const struct Channel *chptr, struct Client *source_p);
index cbab3ed7266c3ee5f7fcbcf4ea1a0d66084cadb0..5ae9c7f96abf8b122573cb34457689fca768e833 100644 (file)
@@ -445,6 +445,7 @@ struct Client
   struct Client    *servptr;    /**< Points to server this Client is on */
   struct Client    *from;       /**< == self, if Local Client, *NEVER* NULL! */
 
+  time_t            signon;     /**< Signon time. For remote clients is oldest nick TS */
   time_t            tsinfo;     /**< TS on the nick, SVINFO on server */
 
   unsigned int      flags;      /**< client flags */
@@ -501,6 +502,7 @@ struct Client
 
   char              *cgisockhost; /**< if this client is a webirc client, this is the ip of where they are from */
   char              *cgihost;     /**< if this client is a webirc client, this is the host of where they are from */
+  int               seen_privmsgs; /**< number of privmsgs seen from the client to channels */
 };
 
 
index ac5238c6bb13a06a6dfc08dbddec4d61312ef665..60c67319891739c0bd525922c7de2a54fcb64a39 100644 (file)
@@ -289,6 +289,9 @@ struct config_file_entry
   int enable_forwarding;
   const EVP_MD *message_digest_algorithm;
   int mass_highlight_nicks;
+  int delay_secs;
+  int delay_message_count;
+  int delay_signon_secs;
 };
 
 struct config_channel_entry
diff --git a/include/delay.h b/include/delay.h
new file mode 100644 (file)
index 0000000..c6ed3e1
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
+ *
+ *  Copyright (c) 2018 Adam <Adam@anope.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *  USA
+ */
+
+struct Client;
+struct Channel;
+
+extern void delay_init(void);
+extern void delay_queue(struct Client *client, struct Channel *channel, int privmsg, unsigned int flags, const char *message);
index 3c5a38b2f45c5b8338535c59170bba9c1f2926da..f6511a93253f84e7e06cfe31f1f3e6a07bb4fe9e 100644 (file)
@@ -61,6 +61,13 @@ enum
   MATCH_HOST   = 2
 };
 
+enum
+{
+  SEND_FLAG_CTCP   = 0x1,
+  SEND_FLAG_LOCAL  = 0x2,
+  SEND_FLAG_REMOTE = 0x4
+};
+
 /*
  * struct decls
  */
@@ -75,7 +82,7 @@ extern void send_queued_all(void);
 extern void sendto_one(struct Client *, const char *, ...) AFP(2,3);
 extern void sendto_channel_butone(struct Client *, struct Client *,
                                   struct Channel *, unsigned int,
-                                  int is_ctcp,
+                                  unsigned int,
                                   const char *, ...) AFP(6,7);
 extern void sendto_common_channels_local(struct Client *, int, unsigned int, unsigned int,
                                          const char *, ...) AFP(5,6);
index 24b0bc696e7dcb5f50fcae1eb8d0b86de4a150d8..adf0821d1bd02231296a23ea6ece50e812754705 100644 (file)
@@ -40,6 +40,7 @@
 #include "hash.h"
 #include "packet.h"
 #include "s_user.h"
+#include "delay.h"
 
 enum
 {
@@ -213,31 +214,6 @@ flood_attack_channel(int p_or_n, struct Client *source_p,
   return 0;
 }
 
-static void
-flags_to_prefix(unsigned int flags, char *c)
-{
-  if (flags & CHFL_VOICE)
-  {
-    *c = '+';
-  }
-  else if (flags & CHFL_HALFOP)
-  {
-    *c = '%';
-   }
-  else if (flags & CHFL_CHANOP)
-  {
-    *c = '@';
-  }
-  else if (flags & CHFL_PROTECTED)
-  {
-    *c = CHANPROTECT_PREFIX;
-  }
-  else if (flags & CHFL_OWNER)
-  {
-    *c = CHANOWNER_PREFIX;
-  }
-}
-
 /* msg_channel()
  *
  * inputs      - flag privmsg or notice
@@ -281,6 +257,8 @@ msg_channel(int p_or_n, const char *command, struct Client *client_p,
       if (flood_attack_channel(p_or_n, source_p, chptr))
         return;
 
+      source_p->seen_privmsgs++;
+
       ctcp_reply = p_or_n == NOTICE && msg_is_ctcp(text);
       if (MyClient(source_p) && !ctcp_reply && target_check_channel(source_p, chptr))
       {
@@ -304,13 +282,25 @@ msg_channel(int p_or_n, const char *command, struct Client *client_p,
       return;
 
     if (e->flags)
-      flags_to_prefix(e->flags, &c);
+      channel_flags_to_prefix(e->flags, &c);
+
+    int send_flags = SEND_FLAG_LOCAL | SEND_FLAG_REMOTE;
+
+    if (IsClient(source_p) && !IsIdentified(source_p)
+        && !HasFlag(source_p, FLAGS_SERVICE) && !HasUMode(source_p, UMODE_OPER)
+        && (source_p->seen_privmsgs < ConfigFileEntry.delay_message_count || source_p->signon + ConfigFileEntry.delay_signon_secs > CurrentTime))
+    {
+      delay_queue(source_p, chptr, p_or_n == PRIVMSG, e->flags, text);
+      send_flags = SEND_FLAG_REMOTE; // not forwarded to users
+    }
 
     if (c)
-      sendto_channel_butone(client_p, source_p, chptr, e->flags, msg_is_ctcp(text), "%s %c%s :%s",
+      sendto_channel_butone(client_p, source_p, chptr, e->flags,
+                            send_flags | (msg_is_ctcp(text) ? SEND_FLAG_CTCP : 0), "%s %c%s :%s",
                             command, c, chptr->chname, text);
     else
-      sendto_channel_butone(client_p, source_p, chptr, 0, msg_is_ctcp(text), "%s %s :%s",
+      sendto_channel_butone(client_p, source_p, chptr, 0,
+                            send_flags | (msg_is_ctcp(text) ? SEND_FLAG_CTCP : 0), "%s %s :%s",
                             command, chptr->chname, text);
     return;
   }
index 01dcd1acde1782ac8916cb7f5c435d339b64a416..2cc83d457313607c236bd2b01ecd6cca411b24a5 100644 (file)
@@ -326,7 +326,13 @@ nick_from_server(struct Client *client_p, struct Client *source_p, int parc,
     if (parc > 2)
       source_p->hopcount = atoi(parv[2]);
     if (newts)
+    {
       source_p->tsinfo = newts;
+      if (newts < CurrentTime)
+      {
+        source_p->signon = newts;
+      }
+    }
     else
       newts = source_p->tsinfo = CurrentTime;
 
@@ -413,6 +419,11 @@ uid_from_server(struct Client *client_p, struct Client *source_p, int parc,
 
   source_p->hopcount = atoi(parv[2]);
   source_p->tsinfo = newts;
+  if (newts < CurrentTime)
+  {
+    // take a guess based on nick ts
+    source_p->signon = newts;
+  }
   strlcpy(source_p->svid, svsid, sizeof(source_p->svid));
 
   /* copy the nick in place */
index 50634f48c9c76f0d09dcee316794e9e70cd2915e..bbf67db3d5eb32b9e55c8ec7f58413ed339dabda 100644 (file)
@@ -22,6 +22,7 @@ libplexus_la_SOURCES =           \
                conf_parser.y     \
                conf_lexer.l      \
                dbuf.c            \
+               delay.c           \
                dnsbl.c           \
                event.c           \
                extban.c          \
index 7009a8f4d2eabc729f337d91a0cf1ba67ce632a3..442eaf65cd20ca2ced64fe9840fee5440eed2bc8 100644 (file)
@@ -1004,6 +1004,32 @@ msg_is_ctcp(const char *msg)
   return 0;
 }
 
+void
+channel_flags_to_prefix(unsigned int flags, char *c)
+{
+  if (flags & CHFL_VOICE)
+  {
+    *c = '+';
+  }
+  else if (flags & CHFL_HALFOP)
+  {
+    *c = '%';
+   }
+  else if (flags & CHFL_CHANOP)
+  {
+    *c = '@';
+  }
+  else if (flags & CHFL_PROTECTED)
+  {
+    *c = CHANPROTECT_PREFIX;
+  }
+  else if (flags & CHFL_OWNER)
+  {
+    *c = CHANOWNER_PREFIX;
+  }
+}
+
+
 /*!
  * \param chptr    pointer to Channel struct
  * \param source_p pointer to Client struct
index 5e82a33de037b17761973955b59c20f42bd1a65f..aa7c4f24f343a5121a2942967037c37ac3dcff71 100644 (file)
@@ -144,6 +144,7 @@ make_client(struct Client *from)
   SetUnknown(client_p);
   strcpy(client_p->username, "unknown");
   strcpy(client_p->svid, "0");
+  client_p->signon = CurrentTime;
 
   return client_p;
 }
index 8110cf2a088bc5eb08547bc5c4c9230f9b5c39bb..cd7accc65399bf733e77de0f0d7d610b692da267 100644 (file)
@@ -1303,6 +1303,9 @@ set_default_conf(void)
   ConfigFileEntry.enable_forwarding = 0;
   ConfigFileEntry.message_digest_algorithm = EVP_sha1();
   ConfigFileEntry.mass_highlight_nicks = 0;
+  ConfigFileEntry.delay_secs = 0;
+  ConfigFileEntry.delay_message_count = 0;
+  ConfigFileEntry.delay_signon_secs = 0;
 }
 
 static void
index 09c99765c533f873aeaebfeb9da3e27fe1f705e9..d2a74cd591f8aa09a4b4dc7bf0393d3a552ba0e2 100644 (file)
@@ -180,6 +180,9 @@ default_floodtime           { return DEFAULT_FLOODTIME; }
 default_split_server_count  { return DEFAULT_SPLIT_SERVER_COUNT; }
 default_split_user_count    { return DEFAULT_SPLIT_USER_COUNT; }
 defer                       { return DEFER; }
+delay_secs                  { return DELAY_SECS; }
+delay_message_count         { return DELAY_MESSAGE_COUNT; }
+delay_signon_secs           { return DELAY_SIGNON_SECS; }
 deny                        { return DENY; }
 description                 { return DESCRIPTION; }
 die                         { return DIE; }
index 375e8fe7b17aba1d2cf81eafd76d1eb0c0c186fc..c5cbe4b4544fb9a4155a541fab66872e089000a6 100644 (file)
@@ -191,6 +191,9 @@ reset_block_state(void)
 %token  DEFAULT_SPLIT_SERVER_COUNT
 %token  DEFAULT_SPLIT_USER_COUNT
 %token  DEFER
+%token  DELAY_SECS
+%token  DELAY_MESSAGE_COUNT
+%token  DELAY_SIGNON_SECS
 %token  DENY
 %token  DESCRIPTION
 %token  DIE
@@ -3013,7 +3016,7 @@ general_item:       general_hide_spoof_ips | general_ignore_bogus_ts |
                     general_cloak_key |
                     general_account_whois | general_disable_chmodes | general_use_target_change |
                     general_enable_extbans | general_enable_forwarding | general_ssl_message_digest_algorithm |
-                    general_mass_highlight_nicks |
+                    general_mass_highlight_nicks | general_delay_secs | general_delay_message_count | general_delay_signon_secs |
                    error;
 
 
@@ -3323,6 +3326,21 @@ general_mass_highlight_nicks: MASS_HIGHLIGHT_NICKS '=' NUMBER ';'
   ConfigFileEntry.mass_highlight_nicks = $3;
 };
 
+general_delay_secs: DELAY_SECS '=' timespec ';'
+{
+  ConfigFileEntry.delay_secs = $3;
+};
+
+general_delay_message_count: DELAY_MESSAGE_COUNT '=' NUMBER ';'
+{
+  ConfigFileEntry.delay_message_count = $3;
+};
+
+general_delay_signon_secs: DELAY_SIGNON_SECS '=' timespec ';'
+{
+  ConfigFileEntry.delay_signon_secs = $3;
+};
+
 umode_oitems:    umode_oitems ',' umode_oitem | umode_oitem;
 umode_oitem: T_NOCTCP
 {
diff --git a/src/delay.c b/src/delay.c
new file mode 100644 (file)
index 0000000..2aed722
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
+ *
+ *  Copyright (c) 2018 Adam <Adam@anope.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *  USA
+ */
+
+#include "ircd_defs.h"
+#include "ircd.h"
+#include "list.h"
+#include "mempool.h"
+#include "irc_string.h"
+#include "client.h"
+#include "hash.h"
+#include "send.h"
+#include "event.h"
+#include "conf.h"
+
+struct delayed_message
+{
+  char uid[IDLEN + 1];
+  char chname[CHANNELLEN + 1];
+  time_t ts;
+  int privmsg;
+  unsigned int flags;
+  char message[IRCD_BUFSIZE];
+  time_t created;
+  dlink_node node;
+};
+
+static mp_pool_t *delay_pool;
+static dlink_list delay_list;
+
+static void delay_process(void *);
+
+void
+delay_init(void)
+{
+  delay_pool = mp_pool_new("delay message", sizeof(struct delayed_message), 128);
+  eventAddIsh("delay_process", delay_process, NULL, 1);
+}
+
+void
+delay_queue(struct Client *client, struct Channel *channel, int privmsg, unsigned int flags, const char *message)
+{
+  struct delayed_message *dmsg = mp_pool_get(delay_pool);
+  strlcpy(dmsg->uid, client->id, sizeof(dmsg->uid));
+  strlcpy(dmsg->chname, channel->chname, sizeof(dmsg->chname));
+  dmsg->ts = channel->channelts;
+  dmsg->privmsg = privmsg;
+  dmsg->flags = flags;
+  strlcpy(dmsg->message, message, sizeof(dmsg->message));
+  dmsg->created = CurrentTime;
+  dlinkAddTail(dmsg, &dmsg->node, &delay_list);
+}
+
+static void
+delay_process(void *unused)
+{
+  dlink_node *ptr, *ptr_next;
+
+  DLINK_FOREACH_SAFE(ptr, ptr_next, delay_list.head)
+  {
+    struct delayed_message *dmsg = ptr->data;
+
+    if (dmsg->created + ConfigFileEntry.delay_secs > CurrentTime)
+    {
+      break;
+    }
+
+    struct Client *client = hash_find_id(dmsg->uid);
+    if (client == NULL)
+    {
+      goto next;
+    }
+
+    struct Channel *channel = hash_find_channel(dmsg->chname);
+    if (channel == NULL || dmsg->ts != channel->channelts)
+    {
+      goto next;
+    }
+
+    const char *command = dmsg->privmsg ? "PRIVMSG" : "NOTICE";
+    const char *text = dmsg->message;
+    char c = 0;
+    channel_flags_to_prefix(dmsg->flags, &c);
+
+    if (can_send(channel, client, NULL, text, !dmsg->privmsg) >= 0)
+    {
+      goto next;
+    }
+
+    if (c)
+      sendto_channel_butone(client->from, client, channel, dmsg->flags,
+                            SEND_FLAG_LOCAL | (msg_is_ctcp(text) ? SEND_FLAG_CTCP : 0), "%s %c%s :%s",
+                            command, c, channel->chname, text);
+    else
+      sendto_channel_butone(client->from, client, channel, 0,
+                            SEND_FLAG_LOCAL | (msg_is_ctcp(text) ? SEND_FLAG_CTCP : 0), "%s %s :%s",
+                            command, channel->chname, text);
+
+   next:
+    dlinkDelete(ptr, &delay_list);
+    mp_pool_release(dmsg);
+  }
+}
index 5352cd8c66e7fd8268965095ab94c8dbb2440488..fddcf192a64317ca97cd8265f36c1602608be20b 100644 (file)
@@ -65,6 +65,7 @@
 #include "ssl.h"
 #include "httpd.h"
 #include "userhost.h"
+#include "delay.h"
 
 
 #ifdef HAVE_LIBGEOIP
@@ -576,6 +577,7 @@ plexus_main(int argc, char *argv[])
   assemble_cmode_buffer();
   extban_init();
   cloak_reload();
+  delay_init();
 
   write_pidfile(pidFileName);
 
index 198a778b98f33c34bbc4083e4af0bee25607fd13..af7fa22b7fa740297c7cb20dabd001eb891f17e6 100644 (file)
@@ -685,7 +685,7 @@ handle_numeric(char numeric[], struct Client *client_p, struct Client *source_p,
                  numeric, ID_or_name(target_p, target_p), parv[2]);
   }
   else
-    sendto_channel_butone(client_p, source_p, chptr, 0, 0, "%s %s %s",
+    sendto_channel_butone(client_p, source_p, chptr, 0, SEND_FLAG_LOCAL | SEND_FLAG_REMOTE, "%s %s %s",
                           numeric, chptr->chname, parv[2]);
 }
 
index 48b8fca1ad6141b3fb2b7b7e5156b3120ca11363..df75661999e83b77b7b41b1265854e0a829f9495 100644 (file)
@@ -615,6 +615,10 @@ register_remote_user(struct Client *source_p,
   userhost_add(source_p->realhost, 1);
   SetUserHost(source_p);
 
+  /* Initialize number of privmsgs if bursting to not trigger delay */
+  if (!HasFlag(source_p->servptr, FLAGS_EOB))
+    source_p->seen_privmsgs = ConfigFileEntry.delay_message_count;
+
   if (HasFlag(source_p->servptr, FLAGS_EOB))
     sendto_snomask(SNO_CCONN, L_ALL | SNO_REMOTE,
                    "Client connecting from %s: %s (%s@%s) [%s] [%s]",
index 784acb26d88fe8735164851d92032fe45a15eb4e..6a8309d850a8fe1d82d8f6328e05e7f3cd21c3c0 100644 (file)
@@ -324,7 +324,7 @@ sendto_one(struct Client *to, const char *pattern, ...)
 void
 sendto_channel_butone(struct Client *one, struct Client *from,
                       struct Channel *chptr, unsigned int type,
-                      int is_ctcp,
+                      unsigned int flags,
                       const char *pattern, ...)
 {
   va_list alocal, aremote, auid;
@@ -367,7 +367,7 @@ sendto_channel_butone(struct Client *one, struct Client *from,
     if (MyClient(target_p) && HasUMode(target_p, UMODE_DEAF))
       continue;
 
-    if (is_ctcp && is_noctcp(from, target_p))
+    if ((flags & SEND_FLAG_CTCP) && is_noctcp(from, target_p))
       continue;
 
     if (is_bwsave(chptr, target_p))
@@ -378,7 +378,7 @@ sendto_channel_butone(struct Client *one, struct Client *from,
 
     if (MyConnect(target_p))
     {
-      if (target_p->localClient->serial != current_serial)
+      if ((flags & SEND_FLAG_LOCAL) && target_p->localClient->serial != current_serial)
       {
         send_message(target_p, local_buf);
         target_p->localClient->serial = current_serial;
@@ -389,7 +389,7 @@ sendto_channel_butone(struct Client *one, struct Client *from,
       /* Now check whether a message has been sent to this
        * remote link already
        */
-      if (target_p->from->localClient->serial != current_serial)
+      if ((flags & SEND_FLAG_REMOTE) && target_p->from->localClient->serial != current_serial)
       {
         if (IsCapable(target_p->from, CAP_TS6))
           send_message_remote(target_p->from, from, uid_buf);