diff --git a/src/main/java/com/threerings/nio/PolicyServer.java b/src/main/java/com/threerings/nio/PolicyServer.java index d20e6781c..264aef199 100644 --- a/src/main/java/com/threerings/nio/PolicyServer.java +++ b/src/main/java/com/threerings/nio/PolicyServer.java @@ -48,7 +48,7 @@ public class PolicyServer extends ConnectionManager public PolicyServer (Lifecycle cycle) throws IOException { - super(cycle); + super(cycle, LATENCY_GRACE); } /** diff --git a/src/main/java/com/threerings/nio/conman/Connection.java b/src/main/java/com/threerings/nio/conman/Connection.java index 29492dab2..a230e6586 100644 --- a/src/main/java/com/threerings/nio/conman/Connection.java +++ b/src/main/java/com/threerings/nio/conman/Connection.java @@ -34,9 +34,6 @@ import java.nio.channels.SocketChannel; */ public abstract class Connection implements NetEventHandler { - /** The number of milliseconds of idle upstream that are allowed to elapse before the client - * sends a ping message to the server to let it know that we're still alive. */ - public static final long PING_INTERVAL = 60 * 1000L; /** The key used by the NIO code to track this connection. */ public SelectionKey selkey; @@ -48,12 +45,14 @@ public abstract class Connection implements NetEventHandler * @param channel The socket channel from which we'll be reading messages. * @param createStamp The time at which this connection was created. */ - public void init (ConnectionManager cmgr, SocketChannel channel, long createStamp) + public void init (ConnectionManager cmgr, SocketChannel channel, long createStamp, + long idleTime) throws IOException { _cmgr = cmgr; _channel = channel; _lastEvent = createStamp; + _idleTime = idleTime; _connectionId = ++_lastConnectionId; } @@ -151,13 +150,13 @@ public abstract class Connection implements NetEventHandler public boolean checkIdle (long now) { long idleMillis = now - _lastEvent; - if (idleMillis < PING_INTERVAL + LATENCY_GRACE) { + if (idleMillis < _idleTime) { return false; } - if (isClosed()) { - return true; + if (!isClosed()) { + log.info("Disconnecting non-communicative client", + "conn", this, "idle", idleMillis + "ms"); } - log.info("Disconnecting non-communicative client", "conn", this, "idle", idleMillis + "ms"); return true; } @@ -201,10 +200,8 @@ public abstract class Connection implements NetEventHandler protected int _connectionId; + protected long _idleTime; + /** The last connection id assigned. */ protected static int _lastConnectionId; - - /** The number of milliseconds beyond the ping interval that we allow a client's network - * connection to be idle before we forcibly disconnect them. */ - protected static final long LATENCY_GRACE = 30 * 1000L; } diff --git a/src/main/java/com/threerings/nio/conman/ConnectionManager.java b/src/main/java/com/threerings/nio/conman/ConnectionManager.java index 85c847c56..316686572 100644 --- a/src/main/java/com/threerings/nio/conman/ConnectionManager.java +++ b/src/main/java/com/threerings/nio/conman/ConnectionManager.java @@ -62,12 +62,13 @@ public abstract class ConnectionManager extends LoopingThread /** * Creates a connection manager instance. */ - public ConnectionManager (Lifecycle cycle) + public ConnectionManager (Lifecycle cycle, long idleTime) throws IOException { super("ConnectionManager"); cycle.addComponent(this); _selector = Selector.open(); + _idleTime = idleTime; } /** @@ -216,7 +217,7 @@ public abstract class ConnectionManager extends LoopingThread // create a new authing connection object to manage the authentication of this client // connection and register it with our selection set channel.configureBlocking(false); - conn.init(this, channel, System.currentTimeMillis()); + conn.init(this, channel, System.currentTimeMillis(), _idleTime); conn.selkey = register(channel, SelectionKey.OP_READ, conn); _handlers.put(conn.selkey, conn); synchronized (this) { @@ -636,6 +637,8 @@ public abstract class ConnectionManager extends LoopingThread @Inject(optional=true) @Named("presents.net.selectLoopTime") protected int _selectLoopTime = 100; + protected final long _idleTime; + /** Used to denote asynchronous close requests. */ protected static final byte[] ASYNC_CLOSE_REQUEST = new byte[0]; @@ -644,4 +647,8 @@ public abstract class ConnectionManager extends LoopingThread /** Report our activity every 30 seconds. */ protected static final long DEBUG_REPORT_INTERVAL = 30*1000L; + + /** The number of milliseconds beyond the ping interval that we allow a client's network + * connection to be idle before we forcibly disconnect them. */ + protected static final long LATENCY_GRACE = 30 * 1000L; } diff --git a/src/main/java/com/threerings/presents/server/net/PresentsConnection.java b/src/main/java/com/threerings/presents/server/net/PresentsConnection.java index e5fedfe85..bcc18bd59 100644 --- a/src/main/java/com/threerings/presents/server/net/PresentsConnection.java +++ b/src/main/java/com/threerings/presents/server/net/PresentsConnection.java @@ -60,10 +60,11 @@ public class PresentsConnection extends Connection * {@link PresentsConnectionManager} as cmgr. */ @Override - public void init (ConnectionManager cmgr, SocketChannel channel, long createStamp) + public void init (ConnectionManager cmgr, SocketChannel channel, long createStamp, + long idleTime) throws IOException { - super.init(cmgr, channel, createStamp); + super.init(cmgr, channel, createStamp, idleTime); _pcmgr = (PresentsConnectionManager)cmgr; } diff --git a/src/main/java/com/threerings/presents/server/net/PresentsConnectionManager.java b/src/main/java/com/threerings/presents/server/net/PresentsConnectionManager.java index 1cd0546ca..1efb3529c 100644 --- a/src/main/java/com/threerings/presents/server/net/PresentsConnectionManager.java +++ b/src/main/java/com/threerings/presents/server/net/PresentsConnectionManager.java @@ -51,6 +51,7 @@ import com.threerings.presents.annotation.AuthInvoker; import com.threerings.presents.client.Client; import com.threerings.presents.data.PresentsConMgrStats; import com.threerings.presents.net.Message; +import com.threerings.presents.net.PingRequest; import com.threerings.presents.net.PongResponse; import com.threerings.presents.net.Transport; import com.threerings.presents.server.Authenticator; @@ -76,7 +77,7 @@ public class PresentsConnectionManager extends ConnectionManager public PresentsConnectionManager (Lifecycle cycle, ReportManager repmgr) throws IOException { - super(cycle); + super(cycle, LATENCY_GRACE + PingRequest.PING_INTERVAL); repmgr.registerReporter(this); _stats = new PresentsConMgrStats(); } @@ -306,7 +307,7 @@ public class PresentsConnectionManager extends ConnectionManager // have the non-blocking connect process started SocketChannel sockchan = SocketChannel.open(); sockchan.configureBlocking(false); - conn.init(this, sockchan, System.currentTimeMillis()); + conn.init(this, sockchan, System.currentTimeMillis(), _idleTime); _connectq.append(Tuple.newTuple(conn, new InetSocketAddress(hostname, port))); } @@ -451,7 +452,7 @@ public class PresentsConnectionManager extends ConnectionManager // construct a new running connection to handle this connections network traffic // from here on out PresentsConnection rconn = new PresentsConnection(); - rconn.init(this, conn.getChannel(), iterStamp); + rconn.init(this, conn.getChannel(), iterStamp, _idleTime); rconn.selkey = conn.selkey; // we need to keep using the same object input and output streams from the