From 2c3e4d9528c17786610199b2dcd9f4f5cbea5864 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Fri, 1 Jun 2001 22:12:03 +0000 Subject: [PATCH] Wired up connection observer stuff. Created skeleton client manager. Wired up post-authentication authing to running transition. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@21 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../presents/server/ClientManager.java | 60 ++++++++++ .../presents/server/PresentsServer.java | 13 ++- .../presents/server/net/AuthManager.java | 17 ++- .../presents/server/net/Connection.java | 11 +- .../server/net/ConnectionManager.java | 105 +++++++++++++++++- .../server/net/ConnectionObserver.java | 7 +- 6 files changed, 203 insertions(+), 10 deletions(-) create mode 100644 src/java/com/threerings/presents/server/ClientManager.java diff --git a/src/java/com/threerings/presents/server/ClientManager.java b/src/java/com/threerings/presents/server/ClientManager.java new file mode 100644 index 000000000..ec5fc9af5 --- /dev/null +++ b/src/java/com/threerings/presents/server/ClientManager.java @@ -0,0 +1,60 @@ +// +// $Id: ClientManager.java,v 1.1 2001/06/01 22:12:03 mdb Exp $ + +package com.threerings.cocktail.cher.server; + +import java.io.IOException; + +import com.threerings.cocktail.cher.Log; +import com.threerings.cocktail.cher.server.net.*; + +/** + * The client manager is responsible for managing the clients (surprise, + * surprise) which are slightly more than just connections. Clients + * persist in the absence of connections in case a user goes bye bye + * unintentionally and wants to reconnect and continue their session. + */ +public class ClientManager implements ConnectionObserver +{ + public ClientManager (ConnectionManager conmgr) + { + // register ourselves as a connection observer + conmgr.addConnectionObserver(this); + } + + /** + * Called when a new connection is established with the connection + * manager. Only fully authenticated connections will be passed on to + * the connection observer. + * + * @param conn The newly established connection. + */ + public void connectionEstablished (Connection conn) + { + Log.info("Connection established: " + conn); + } + + /** + * Called if a connection fails for any reason. If a connection fails, + * connectionClosed will not be called. This call to + * connectionFailed is the last the observers will hear + * about it. + * + * @param conn The connection in that failed. + * @param fault The exception associated with the failure. + */ + public void connectionFailed (Connection conn, IOException fault) + { + Log.info("Connection failed: " + conn + ": " + fault); + } + + /** + * Called when a connection has been closed in an orderly manner. + * + * @param conn The recently closed connection. + */ + public void connectionClosed (Connection conn) + { + Log.info("Connection closed: " + conn); + } +} diff --git a/src/java/com/threerings/presents/server/PresentsServer.java b/src/java/com/threerings/presents/server/PresentsServer.java index 2ff9452a4..8b247734a 100644 --- a/src/java/com/threerings/presents/server/PresentsServer.java +++ b/src/java/com/threerings/presents/server/PresentsServer.java @@ -1,5 +1,5 @@ // -// $Id: PresentsServer.java,v 1.3 2001/06/01 20:35:39 mdb Exp $ +// $Id: PresentsServer.java,v 1.4 2001/06/01 22:12:03 mdb Exp $ package com.threerings.cocktail.cher.server; @@ -18,7 +18,10 @@ public class CherServer public static AuthManager authmgr; /** The manager of network connections. */ - public static ConnectionManager cmgr; + public static ConnectionManager conmgr; + + /** The manager of clients. */ + public static ClientManager clmgr; /** The distributed object manager. */ public static DObjectManager omgr; @@ -32,7 +35,9 @@ public class CherServer // create our authentication manager authmgr = new AuthManager(new DummyAuthenticator()); // create our connection manager - cmgr = new ConnectionManager(authmgr); + conmgr = new ConnectionManager(authmgr); + // create our client manager + clmgr = new ClientManager(conmgr); // create our distributed object manager omgr = new CherDObjectMgr(); @@ -51,7 +56,7 @@ public class CherServer // start up the auth manager authmgr.start(); // start up the connection manager - cmgr.start(); + conmgr.start(); // invoke the dobjmgr event loop ((CherDObjectMgr)omgr).run(); } diff --git a/src/java/com/threerings/presents/server/net/AuthManager.java b/src/java/com/threerings/presents/server/net/AuthManager.java index 0d3a2ba67..8584a9412 100644 --- a/src/java/com/threerings/presents/server/net/AuthManager.java +++ b/src/java/com/threerings/presents/server/net/AuthManager.java @@ -1,5 +1,5 @@ // -// $Id: AuthManager.java,v 1.2 2001/05/30 23:58:31 mdb Exp $ +// $Id: AuthManager.java,v 1.3 2001/06/01 22:12:03 mdb Exp $ package com.threerings.cocktail.cher.server.net; @@ -39,6 +39,16 @@ public class AuthManager extends LoopingThread _authq.append(aconn); } + /** + * The connection manager introduces itself to the auth manager so + * that the auth manager can let it know when it has authorized + * connections. + */ + public void setConnectionManager (ConnectionManager conmgr) + { + _conmgr = conmgr; + } + /** * Process auth requests. */ @@ -54,6 +64,10 @@ public class AuthManager extends LoopingThread // now ship the response back aconn.postMessage(rsp); + // if the authentication request was granted, let the + // connection manager know that we just authed a connection + _conmgr.connectionDidAuthenticate(aconn); + } catch (Exception e) { Log.warning("Failure processing authreq [conn=" + aconn + "]."); Log.logStackTrace(e); @@ -61,5 +75,6 @@ public class AuthManager extends LoopingThread } protected Authenticator _author; + protected ConnectionManager _conmgr; protected Queue _authq = new Queue(); } diff --git a/src/java/com/threerings/presents/server/net/Connection.java b/src/java/com/threerings/presents/server/net/Connection.java index 7db51fd8f..82be5235e 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.2 2001/05/30 23:58:31 mdb Exp $ +// $Id: Connection.java,v 1.3 2001/06/01 22:12:03 mdb Exp $ package com.threerings.cocktail.cher.server.net; @@ -62,6 +62,15 @@ public abstract class Connection implements NetEventHandler return _out; } + /** + * Returns the non-blocking socket object used to construct this + * connection. + */ + public NonblockingSocket getSocket () + { + return _socket; + } + /** * Called when our client socket has data available for reading. */ diff --git a/src/java/com/threerings/presents/server/net/ConnectionManager.java b/src/java/com/threerings/presents/server/net/ConnectionManager.java index 8bda0ed65..244b6c95a 100644 --- a/src/java/com/threerings/presents/server/net/ConnectionManager.java +++ b/src/java/com/threerings/presents/server/net/ConnectionManager.java @@ -1,10 +1,11 @@ // -// $Id: ConnectionManager.java,v 1.2 2001/05/30 23:58:31 mdb Exp $ +// $Id: ConnectionManager.java,v 1.3 2001/06/01 22:12:03 mdb Exp $ package com.threerings.cocktail.cher.server.net; import java.io.DataOutputStream; import java.io.IOException; +import java.util.ArrayList; import ninja2.core.io_core.nbio.*; import com.samskivert.util.LoopingThread; @@ -40,6 +41,8 @@ public class ConnectionManager extends LoopingThread // keep a handle on our authentication manager _authmgr = authmgr; + // complete the introductions + _authmgr.setConnectionManager(this); // we use this to wait for activity on our sockets _selset = new SelectSet(); @@ -69,6 +72,61 @@ public class ConnectionManager extends LoopingThread return _authmgr; } + /** + * Adds the specified connection observer to the observers list. + * Connection observers will be notified of connection-related + * events. An observer will not be added to the list twice. + * + * @see ConnectionObserver + */ + public void addConnectionObserver (ConnectionObserver observer) + { + synchronized (_observers) { + if (!_observers.contains(observer)) { + _observers.add(observer); + } + } + } + + /** + * Removes the specified connection observer from the observers list. + */ + public void removeConnectionObserver (ConnectionObserver observer) + { + synchronized (_observers) { + _observers.remove(observer); + } + } + + /** + * Notifies the connection observers of a connection event. Used + * internally. + */ + protected void notifyObservers (int code, Connection conn, + IOException cause) + { + synchronized (_observers) { + for (int i = 0; i < _observers.size(); i++) { + ConnectionObserver obs = + (ConnectionObserver)_observers.get(i); + switch (code) { + case CONNECTION_ESTABLISHED: + obs.connectionEstablished(conn); + break; + case CONNECTION_FAILED: + obs.connectionFailed(conn, cause); + break; + case CONNECTION_CLOSED: + obs.connectionClosed(conn); + break; + default: + throw new RuntimeException("Invalid code supplied to " + + "notifyObservers: " + code); + } + } + } + } + protected void willStart () { Log.info("Connection Manager thread running."); @@ -95,6 +153,30 @@ public class ConnectionManager extends LoopingThread } } + // check for connections that have completed authentication + Connection conn; + while ((conn = (Connection)_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()); + // wire this connection up to receive network events + _selset.add(rconn.getSelectItem()); + + // and let our observers know about our new connection + notifyObservers(CONNECTION_ESTABLISHED, rconn, null); + + } catch (IOException ioe) { + Log.warning("Failure upgrading authing connection to " + + "running connection."); + Log.logStackTrace(ioe); + } + } + // check for incoming network events int ecount = _selset.select(SELECT_LOOP_TIME); if (ecount == 0) { @@ -185,6 +267,7 @@ public class ConnectionManager extends LoopingThread _selset.remove(conn.getSelectItem()); // let our observers know what's up + notifyObservers(CONNECTION_FAILED, conn, ioe); } /** @@ -198,6 +281,17 @@ public class ConnectionManager extends LoopingThread _selset.remove(conn.getSelectItem()); // let our observers know what's up + notifyObservers(CONNECTION_CLOSED, conn, null); + } + + /** + * Called by the auth manager to indicate that a connection was + * successfully authenticated. + */ + void connectionDidAuthenticate (Connection conn) + { + // slap this sucker onto the authenticated connections queue + _authq.append(conn); } protected AuthManager _authmgr; @@ -210,6 +304,10 @@ public class ConnectionManager extends LoopingThread protected FramingOutputStream _framer; protected DataOutputStream _dout; + protected Queue _authq = new Queue(); + + protected ArrayList _observers = new ArrayList(); + /** The default port on which we listen for connections. */ protected static final int DEFAULT_CM_PORT = 4007; @@ -219,6 +317,11 @@ public class ConnectionManager extends LoopingThread */ protected static final int SELECT_LOOP_TIME = 30 * 1000; + // codes for notifyObservers() + protected static final int CONNECTION_ESTABLISHED = 0; + protected static final int CONNECTION_FAILED = 1; + protected static final int CONNECTION_CLOSED = 2; + // register our shared objects static { Registry.registerTypedObjects(); diff --git a/src/java/com/threerings/presents/server/net/ConnectionObserver.java b/src/java/com/threerings/presents/server/net/ConnectionObserver.java index 47855fa87..950f83907 100644 --- a/src/java/com/threerings/presents/server/net/ConnectionObserver.java +++ b/src/java/com/threerings/presents/server/net/ConnectionObserver.java @@ -1,5 +1,5 @@ // -// $Id: ConnectionObserver.java,v 1.2 2001/05/30 23:58:31 mdb Exp $ +// $Id: ConnectionObserver.java,v 1.3 2001/06/01 22:12:03 mdb Exp $ package com.threerings.cocktail.cher.server.net; @@ -19,7 +19,8 @@ public interface ConnectionObserver { /** * Called when a new connection is established with the connection - * manager. + * manager. Only fully authenticated connections will be passed on to + * the connection observer. * * @param conn The newly established connection. */ @@ -28,7 +29,7 @@ public interface ConnectionObserver /** * Called if a connection fails for any reason. If a connection fails, * connectionClosed will not be called. This call to - * connectionFailued is the last the observers will hear + * connectionFailed is the last the observers will hear * about it. * * @param conn The connection in that failed.