]> jfr.im git - irc/rqf/shadowircd.git/blobdiff - modules/core/m_message.c
.cvsignore files removed, SVN-Access replaced by Mercurial-Access
[irc/rqf/shadowircd.git] / modules / core / m_message.c
index 67a69da8c6d145fac713c1fb2f8cdabd9be252df..2a21973ca717499c9e9777fa9fd421068b97682c 100644 (file)
@@ -561,63 +561,75 @@ expire_tgchange(void *unused)
        }
 }
 
-static int\r
-add_target(struct Client *source_p, struct Client *target_p)\r
-{\r
-       unsigned int i, j;\r
-       /* messaging themselves, doesnt incur any penalties */\r
-       if(source_p == target_p)\r
-               return 1;\r
-\r
-       if(USED_TARGETS(source_p))\r
-       {\r
-               /* hunt for an existing target */\r
-               for(i = PREV_FREE_TARGET(source_p), j = USED_TARGETS(source_p);\r
-                       j;\r
-                       --j, PREV_TARGET(i))\r
-               {\r
-                       if(source_p->localClient->targets[i] == target_p)\r
-                               return 1;\r
-               }\r
-\r
-               /* first message after connect, we may only start clearing\r
-                * slots after this message --anfl\r
-                */\r
-               if(!IsTGChange(source_p))\r
-               {\r
-                       SetTGChange(source_p);\r
-                       source_p->localClient->target_last = rb_current_time();\r
-               }\r
-               /* clear as many targets as we can */\r
-               else if((i = (rb_current_time() - source_p->localClient->target_last) / 60))\r
-               {\r
-                       if(i > USED_TARGETS(source_p))\r
-                               USED_TARGETS(source_p) = 0;\r
-                       else\r
-                               USED_TARGETS(source_p) -= i;\r
-\r
-                       source_p->localClient->target_last = rb_current_time();\r
-               }\r
-               /* cant clear any, full target list */\r
-               else if(USED_TARGETS(source_p) == 10)\r
-               {\r
-                       add_tgchange(source_p->sockhost);\r
-                       return 0;\r
-               }\r
-       }\r
-       /* no targets in use, reset their target_last so that they cant\r
-        * abuse a long idle to get targets back more quickly\r
-        */\r
-       else\r
-       {\r
-               source_p->localClient->target_last = rb_current_time();\r
-               SetTGChange(source_p);\r
-       }\r
-\r
-       source_p->localClient->targets[FREE_TARGET(source_p)] = target_p;\r
-       NEXT_TARGET(FREE_TARGET(source_p));\r
-       ++USED_TARGETS(source_p);\r
-       return 1;\r
+static int
+add_target(struct Client *source_p, struct Client *target_p)
+{
+       int i, j;
+       uint32_t hashv;
+
+       /* can msg themselves or services without using any target slots */
+       if(source_p == target_p || IsService(target_p))
+               return 1;
+
+       /* special condition for those who have had PRIVMSG crippled to allow them
+        * to talk to IRCops still.
+        *
+        * XXX: is this controversial?
+        */
+       if(source_p->localClient->target_last > rb_current_time() && IsOper(target_p))
+               return 1;
+
+       hashv = fnv_hash_upper((const unsigned char *)use_id(target_p), 32);
+
+       if(USED_TARGETS(source_p))
+       {
+               /* hunt for an existing target */
+               for(i = PREV_FREE_TARGET(source_p), j = USED_TARGETS(source_p);
+                   j; --j, PREV_TARGET(i))
+               {
+                       if(source_p->localClient->targets[i] == hashv)
+                               return 1;
+               }
+
+               /* first message after connect, we may only start clearing
+                * slots after this message --anfl
+                */
+               if(!IsTGChange(source_p))
+               {
+                       SetTGChange(source_p);
+                       source_p->localClient->target_last = rb_current_time();
+               }
+               /* clear as many targets as we can */
+               else if((i = (rb_current_time() - source_p->localClient->target_last) / 60))
+               {
+                       if(i > USED_TARGETS(source_p))
+                               USED_TARGETS(source_p) = 0;
+                       else
+                               USED_TARGETS(source_p) -= i;
+
+                       source_p->localClient->target_last = rb_current_time();
+               }
+               /* cant clear any, full target list */
+               else if(USED_TARGETS(source_p) == 10)
+               {
+                       ServerStats.is_tgch++;
+                       add_tgchange(source_p->sockhost);
+                       return 0;
+               }
+       }
+       /* no targets in use, reset their target_last so that they cant
+        * abuse a long idle to get targets back more quickly
+        */
+       else
+       {
+               source_p->localClient->target_last = rb_current_time();
+               SetTGChange(source_p);
+       }
+
+       source_p->localClient->targets[FREE_TARGET(source_p)] = hashv;
+       NEXT_TARGET(FREE_TARGET(source_p));
+       ++USED_TARGETS(source_p);
+       return 1;
 }
 
 /*