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
This commit is contained in:
Michael Bayne
2001-06-01 22:12:03 +00:00
parent 1929898dd8
commit 2c3e4d9528
6 changed files with 203 additions and 10 deletions
@@ -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,
* <code>connectionClosed</code> will not be called. This call to
* <code>connectionFailed</code> 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);
}
}
@@ -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; package com.threerings.cocktail.cher.server;
@@ -18,7 +18,10 @@ public class CherServer
public static AuthManager authmgr; public static AuthManager authmgr;
/** The manager of network connections. */ /** 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. */ /** The distributed object manager. */
public static DObjectManager omgr; public static DObjectManager omgr;
@@ -32,7 +35,9 @@ public class CherServer
// create our authentication manager // create our authentication manager
authmgr = new AuthManager(new DummyAuthenticator()); authmgr = new AuthManager(new DummyAuthenticator());
// create our connection manager // 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 // create our distributed object manager
omgr = new CherDObjectMgr(); omgr = new CherDObjectMgr();
@@ -51,7 +56,7 @@ public class CherServer
// start up the auth manager // start up the auth manager
authmgr.start(); authmgr.start();
// start up the connection manager // start up the connection manager
cmgr.start(); conmgr.start();
// invoke the dobjmgr event loop // invoke the dobjmgr event loop
((CherDObjectMgr)omgr).run(); ((CherDObjectMgr)omgr).run();
} }
@@ -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; package com.threerings.cocktail.cher.server.net;
@@ -39,6 +39,16 @@ public class AuthManager extends LoopingThread
_authq.append(aconn); _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. * Process auth requests.
*/ */
@@ -54,6 +64,10 @@ public class AuthManager extends LoopingThread
// now ship the response back // now ship the response back
aconn.postMessage(rsp); 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) { } catch (Exception e) {
Log.warning("Failure processing authreq [conn=" + aconn + "]."); Log.warning("Failure processing authreq [conn=" + aconn + "].");
Log.logStackTrace(e); Log.logStackTrace(e);
@@ -61,5 +75,6 @@ public class AuthManager extends LoopingThread
} }
protected Authenticator _author; protected Authenticator _author;
protected ConnectionManager _conmgr;
protected Queue _authq = new Queue(); protected Queue _authq = new Queue();
} }
@@ -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; package com.threerings.cocktail.cher.server.net;
@@ -62,6 +62,15 @@ public abstract class Connection implements NetEventHandler
return _out; 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. * Called when our client socket has data available for reading.
*/ */
@@ -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; package com.threerings.cocktail.cher.server.net;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import ninja2.core.io_core.nbio.*; import ninja2.core.io_core.nbio.*;
import com.samskivert.util.LoopingThread; import com.samskivert.util.LoopingThread;
@@ -40,6 +41,8 @@ public class ConnectionManager extends LoopingThread
// keep a handle on our authentication manager // keep a handle on our authentication manager
_authmgr = authmgr; _authmgr = authmgr;
// complete the introductions
_authmgr.setConnectionManager(this);
// we use this to wait for activity on our sockets // we use this to wait for activity on our sockets
_selset = new SelectSet(); _selset = new SelectSet();
@@ -69,6 +72,61 @@ public class ConnectionManager extends LoopingThread
return _authmgr; 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 () protected void willStart ()
{ {
Log.info("Connection Manager thread running."); 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 // check for incoming network events
int ecount = _selset.select(SELECT_LOOP_TIME); int ecount = _selset.select(SELECT_LOOP_TIME);
if (ecount == 0) { if (ecount == 0) {
@@ -185,6 +267,7 @@ public class ConnectionManager extends LoopingThread
_selset.remove(conn.getSelectItem()); _selset.remove(conn.getSelectItem());
// let our observers know what's up // 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()); _selset.remove(conn.getSelectItem());
// let our observers know what's up // 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; protected AuthManager _authmgr;
@@ -210,6 +304,10 @@ public class ConnectionManager extends LoopingThread
protected FramingOutputStream _framer; protected FramingOutputStream _framer;
protected DataOutputStream _dout; protected DataOutputStream _dout;
protected Queue _authq = new Queue();
protected ArrayList _observers = new ArrayList();
/** The default port on which we listen for connections. */ /** The default port on which we listen for connections. */
protected static final int DEFAULT_CM_PORT = 4007; 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; 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 // register our shared objects
static { static {
Registry.registerTypedObjects(); Registry.registerTypedObjects();
@@ -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; package com.threerings.cocktail.cher.server.net;
@@ -19,7 +19,8 @@ public interface ConnectionObserver
{ {
/** /**
* Called when a new connection is established with the connection * 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. * @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, * Called if a connection fails for any reason. If a connection fails,
* <code>connectionClosed</code> will not be called. This call to * <code>connectionClosed</code> will not be called. This call to
* <code>connectionFailued</code> is the last the observers will hear * <code>connectionFailed</code> is the last the observers will hear
* about it. * about it.
* *
* @param conn The connection in that failed. * @param conn The connection in that failed.