com.threerings.presents.server
Class PresentsSession

java.lang.Object
  extended by com.threerings.presents.server.PresentsSession
All Implemented Interfaces:
ClientResolutionListener, PresentsConnection.MessageHandler
Direct Known Subclasses:
BureauSession, CrowdSession, PeerSession

public class PresentsSession
extends Object
implements PresentsConnection.MessageHandler, ClientResolutionListener

Represents a client session in the server. It is associated with a connection instance (while the client is connected) and acts as the intermediary for the remote client in terms of passing along events forwarded by the client, ensuring that subscriptions are maintained on behalf of the client and that events are forwarded to the client.

A note on synchronization: the client object is structured so that its Subscriber implementation (which is called from the dobjmgr thread) can proceed without synchronization. This does not overlap with its other client duties which are called from the conmgr thread and therefore also need not be synchronized.


Nested Class Summary
protected  class PresentsSession.ClientProxy
          Used to track information about an object subscription.
protected static class PresentsSession.CompoundDispatcher
          Processes compound messages.
protected static class PresentsSession.ForwardEventDispatcher
          Processes forward event requests.
protected static class PresentsSession.LogoffDispatcher
          Processes logoff requests.
protected static interface PresentsSession.MessageDispatcher
          Message dispatchers are used to dispatch each different type of message.
protected static class PresentsSession.PingDispatcher
          Processes ping requests.
protected static class PresentsSession.SubscribeDispatcher
          Processes subscribe requests.
protected static class PresentsSession.ThrottleUpdatedDispatcher
          Processes throttle updated messages.
protected static class PresentsSession.TransmitDatagramsDispatcher
          Processes datagram transmission requests.
protected static class PresentsSession.UnsubscribeDispatcher
          Processes unsubscribe requests.
static interface PresentsSession.UserChangeListener
          Used by setUsername(com.threerings.util.Name, com.threerings.presents.server.PresentsSession.UserChangeListener) to report success or failure.
 
Field Summary
protected  AuthRequest _areq
           
protected  Object _authdata
           
protected  Name _authname
           
protected  ClientManager _clmgr
           
protected  ClientObject _clobj
           
protected  CompoundDownstreamMessage _compound
          Message in which we're currently compounding messages to send, or null if we're sending them straight on.
protected  int _compoundDepth
          The count of startCompoundMessage calls that have occurred without a finishCompoundMessage.
protected  ConnectionManager _conmgr
           
protected  PresentsConnection _conn
           
protected  int _connectTime
          The total number of seconds for which the user was connected to the server in this session.
protected  HashSet<Integer> _destroyedSubs
          The Oids of objects that have been destroyed while we were subscribed.
protected static Map<Class<?>,PresentsSession.MessageDispatcher> _disps
          A mapping of message dispatchers.
protected  InvocationManager _invmgr
           
protected  ClassLoader _loader
           
protected  int _messagesDropped
           
protected  int _messagesIn
           
protected  int _messagesOut
           
protected  int _messagesPerSec
          The configured throttle setting (resent to reconnecting clients).
protected  long _networkStamp
          The time at which this client most recently connected or disconnected.
protected  PresentsDObjectMgr _omgr
           
protected  List<Integer> _pendingThrottles
          Used to keep throttles around until we know the client is ready for us to apply them.
protected  long _sessionStamp
          The time at which this client started their session.
protected  IntMap<PresentsSession.ClientProxy> _subscrips
           
protected  Throttle _throttle
          Prevent the client from sending too many messages too frequently.
protected static long DEFAULT_FLUSH_TIME
          Default period a user is allowed after disconn before their session is forcibly ended.
protected static boolean PING_DEBUG
           
 
Constructor Summary
PresentsSession()
           
 
Method Summary
 boolean checkExpired(long now)
          Returns true if this session has been disconnected for sufficiently long that it should be forcibly ended.
protected  void clearSubscrips(boolean verbose)
          Clears out the tracked client subscriptions.
protected  void clientObjectDidChange(ClientObject newClobj)
          Called after the new client object has been committed to this client due to a call to setUsername(com.threerings.util.Name, com.threerings.presents.server.PresentsSession.UserChangeListener).
protected  void clientObjectWillChange(ClientObject oldClobj, ClientObject newClobj)
          Called when setUsername(com.threerings.util.Name, com.threerings.presents.server.PresentsSession.UserChangeListener) has been called and the new client object is about to be applied to this client.
 void clientResolved(Name username, ClientObject clobj)
          Called when resolution completed successfully.
protected  void connectionFailed(IOException fault)
          Called by the connection manager when this client's connection fails.
protected  BootstrapData createBootstrapData()
          Derived client classes can override this member to create derived bootstrap data classes that contain extra bootstrap information, if desired.
protected  Throttle createIncomingMessageThrottle()
          Creates our incoming message throttle.
protected  PresentsSession.ClientProxy createProxySubscriber()
          Creates a properly initialized inner-class proxy subscriber.
protected  void dispatchMessage(Message message)
          Processes a message without throttling.
 void endSession()
          Forcibly terminates a client's session.
protected  void finishCompoundMessage()
          Sends the compound message created in startCompoundMessage.
protected  void finishResumeSession()
          This is called from the dobjmgr thread to complete the session resumption.
 Name getAuthName()
          Returns the username with which this client authenticated.
 ClientObject getClientObject()
          returns the client object that is associated with this client.
protected  PresentsConnection getConnection()
          The connection instance must be accessed via this member function because it is read from both the dobjmgr and conmgr threads and is modified by the conmgr thread.
 Credentials getCredentials()
          Returns the credentials used to authenticate this session.
protected  long getFlushTime()
          Returns the duration (in milliseconds) after which a disconnected session will be terminated and flushed.
 InetAddress getInetAddress()
          Returns the address of the connected client or null if this client is not connected.
 long getNetworkStamp()
          Returns the time at which this client most recently connected or disconnected.
 byte[] getSecret()
          Returns the shared secret for this session.
 long getSessionStamp()
          Returns the time at which this client started their network session.
 TimeZone getTimeZone()
          Returns the time zone in which the client is operating.
 boolean getTransmitDatagrams()
          Checks whether the client has requested that datagram transmission be enabled.
 void handleMessage(Message message)
          Called when a complete message has been parsed from incoming network data.
protected  void handleThrottleExceeded()
          Called when a client exceeds their allotted incoming messages per second throttle.
protected  void populateBootstrapData(BootstrapData data)
          Derived client classes can override this member to populate the bootstrap data with additional information.
protected  boolean postMessage(DownstreamMessage msg, PresentsConnection expect)
          Queues a message for delivery to the client.
 void resolutionFailed(Name username, Exception reason)
          Called when resolution fails.
protected  void resumeSession(AuthRequest req, PresentsConnection conn)
          Called by the client manager when a new connection arrives that authenticates as this already established client.
protected  void safeEndSession()
          Queues up a runnable on the object manager thread where we can safely end the session.
protected  void safePostMessage(DownstreamMessage msg)
          Callable from non-dobjmgr thread, this queues up a runnable on the dobjmgr thread to post the supplied message to this client.
protected  void safePostMessage(DownstreamMessage msg, PresentsConnection expect)
          Callable from non-dobjmgr thread, this queues up a runnable on the dobjmgr thread to post the supplied message to this client.
protected  void sendBootstrap()
          This is called once we have a handle on the client distributed object.
protected  void sendThrottleUpdate()
          Sends the throttle update to the client.
protected  void sessionConnectionClosed()
          Called on the dobjmgr thread when the connection associated with this session has been closed and unmapped.
protected  void sessionDidEnd()
          Called when the client session ends (either because the client logged off or because the server forcibly terminated the session).
protected  void sessionWillResume()
          Called when the client resumes a session (after having disconnected and reconnected).
protected  void sessionWillStart()
          Called when the client session is first started.
 void setClassLoader(ClassLoader loader)
          Configures this session with a custom class loader that will be used when unserializing classes from the network.
protected  void setConnection(PresentsConnection conn)
          Sets our connection reference in a thread safe way.
 void setIncomingMessageThrottle(int messagesPerSec)
          Configures the rate at which incoming messages are throttled for this client.
 void setUsername(Name username, PresentsSession.UserChangeListener ucl)
          Danger: this method is not for general consumption.
 void shutdown()
          This is called when the server is shut down in the middle of a client session.
protected  void startCompoundMessage()
          Collects downstream messages in a compound message until finishCompoundMessage is called.
protected  void startSession(Name authname, AuthRequest req, PresentsConnection conn, Object authdata)
          Initializes this client instance with the specified username, connection instance and client object and begins a client session.
protected  void subscribedToObject(DObject object)
          Called to inform derived classes when the client has subscribed to a distributed object.
protected  void throttleUpdated()
          Notifies this client that its throttle was updated.
 String toString()
           
protected  void toString(StringBuilder buf)
          Derived classes override this to augment stringification.
protected  void unmapSubscrip(int oid)
          Makes a note that this client is no longer subscribed to this object.
protected  void unsubscribedFromObject(DObject object)
          Called to inform derived classes when the client has unsubscribed from a distributed object.
 boolean updateUsername(Name username)
          Double Danger: this method is not for general consumption.
protected  void wasUnmapped()
          Called by the connection manager when this client's connection is unmapped.
protected  String who()
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

_clmgr

@Inject
protected ClientManager _clmgr

_conmgr

@Inject
protected ConnectionManager _conmgr

_omgr

@Inject
protected PresentsDObjectMgr _omgr

_invmgr

@Inject
protected InvocationManager _invmgr

_areq

protected AuthRequest _areq

_authdata

protected Object _authdata

_authname

protected Name _authname

_conn

protected PresentsConnection _conn

_clobj

protected ClientObject _clobj

_subscrips

protected IntMap<PresentsSession.ClientProxy> _subscrips

_compound

protected CompoundDownstreamMessage _compound
Message in which we're currently compounding messages to send, or null if we're sending them straight on.


_compoundDepth

protected int _compoundDepth
The count of startCompoundMessage calls that have occurred without a finishCompoundMessage. _compound won't be set until this reaches 0 again.


_destroyedSubs

protected HashSet<Integer> _destroyedSubs
The Oids of objects that have been destroyed while we were subscribed.


_loader

protected ClassLoader _loader

_sessionStamp

protected long _sessionStamp
The time at which this client started their session.


_networkStamp

protected long _networkStamp
The time at which this client most recently connected or disconnected.


_connectTime

protected int _connectTime
The total number of seconds for which the user was connected to the server in this session.


_messagesPerSec

protected int _messagesPerSec
The configured throttle setting (resent to reconnecting clients).


_throttle

protected Throttle _throttle
Prevent the client from sending too many messages too frequently.


_pendingThrottles

protected List<Integer> _pendingThrottles
Used to keep throttles around until we know the client is ready for us to apply them.


_messagesIn

protected int _messagesIn

_messagesOut

protected int _messagesOut

_messagesDropped

protected int _messagesDropped

_disps

protected static Map<Class<?>,PresentsSession.MessageDispatcher> _disps
A mapping of message dispatchers.


DEFAULT_FLUSH_TIME

protected static final long DEFAULT_FLUSH_TIME
Default period a user is allowed after disconn before their session is forcibly ended.

See Also:
Constant Field Values

PING_DEBUG

protected static final boolean PING_DEBUG
Constructor Detail

PresentsSession

public PresentsSession()
Method Detail

getCredentials

public Credentials getCredentials()
Returns the credentials used to authenticate this session.


getTimeZone

public TimeZone getTimeZone()
Returns the time zone in which the client is operating.


getSecret

public byte[] getSecret()
Returns the shared secret for this session.


checkExpired

public boolean checkExpired(long now)
Returns true if this session has been disconnected for sufficiently long that it should be forcibly ended.


getSessionStamp

public long getSessionStamp()
Returns the time at which this client started their network session.


getNetworkStamp

public long getNetworkStamp()
Returns the time at which this client most recently connected or disconnected.


getAuthName

public Name getAuthName()
Returns the username with which this client authenticated. Note: if setUsername(com.threerings.util.Name, com.threerings.presents.server.PresentsSession.UserChangeListener) has been called this may differ from getClientObject().username.


getInetAddress

public InetAddress getInetAddress()
Returns the address of the connected client or null if this client is not connected.


getTransmitDatagrams

public boolean getTransmitDatagrams()
Checks whether the client has requested that datagram transmission be enabled.


setClassLoader

public void setClassLoader(ClassLoader loader)
Configures this session with a custom class loader that will be used when unserializing classes from the network.


setIncomingMessageThrottle

public void setIncomingMessageThrottle(int messagesPerSec)
Configures the rate at which incoming messages are throttled for this client. This will communicate the new limit to the client and begin enforcing the limit when the client has acknowledged the new limit.

Note: this means that a hacked client can refuse to ACK message rate reductions and continue to use the most generous rate ever assigned to it. Don't increase the throttle beyond the default for untrusted clients. This mechanism exists so that trusted clients can have their throttle relaxed in a robust manner which will not result in disconnects if the client happens to be at or near the throttle limit when the throttle is reduced.


setUsername

public void setUsername(Name username,
                        PresentsSession.UserChangeListener ucl)
Danger: this method is not for general consumption. This changes the username of the client, but should only be done very early in a user's session, when you know that no one has mapped the user based on their username or has in any other way made use of their username in a way that will break. However, it should not be done too early in the session. The client must be fully resolved.

It exists to support systems wherein a user logs in with an account username and then chooses a "screen name" by which they will play (often from a small set of available "characters" available per account). This will take care of remapping the username to client object mappings that were made by the Presents services when the user logs on, but anything else that has had its grubby mits on the username will be left to its own devices, hence the care that must be exercised when using this method.

Parameters:
ucl - an entity that will (optionally) be notified when the username conversion process is complete.

updateUsername

public boolean updateUsername(Name username)
Double Danger: this method is not for general consumption. Like #setUsername, this changes the username of the client, but unlike setUsername, it does it in the existing client object. Care must be taken to ensure that any client or server code either doesn't map things based on username before this call, or that it's updated to reflect the change.

Returns:
- true if the client was successfully renamed, false otherwise

getClientObject

public ClientObject getClientObject()
returns the client object that is associated with this client.


endSession

public void endSession()
Forcibly terminates a client's session. This must be called from the dobjmgr thread.


shutdown

public void shutdown()
This is called when the server is shut down in the middle of a client session. In this circumstance, endSession() will not be called and so any persistent data that might normally be flushed at the end of a client's session should likely be flushed here.


clientResolved

public void clientResolved(Name username,
                           ClientObject clobj)
Description copied from interface: ClientResolutionListener
Called when resolution completed successfully.

Specified by:
clientResolved in interface ClientResolutionListener

resolutionFailed

public void resolutionFailed(Name username,
                             Exception reason)
Description copied from interface: ClientResolutionListener
Called when resolution fails.

Specified by:
resolutionFailed in interface ClientResolutionListener

handleMessage

public void handleMessage(Message message)
Description copied from interface: PresentsConnection.MessageHandler
Called when a complete message has been parsed from incoming network data.

Specified by:
handleMessage in interface PresentsConnection.MessageHandler

dispatchMessage

protected void dispatchMessage(Message message)
Processes a message without throttling.


clientObjectWillChange

protected void clientObjectWillChange(ClientObject oldClobj,
                                      ClientObject newClobj)
Called when setUsername(com.threerings.util.Name, com.threerings.presents.server.PresentsSession.UserChangeListener) has been called and the new client object is about to be applied to this client. The old client object will not yet have been destroyed, so any final events can be sent along prior to the new object being put into effect.


clientObjectDidChange

protected void clientObjectDidChange(ClientObject newClobj)
Called after the new client object has been committed to this client due to a call to setUsername(com.threerings.util.Name, com.threerings.presents.server.PresentsSession.UserChangeListener).


startSession

protected void startSession(Name authname,
                            AuthRequest req,
                            PresentsConnection conn,
                            Object authdata)
Initializes this client instance with the specified username, connection instance and client object and begins a client session.


resumeSession

protected void resumeSession(AuthRequest req,
                             PresentsConnection conn)
Called by the client manager when a new connection arrives that authenticates as this already established client. This must only be called from the congmr thread.


finishResumeSession

protected void finishResumeSession()
This is called from the dobjmgr thread to complete the session resumption. We call some call backs and send the bootstrap info to the client.


sendThrottleUpdate

protected void sendThrottleUpdate()
Sends the throttle update to the client.


safeEndSession

protected void safeEndSession()
Queues up a runnable on the object manager thread where we can safely end the session.


createIncomingMessageThrottle

protected Throttle createIncomingMessageThrottle()
Creates our incoming message throttle. Use setIncomingMessageThrottle(int) to adjust the throttle for running clients.


handleThrottleExceeded

protected void handleThrottleExceeded()
Called when a client exceeds their allotted incoming messages per second throttle.


unmapSubscrip

protected void unmapSubscrip(int oid)
Makes a note that this client is no longer subscribed to this object. The subscription map is used to clean up after the client when it goes away.


clearSubscrips

protected void clearSubscrips(boolean verbose)
Clears out the tracked client subscriptions. Called when the client goes away and shouldn't be called otherwise.


sessionWillStart

protected void sessionWillStart()
Called when the client session is first started. The client object has been created at this point and after this method is executed, the bootstrap information will be sent to the client which will trigger the start of the session. Derived classes that override this method should be sure to call super.sessionWillStart.

Note: This function will be called on the dobjmgr thread which means that object manipulations are OK, but client instance manipulations must done carefully.


sessionWillResume

protected void sessionWillResume()
Called when the client resumes a session (after having disconnected and reconnected). After this method is executed, the bootstrap information will be sent to the client which will trigger the resumption of the session. Derived classes that override this method should be sure to call super.sessionWillResume.

Note: This function will be called on the dobjmgr thread which means that object manipulations are OK, but client instance manipulations must done carefully.


sessionDidEnd

protected void sessionDidEnd()
Called when the client session ends (either because the client logged off or because the server forcibly terminated the session). Derived classes that override this method should be sure to call super.sessionDidEnd.

Note: This function will be called on the dobjmgr thread which means that object manipulations are OK, but client instance manipulations must done carefully.


subscribedToObject

protected void subscribedToObject(DObject object)
Called to inform derived classes when the client has subscribed to a distributed object.


unsubscribedFromObject

protected void unsubscribedFromObject(DObject object)
Called to inform derived classes when the client has unsubscribed from a distributed object.


sendBootstrap

protected void sendBootstrap()
This is called once we have a handle on the client distributed object. It sends a bootstrap notification to the client with all the information it will need to interact with the server.


createBootstrapData

protected BootstrapData createBootstrapData()
Derived client classes can override this member to create derived bootstrap data classes that contain extra bootstrap information, if desired.


populateBootstrapData

protected void populateBootstrapData(BootstrapData data)
Derived client classes can override this member to populate the bootstrap data with additional information. They should be sure to call super.populateBootstrapData before doing their own populating, however.

Note: This function will be called on the dobjmgr thread which means that object manipulations are OK, but client instance manipulations must be done carefully.


wasUnmapped

protected void wasUnmapped()
Called by the connection manager when this client's connection is unmapped. That may be because of a connection failure (in which case this call will be followed up by a call to connectionFailed) or it may be because of an orderly closing of the connection. In either case, the client can deal with its lack of a connection in this method. This is invoked by the conmgr thread and should behave accordingly.


sessionConnectionClosed

protected void sessionConnectionClosed()
Called on the dobjmgr thread when the connection associated with this session has been closed and unmapped. If the user logged off before closing their connection, this will be preceded by a call to sessionDidEnd().


connectionFailed

protected void connectionFailed(IOException fault)
Called by the connection manager when this client's connection fails. This is invoked on the conmgr thread and should behave accordingly.


setConnection

protected void setConnection(PresentsConnection conn)
Sets our connection reference in a thread safe way. Also establishes the back reference to us as the connection's message handler.


getConnection

protected PresentsConnection getConnection()
The connection instance must be accessed via this member function because it is read from both the dobjmgr and conmgr threads and is modified by the conmgr thread.

Returns:
The connection instance associated with this client or null if the client is not currently connected.

safePostMessage

protected final void safePostMessage(DownstreamMessage msg)
Callable from non-dobjmgr thread, this queues up a runnable on the dobjmgr thread to post the supplied message to this client.


safePostMessage

protected final void safePostMessage(DownstreamMessage msg,
                                     PresentsConnection expect)
Callable from non-dobjmgr thread, this queues up a runnable on the dobjmgr thread to post the supplied message to this client.


startCompoundMessage

protected void startCompoundMessage()
Collects downstream messages in a compound message until finishCompoundMessage is called.


finishCompoundMessage

protected void finishCompoundMessage()
Sends the compound message created in startCompoundMessage.


postMessage

protected boolean postMessage(DownstreamMessage msg,
                              PresentsConnection expect)
Queues a message for delivery to the client.


throttleUpdated

protected void throttleUpdated()
Notifies this client that its throttle was updated.


toString

public String toString()
Overrides:
toString in class Object

who

protected String who()

getFlushTime

protected long getFlushTime()
Returns the duration (in milliseconds) after which a disconnected session will be terminated and flushed.


toString

protected void toString(StringBuilder buf)
Derived classes override this to augment stringification.


createProxySubscriber

protected PresentsSession.ClientProxy createProxySubscriber()
Creates a properly initialized inner-class proxy subscriber.