001 /**
002 * Jetrix TetriNET Server
003 * Copyright (C) 2001-2003 Emmanuel Bourg
004 *
005 * This program is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU General Public License
007 * as published by the Free Software Foundation; either version 2
008 * of the License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License
016 * along with this program; if not, write to the Free Software
017 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
018 */
019
020 package net.jetrix.filter;
021
022 import java.util.*;
023
024 import net.jetrix.*;
025 import net.jetrix.messages.channel.PlineMessage;
026
027 /**
028 * Blocks spam over pline.
029 *
030 * @author Emmanuel Bourg
031 * @version $Revision: 798 $, $Date: 2009-02-18 16:24:28 +0100 (Wed, 18 Feb 2009) $
032 */
033 public class FloodFilter extends GenericFilter
034 {
035 private long timestamp[][];
036 private int index[];
037 private int capacity = 8;
038 private int delay = 5000;
039
040 /** Minimum time between two warnings (in seconds) */
041 private int warningPeriod = 10;
042
043 /** Date of the last warning */
044 private long lastWarning;
045
046 public void init()
047 {
048 // reading parameters
049 capacity = config.getInt("capacity", capacity);
050 delay = config.getInt("delay", delay);
051 warningPeriod = config.getInt("warningPeriod", warningPeriod);
052
053 timestamp = new long[6][capacity];
054 index = new int[6];
055 }
056
057 public void onMessage(PlineMessage m, List<Message> out)
058 {
059 int slot = m.getSlot();
060 // no check for server messages
061 if (slot < 1 || slot > 6)
062 {
063 out.add(m);
064 return;
065 }
066
067 String text = m.getText();
068 float charsByLine = 70;
069 int lineCount = (int) Math.ceil(text.length() / charsByLine);
070
071 long now = System.currentTimeMillis();
072 boolean isRateExceeded = false;
073 for (int i = 0; i < lineCount; i++)
074 {
075 isRateExceeded = isRateExceeded || isRateExceeded(slot - 1, now);
076 }
077
078 if (slot > 0 && isRateExceeded)
079 {
080 if ((now - lastWarning) > warningPeriod * 1000)
081 {
082 User user = getChannel().getPlayer(slot);
083 out.add(new PlineMessage("filter.flood.blocked", user.getName()));
084 lastWarning = now;
085 }
086 }
087 else
088 {
089 out.add(m);
090 }
091 }
092
093 /**
094 * Records a message timestamp and checks the data rate.
095 *
096 * @param slot message source slot
097 * @param t message timestamp
098 *
099 * @return <tt>true</tt> if over <tt>capacity</tt> messages in less than the <tt>delay</tt> specified
100 */
101 private boolean isRateExceeded(int slot, long t)
102 {
103 long t1 = timestamp[slot][index[slot]];
104 timestamp[slot][index[slot]] = t;
105 index[slot] = (index[slot] + 1) % capacity;
106
107 return (t - t1) < delay;
108 }
109
110 public String getName()
111 {
112 return "Flood Filter";
113 }
114
115 public String getDescription()
116 {
117 return "Blocks exceeding messages on pline";
118 }
119
120 public String getVersion()
121 {
122 return "1.0";
123 }
124
125 public String getAuthor()
126 {
127 return "Emmanuel Bourg";
128 }
129
130 }