// // $Id$ // // Narya library - tools for developing networked games // Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved // http://www.threerings.net/code/narya/ // // This library is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License as published // by the Free Software Foundation; either version 2.1 of the License, or // (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA package com.threerings.presents.client; import com.samskivert.util.RunAnywhere; import com.threerings.presents.net.AuthResponse; import com.threerings.presents.net.AuthResponseData; import com.threerings.presents.net.Message; import com.threerings.presents.net.UpstreamMessage; import static com.threerings.presents.Log.log; /** * Handles sending and receiving messages for the client. */ public abstract class Communicator { /** * Creates a new communicator instance which is associated with the supplied client. */ public Communicator (Client client) { _client = client; } /** * Logs on to the server and initiates our full-duplex message exchange. */ public abstract void logon (); /** * Delivers a logoff notification to the server and shuts down the network connection. Also * causes all communication threads to terminate. */ public abstract void logoff (); /** * Notifies the communicator that the client has received its bootstrap data. */ public abstract void gotBootstrap (); /** * Queues up the specified message for delivery upstream. */ public abstract void postMessage (UpstreamMessage msg); /** * Configures this communicator with a custom class loader to be used when reading and writing * objects over the network. */ public abstract void setClassLoader (ClassLoader loader); /** * Returns the time at which we last sent a packet to the server. */ public long getLastWrite () { return _lastWrite; } /** * Checks whether we should transmit datagrams. */ public boolean getTransmitDatagrams () { return false; } /** * Makes a note of the time at which we last communicated with the server. */ protected synchronized void updateWriteStamp () { _lastWrite = RunAnywhere.currentTimeMillis(); } /** * Subclasses must call this method when they receive the authentication response. */ protected void gotAuthResponse (AuthResponse rsp) throws LogonException { AuthResponseData data = rsp.getData(); if (!data.code.equals(AuthResponseData.SUCCESS)) { throw new LogonException(data.code); } logonSucceeded(data); } /** * Called when the authentication process completes successfully. Derived classes can override * this method and complete any initialization that need wait for authentication success. */ protected synchronized void logonSucceeded (AuthResponseData data) { // create our distributed object manager _omgr = new ClientDObjectMgr(this, _client); // 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 } /** * 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 (Message msg) { // post this message to the dobjmgr queue _omgr.processMessage(msg); } protected void notifyClientObservers (ObserverOps.Session op) { if (_client != null) { _client.notifyObservers(op); } else { log.warning("Dropping client observer notification.", "op", op); } } protected void clientCleanup (Exception logonError) { if (_client != null) { _client.cleanup(logonError); _client = null; // prevent any post-cleanup tomfoolery } } protected Client _client; protected ClientDObjectMgr _omgr; protected long _lastWrite; }