[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.
|