jabberd2  2.2.16
util/rate.c
Go to the documentation of this file.
00001 /*
00002  * jabberd - Jabber Open Source Server
00003  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
00004  *                    Ryan Eatmon, Robert Norris
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
00019  */
00020 
00021 /* rate controls (for implementing connect-limiting or karma) */
00022 
00023 #include "util.h"
00024 
00025 rate_t rate_new(int total, int seconds, int wait)
00026 {
00027     rate_t rt = (rate_t) calloc(1, sizeof(struct rate_st));
00028 
00029     rt->total = total;
00030     rt->seconds = seconds;
00031     rt->wait = wait;
00032 
00033     return rt;
00034 }
00035 
00036 void rate_free(rate_t rt)
00037 {
00038     free(rt);
00039 }
00040 
00041 void rate_reset(rate_t rt)
00042 {
00043     rt->time = 0;
00044     rt->count = 0;
00045     rt->bad = 0;
00046 }
00047 
00048 void rate_add(rate_t rt, int count)
00049 {
00050     time_t now;
00051 
00052     now = time(NULL);
00053 
00054     /* rate expired */
00055     if(now - rt->time >= rt->seconds)
00056         rate_reset(rt);
00057 
00058     rt->count += count;
00059 
00060     /* first event, so set the time */
00061     if(rt->time == 0)
00062         rt->time = now;
00063 
00064     /* uhoh, they stuffed up */
00065     if(rt->count >= rt->total)
00066         rt->bad = now;
00067 }
00068 
00069 int rate_left(rate_t rt)
00070 {
00071     /* if we're bad, then there's none left */
00072     if(rt->bad != 0)
00073         return 0;
00074 
00075     return rt->total - rt->count;
00076 }
00077 
00078 int rate_check(rate_t rt)
00079 {
00080     /* not tracking */
00081     if(rt->time == 0)
00082         return 1;
00083 
00084     /* under the limit */
00085     if(rt->count < rt->total)
00086         return 1;
00087 
00088     /* currently bad */
00089     if(rt->bad != 0)
00090     {
00091         /* wait over, they're good again */
00092         if(time(NULL) - rt->bad >= rt->wait)
00093         {
00094             rate_reset(rt);
00095             return 1;
00096         }
00097 
00098         /* keep them waiting */
00099         return 0;
00100     }
00101 
00102     /* they're inside the time, and not bad yet */
00103     return 1;
00104 }