Added moveToServer() which does pretty much what it says. Boy I love writing

everything in two languages. Especially when one doesn't support inner classes
and has non-C syntax just to make life easier for parser writers.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4762 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2007-07-13 21:57:55 +00:00
parent fd687a2774
commit 77e3f22d90
2 changed files with 116 additions and 6 deletions
@@ -31,6 +31,7 @@ import flash.utils.Timer;
import com.threerings.util.MethodQueue;
import com.threerings.util.ObserverList;
import com.threerings.presents.client.InvocationService_ConfirmListener;
import com.threerings.presents.data.ClientObject;
import com.threerings.presents.data.InvocationCodes;
@@ -270,6 +271,27 @@ public class Client extends EventDispatcher
return true;
}
/**
* Transitions a logged on client from its current server to the specified new server.
* Currently this simply logs the client off of its current server (if it is logged on) and
* logs it onto the new server, but in the future we may aim to do something fancier.
*
* <p> If we fail to connect to the new server, the client <em>will not</em> be automatically
* reconnected to the old server. It will be in a logged off state. However, it will be
* reconfigured with the hostname and ports of the old server so that the caller can notify the
* user of the failure and then simply call {@link #logon} to attempt to reconnect to the old
* server.
*
* @param observer an observer that will be notified when we have successfully logged onto the
* other server, or if the move failed.
*/
public function moveToServer (hostname :String, ports :Array,
obs :InvocationService_ConfirmListener) :void
{
// the server switcher will take care of everything for us
new ServerSwitcher(this, hostname, ports, obs).switchServers();
}
/**
* Requests that the client log off of the server to which it is connected.
*
@@ -299,8 +321,7 @@ public class Client extends EventDispatcher
return true;
}
public function gotBootstrap (data :BootstrapData, omgr :DObjectManager)
:void
public function gotBootstrap (data :BootstrapData, omgr :DObjectManager) :void
{
log.debug("Got bootstrap " + data + ".");
@@ -27,8 +27,9 @@ import com.samskivert.util.Interval;
import com.samskivert.util.ObserverList;
import com.samskivert.util.RunAnywhere;
import com.samskivert.util.RunQueue;
import com.samskivert.util.StringUtil;
import com.threerings.presents.Log;
import com.threerings.presents.data.AuthCodes;
import com.threerings.presents.data.ClientObject;
import com.threerings.presents.data.InvocationCodes;
import com.threerings.presents.dobj.DEvent;
@@ -40,6 +41,8 @@ import com.threerings.presents.net.Credentials;
import com.threerings.presents.net.PingRequest;
import com.threerings.presents.net.PongResponse;
import static com.threerings.presents.Log.log;
/**
* Through the client object, a connection to the system is established and maintained. The client
* object maintains two separate threads (a reader and a writer) by which all network traffic is
@@ -108,6 +111,7 @@ public class Client
* ports (which will be tried in succession).
*
* @see #logon
* @see #moveToServer
*/
public void setServer (String hostname, int[] ports)
{
@@ -393,6 +397,26 @@ public class Client
return true;
}
/**
* Transitions a logged on client from its current server to the specified new server.
* Currently this simply logs the client off of its current server (if it is logged on) and
* logs it onto the new server, but in the future we may aim to do something fancier.
*
* <p> If we fail to connect to the new server, the client <em>will not</em> be automatically
* reconnected to the old server. It will be in a logged off state. However, it will be
* reconfigured with the hostname and ports of the old server so that the caller can notify the
* user of the failure and then simply call {@link #logon} to attempt to reconnect to the old
* server.
*
* @param observer an observer that will be notified when we have successfully logged onto the
* other server, or if the move failed.
*/
public void moveToServer (String hostname, int[] ports, InvocationService.ConfirmListener obs)
{
// the server switcher will take care of everything for us
new ServerSwitcher(hostname, ports, obs).switchServers();
}
/**
* Requests that the client log off of the server to which it is connected.
*
@@ -406,7 +430,7 @@ public class Client
{
// if we have no communicator, we're not logged on anyway
if (_comm == null) {
Log.warning("Ignoring request to logoff because we're not logged on.");
log.warning("Ignoring request to logoff because we're not logged on.");
return true;
}
@@ -464,7 +488,7 @@ public class Client
*/
protected void gotBootstrap (BootstrapData data, DObjectManager omgr)
{
Log.debug("Got bootstrap " + data + ".");
log.fine("Got bootstrap " + data + ".");
// keep these around for interested parties
_bstrap = data;
@@ -509,7 +533,7 @@ public class Client
if (_dcalc != null) {
// if our current calculator is done, clear it out
if (_dcalc.isDone()) {
Log.debug("Time offset from server: " + _serverDelta + "ms.");
log.fine("Time offset from server: " + _serverDelta + "ms.");
_dcalc = null;
} else if (_dcalc.shouldSendPing()) {
// otherwise, send another ping
@@ -742,6 +766,71 @@ public class Client
protected boolean _rejected;
}
/** Handles the process of switching between servers. See {@link #moveToServer}. */
protected class ServerSwitcher extends ClientAdapter
{
public ServerSwitcher (String hostname, int[] ports, InvocationService.ConfirmListener obs)
{
_hostname = hostname;
_ports = ports;
_observer = obs;
}
public void switchServers ()
{
addClientObserver(this);
if (!isLoggedOn()) {
// if we're not logged on right now, just do the switch immediately
clientDidClear(Client.this);
} else {
// note our current connection information so that we can restore it if our logon
// attempt fails
_oldHostname = Client.this._hostname;
_oldPorts = Client.this._ports;
// otherwise logoff and wait for all of our callbacks to clear
logoff(true);
}
}
public void clientDidClear (Client client)
{
// configure the client to point to the new server and logon
setServer(_hostname, _ports);
if (!logon()) {
log.warning("logon() failed during server switch? [hostname=" + _hostname +
", ports=" + StringUtil.toString(_ports) + "].");
clientFailedToLogon(Client.this, new Exception("logon() failed?"));
}
}
public void clientDidLogon (Client client)
{
removeClientObserver(this);
if (_observer != null) {
_observer.requestProcessed();
}
}
public void clientFailedToLogon (Client client, Exception cause)
{
removeClientObserver(this);
if (_oldHostname != null) { // restore our previous server and ports
setServer(_oldHostname, _oldPorts);
}
if (_observer != null) {
_observer.requestFailed((cause instanceof LogonException) ?
cause.getMessage() : AuthCodes.SERVER_ERROR);
}
}
protected String _hostname, _oldHostname;
protected int[] _ports, _oldPorts;
protected InvocationService.ConfirmListener _observer;
}
/** The credentials we used to authenticate with the server. */
protected Credentials _creds;