]>
jfr.im git - solanum.git/blob - src/ratelimit.c
2 * charybdis: an advanced ircd
3 * ratelimit.c: Per-client ratelimiting for high-bandwidth commands.
5 * Copyright (c) 2012 Keith Buck <mr_flea -at- esper.net>
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice is present in all copies.
11 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
12 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
13 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
14 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
15 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
18 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
19 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
20 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21 * POSSIBILITY OF SUCH DAMAGE.
27 #include "ratelimit.h"
30 * ratelimit_client(struct Client *client_p, int penalty)
32 * Applies a penalty to a client for executing a rate-limited command.
35 * - the client to be rate-limited
36 * - the penalty to apply
39 * - 1 if the user has been penalized and the command should be
41 * - 0 if the command should not execute and the user has not
42 * been penalized (they are executing commands too fast and have
44 * The caller should return RPL_LOAD2HI
47 * - The ratelimit for the user will be initialized if it hasn't
48 * been initialized yet.
50 int ratelimit_client(struct Client
*client_p
, unsigned int penalty
)
53 s_assert(MyClient(client_p
));
55 if (!client_p
->localClient
->ratelimit
)
57 /* Not initialized yet - do it now. */
58 client_p
->localClient
->ratelimit
= rb_current_time() - ConfigFileEntry
.max_ratelimit_tokens
;
61 /* Don't make it impossible to execute anything. */
62 if (penalty
> ConfigFileEntry
.max_ratelimit_tokens
)
63 penalty
= ConfigFileEntry
.max_ratelimit_tokens
;
65 if (client_p
->localClient
->ratelimit
<= rb_current_time() - ConfigFileEntry
.max_ratelimit_tokens
)
67 client_p
->localClient
->ratelimit
= rb_current_time() - ConfigFileEntry
.max_ratelimit_tokens
+ penalty
;
71 if (client_p
->localClient
->ratelimit
+ penalty
> rb_current_time())
77 client_p
->localClient
->ratelimit
+= penalty
;
83 * ratelimit_client_who(struct Client *client_p, int penalty)
85 * Rate-limits a client for a WHO query if they have no remaining "free"
86 * WHO queries to execute.
89 * - same as ratelimit_client
92 * - same as ratelimit_client
95 * - A "free who" token will be removed from the user if one exists.
96 * If one doesn't exist, the user will be ratelimited as normal.
98 int ratelimit_client_who(struct Client
*client_p
, unsigned int penalty
)
101 s_assert(MyClient(client_p
));
103 if (client_p
->localClient
->join_who_credits
)
105 --client_p
->localClient
->join_who_credits
;
109 return ratelimit_client(client_p
, penalty
);
113 * credit_client_join(struct Client *client_p)
115 * Gives a user a credit to execute a WHO for joining a channel.
118 * - the client to be credited
126 void credit_client_join(struct Client
*client_p
)
129 s_assert(MyClient(client_p
));
131 ++client_p
->localClient
->join_who_credits
;