[jetrix-cvs] SF.net SVN: jetrix:[866] jetrix/trunk
Brought to you by:
smanux
From: <sm...@us...> - 2010-08-23 15:02:58
|
Revision: 866 http://jetrix.svn.sourceforge.net/jetrix/?rev=866&view=rev Author: smanux Date: 2010-08-23 15:02:51 +0000 (Mon, 23 Aug 2010) Log Message: ----------- Implemented the speed check Modified Paths: -------------- jetrix/trunk/doc/changelog.txt jetrix/trunk/src/etc/conf/server.xml jetrix/trunk/src/java/net/jetrix/config/ServerConfig.java jetrix/trunk/src/java/net/jetrix/listeners/ClientListener.java jetrix/trunk/src/java/net/jetrix/messages/channel/LevelMessage.java Added Paths: ----------- jetrix/trunk/src/etc/data/speedcheck.field jetrix/trunk/src/java/net/jetrix/listeners/interceptor/InteractiveInterceptor.java jetrix/trunk/src/java/net/jetrix/listeners/interceptor/SpeedCheckInterceptor.java Modified: jetrix/trunk/doc/changelog.txt =================================================================== --- jetrix/trunk/doc/changelog.txt 2010-08-23 14:40:34 UTC (rev 865) +++ jetrix/trunk/doc/changelog.txt 2010-08-23 15:02:51 UTC (rev 866) @@ -22,6 +22,7 @@ - Channels can now be created from the administration console - The IP of the server is no longer submitted to tfast.org since the site is dead - The web administration console has been moved from port 8080 to port 31460 +- The client speed can now be checked by setting the server property 'speedcheck.enabled" to "true" Developer visible changes - added a readLine(Reader) method in the Protocol interface Modified: jetrix/trunk/src/etc/conf/server.xml =================================================================== --- jetrix/trunk/src/etc/conf/server.xml 2010-08-23 14:40:34 UTC (rev 865) +++ jetrix/trunk/src/etc/conf/server.xml 2010-08-23 15:02:51 UTC (rev 866) @@ -129,7 +129,7 @@ <!-- Extended properties --> <properties> - <property name="speedcheck.enable" value="false"/> + <property name="speedcheck.enabled" value="false"/> </properties> </tetrinet-server> Added: jetrix/trunk/src/etc/data/speedcheck.field =================================================================== --- jetrix/trunk/src/etc/data/speedcheck.field (rev 0) +++ jetrix/trunk/src/etc/data/speedcheck.field 2010-08-23 15:02:51 UTC (rev 866) @@ -0,0 +1,22 @@ +000040040000 +000000000000 +000040011011 +011100000100 +100010011111 +111110000000 +000000010001 +100010010001 +101010011111 +111110000000 +000000010001 +100010010101 +101010011111 +111110000000 +000000011111 +111040000100 +101000011111 +111110000000 +000000010001 +101110010001 +101010011111 +111010000000 \ No newline at end of file Modified: jetrix/trunk/src/java/net/jetrix/config/ServerConfig.java =================================================================== --- jetrix/trunk/src/java/net/jetrix/config/ServerConfig.java 2010-08-23 14:40:34 UTC (rev 865) +++ jetrix/trunk/src/java/net/jetrix/config/ServerConfig.java 2010-08-23 15:02:51 UTC (rev 866) @@ -1044,7 +1044,6 @@ */ public void setProperty(String key, String value) { - System.out.println("setting " + key + " to " + value); properties.setProperty(key, value); } } Modified: jetrix/trunk/src/java/net/jetrix/listeners/ClientListener.java =================================================================== --- jetrix/trunk/src/java/net/jetrix/listeners/ClientListener.java 2010-08-23 14:40:34 UTC (rev 865) +++ jetrix/trunk/src/java/net/jetrix/listeners/ClientListener.java 2010-08-23 15:02:51 UTC (rev 866) @@ -205,7 +205,8 @@ Collection<ClientInterceptor> validators = new ArrayList<ClientInterceptor>(); validators.add(new AccessInterceptor()); validators.add(new NameCheckInterceptor()); - + validators.add(new SpeedCheckInterceptor()); + // run the validators for (ClientInterceptor interceptor : validators) { Added: jetrix/trunk/src/java/net/jetrix/listeners/interceptor/InteractiveInterceptor.java =================================================================== --- jetrix/trunk/src/java/net/jetrix/listeners/interceptor/InteractiveInterceptor.java (rev 0) +++ jetrix/trunk/src/java/net/jetrix/listeners/interceptor/InteractiveInterceptor.java 2010-08-23 15:02:51 UTC (rev 866) @@ -0,0 +1,179 @@ +/** + * Jetrix TetriNET Server + * Copyright (C) 2010 Emmanuel Bourg + * + * This program is free software; 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 + * of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +package net.jetrix.listeners.interceptor; + +import java.io.IOException; +import java.net.SocketException; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; + +import net.jetrix.Client; +import net.jetrix.Destination; +import net.jetrix.Message; +import net.jetrix.clients.QueryClient; +import net.jetrix.clients.TetrinetClient; +import net.jetrix.messages.channel.PlayerNumMessage; + +/** + * Interceptor expecting a response from the client (a password, a speed check, etc). + * + * @author Emmanuel Bourg + * @version $Revision$, $Date$ + * @since 0.3 + */ +public abstract class InteractiveInterceptor implements ClientInterceptor, Destination +{ + protected Logger log = Logger.getLogger("net.jetrix"); + + private BlockingQueue<Boolean> queue = new ArrayBlockingQueue<Boolean>(1); + + private boolean running; + + public void process(Client client) throws ClientValidationException + { + if (client instanceof QueryClient) + { + return; + } + + // adjust the read timeout for the client + if (client instanceof TetrinetClient) + { + TetrinetClient c = (TetrinetClient) client; + try + { + c.getSocket().setSoTimeout(2 * getTimeout() * 1000); + } + catch (SocketException e) + { + e.printStackTrace(); + } + } + + // start listening the messages sent by the client + MessageReader messageReader = new MessageReader(client); + messageReader.start(); + + // initiates the dialogue + client.send(new PlayerNumMessage(1)); + prologue(client); + + // wait until the client is processed + try + { + Boolean accepted = queue.poll(getTimeout(), TimeUnit.SECONDS); + if ((accepted == null || accepted == Boolean.FALSE) && isValidating()) + { + log.info("Rejecting " + client); + client.disconnect(); + throw new ClientValidationException(); + } + else + { + log.info("Accepting: " + client); + } + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + + /** + * Returns the time to wait for a response from the client. + */ + protected abstract int getTimeout(); + + /** + * Initiates the interaction with the client (i.e. display a message) + */ + protected abstract void prologue(Client client); + + /** + * Process a message received from the client. + * + * @param message + */ + public abstract void send(Message message); + + + protected void accept() + { + try + { + running = false; + queue.put(Boolean.TRUE); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + + protected void reject() + { + try + { + running = false; + queue.put(Boolean.FALSE); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + + private class MessageReader extends Thread + { + private Client client; + + private MessageReader(Client client) + { + setDaemon(true); + this.client = client; + } + + public void run() + { + running = true; + + try + { + log.finer("Message reader started (" + this + ")"); + Message message; + while (running && (message = client.receive()) != null) + { + send(message); + } + } + catch (IOException e) + { + log.log(Level.WARNING, "Error reading client message during the interception", e); + } + finally + { + log.finer("Message reader stopped (" + this + ")"); + } + } + } +} Property changes on: jetrix/trunk/src/java/net/jetrix/listeners/interceptor/InteractiveInterceptor.java ___________________________________________________________________ Added: svn:keywords + Date Author Id Revision HeadURL Added: svn:eol-style + native Added: jetrix/trunk/src/java/net/jetrix/listeners/interceptor/SpeedCheckInterceptor.java =================================================================== --- jetrix/trunk/src/java/net/jetrix/listeners/interceptor/SpeedCheckInterceptor.java (rev 0) +++ jetrix/trunk/src/java/net/jetrix/listeners/interceptor/SpeedCheckInterceptor.java 2010-08-23 15:02:51 UTC (rev 866) @@ -0,0 +1,161 @@ +/** + * Jetrix TetriNET Server + * Copyright (C) 2010 Emmanuel Bourg + * + * This program is free software; 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 + * of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +package net.jetrix.listeners.interceptor; + +import java.io.IOException; +import java.util.logging.Level; + +import net.jetrix.Client; +import net.jetrix.Field; +import net.jetrix.Message; +import net.jetrix.Server; +import net.jetrix.config.Block; +import net.jetrix.config.ServerConfig; +import net.jetrix.config.Settings; +import net.jetrix.messages.channel.EndGameMessage; +import net.jetrix.messages.channel.FieldMessage; +import net.jetrix.messages.channel.GmsgMessage; +import net.jetrix.messages.channel.NewGameMessage; +import net.jetrix.messages.channel.PlayerLostMessage; + +/** + * Interceptor checking the delay between two successive pieces. + * + * @author Emmanuel Bourg + * @version $Revision$, $Date$ + * @since 0.3 + */ +public class SpeedCheckInterceptor extends InteractiveInterceptor +{ + /** The time the speed check was started */ + private long startTime; + + /** The cumulated delay between the piece drops (~83000 expected for a standard client, 17500 for a tetrifast client) */ + private long sum = -1; + + protected Field getField() + { + Field field = new Field(); + + try + { + field.load("data/speedcheck.field"); + } + catch (IOException e) + { + log.log(Level.WARNING, "Unable to load the speedcheck field", e); + } + + return field; + } + + public void process(Client client) throws ClientValidationException + { + ServerConfig config = Server.getInstance().getConfig(); + boolean enabled = "true".equals(config.getProperty("speedcheck.enabled")); + + // skip the test for tetrifast clients + if (enabled && !"tetrifast".equals(client.getProtocol().getName())) + { + super.process(client); + } + } + + protected void prologue(Client client) + { + // start the game at high speed with squares only + Settings settings = new Settings(); + settings.setOccurancy(Block.SQUARE, 100); + settings.setStartingLevel(99); + settings.setAverageLevels(false); + + client.send(new NewGameMessage(settings)); + + FieldMessage fieldmessage = new FieldMessage(getField().getFieldString()); + fieldmessage.setSlot(1); + client.send(fieldmessage); + + client.send(new GmsgMessage("*** Please wait, the server is checking your client...")); + client.send(new GmsgMessage("*** Do not move, rotate or drop pieces.")); + } + + public void send(Message message) + { + Client client = (Client) message.getSource(); + + if (message instanceof PlayerLostMessage) + { + // stop the game + message.getSource().send(new EndGameMessage()); + + if (isFast()) + { + log.warning("Speed check failed for " + client); + reject(); + } + else + { + accept(); + } + } + else if (message instanceof FieldMessage) + { + FieldMessage msg = (FieldMessage) message; + + long now = System.currentTimeMillis(); + + if (sum == -1 && isFirstPiece(msg)) + { + // start the timer after the first drop + startTime = now; + sum = 0L; + } + + if (sum >= 0) + { + sum += (now - startTime); + } + } + } + + protected boolean isFirstPiece(FieldMessage msg) + { + Field field = new Field(); + field.update(msg); + + return field.getBlock(5, 0) == Field.BLOCK_YELLOW; + } + + protected boolean isFast() + { + // the client must not be more than 10% faster + return sum < 83000 * 0.9; + } + + protected int getTimeout() + { + return 30; + } + + public boolean isValidating() + { + return true; + } +} Property changes on: jetrix/trunk/src/java/net/jetrix/listeners/interceptor/SpeedCheckInterceptor.java ___________________________________________________________________ Added: svn:keywords + Date Author Id Revision HeadURL Added: svn:eol-style + native Modified: jetrix/trunk/src/java/net/jetrix/messages/channel/LevelMessage.java =================================================================== --- jetrix/trunk/src/java/net/jetrix/messages/channel/LevelMessage.java 2010-08-23 14:40:34 UTC (rev 865) +++ jetrix/trunk/src/java/net/jetrix/messages/channel/LevelMessage.java 2010-08-23 15:02:51 UTC (rev 866) @@ -29,6 +29,15 @@ { private int level; + public LevelMessage() + { + } + + public LevelMessage(int level) + { + this.level = level; + } + public int getLevel() { return level; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |