/************************************************************************
 *   IRC - Internet Relay Chat, server/s_flood.c
 *
 *   Copyright (C) 2000-2003 TR-IRCD Development
 *
 *   Copyright (C) 1990 Jarkko Oikarinen and
 *                      University of Oulu, Co Center
 *
 *   See file AUTHORS in IRC package for additional names of
 *   the programmers.
 *
 *   This program is free softwmare; 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "struct.h"
#include "common.h"
#include "sys.h"
#include "h.h"
#include "s_bsd.h"
#include "parse.h"
#include "fd.h"
#include "packet.h"
#include "zlink.h"
#include "dh.h"
#include "s_conf.h"

/*
 * flood_recalc
 *
 * recalculate the number of allowed flood lines. this should be called
 * once a second on any given client. We then attempt to flush some data.
 */

void flood_recalc(int fd, void *data)
{
    aClient *client_p = data;
    int max_flood_per_sec = MAX_FLOOD_PER_SEC;

    /* This can happen in the event that the client detached. */
    if (!MyClient(client_p))
	return;
    /* If we're a server, skip to the end. Realising here that this call is
     * cheap and it means that if a op is downgraded they still get considered
     * for anti-flood protection ..
     */
    if (!IsPrivileged(client_p)) {

	/* Is the grace period still active? */
	if (client_p->user && !IsFloodDone(client_p))
	    max_flood_per_sec = MAX_FLOOD_PER_SEC_I;

	/* ok, we have to recalculate the number of messages we can receive
	 * in this second, based upon what happened in the last second.
	 * If we still exceed the flood limit, don't move the parsed limit.
	 * If we are below the flood limit, increase the flood limit.
	 *   -- adrian
	 */

	/* Set to 1 to start with, let it rise/fall after that... */
	if (client_p->allow_read == 0)
	    client_p->allow_read = 1;
	else if (client_p->actually_read < client_p->allow_read)
	    /* Raise the allowed messages if we flooded under the limit */
	    client_p->allow_read++;
	else
	    /* Drop the limit to avoid flooding .. */
	    client_p->allow_read--;
	/* Enforce floor/ceiling restrictions */
	if (client_p->allow_read < 1)
	    client_p->allow_read = 1;
	else if (client_p->allow_read > max_flood_per_sec)
	    client_p->allow_read = max_flood_per_sec;
	/* Reset the sent-per-second count */
	client_p->sent_parsed = 0;
	client_p->actually_read = 0;
	parse_client_queued(client_p);
	if (!IsDead(client_p)) {
	    /* and finally, reset the flood check */
	    comm_setflush(fd, 1000, flood_recalc, client_p);
	}
    }
}

/* flood_endgrace()
 *
 * marks the end of the clients grace period
 */
void flood_endgrace(struct Client *client_p)
{
    client_p->protoflags |= PFLAGS_FLOODDONE;
    /* Drop their flood limit back down */
    client_p->allow_read = MAX_FLOOD_PER_SEC;

    /* sent_parsed could be way over MAX_FLOOD but under MAX_FLOOD_BURST,
     * so reset it.
     */
    client_p->sent_parsed = 0;
}


syntax highlighted by Code2HTML, v. 0.9.1