Bit the bullet and implemented invocation service groups so that our various
MetaSOY clients (Swiftly, World, and soon Admin Dashboard) don't have to know about a bunch of unrelated crap. Fricking complexity++, grumble. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4551 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -21,6 +21,8 @@
|
||||
|
||||
package com.threerings.presents.client;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.samskivert.util.Interval;
|
||||
import com.samskivert.util.ObserverList;
|
||||
import com.samskivert.util.RunAnywhere;
|
||||
@@ -36,9 +38,9 @@ import com.threerings.presents.net.PingRequest;
|
||||
import com.threerings.presents.net.PongResponse;
|
||||
|
||||
/**
|
||||
* 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 managed.
|
||||
* 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
|
||||
* managed.
|
||||
*/
|
||||
public class Client
|
||||
{
|
||||
@@ -47,22 +49,17 @@ public class Client
|
||||
public static final int[] DEFAULT_SERVER_PORTS = { 47624 };
|
||||
|
||||
/**
|
||||
* Constructs a client object with the supplied credentials and
|
||||
* RunQueue. The creds will be used to authenticate with any server to
|
||||
* which this client attempts to connect. The RunQueue is used to
|
||||
* operate the distributed object event dispatch mechanism. To allow
|
||||
* the dobj event dispatch to coexist with threads like the AWT
|
||||
* thread, the client will request that the RunQueue queue up a
|
||||
* runnable whenever there are distributed object events that need to
|
||||
* be processed. The RunQueue can then queue that runnable up on the
|
||||
* AWT thread if it is so inclined to make life simpler for the rest
|
||||
* of the application.
|
||||
* Constructs a client object with the supplied credentials and RunQueue. The creds will be
|
||||
* used to authenticate with any server to which this client attempts to connect. The RunQueue
|
||||
* is used to operate the distributed object event dispatch mechanism. To allow the dobj event
|
||||
* dispatch to coexist with threads like the AWT thread, the client will request that the
|
||||
* RunQueue queue up a runnable whenever there are distributed object events that need to be
|
||||
* processed. The RunQueue can then queue that runnable up on the AWT thread if it is so
|
||||
* inclined to make life simpler for the rest of the application.
|
||||
*
|
||||
* @param creds the credentials to use when logging on to the server.
|
||||
* These can be null, but <code>setCredentials</code> must then be
|
||||
* called before any call to <code>logon</code>.
|
||||
* @param runQueue a RunQueue that can be used to process incoming
|
||||
* events.
|
||||
* @param creds the credentials to use when logging on to the server. These can be null, but
|
||||
* <code>setCredentials</code> must then be called before any call to <code>logon</code>.
|
||||
* @param runQueue a RunQueue that can be used to process incoming events.
|
||||
*/
|
||||
public Client (Credentials creds, RunQueue runQueue)
|
||||
{
|
||||
@@ -71,10 +68,9 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the supplied observer with this client. While registered
|
||||
* the observer will receive notifications of state changes within the
|
||||
* client. The function will refuse to register an already registered
|
||||
* observer.
|
||||
* Registers the supplied observer with this client. While registered the observer will receive
|
||||
* notifications of state changes within the client. The function will refuse to register an
|
||||
* already registered observer.
|
||||
*
|
||||
* @see ClientObserver
|
||||
* @see SessionObserver
|
||||
@@ -87,9 +83,8 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the supplied observer. Upon return of this function,
|
||||
* the observer will no longer receive notifications of state changes
|
||||
* within the client.
|
||||
* Unregisters the supplied observer. Upon return of this function, the observer will no longer
|
||||
* receive notifications of state changes within the client.
|
||||
*/
|
||||
public void removeClientObserver (SessionObserver observer)
|
||||
{
|
||||
@@ -105,7 +100,7 @@ public class Client
|
||||
{
|
||||
_standalone = standalone;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether or not this client is operating in a standalone mode.
|
||||
*/
|
||||
@@ -113,10 +108,10 @@ public class Client
|
||||
{
|
||||
return _standalone;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configures the client to communicate with the server on the supplied
|
||||
* hostname and set of ports (which will be tried in succession).
|
||||
* Configures the client to communicate with the server on the supplied hostname and set of
|
||||
* ports (which will be tried in succession).
|
||||
*
|
||||
* @see #logon
|
||||
*/
|
||||
@@ -127,8 +122,8 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the RunQueue in use by this client. This can be used to
|
||||
* queue up event dispatching stints.
|
||||
* Returns the RunQueue in use by this client. This can be used to queue up event dispatching
|
||||
* stints.
|
||||
*/
|
||||
public RunQueue getRunQueue ()
|
||||
{
|
||||
@@ -136,8 +131,7 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hostname of the server to which this client is
|
||||
* currently configured to connect.
|
||||
* Returns the hostname of the server to which this client is currently configured to connect.
|
||||
*/
|
||||
public String getHostname ()
|
||||
{
|
||||
@@ -145,8 +139,7 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the port on which this client is currently configured to
|
||||
* connect to the server.
|
||||
* Returns the port on which this client is currently configured to connect to the server.
|
||||
*/
|
||||
public int[] getPorts ()
|
||||
{
|
||||
@@ -154,8 +147,8 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the credentials with which this client is currently
|
||||
* configured to connect to the server.
|
||||
* Returns the credentials with which this client is currently configured to connect to the
|
||||
* server.
|
||||
*/
|
||||
public Credentials getCredentials ()
|
||||
{
|
||||
@@ -163,9 +156,8 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the credentials that will be used by this client to
|
||||
* authenticate with the server. This should be done before any call
|
||||
* to <code>logon</code>.
|
||||
* Sets the credentials that will be used by this client to authenticate with the server. This
|
||||
* should be done before any call to <code>logon</code>.
|
||||
*/
|
||||
public void setCredentials (Credentials creds)
|
||||
{
|
||||
@@ -181,9 +173,8 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the version string reported to the server during
|
||||
* authentication. Some server implementations may wish to refuse
|
||||
* connections by old or invalid client versions.
|
||||
* Sets the version string reported to the server during authentication. Some server
|
||||
* implementations may wish to refuse connections by old or invalid client versions.
|
||||
*/
|
||||
public void setVersion (String version)
|
||||
{
|
||||
@@ -191,8 +182,8 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the client with a custom class loader which will be used
|
||||
* when reading objects off of the network.
|
||||
* Configures the client with a custom class loader which will be used when reading objects off
|
||||
* of the network.
|
||||
*/
|
||||
public void setClassLoader (ClassLoader loader)
|
||||
{
|
||||
@@ -203,10 +194,19 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data associated with our authentication response. Users
|
||||
* of the Presents system may wish to communicate authentication
|
||||
* related information to their client by extending and augmenting
|
||||
* {@link AuthResponseData}.
|
||||
* Marks this client as interested in the specified bootstrap services group. Any services
|
||||
* registered as bootstrap services with the supplied group name will be included in this
|
||||
* clients bootstrap services set. This must be called before {@link #logon}.
|
||||
*/
|
||||
public void addBootstrapGroup (String group)
|
||||
{
|
||||
_bootGroups.add(group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data associated with our authentication response. Users of the Presents system
|
||||
* may wish to communicate authentication related information to their client by extending and
|
||||
* augmenting {@link AuthResponseData}.
|
||||
*/
|
||||
public AuthResponseData getAuthResponseData ()
|
||||
{
|
||||
@@ -214,13 +214,11 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distributed object manager associated with this
|
||||
* session. This reference is only valid for the duration of the
|
||||
* session and a new reference must be obtained if the client
|
||||
* Returns the distributed object manager associated with this session. This reference is only
|
||||
* valid for the duration of the session and a new reference must be obtained if the client
|
||||
* disconnects and reconnects to the server.
|
||||
*
|
||||
* @return the dobjmgr in effect or null if we have no established
|
||||
* connection to the server.
|
||||
* @return the dobjmgr in effect or null if we have no established connection to the server.
|
||||
*/
|
||||
public DObjectManager getDObjectManager ()
|
||||
{
|
||||
@@ -228,17 +226,15 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the distributed object manager associated with this
|
||||
* client to allow objects of the specified class to linger around the
|
||||
* specified number of milliseconds after their last subscriber has
|
||||
* been removed before the client finally removes its object proxy and
|
||||
* flushes the object. Normally, objects are flushed immediately
|
||||
* following the removal of their last subscriber.
|
||||
* Instructs the distributed object manager associated with this client to allow objects of the
|
||||
* specified class to linger around the specified number of milliseconds after their last
|
||||
* subscriber has been removed before the client finally removes its object proxy and flushes
|
||||
* the object. Normally, objects are flushed immediately following the removal of their last
|
||||
* subscriber.
|
||||
*
|
||||
* <p><em>Note:</em> the delay will be applied to derived classes as
|
||||
* well as exact matches. <em>Note also:</em> this method cannot be
|
||||
* called until after the client has established a connection with the
|
||||
* server and the distributed object manager is available.
|
||||
* <p><em>Note:</em> the delay will be applied to derived classes as well as exact
|
||||
* matches. <em>Note also:</em> this method cannot be called until after the client has
|
||||
* established a connection with the server and the distributed object manager is available.
|
||||
*/
|
||||
public void registerFlushDelay (Class objclass, long delay)
|
||||
{
|
||||
@@ -247,8 +243,8 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the oid of the client object associated with this session.
|
||||
* It is only valid for the duration of the session.
|
||||
* Returns the oid of the client object associated with this session. It is only valid for the
|
||||
* duration of the session.
|
||||
*/
|
||||
public int getClientOid ()
|
||||
{
|
||||
@@ -256,8 +252,8 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the client object associated with this
|
||||
* session. It is only valid for the duration of the session.
|
||||
* Returns a reference to the client object associated with this session. It is only valid for
|
||||
* the duration of the session.
|
||||
*/
|
||||
public ClientObject getClientObject ()
|
||||
{
|
||||
@@ -265,8 +261,8 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the invocation director associated with this session. This
|
||||
* reference is only valid for the duration of the session.
|
||||
* Returns the invocation director associated with this session. This reference is only valid
|
||||
* for the duration of the session.
|
||||
*/
|
||||
public InvocationDirector getInvocationDirector ()
|
||||
{
|
||||
@@ -274,9 +270,9 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first bootstrap service that could be located that
|
||||
* implements the supplied {@link InvocationService} derivation.
|
||||
* <code>null</code> is returned if no such service could be found.
|
||||
* Returns the first bootstrap service that could be located that implements the supplied
|
||||
* {@link InvocationService} derivation. <code>null</code> is returned if no such service
|
||||
* could be found.
|
||||
*/
|
||||
public InvocationService getService (Class sclass)
|
||||
{
|
||||
@@ -295,10 +291,9 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #getService} except that a {@link RuntimeException} is
|
||||
* thrown if the service is not available. Useful to avoid redundant
|
||||
* error checking when you know that the shit will hit the fan if a
|
||||
* particular invocation service is not available.
|
||||
* Like {@link #getService} except that a {@link RuntimeException} is thrown if the service is
|
||||
* not available. Useful to avoid redundant error checking when you know that the shit will hit
|
||||
* the fan if a particular invocation service is not available.
|
||||
*/
|
||||
public InvocationService requireService (Class sclass)
|
||||
{
|
||||
@@ -312,8 +307,7 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the bootstrap data provided to this client
|
||||
* at logon time.
|
||||
* Returns a reference to the bootstrap data provided to this client at logon time.
|
||||
*/
|
||||
public BootstrapData getBootstrapData ()
|
||||
{
|
||||
@@ -321,30 +315,28 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a server time stamp to a value comparable to client clock
|
||||
* readings.
|
||||
* Converts a server time stamp to a value comparable to client clock readings.
|
||||
*/
|
||||
public long fromServerTime (long stamp)
|
||||
{
|
||||
// when we calcuated our time delta, we did it such that: C - S =
|
||||
// dT, thus to convert server to client time we do: C = S + dT
|
||||
// when we calcuated our time delta, we did it such that: C - S = dT, thus to convert
|
||||
// server to client time we do: C = S + dT
|
||||
return stamp + _serverDelta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a client clock reading to a value comparable to a server
|
||||
* time stamp.
|
||||
* Converts a client clock reading to a value comparable to a server time stamp.
|
||||
*/
|
||||
public long toServerTime (long stamp)
|
||||
{
|
||||
// when we calcuated our time delta, we did it such that: C - S =
|
||||
// dT, thus to convert server to client time we do: S = C - dT
|
||||
// when we calcuated our time delta, we did it such that: C - S = dT, thus to convert
|
||||
// server to client time we do: S = C - dT
|
||||
return stamp - _serverDelta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if we are in active communication (we may not yet be logged
|
||||
* on, but we could be trying to log on).
|
||||
* Returns true if we are in active communication (we may not yet be logged on, but we could be
|
||||
* trying to log on).
|
||||
*/
|
||||
public synchronized boolean isActive ()
|
||||
{
|
||||
@@ -357,17 +349,16 @@ public class Client
|
||||
*/
|
||||
public synchronized boolean isLoggedOn ()
|
||||
{
|
||||
// we're not "logged on" until we're fully done with the
|
||||
// procedure, meaning we have a client object reference
|
||||
// we're not "logged on" until we're fully done with the procedure, meaning we have a
|
||||
// client object reference
|
||||
return (_clobj != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that this client connect and logon to the server with
|
||||
* which it was previously configured.
|
||||
* Requests that this client connect and logon to the server with which it was previously
|
||||
* configured.
|
||||
*
|
||||
* @return false if we're already logged on, true if a logon attempt
|
||||
* was initiated.
|
||||
* @return false if we're already logged on, true if a logon attempt was initiated.
|
||||
*/
|
||||
public synchronized boolean logon ()
|
||||
{
|
||||
@@ -376,14 +367,14 @@ public class Client
|
||||
return false;
|
||||
}
|
||||
|
||||
// otherwise create a new communicator instance and start it up.
|
||||
// this will initiate the logon process
|
||||
// otherwise create a new communicator instance and start it up. this will initiate the
|
||||
// logon process
|
||||
_comm = new Communicator(this);
|
||||
_comm.setClassLoader(_loader);
|
||||
_comm.logon();
|
||||
|
||||
// register an interval that we'll use to keep the clock synced
|
||||
// and to send pings when appropriate
|
||||
// register an interval that we'll use to keep the clock synced and to send pings when
|
||||
// appropriate
|
||||
if (_tickInterval == null) {
|
||||
_tickInterval = new Interval() {
|
||||
public void expired () {
|
||||
@@ -397,28 +388,23 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the client log off of the server to which it is
|
||||
* connected.
|
||||
* Requests that the client log off of the server to which it is connected.
|
||||
*
|
||||
* @param abortable If true, the client will call
|
||||
* <code>clientWillDisconnect</code> on all of the client observers
|
||||
* and abort the logoff process if any of them return false. If false,
|
||||
* @param abortable If true, the client will call <code>clientWillDisconnect</code> on all of
|
||||
* the client observers and abort the logoff process if any of them return false. If false,
|
||||
* <code>clientWillDisconnect</code> will not be called at all.
|
||||
*
|
||||
* @return true if the logoff succeeded, false if it failed due to a
|
||||
* disagreeable observer.
|
||||
* @return true if the logoff succeeded, false if it failed due to a disagreeable observer.
|
||||
*/
|
||||
public boolean logoff (boolean abortable)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
// if the request is abortable, let's run it past the observers
|
||||
// before we act upon it
|
||||
// if the request is abortable, let's run it past the observers before we act upon it
|
||||
if (abortable && notifyObservers(CLIENT_WILL_LOGOFF, null)) {
|
||||
return false;
|
||||
}
|
||||
@@ -427,29 +413,25 @@ public class Client
|
||||
_tickInterval.cancel();
|
||||
_tickInterval = null;
|
||||
|
||||
// ask the communicator to send a logoff message and disconnect
|
||||
// from the server
|
||||
// ask the communicator to send a logoff message and disconnect from the server
|
||||
_comm.logoff();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* For standalone mode, this notifies observers that the client has logged
|
||||
* off and cleans up.
|
||||
* For standalone mode, this notifies observers that the client has logged off and cleans up.
|
||||
*/
|
||||
public void standaloneLogoff ()
|
||||
{
|
||||
notifyObservers(CLIENT_DID_LOGOFF, null);
|
||||
cleanup(null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by the {@link ClientDObjectMgr} when our bootstrap
|
||||
* notification arrives. If the client and server are being run in
|
||||
* "merged" mode in a single JVM, this is how the client is configured
|
||||
* with the server's distributed object manager and provided with
|
||||
* bootstrap data.
|
||||
* Called by the {@link ClientDObjectMgr} when our bootstrap notification arrives. If the
|
||||
* client and server are being run in "merged" mode in a single JVM, this is how the client is
|
||||
* configured with the server's distributed object manager and provided with bootstrap data.
|
||||
*/
|
||||
public void gotBootstrap (BootstrapData data, DObjectManager omgr)
|
||||
{
|
||||
@@ -465,20 +447,18 @@ public class Client
|
||||
// initialize our invocation director
|
||||
_invdir.init(omgr, _cloid, this);
|
||||
|
||||
// send a few pings to the server to establish the clock offset
|
||||
// between this client and server standard time
|
||||
// send a few pings to the server to establish the clock offset between this client and
|
||||
// server standard time
|
||||
establishClockDelta(System.currentTimeMillis());
|
||||
|
||||
// we can't quite call initialization completed at this point
|
||||
// because we need for the invocation director to fully initialize
|
||||
// (which requires a round trip to the server) before turning the
|
||||
// client loose to do things like request invocation services
|
||||
// we can't quite call initialization completed at this point because we need for the
|
||||
// invocation director to fully initialize (which requires a round trip to the server)
|
||||
// before turning the client loose to do things like request invocation services
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every five seconds; ensures that we ping the server if we
|
||||
* haven't communicated in a long while and periodically resyncs the
|
||||
* client and server clock deltas.
|
||||
* Called every five seconds; ensures that we ping the server if we haven't communicated in a
|
||||
* long while and periodically resyncs the client and server clock deltas.
|
||||
*/
|
||||
protected void tick ()
|
||||
{
|
||||
@@ -501,8 +481,8 @@ public class Client
|
||||
}
|
||||
|
||||
} else if (now - _comm.getLastWrite() > PingRequest.PING_INTERVAL) {
|
||||
// if we haven't sent anything over the network in a while, we
|
||||
// ping the server to let it know that we're still alive
|
||||
// if we haven't sent anything over the network in a while, we ping the server to let
|
||||
// it know that we're still alive
|
||||
_comm.postMessage(new PingRequest());
|
||||
|
||||
} else if (now - _lastSync > CLOCK_SYNC_INTERVAL) {
|
||||
@@ -512,10 +492,9 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Called during initialization to initiate a sequence of ping/pong
|
||||
* messages which will be used to determine (with "good enough"
|
||||
* accuracy) the difference between the client clock and the server
|
||||
* clock so that we can later interpret server timestamps.
|
||||
* Called during initialization to initiate a sequence of ping/pong messages which will be used
|
||||
* to determine (with "good enough" accuracy) the difference between the client clock and the
|
||||
* server clock so that we can later interpret server timestamps.
|
||||
*/
|
||||
protected void establishClockDelta (long now)
|
||||
{
|
||||
@@ -530,8 +509,8 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the {@link Communicator} if it is experiencing trouble logging
|
||||
* on but is still trying fallback strategies.
|
||||
* Called by the {@link Communicator} if it is experiencing trouble logging on but is still
|
||||
* trying fallback strategies.
|
||||
*/
|
||||
protected void reportLogonTribulations (final LogonException cause)
|
||||
{
|
||||
@@ -543,8 +522,8 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the invocation director when it successfully subscribes
|
||||
* to the client object immediately following logon.
|
||||
* Called by the invocation director when it successfully subscribes to the client object
|
||||
* immediately following logon.
|
||||
*/
|
||||
protected void gotClientObject (ClientObject clobj)
|
||||
{
|
||||
@@ -556,8 +535,7 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the invocation director if it fails to subscribe to the
|
||||
* client object after logon.
|
||||
* Called by the invocation director if it fails to subscribe to the client object after logon.
|
||||
*/
|
||||
protected void getClientObjectFailed (Exception cause)
|
||||
{
|
||||
@@ -566,8 +544,7 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the invocation director when it discovers that the client
|
||||
* object has changed.
|
||||
* Called by the invocation director when it discovers that the client object has changed.
|
||||
*/
|
||||
protected void clientObjectDidChange (ClientObject clobj)
|
||||
{
|
||||
@@ -589,17 +566,16 @@ public class Client
|
||||
}
|
||||
};
|
||||
|
||||
// we need to run immediately if this is WILL_LOGOFF or if we have
|
||||
// no RunQueue (which currently only happens in some really obscure
|
||||
// circumstances where we're using a Client instance on the server
|
||||
// so that we can sort of pretend to be a real client)
|
||||
// we need to run immediately if this is WILL_LOGOFF or if we have no RunQueue (which
|
||||
// currently only happens in some really obscure circumstances where we're using a Client
|
||||
// instance on the server so that we can sort of pretend to be a real client)
|
||||
if (code == CLIENT_WILL_LOGOFF || _runQueue == null) {
|
||||
unit.run();
|
||||
return noty.getRejected();
|
||||
|
||||
} else {
|
||||
// otherwise we can queue this notification up with our
|
||||
// RunQueue and ensure that it's run on the proper thread
|
||||
// otherwise we can queue this notification up with our RunQueue and ensure that it's
|
||||
// run on the proper thread
|
||||
_runQueue.postRunnable(unit);
|
||||
return false;
|
||||
}
|
||||
@@ -607,12 +583,10 @@ public class Client
|
||||
|
||||
synchronized void cleanup (final Exception logonError)
|
||||
{
|
||||
// we know that prior to the call to this method, the observers
|
||||
// were notified with CLIENT_DID_LOGOFF; that may not have been
|
||||
// invoked yet, so we don't want to clear out our communicator
|
||||
// reference immediately; instead we queue up a runnable unit to
|
||||
// do so to ensure that it won't happen until CLIENT_DID_LOGOFF
|
||||
// was dispatched
|
||||
// we know that prior to the call to this method, the observers were notified with
|
||||
// CLIENT_DID_LOGOFF; that may not have been invoked yet, so we don't want to clear out our
|
||||
// communicator reference immediately; instead we queue up a runnable unit to do so to
|
||||
// ensure that it won't happen until CLIENT_DID_LOGOFF was dispatched
|
||||
_runQueue.postRunnable(new Runnable() {
|
||||
public void run () {
|
||||
// clear out our references
|
||||
@@ -625,11 +599,10 @@ public class Client
|
||||
// and let our invocation director know we're logged off
|
||||
_invdir.cleanup();
|
||||
|
||||
// if we were cleaned up due to a failure to logon, we can
|
||||
// report the logon error now that the communicator is
|
||||
// cleaned up; this allows a logon failure listener to
|
||||
// immediately try another logon (hopefully with something
|
||||
// changed like the server or port)
|
||||
// if we were cleaned up due to a failure to logon, we can report the logon error
|
||||
// now that the communicator is cleaned up; this allows a logon failure listener to
|
||||
// immediately try another logon (hopefully with something changed like the server
|
||||
// or port)
|
||||
if (logonError != null) {
|
||||
notifyObservers(CLIENT_FAILED_TO_LOGON, logonError);
|
||||
} else {
|
||||
@@ -640,18 +613,15 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when we receive a pong packet. We may be in the process of
|
||||
* calculating the client/server time differential, or we may have
|
||||
* already done that at which point we ignore pongs.
|
||||
* Called when we receive a pong packet. We may be in the process of calculating the client/
|
||||
* server time differential, or we may have already done that at which point we ignore pongs.
|
||||
*/
|
||||
void gotPong (PongResponse pong)
|
||||
{
|
||||
// if we're not currently calculating our client/server delta, then
|
||||
// we can throw away the pong
|
||||
// if we're not currently calculating our delta, then we can throw away the pong
|
||||
if (_dcalc != null) {
|
||||
// we update the delta after every receipt so as to immediately
|
||||
// obtain an estimate of the clock delta and then refine it as
|
||||
// more packets come in
|
||||
// we update the delta after every receipt so as to immediately obtain an estimate of
|
||||
// the clock delta and then refine it as more packets come in
|
||||
_dcalc.gotPong(pong);
|
||||
_serverDelta = _dcalc.getTimeDelta();
|
||||
}
|
||||
@@ -684,8 +654,7 @@ public class Client
|
||||
|
||||
case CLIENT_FAILED_TO_LOGON:
|
||||
if (obs instanceof ClientObserver) {
|
||||
((ClientObserver)obs).clientFailedToLogon(
|
||||
Client.this, _cause);
|
||||
((ClientObserver)obs).clientFailedToLogon(Client.this, _cause);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -697,8 +666,7 @@ public class Client
|
||||
|
||||
case CLIENT_CONNECTION_FAILED:
|
||||
if (obs instanceof ClientObserver) {
|
||||
((ClientObserver)obs).clientConnectionFailed(
|
||||
Client.this, _cause);
|
||||
((ClientObserver)obs).clientConnectionFailed(Client.this, _cause);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -721,8 +689,7 @@ public class Client
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new RuntimeException("Invalid code supplied to " +
|
||||
"notifyObservers: " + _code);
|
||||
throw new RuntimeException("Invalid code supplied to notifyObservers: " + _code);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -739,8 +706,7 @@ public class Client
|
||||
/** The version string reported to the server at auth time. */
|
||||
protected String _version = "";
|
||||
|
||||
/** An entity that gives us the ability to process events on the main
|
||||
* client thread. */
|
||||
/** An entity that gives us the ability to process events on the main client thread. */
|
||||
protected RunQueue _runQueue;
|
||||
|
||||
/** The distributed object manager we're using during this session. */
|
||||
@@ -757,7 +723,7 @@ public class Client
|
||||
|
||||
/** Whether or not this client is operating in a standalone mode. */
|
||||
protected boolean _standalone;
|
||||
|
||||
|
||||
/** The game server host. */
|
||||
protected String _hostname;
|
||||
|
||||
@@ -771,22 +737,23 @@ public class Client
|
||||
/** The entity that manages our network communications. */
|
||||
protected Communicator _comm;
|
||||
|
||||
/** A custom class loader used to load objects that come in over the
|
||||
* network. */
|
||||
/** A custom class loader used to load objects that come in over the network. */
|
||||
protected ClassLoader _loader = getClass().getClassLoader();
|
||||
|
||||
/** General startup information provided by the server. */
|
||||
protected BootstrapData _bstrap;
|
||||
|
||||
/** The set of bootstrap service groups this client cares about. */
|
||||
protected HashSet<String> _bootGroups = new HashSet<String>();
|
||||
|
||||
/** Manages invocation services. */
|
||||
protected InvocationDirector _invdir = new InvocationDirector();
|
||||
|
||||
/** The difference between the server clock and the client clock
|
||||
* (estimated immediately after logging on). */
|
||||
/** The difference between the server clock and the client clock (estimated immediately after
|
||||
* logging on). */
|
||||
protected long _serverDelta;
|
||||
|
||||
/** Used when establishing our clock delta between the client and
|
||||
* server. */
|
||||
/** Used when establishing our clock delta between the client and server. */
|
||||
protected DeltaCalculator _dcalc;
|
||||
|
||||
/** The last time at which we synced our clock with the server. */
|
||||
|
||||
@@ -54,9 +54,8 @@ import com.threerings.presents.net.LogoffRequest;
|
||||
import com.threerings.presents.net.UpstreamMessage;
|
||||
|
||||
/**
|
||||
* The client performs all network I/O on separate threads (one for
|
||||
* reading and one for writing). The communicator class encapsulates that
|
||||
* functionality.
|
||||
* The client performs all network I/O on separate threads (one for reading and one for
|
||||
* writing). The communicator class encapsulates that functionality.
|
||||
*
|
||||
* <pre>
|
||||
* Logon synopsis:
|
||||
@@ -79,8 +78,7 @@ import com.threerings.presents.net.UpstreamMessage;
|
||||
public class Communicator
|
||||
{
|
||||
/**
|
||||
* Creates a new communicator instance which is associated with the
|
||||
* supplied client.
|
||||
* Creates a new communicator instance which is associated with the supplied client.
|
||||
*/
|
||||
public Communicator (Client client)
|
||||
{
|
||||
@@ -88,8 +86,7 @@ public class Communicator
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs on to the server and initiates our full-duplex message
|
||||
* exchange.
|
||||
* Logs on to the server and initiates our full-duplex message exchange.
|
||||
*/
|
||||
public void logon ()
|
||||
{
|
||||
@@ -98,21 +95,19 @@ public class Communicator
|
||||
throw new RuntimeException("Communicator already started.");
|
||||
}
|
||||
|
||||
// start up the reader thread. it will connect to the server and
|
||||
// start up the writer thread if everything went successfully
|
||||
// start up the reader thread. it will connect to the server and start up the writer thread
|
||||
// if everything went successfully
|
||||
_reader = new Reader();
|
||||
_reader.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delivers a logoff notification to the server and shuts down the
|
||||
* network connection. Also causes all communication threads to
|
||||
* terminate.
|
||||
* Delivers a logoff notification to the server and shuts down the network connection. Also
|
||||
* causes all communication threads to terminate.
|
||||
*/
|
||||
public synchronized void logoff ()
|
||||
{
|
||||
// if our socket is already closed, we've already taken care of
|
||||
// this business
|
||||
// if our socket is already closed, we've already taken care of this business
|
||||
if (_channel == null) {
|
||||
return;
|
||||
}
|
||||
@@ -122,27 +117,22 @@ public class Communicator
|
||||
|
||||
// let our reader and writer know that it's time to go
|
||||
if (_reader != null) {
|
||||
// if logoff() is being called by the client as part of a
|
||||
// normal shutdown, this will cause the reader thread to be
|
||||
// interrupted and shutdown gracefully. if logoff is being
|
||||
// called by the reader thread as a result of a failed socket,
|
||||
// it won't interrupt itself as it is already shutting down
|
||||
// gracefully. if the JVM is buggy and calling interrupt() on
|
||||
// a thread that is blocked on a socket doesn't wake it up,
|
||||
// then when we close() the socket a bit further down, we have
|
||||
// another chance that the reader thread will wake up; this
|
||||
// time slightly less gracefully because it will think there's
|
||||
// a network error when in fact we're just shutting down, but
|
||||
// at least it will cleanly exit
|
||||
// if logoff() is being called by the client as part of a normal shutdown, this will
|
||||
// cause the reader thread to be interrupted and shutdown gracefully. if logoff is
|
||||
// being called by the reader thread as a result of a failed socket, it won't interrupt
|
||||
// itself as it is already shutting down gracefully. if the JVM is buggy and calling
|
||||
// interrupt() on a thread that is blocked on a socket doesn't wake it up, then when we
|
||||
// close() the socket a bit further down, we have another chance that the reader thread
|
||||
// will wake up; this time slightly less gracefully because it will think there's a
|
||||
// network error when in fact we're just shutting down, but at least it will cleanly
|
||||
// exit
|
||||
_reader.shutdown();
|
||||
}
|
||||
if (_writer != null) {
|
||||
// shutting down the writer thread is simpler because we can
|
||||
// post a termination message on the queue and be sure that it
|
||||
// will receive it. when the writer thread has delivered our
|
||||
// logoff request and exited, we will complete the logoff
|
||||
// process by closing our socket and invoking the
|
||||
// clientDidLogoff callback
|
||||
// shutting down the writer thread is simpler because we can post a termination message
|
||||
// on the queue and be sure that it will receive it. when the writer thread has
|
||||
// delivered our logoff request and exited, we will complete the logoff process by
|
||||
// closing our socket and invoking the clientDidLogoff callback
|
||||
_writer.shutdown();
|
||||
}
|
||||
}
|
||||
@@ -157,8 +147,8 @@ public class Communicator
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures this communicator with a custom class loader to be used
|
||||
* when reading and writing objects over the network.
|
||||
* Configures this communicator with a custom class loader to be used when reading and writing
|
||||
* objects over the network.
|
||||
*/
|
||||
public void setClassLoader (ClassLoader loader)
|
||||
{
|
||||
@@ -169,10 +159,9 @@ public class Communicator
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback called by the reader when the authentication process
|
||||
* completes successfully. Here we extract the bootstrap information
|
||||
* for the client and start up the writer thread to manage the other
|
||||
* half of our bi-directional message stream.
|
||||
* Callback called by the reader when the authentication process completes successfully. Here
|
||||
* we extract the bootstrap information for the client and start up the writer thread to manage
|
||||
* the other half of our bi-directional message stream.
|
||||
*/
|
||||
protected synchronized void logonSucceeded (AuthResponseData data)
|
||||
{
|
||||
@@ -188,22 +177,21 @@ public class Communicator
|
||||
_writer = new Writer();
|
||||
_writer.start();
|
||||
|
||||
// fill the auth data into the client's local field so that it can
|
||||
// be requested by external entities
|
||||
// fill the auth data into the client's local field so that it can be requested by external
|
||||
// entities
|
||||
_client._authData = data;
|
||||
|
||||
// wait for the bootstrap notification before we claim that we're
|
||||
// actually logged on
|
||||
// wait for the bootstrap notification before we claim that we're actually logged on
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback called by the reader or writer thread when something goes
|
||||
* awry with our socket connection to the server.
|
||||
* Callback called by the reader or writer thread when something goes awry with our socket
|
||||
* connection to the server.
|
||||
*/
|
||||
protected synchronized void connectionFailed (IOException ioe)
|
||||
{
|
||||
// make sure the socket isn't already closed down (meaning we've
|
||||
// already dealt with the failed connection)
|
||||
// make sure the socket isn't already closed down (meaning we've already dealt with the
|
||||
// failed connection)
|
||||
if (_channel == null) {
|
||||
return;
|
||||
}
|
||||
@@ -219,13 +207,12 @@ public class Communicator
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback called by the reader if the server closes the other end of
|
||||
* the connection.
|
||||
* Callback called by the reader if the server closes the other end of the connection.
|
||||
*/
|
||||
protected synchronized void connectionClosed ()
|
||||
{
|
||||
// make sure the socket isn't already closed down (meaning we've
|
||||
// already dealt with the closed connection)
|
||||
// make sure the socket isn't already closed down (meaning we've already dealt with the
|
||||
// closed connection)
|
||||
if (_channel == null) {
|
||||
return;
|
||||
}
|
||||
@@ -244,8 +231,8 @@ public class Communicator
|
||||
_reader = null;
|
||||
|
||||
if (_writer == null) {
|
||||
// there's no writer during authentication, so we may be
|
||||
// responsible for closing the socket channel
|
||||
// there's no writer during authentication, so we may be responsible for closing the
|
||||
// socket channel
|
||||
closeChannel();
|
||||
|
||||
// let the client know when we finally go away
|
||||
@@ -267,9 +254,8 @@ public class Communicator
|
||||
// let the client observers know that we're logged off
|
||||
_client.notifyObservers(Client.CLIENT_DID_LOGOFF, null);
|
||||
|
||||
// now that the writer thread has gone away, we can safely close
|
||||
// our socket and let the client know that the logoff process has
|
||||
// completed
|
||||
// now that the writer thread has gone away, we can safely close our socket and let the
|
||||
// client know that the logoff process has completed
|
||||
closeChannel();
|
||||
|
||||
// let the client know when we finally go away
|
||||
@@ -279,9 +265,8 @@ public class Communicator
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the socket channel that we have open to the server. Called
|
||||
* by either {@link #readerDidExit} or {@link #writerDidExit}
|
||||
* whichever is called last.
|
||||
* Closes the socket channel that we have open to the server. Called by either {@link
|
||||
* #readerDidExit} or {@link #writerDidExit} whichever is called last.
|
||||
*/
|
||||
protected void closeChannel ()
|
||||
{
|
||||
@@ -319,16 +304,13 @@ public class Communicator
|
||||
try {
|
||||
ByteBuffer buffer = _fout.frameAndReturnBuffer();
|
||||
if (buffer.limit() > 4096) {
|
||||
String txt = StringUtil.truncate(
|
||||
String.valueOf(msg), 80, "...");
|
||||
Log.info("Whoa, writin' a big one [msg=" + txt +
|
||||
", size=" + buffer.limit() + "].");
|
||||
String txt = StringUtil.truncate(String.valueOf(msg), 80, "...");
|
||||
Log.info("Whoa, writin' a big one [msg=" + txt + ", size=" + buffer.limit() + "].");
|
||||
}
|
||||
int wrote = _channel.write(buffer);
|
||||
if (wrote != buffer.limit()) {
|
||||
Log.warning("Aiya! Couldn't write entire message [msg=" + msg +
|
||||
", size=" + buffer.limit() +
|
||||
", wrote=" + wrote + "].");
|
||||
", size=" + buffer.limit() + ", wrote=" + wrote + "].");
|
||||
// } else {
|
||||
// Log.info("Wrote " + wrote + " bytes.");
|
||||
}
|
||||
@@ -350,8 +332,7 @@ public class Communicator
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a note of the time at which we last communicated with the
|
||||
* server.
|
||||
* Makes a note of the time at which we last communicated with the server.
|
||||
*/
|
||||
protected synchronized void updateWriteStamp ()
|
||||
{
|
||||
@@ -359,17 +340,15 @@ public class Communicator
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a new message from the socket (blocking until a message has
|
||||
* arrived).
|
||||
* Reads a new message from the socket (blocking until a message has arrived).
|
||||
*/
|
||||
protected DownstreamMessage receiveMessage ()
|
||||
throws IOException
|
||||
{
|
||||
// read in the next message frame (readFrame() can return false
|
||||
// meaning it only read part of the frame from the network, in
|
||||
// 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)
|
||||
// read in the next message frame (readFrame() can return false meaning it only read part
|
||||
// of the frame from the network, in 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(_channel));
|
||||
|
||||
try {
|
||||
@@ -386,8 +365,8 @@ public class Communicator
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback called by the reader thread when it has parsed a new
|
||||
* message from the socket and wishes to have it processed.
|
||||
* Callback called by the reader thread when it has parsed a new message from the socket and
|
||||
* wishes to have it processed.
|
||||
*/
|
||||
protected void processMessage (DownstreamMessage msg)
|
||||
{
|
||||
@@ -396,9 +375,8 @@ public class Communicator
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels our preferred port saving interval. This method is called from
|
||||
* the communication reader thread and the interval thread and must thus be
|
||||
* synchronized.
|
||||
* Cancels our preferred port saving interval. This method is called from the communication
|
||||
* reader thread and the interval thread and must thus be synchronized.
|
||||
*/
|
||||
protected synchronized boolean clearPPI (boolean cancel)
|
||||
{
|
||||
@@ -414,10 +392,9 @@ public class Communicator
|
||||
}
|
||||
|
||||
/**
|
||||
* The reader encapsulates the authentication and message reading
|
||||
* process. It calls back to the <code>Communicator</code> class to do
|
||||
* things, but the general flow of the reader thread is encapsulated
|
||||
* in this class.
|
||||
* The reader encapsulates the authentication and message reading process. It calls back to the
|
||||
* {@link Communicator} class to do things, but the general flow of the reader thread is
|
||||
* encapsulated in this class.
|
||||
*/
|
||||
protected class Reader extends LoopingThread
|
||||
{
|
||||
@@ -452,8 +429,8 @@ public class Communicator
|
||||
// look up the address of the target server
|
||||
InetAddress host = InetAddress.getByName(_client.getHostname());
|
||||
|
||||
// obtain the list of available ports on which to attempt our
|
||||
// client connection and determine our preferred port
|
||||
// obtain the list of available ports on which to attempt our client connection and
|
||||
// determine our preferred port
|
||||
String pportKey = _client.getHostname() + ".preferred_port";
|
||||
int[] ports = _client.getPorts();
|
||||
int pport = PresentsPrefs.config.getValue(pportKey, ports[0]);
|
||||
@@ -468,18 +445,16 @@ public class Communicator
|
||||
try {
|
||||
synchronized (Communicator.this) {
|
||||
clearPPI(true);
|
||||
_prefPortInterval =
|
||||
new PrefPortInterval(pportKey, port, nextPort);
|
||||
_prefPortInterval = new PrefPortInterval(pportKey, port, nextPort);
|
||||
_channel = SocketChannel.open(addr);
|
||||
_prefPortInterval.schedule(PREF_PORT_DELAY);
|
||||
}
|
||||
break;
|
||||
|
||||
} catch (IOException ioe) {
|
||||
if (ioe instanceof ConnectException &&
|
||||
ii < (ports.length-1)) {
|
||||
if (ioe instanceof ConnectException && ii < (ports.length-1)) {
|
||||
_client.reportLogonTribulations(
|
||||
new LogonException(
|
||||
AuthCodes.TRYING_NEXT_PORT, true));
|
||||
new LogonException(AuthCodes.TRYING_NEXT_PORT, true));
|
||||
continue; // try the next port
|
||||
}
|
||||
throw ioe;
|
||||
@@ -488,8 +463,8 @@ public class Communicator
|
||||
|
||||
_channel.configureBlocking(true);
|
||||
|
||||
// our messages are framed (preceded by their length), so we
|
||||
// use these helper streams to manage the framing
|
||||
// our messages are framed (preceded by their length), so we use these helper streams
|
||||
// to manage the framing
|
||||
_fin = new FramedInputStream();
|
||||
_fout = new FramingOutputStream();
|
||||
|
||||
@@ -503,8 +478,8 @@ public class Communicator
|
||||
throws IOException, LogonException
|
||||
{
|
||||
// construct an auth request and send it
|
||||
AuthRequest req = new AuthRequest(_client.getCredentials(),
|
||||
_client.getVersion());
|
||||
AuthRequest req = new AuthRequest(
|
||||
_client.getCredentials(), _client.getVersion(), _client._bootGroups);
|
||||
sendMessage(req);
|
||||
|
||||
// now wait for the auth response
|
||||
@@ -513,8 +488,8 @@ public class Communicator
|
||||
AuthResponseData data = rsp.getData();
|
||||
Log.debug("Got auth response: " + data);
|
||||
|
||||
// if the auth request failed, we want to let the communicator
|
||||
// know by throwing a logon exception
|
||||
// if the auth request failed, we want to let the communicator know by throwing a logon
|
||||
// exception
|
||||
if (!data.code.equals(AuthResponseData.SUCCESS)) {
|
||||
throw new LogonException(data.code);
|
||||
}
|
||||
@@ -523,9 +498,8 @@ public class Communicator
|
||||
logonSucceeded(data);
|
||||
}
|
||||
|
||||
// now that we're authenticated, we manage the reading
|
||||
// half of things by continuously reading messages from
|
||||
// the socket and processing them
|
||||
// now that we're authenticated, we manage the reading half of things by continuously
|
||||
// reading messages from the socket and processing them
|
||||
protected void iterate ()
|
||||
{
|
||||
DownstreamMessage msg = null;
|
||||
@@ -538,14 +512,12 @@ public class Communicator
|
||||
processMessage(msg);
|
||||
|
||||
} catch (InterruptedIOException iioe) {
|
||||
// somebody set up us the bomb! we've been interrupted
|
||||
// which means that we're being shut down, so we just
|
||||
// report it and return from iterate() like a good monkey
|
||||
// somebody set up us the bomb! we've been interrupted which means that we're being
|
||||
// shut down, so we just report it and return from iterate() like a good monkey
|
||||
Log.debug("Reader thread woken up in time to die.");
|
||||
|
||||
} catch (EOFException eofe) {
|
||||
// let the communicator know that our connection was
|
||||
// closed
|
||||
// let the communicator know that our connection was closed
|
||||
connectionClosed();
|
||||
// and shut ourselves down
|
||||
shutdown();
|
||||
@@ -557,8 +529,7 @@ public class Communicator
|
||||
shutdown();
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.warning("Error processing message [msg=" + msg +
|
||||
", error=" + e + "].");
|
||||
Log.warning("Error processing message [msg=" + msg + ", error=" + e + "].");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,8 +541,8 @@ public class Communicator
|
||||
|
||||
protected void didShutdown ()
|
||||
{
|
||||
// If we haven't recorded a preferred port yet, instead do the
|
||||
// failure action since we didn't stay connected long enough.
|
||||
// if we haven't recorded a preferred port yet, instead do the failure action since we
|
||||
// didn't stay connected long enough
|
||||
clearPPI(true);
|
||||
|
||||
// let the communicator know when we finally go away
|
||||
@@ -580,17 +551,16 @@ public class Communicator
|
||||
|
||||
protected void kick ()
|
||||
{
|
||||
// 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
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The writer encapsulates the message writing process. It calls back
|
||||
* to the <code>Communicator</code> class to do things, but the
|
||||
* general flow of the writer thread is encapsulated in this class.
|
||||
* The writer encapsulates the message writing process. It calls back to the {@link
|
||||
* Communicator} class to do things, but the general flow of the writer thread is encapsulated
|
||||
* in this class.
|
||||
*/
|
||||
protected class Writer extends LoopingThread
|
||||
{
|
||||
@@ -599,9 +569,8 @@ public class Communicator
|
||||
// fetch the next message from the queue
|
||||
UpstreamMessage msg = _msgq.get();
|
||||
|
||||
// if this is a termination message, we're being
|
||||
// requested to exit, so we want to bail now rather
|
||||
// than continuing
|
||||
// if this is a termination message, we're being requested to exit, so we want to bail
|
||||
// now rather than continuing
|
||||
if (msg instanceof TerminationMessage) {
|
||||
return;
|
||||
}
|
||||
@@ -611,8 +580,7 @@ public class Communicator
|
||||
sendMessage(msg);
|
||||
|
||||
} catch (IOException ioe) {
|
||||
// let the communicator know if we have any
|
||||
// problems
|
||||
// let the communicator know if we have any problems
|
||||
connectionFailed(ioe);
|
||||
// and bail
|
||||
shutdown();
|
||||
@@ -632,8 +600,8 @@ public class Communicator
|
||||
|
||||
protected void kick ()
|
||||
{
|
||||
// post a bogus message to the outgoing queue to ensure that
|
||||
// the writer thread notices that it's time to go
|
||||
// post a bogus message to the outgoing queue to ensure that the writer thread notices
|
||||
// that it's time to go
|
||||
postMessage(new TerminationMessage());
|
||||
}
|
||||
}
|
||||
@@ -643,12 +611,11 @@ public class Communicator
|
||||
{
|
||||
}
|
||||
|
||||
/** Used to save our preferred port once we know our connection is not
|
||||
* going to be unceremoniously closed by Windows Connection Sharing. */
|
||||
/** Used to save our preferred port once we know our connection is not going to be
|
||||
* unceremoniously closed by Windows Connection Sharing. */
|
||||
protected class PrefPortInterval extends Interval
|
||||
{
|
||||
public PrefPortInterval (String key, int thisPort, int nextPort)
|
||||
{
|
||||
public PrefPortInterval (String key, int thisPort, int nextPort) {
|
||||
super();
|
||||
_key = key;
|
||||
_thisPort = thisPort;
|
||||
@@ -691,8 +658,7 @@ public class Communicator
|
||||
protected ClientDObjectMgr _omgr;
|
||||
protected ClassLoader _loader;
|
||||
|
||||
/** We use this interval to record the preferred port if it stays connected
|
||||
* long enough. */
|
||||
/** We use this interval to record the preferred port if it stays connected long enough. */
|
||||
protected PrefPortInterval _prefPortInterval;
|
||||
|
||||
/** Time a port must remain connected before we mark it as preferred. */
|
||||
@@ -700,8 +666,7 @@ public class Communicator
|
||||
|
||||
/** Used to control low-level message logging. */
|
||||
protected static RuntimeAdjust.BooleanAdjust _logMessages =
|
||||
new RuntimeAdjust.BooleanAdjust(
|
||||
"Toggles whether or not all sent and received low-level " +
|
||||
"network events are logged.", "narya.presents.log_events",
|
||||
PresentsPrefs.config, false);
|
||||
new RuntimeAdjust.BooleanAdjust("Toggles whether or not all sent and received low-level " +
|
||||
"network events are logged.", "narya.presents.log_events",
|
||||
PresentsPrefs.config, false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user