diff --git a/src/java/com/threerings/presents/client/Communicator.java b/src/java/com/threerings/presents/client/Communicator.java
index 970973112..ec49c9ad9 100644
--- a/src/java/com/threerings/presents/client/Communicator.java
+++ b/src/java/com/threerings/presents/client/Communicator.java
@@ -1,16 +1,15 @@
//
-// $Id: Communicator.java,v 1.24 2002/10/31 18:44:34 mdb Exp $
+// $Id: Communicator.java,v 1.25 2002/11/18 18:53:10 mdb Exp $
package com.threerings.presents.client;
import java.io.EOFException;
import java.io.IOException;
-import java.io.InputStream;
import java.io.InterruptedIOException;
-import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
import java.net.InetAddress;
-import java.net.Socket;
import com.samskivert.io.NestableIOException;
import com.samskivert.util.Interval;
@@ -26,6 +25,7 @@ import com.threerings.io.ObjectOutputStream;
import com.threerings.presents.Log;
import com.threerings.presents.dobj.DObjectManager;
import com.threerings.presents.net.*;
+import java.net.InetSocketAddress;
/**
* The client performs all network I/O on separate threads (one for
@@ -106,7 +106,7 @@ public class Communicator
{
// if our socket is already closed, we've already taken care of
// this business
- if (_socket == null) {
+ if (_channel == null) {
return;
}
@@ -186,7 +186,7 @@ public class Communicator
{
// make sure the socket isn't already closed down (meaning we've
// already dealt with the failed connection)
- if (_socket == null) {
+ if (_channel == null) {
return;
}
@@ -208,7 +208,7 @@ public class Communicator
{
// make sure the socket isn't already closed down (meaning we've
// already dealt with the closed connection)
- if (_socket == null) {
+ if (_channel == null) {
return;
}
@@ -246,11 +246,11 @@ public class Communicator
// our socket and let the client know that the logoff process has
// completed
try {
- _socket.close();
- } catch (IOException cle) {
- Log.warning("Error closing failed socket: " + cle);
+ _channel.close();
+ } catch (IOException ioe) {
+ Log.warning("Error closing failed socket: " + ioe);
}
- _socket = null;
+ _channel = null;
// clear these out because they are probably large and in charge
_oin = null;
@@ -278,7 +278,20 @@ public class Communicator
_oout.flush();
// then write the framed message to actual output stream
- _fout.writeFrameAndReset(_out);
+ try {
+ ByteBuffer buffer = _fout.frameAndReturnBuffer();
+ int wrote = _channel.write(buffer);
+ if (wrote != buffer.limit()) {
+ Log.warning("Aiya! Couldn't write entire message [msg=" + msg +
+ ", size=" + buffer.limit() +
+ ", wrote=" + wrote + "].");
+// } else {
+// Log.info("Wrote " + wrote + " bytes.");
+ }
+
+ } finally {
+ _fout.resetFrame();
+ }
// make a note of our most recent write time
updateWriteStamp();
@@ -315,7 +328,7 @@ public class Communicator
// which case we simply call it again because we can't do anything
// until it has a whole frame; it will throw an exception if it
// hits EOF or if something goes awry)
- while (!_fin.readFrame(_in));
+ while (!_fin.readFrame(_channel));
try {
DownstreamMessage msg = (DownstreamMessage)_oin.readObject();
@@ -359,6 +372,7 @@ public class Communicator
} catch (Exception e) {
Log.debug("Logon failed: " + e);
+ Log.logStackTrace(e);
// let the observers know that we've failed
_client.notifyObservers(Client.CLIENT_FAILED_TO_LOGON, e);
// and terminate our communicator thread
@@ -370,7 +384,7 @@ public class Communicator
throws IOException
{
// if we're already connected, we freak out
- if (_socket != null) {
+ if (_channel != null) {
throw new IOException("Already connected.");
}
@@ -379,13 +393,9 @@ public class Communicator
int port = _client.getPort();
// establish a socket connection to said server
- Log.debug("Connecting to server [host=" + host +
- ", port=" + port + "].");
- _socket = new Socket(host, port);
-
- // get a handle on our input and output streams
- _in = _socket.getInputStream();
- _out = _socket.getOutputStream();
+ Log.debug("Connecting [host=" + host + ", port=" + port + "].");
+ _channel = SocketChannel.open(new InetSocketAddress(host, port));
+ _channel.configureBlocking(true);
// our messages are framed (preceded by their length), so we
// use these helper streams to manage the framing
@@ -477,7 +487,7 @@ public class Communicator
// we want to interrupt the reader thread as it may be blocked
// listening to the socket; this is only called if the reader
// thread doesn't shut itself down
- interrupt();
+// interrupt();
}
}
@@ -541,9 +551,7 @@ public class Communicator
protected Reader _reader;
protected Writer _writer;
- protected Socket _socket;
- protected InputStream _in;
- protected OutputStream _out;
+ protected SocketChannel _channel;
protected Queue _msgq = new Queue();
protected int _piid;
diff --git a/src/java/com/threerings/presents/server/net/AuthingConnection.java b/src/java/com/threerings/presents/server/net/AuthingConnection.java
index 1ba547dae..129d9cf97 100644
--- a/src/java/com/threerings/presents/server/net/AuthingConnection.java
+++ b/src/java/com/threerings/presents/server/net/AuthingConnection.java
@@ -1,10 +1,12 @@
//
-// $Id: AuthingConnection.java,v 1.8 2002/10/29 23:51:26 mdb Exp $
+// $Id: AuthingConnection.java,v 1.9 2002/11/18 18:53:10 mdb Exp $
package com.threerings.presents.server.net;
import java.io.IOException;
-import ninja2.core.io_core.nbio.NonblockingSocket;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
+
import com.samskivert.util.StringUtil;
import com.threerings.presents.Log;
@@ -23,11 +25,11 @@ public class AuthingConnection extends Connection
* Creates a new authing connection object that will manage the
* authentication process for the suppled client socket.
*/
- public AuthingConnection (ConnectionManager cmgr,
- NonblockingSocket socket)
+ public AuthingConnection (ConnectionManager cmgr, SelectionKey selkey,
+ SocketChannel channel)
throws IOException
{
- super(cmgr, socket, System.currentTimeMillis());
+ super(cmgr, selkey, channel, System.currentTimeMillis());
// we are our own message handler
setMessageHandler(this);
@@ -80,10 +82,13 @@ public class AuthingConnection extends Connection
_authrsp = authrsp;
}
+ /**
+ * Generates a string representation of this instance.
+ */
public String toString ()
{
return "[mode=AUTHING, addr=" +
- StringUtil.toString(_socket.getInetAddress()) + "]";
+ StringUtil.toString(_channel.socket().getInetAddress()) + "]";
}
protected AuthRequest _authreq;
diff --git a/src/java/com/threerings/presents/server/net/Connection.java b/src/java/com/threerings/presents/server/net/Connection.java
index 3d1ac1794..5e19576a8 100644
--- a/src/java/com/threerings/presents/server/net/Connection.java
+++ b/src/java/com/threerings/presents/server/net/Connection.java
@@ -1,5 +1,5 @@
//
-// $Id: Connection.java,v 1.12 2002/11/06 21:05:13 shaper Exp $
+// $Id: Connection.java,v 1.13 2002/11/18 18:53:10 mdb Exp $
package com.threerings.presents.server.net;
@@ -7,9 +7,11 @@ import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.net.SocketTimeoutException;
-import ninja2.core.io_core.nbio.*;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
import com.samskivert.io.NestableIOException;
@@ -37,24 +39,20 @@ public abstract class Connection implements NetEventHandler
*
* @param cmgr The connection manager with which this connection is
* associated.
- * @param socket The socket from which we'll be reading messages.
+ * @param selkey the key used by the NIO code to track this
+ * connection.
+ * @param channel The socket channel from which we'll be reading
+ * messages.
* @param createStamp The time at which this connection was created.
*/
- public Connection (ConnectionManager cmgr, NonblockingSocket socket,
- long createStamp)
+ public Connection (ConnectionManager cmgr, SelectionKey selkey,
+ SocketChannel channel, long createStamp)
throws IOException
{
_cmgr = cmgr;
- _socket = socket;
+ _selkey = selkey;
+ _channel = channel;
_lastEvent = createStamp;
-
- // create a select item that will allow us to be incorporated into
- // the main event polling loop
- _selitem = new SelectItem(_socket, this, Selectable.READ_READY);
-
- // get a handle on our socket streams
- _in = _socket.getInputStream();
- _out = _socket.getOutputStream();
}
/**
@@ -68,20 +66,20 @@ public abstract class Connection implements NetEventHandler
}
/**
- * Returns the select item associated with this connection.
+ * Returns the selection key associated with our socket channel.
*/
- public SelectItem getSelectItem ()
+ public SelectionKey getSelectionKey ()
{
- return _selitem;
+ return _selkey;
}
/**
* Returns the non-blocking socket object used to construct this
* connection.
*/
- public NonblockingSocket getSocket ()
+ public SocketChannel getChannel ()
{
- return _socket;
+ return _channel;
}
/**
@@ -89,7 +87,7 @@ public abstract class Connection implements NetEventHandler
*/
public boolean isClosed ()
{
- return (_socket == null);
+ return (_channel == null);
}
/**
@@ -133,15 +131,6 @@ public abstract class Connection implements NetEventHandler
closeSocket();
}
- /**
- * Returns the output stream associated with this connection. This
- * should only be used by the connection manager.
- */
- protected OutputStream getOutputStream ()
- {
- return _out;
- }
-
/**
* Returns the object input stream associated with this connection.
* This should only be used by the connection manager.
@@ -197,23 +186,26 @@ public abstract class Connection implements NetEventHandler
*/
protected void closeSocket ()
{
- if (_socket != null) {
+ if (_channel != null) {
+ Log.debug("Closing channel " + this + ".");
+
try {
- _socket.close();
+ _channel.close();
} catch (IOException ioe) {
Log.warning("Error closing connection [conn=" + this +
", error=" + ioe + "].");
}
- // clear out our socket reference to prevent repeat closings
- _socket = null;
+ // clear out our references to prevent repeat closings
+ _selkey = null;
+ _channel = null;
}
}
/**
* Called when our client socket has data available for reading.
*/
- public int handleEvent (long when, Selectable source, short events)
+ public int handleEvent (long when)
{
// make a note that we received an event as of this time
_lastEvent = when;
@@ -228,8 +220,9 @@ public abstract class Connection implements NetEventHandler
_oin = new ObjectInputStream(_fin);
}
- // read the available data and see if we have a whole frame
- if (_fin.readFrame(_in)) {
+ // there may be more than one frame in the buffer, so we keep
+ // reading them until we run out of data
+ while (_fin.readFrame(_channel)) {
// make a note of how many bytes are in this frame
// (including the frame length bytes which aren't reported
// in available())
@@ -246,14 +239,14 @@ public abstract class Connection implements NetEventHandler
} catch (ClassNotFoundException cnfe) {
Log.warning("Error reading message from socket " +
- "[socket=" + _socket + ", error=" + cnfe + "].");
+ "[channel=" + _channel + ", error=" + cnfe + "].");
// deal with the failure
handleFailure(new NestableIOException(
"Unable to decode incoming message.", cnfe));
} catch (IOException ioe) {
Log.warning("Error reading message from socket " +
- "[socket=" + _socket + ", error=" + ioe + "].");
+ "[channel=" + _channel + ", error=" + ioe + "].");
// deal with the failure
handleFailure(ioe);
}
@@ -262,18 +255,18 @@ public abstract class Connection implements NetEventHandler
}
// documentation inherited from interface
- public void checkIdle (long now)
+ public boolean checkIdle (long now)
{
long idleMillis = now - _lastEvent;
if (idleMillis < PingRequest.PING_INTERVAL + LATENCY_GRACE) {
- return;
+ return false;
}
if (isClosed()) {
- return;
+ return false;
}
- Log.info("Disconnecting idle client [conn=" + this +
+ Log.info("Disconnecting non-communicative client [conn=" + this +
", idle=" + idleMillis + "ms].");
- handleFailure(new SocketTimeoutException("Idle too long"));
+ return true;
}
/**
@@ -288,16 +281,14 @@ public abstract class Connection implements NetEventHandler
}
protected ConnectionManager _cmgr;
- protected NonblockingSocket _socket;
- protected SelectItem _selitem;
+ protected SelectionKey _selkey;
+ protected SocketChannel _channel;
protected long _lastEvent;
- protected InputStream _in;
protected FramedInputStream _fin;
protected ObjectInputStream _oin;
- protected OutputStream _out;
protected ObjectOutputStream _oout;
protected MessageHandler _handler;
diff --git a/src/java/com/threerings/presents/server/net/ConnectionManager.java b/src/java/com/threerings/presents/server/net/ConnectionManager.java
index 4c0823299..2fd1bfee9 100644
--- a/src/java/com/threerings/presents/server/net/ConnectionManager.java
+++ b/src/java/com/threerings/presents/server/net/ConnectionManager.java
@@ -1,13 +1,26 @@
//
-// $Id: ConnectionManager.java,v 1.24 2002/11/05 02:17:56 mdb Exp $
+// $Id: ConnectionManager.java,v 1.25 2002/11/18 18:53:10 mdb Exp $
package com.threerings.presents.server.net;
import java.io.IOException;
-import java.net.SocketException;
-import java.util.ArrayList;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Set;
-import ninja2.core.io_core.nbio.*;
import com.samskivert.util.*;
import com.threerings.io.FramingOutputStream;
@@ -41,34 +54,42 @@ public class ConnectionManager extends LoopingThread
throws IOException
{
_port = port;
- _selset = new SelectSet();
+ _selector = SelectorProvider.provider().openSelector();
// register as a "state of server" reporter
PresentsServer.registerReporter(this);
try {
// create our listening socket and add it to the select set
- _listener = new NonblockingServerSocket(_port);
- } catch (SocketException se) {
+ _listener = ServerSocketChannel.open();
+ _listener.configureBlocking(false);
+
+ InetAddress lh = InetAddress.getLocalHost();
+ InetSocketAddress isa = new InetSocketAddress(lh, _port);
+ _listener.socket().bind(isa);
+ Log.info("Server listening on " + isa + ".");
+
+ } catch (IOException ioe) {
Log.warning("Failure creating listen socket " +
"[port=" + _port + "].");
- throw se;
+ throw ioe;
}
- _litem = new SelectItem(_listener, Selectable.ACCEPT_READY);
- // when an ACCEPT_READY event happens, we do this:
- _litem.obj = new NetEventHandler() {
- public int handleEvent (long when, Selectable item, short events) {
+ // register our listening socket and map its select key to a net
+ // event handler that will accept new connections
+ SelectionKey lkey =
+ _listener.register(_selector, SelectionKey.OP_ACCEPT);
+ _handlers.put(lkey, new NetEventHandler() {
+ public int handleEvent (long when) {
acceptConnection();
// there's no easy way to measure bytes read when
// accepting a connection, so we claim nothing
return 0;
}
- public void checkIdle (long now) {
- // we're never idle
+ public boolean checkIdle (long now) {
+ return false; // we're never idle
}
- };
- _selset.add(_litem);
+ });
// we'll use this for sending messages to clients
_framer = new FramingOutputStream();
@@ -217,18 +238,22 @@ public class ConnectionManager extends LoopingThread
}
}
- // close any connections that have seen no network traffic for too
- // long
- int ccount = _selset.size();
- for (int ii = 0; ii < ccount; ii++) {
- ((NetEventHandler)_selset.elementAt(ii).getObj()).
- checkIdle(iterStamp);
+ // close connections that have had no network traffic for too long
+ Iterator hiter = _handlers.values().iterator();
+ while (hiter.hasNext()) {
+ NetEventHandler handler = (NetEventHandler)hiter.next();
+ if (handler.checkIdle(iterStamp)) {
+ // this will queue the connection up for closure on our
+ // next tick
+ closeConnection(((Connection)handler));
+ }
}
// send any messages that are waiting on the outgoing queue
Tuple tup;
while ((tup = (Tuple)_outq.getNonBlocking()) != null) {
Connection conn = (Connection)tup.left;
+
// if the connection to which this message is destined is
// closed, drop the message and move along quietly; this is
// perfectly legal, a user can logoff whenever they like, even
@@ -249,10 +274,27 @@ public class ConnectionManager extends LoopingThread
oout.flush();
// then write framed message to real output stream
- int out = _framer.writeFrameAndReset(conn.getOutputStream());
- synchronized (this) {
- _bytesOut += out;
- _msgsOut++;
+ try {
+ ByteBuffer buffer = _framer.frameAndReturnBuffer();
+ int wrote = conn.getChannel().write(buffer);
+ if (wrote != buffer.limit()) {
+ Log.warning("Aiya! Failed to write complete message " +
+ "[conn=" + conn + ", wrote=" + wrote +
+ ", needed=" + buffer.limit() + "].");
+ // TODO: give them the boot
+// } else {
+// Log.info("Sent [msg=" + outmsg +
+// ", size=" + wrote + "].");
+ }
+
+ int out = buffer.limit();
+ synchronized (this) {
+ _bytesOut += wrote;
+ _msgsOut++;
+ }
+
+ } finally {
+ _framer.resetFrame();
}
} catch (IOException ioe) {
@@ -264,20 +306,21 @@ public class ConnectionManager extends LoopingThread
// check for connections that have completed authentication
AuthingConnection conn;
while ((conn = (AuthingConnection)_authq.getNonBlocking()) != null) {
- // remove the old connection from the select set
- _selset.remove(conn.getSelectItem());
-
- // construct a new running connection to handle this
- // connections network traffic from here on out
try {
- RunningConnection rconn =
- new RunningConnection(this, conn.getSocket(), iterStamp);
+ // construct a new running connection to handle this
+ // connections network traffic from here on out
+ SelectionKey selkey = conn.getSelectionKey();
+ RunningConnection rconn = new RunningConnection(
+ this, selkey, conn.getChannel(), iterStamp);
+
// we need to keep using the same object input and output
// streams from the beginning of the session because they
// have contextual state that needs to be preserved
rconn.inheritStreams(conn);
- // wire this connection up to receive network events
- _selset.add(rconn.getSelectItem());
+
+ // replace the mapping in the handlers table from the old
+ // connection with the new one
+ _handlers.put(selkey, rconn);
// and let our observers know about our new connection
notifyObservers(CONNECTION_ESTABLISHED, rconn,
@@ -290,20 +333,47 @@ public class ConnectionManager extends LoopingThread
}
}
- // check for incoming network events
- int ecount = _selset.select(SELECT_LOOP_TIME);
- if (ecount == 0) {
+ Set ready = null;
+ try {
+ // check for incoming network events
+// Log.debug("Selecting from " +
+// StringUtil.toString(_selector.keys()) + " (" +
+// SELECT_LOOP_TIME + ").");
+ int ecount = _selector.select(SELECT_LOOP_TIME);
+ ready = _selector.selectedKeys();
+ if (ecount == 0) {
+ if (ready.size() == 0) {
+ return;
+ } else {
+ Log.warning("select() returned no selected sockets, " +
+ "but there are " + ready.size() +
+ " in the ready set.");
+ }
+ }
+
+ } catch (IOException ioe) {
+ Log.warning("Failure select()ing [ioe=" + ioe + "].");
return;
}
// process those events
- SelectItem[] active = _selset.getEvents();
- for (int i = 0; i < active.length; i++) {
+// Log.info("Ready set " + StringUtil.toString(ready) + ".");
+ Iterator siter = ready.iterator();
+ while (siter.hasNext()) {
+ SelectionKey selkey = (SelectionKey)siter.next();
try {
- SelectItem item = active[i];
- NetEventHandler handler = (NetEventHandler)item.obj;
- int got = handler.handleEvent(
- iterStamp, item.getSelectable(), item.revents);
+ NetEventHandler handler = (NetEventHandler)
+ _handlers.get(selkey);
+ if (handler == null) {
+ Log.warning("Received network event but have no " +
+ "registered handler [selkey=" + selkey + "].");
+ continue;
+ }
+
+// Log.info("Got event [selkey=" + selkey +
+// ", handler=" + handler + "].");
+
+ int got = handler.handleEvent(iterStamp);
if (got != 0) {
synchronized (this) {
_bytesIn += got;
@@ -319,6 +389,7 @@ public class ConnectionManager extends LoopingThread
Log.logStackTrace(e);
}
}
+ ready.clear();
}
// documentation inherited
@@ -341,34 +412,48 @@ public class ConnectionManager extends LoopingThread
*/
protected void acceptConnection ()
{
- NonblockingSocket socket = null;
+ SocketChannel channel = null;
try {
- socket = _listener.nbAccept();
- if (socket == null) {
+ channel = _listener.accept();
+ if (channel == null) {
// in theory this shouldn't happen because we got an
// ACCEPT_READY event, but better safe than sorry
- // Log.info("Psych! Got ACCEPT_READY, but no connection.");
+ Log.info("Psych! Got ACCEPT_READY, but no connection.");
return;
}
- // create a new authing connection object to manage the
- // authentication of this client connection
- AuthingConnection acon = new AuthingConnection(this, socket);
+ if (!(channel instanceof SelectableChannel)) {
+ Log.warning("Provided with un-selectable socket as " +
+ "result of accept(), can't cope " +
+ "[channel=" + channel + "].");
+ // stick a fork in the socket
+ channel.socket().close();
+ return;
+ }
- // wire this connection into the select set
- _selset.add(acon.getSelectItem());
+ Log.debug("Accepted connection " + channel + ".");
+
+ // create a new authing connection object to manage the
+ // authentication of this client connection and register it
+ // with our selection set
+ SelectableChannel selchan = (SelectableChannel)channel;
+ selchan.configureBlocking(false);
+ SelectionKey selkey = selchan.register(
+ _selector, SelectionKey.OP_READ);
+ _handlers.put(selkey, new AuthingConnection(this, selkey, channel));
+ return;
} catch (IOException ioe) {
Log.warning("Failure accepting new connection: " + ioe);
+ }
- // make sure we don't leak a socket if something went awry
- if (socket != null) {
- try {
- socket.close();
- } catch (IOException ioe2) {
- Log.warning("Failed closing aborted connection: " + ioe2);
- }
+ // make sure we don't leak a socket if something went awry
+ if (channel != null) {
+ try {
+ channel.socket().close();
+ } catch (IOException ioe) {
+ Log.warning("Failed closing aborted connection: " + ioe);
}
}
}
@@ -395,8 +480,9 @@ public class ConnectionManager extends LoopingThread
*/
void connectionFailed (Connection conn, IOException ioe)
{
- // remove this connection from the select set
- _selset.remove(conn.getSelectItem());
+ // remove this connection from our mapping (it is automatically
+ // removed from the Selector when the socket is closed)
+ _handlers.remove(conn.getSelectionKey());
// let our observers know what's up
notifyObservers(CONNECTION_FAILED, conn, ioe, null);
@@ -407,8 +493,9 @@ public class ConnectionManager extends LoopingThread
*/
void connectionClosed (Connection conn)
{
- // remove this connection from the select set
- _selset.remove(conn.getSelectItem());
+ // remove this connection from our mapping (it is automatically
+ // removed from the Selector when the socket is closed)
+ _handlers.remove(conn.getSelectionKey());
// let our observers know what's up
notifyObservers(CONNECTION_CLOSED, conn, null, null);
@@ -416,10 +503,11 @@ public class ConnectionManager extends LoopingThread
protected int _port;
protected Authenticator _author;
- protected SelectSet _selset;
+ protected Selector _selector;
+ protected ServerSocketChannel _listener;
- protected NonblockingServerSocket _listener;
- protected SelectItem _litem;
+ /** Maps selection keys to network event handlers. */
+ protected HashMap _handlers = new HashMap();
protected Queue _deathq = new Queue();
protected Queue _authq = new Queue();
@@ -437,12 +525,12 @@ public class ConnectionManager extends LoopingThread
/**
* How long we wait for network events before checking our running
- * flag to see if we should still be running.
+ * flag to see if we should still be running. We don't want to loop
+ * too tightly, but we need to make sure we don't sit around listening
+ * for incoming network events too long when there are outgoing
+ * messages in the queue.
*/
- // protected static final int SELECT_LOOP_TIME = 30 * 1000;
-
- // while we're testing, use a short loop time
- protected static final int SELECT_LOOP_TIME = 10;
+ protected static final int SELECT_LOOP_TIME = 100;
// codes for notifyObservers()
protected static final int CONNECTION_ESTABLISHED = 0;
diff --git a/src/java/com/threerings/presents/server/net/NetEventHandler.java b/src/java/com/threerings/presents/server/net/NetEventHandler.java
index 96b232a58..d67f149b7 100644
--- a/src/java/com/threerings/presents/server/net/NetEventHandler.java
+++ b/src/java/com/threerings/presents/server/net/NetEventHandler.java
@@ -1,36 +1,36 @@
//
-// $Id: NetEventHandler.java,v 1.5 2002/11/05 02:17:56 mdb Exp $
+// $Id: NetEventHandler.java,v 1.6 2002/11/18 18:53:10 mdb Exp $
package com.threerings.presents.server.net;
-import ninja2.core.io_core.nbio.Selectable;
-
/**
- * When a network event arrives on a particular Selectable,
- * the connection manager calls the net event handler associated with that
- * selectable to process the event. There are only a few handlers (and
- * probably only ever will be): the one that accepts new connections, the
- * one that deals with a connection while the client is authenticating and
- * the one that processes messages from authenticated connections.
- * Providing this interface prevents us from having to do a bunch of
+ * When a network event occurs, the connection manager calls the net event
+ * handler associated with that channel to process the event. There are
+ * only a few handlers (and probably only ever will be): the one that
+ * accepts new connections, the one that deals with a connection while the
+ * client is authenticating and the one that processes messages from
+ * authenticated connections.
+ *
+ *
Utilising this interface prevents us from having to do a bunch of
* inefficient and ugly comparisons; instead we can simply call through an
* interface method to the proper code.
*/
public interface NetEventHandler
{
/**
- * Called when a network event has occurred on the supplied source.
- * The events parameter indicates which event or events
- * have occurred.
+ * Called when a network event has occurred on this handler's source.
*
* @return the number of bytes read from the network as a result of
* handling this event.
*/
- public int handleEvent (long when, Selectable source, short events);
+ public int handleEvent (long when);
/**
- * Called to ensure that this selectable has not been idle for longer
+ * Called to ensure that this channel has not been idle for longer
* than is possible in happily operating circumstances.
+ *
+ * @return true if the handler is idle (in which case it will be
+ * closed shortly), false if it is not.
*/
- public void checkIdle (long now);
+ public boolean checkIdle (long now);
}
diff --git a/src/java/com/threerings/presents/server/net/RunningConnection.java b/src/java/com/threerings/presents/server/net/RunningConnection.java
index b5d13533f..f2c802851 100644
--- a/src/java/com/threerings/presents/server/net/RunningConnection.java
+++ b/src/java/com/threerings/presents/server/net/RunningConnection.java
@@ -1,10 +1,12 @@
//
-// $Id: RunningConnection.java,v 1.8 2002/10/29 23:51:26 mdb Exp $
+// $Id: RunningConnection.java,v 1.9 2002/11/18 18:53:10 mdb Exp $
package com.threerings.presents.server.net;
import java.io.IOException;
-import ninja2.core.io_core.nbio.NonblockingSocket;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
+
import com.samskivert.util.StringUtil;
import com.threerings.presents.net.UpstreamMessage;
@@ -19,12 +21,11 @@ public class RunningConnection extends Connection
* Constructs a new running connection object to manage the supplied
* client socket.
*/
- public RunningConnection (ConnectionManager cmgr,
- NonblockingSocket socket,
- long createStamp)
+ public RunningConnection (ConnectionManager cmgr, SelectionKey selkey,
+ SocketChannel channel, long createStamp)
throws IOException
{
- super(cmgr, socket, createStamp);
+ super(cmgr, selkey, channel, createStamp);
}
/**
@@ -36,12 +37,9 @@ public class RunningConnection extends Connection
public String toString ()
{
- if (_socket != null) {
- return "[mode=RUNNING, id=" + (hashCode() % 1000) +
- ", addr=" + StringUtil.toString(_socket.getInetAddress()) + "]";
- } else {
- return "[mode=RUNNING, id=" + (hashCode() % 1000) +
- ", addr=