More code, more code, more kibbles and code.

git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2001-05-23 04:03:41 +00:00
parent d865c89bee
commit 6717f8d6e5
14 changed files with 402 additions and 71 deletions
@@ -1,5 +1,5 @@
// //
// $Id: Client.java,v 1.1 2001/05/22 06:07:59 mdb Exp $ // $Id: Client.java,v 1.2 2001/05/23 04:03:40 mdb Exp $
package com.samskivert.cocktail.cher.client; package com.samskivert.cocktail.cher.client;
@@ -152,7 +152,7 @@ public class Client
case CLIENT_FAILED_TO_LOGON: case CLIENT_FAILED_TO_LOGON:
obs.clientFailedToLogon(this, cause); obs.clientFailedToLogon(this, cause);
break; break;
case CLIENT_CONNETION_FAILED: case CLIENT_CONNECTION_FAILED:
obs.clientConnectionFailed(this, cause); obs.clientConnectionFailed(this, cause);
break; break;
case CLIENT_WILL_LOGOFF: case CLIENT_WILL_LOGOFF:
@@ -191,7 +191,7 @@ public class Client
// client observer codes // client observer codes
static final int CLIENT_DID_LOGON = 0; static final int CLIENT_DID_LOGON = 0;
static final int CLIENT_FAILED_TO_LOGON = 1; static final int CLIENT_FAILED_TO_LOGON = 1;
static final int CLIENT_CONNETION_FAILED = 2; static final int CLIENT_CONNECTION_FAILED = 2;
static final int CLIENT_WILL_LOGOFF = 3; static final int CLIENT_WILL_LOGOFF = 3;
static final int CLIENT_DID_LOGOFF = 4; static final int CLIENT_DID_LOGOFF = 4;
} }
@@ -1,5 +1,5 @@
// //
// $Id: Communicator.java,v 1.2 2001/05/22 21:51:29 mdb Exp $ // $Id: Communicator.java,v 1.3 2001/05/23 04:03:40 mdb Exp $
package com.samskivert.cocktail.cher.client; package com.samskivert.cocktail.cher.client;
@@ -10,8 +10,10 @@ import java.net.InetAddress;
import com.samskivert.util.Queue; import com.samskivert.util.Queue;
import com.samskivert.cocktail.cher.Log; import com.samskivert.cocktail.cher.Log;
import com.samskivert.cocktail.cher.io.FramingOutputStream; import com.samskivert.cocktail.cher.io.*;
import com.samskivert.cocktail.cher.io.ObjectStreamException;
import com.samskivert.cocktail.cher.net.*; import com.samskivert.cocktail.cher.net.*;
import com.samskivert.cocktail.cher.util.Codes;
/** /**
* The client performs all network I/O on separate threads (one for * The client performs all network I/O on separate threads (one for
@@ -69,12 +71,59 @@ class Communicator
* network connection. Also causes all communication threads to * network connection. Also causes all communication threads to
* terminate. * terminate.
*/ */
public void logoff () public synchronized void logoff ()
{ {
// if our socket is already closed, we've already taken care of
// this business
if (_socket == null) {
return;
}
// 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
_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. we do run the risk that it is in the
// middle of trying to send a message when we close the
// socket, but in theory the send will fail, it will complain
// and then it will cleanly exit. if we were uber paranoid
// about JVMs misbehaving on simultaneous close()/write(), we
// could wait here for the writer thread to exit, but that
// makes me even more nervous because I know that some JVMs
// don't handle Thread.join() properly (hopefully no one is
// still using those JVMs but one can never be sure)
_writer.shutdown();
}
// close down our socket
try {
_socket.close();
} catch (IOException cle) {
Log.warning("Error closing failed socket: " + cle);
}
_socket = null;
// let the client observers know that we're logged off
_client.notifyObservers(Client.CLIENT_DID_LOGOFF, null);
} }
/** /**
* Queues up the specified message for delivery to the server. * Queues up the specified message for delivery upstream.
*/ */
public void postMessage (UpstreamMessage msg) public void postMessage (UpstreamMessage msg)
{ {
@@ -82,17 +131,46 @@ class Communicator
_msgq.append(msg); _msgq.append(msg);
} }
protected void startWriter () /**
* 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)
{ {
// extract bootstrap information
// create a new writer thread and start it up
if (_writer != null) { if (_writer != null) {
throw new RuntimeException("Writer already started!?"); throw new RuntimeException("Writer already started!?");
} }
// create a new writer thread and start it up
_writer = new Writer(); _writer = new Writer();
_writer.start(); _writer.start();
} }
/**
* 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)
if (_socket == null) {
return;
}
// let the client know that things went south
_client.notifyObservers(Client.CLIENT_CONNECTION_FAILED, ioe);
// and request that we go through the motions of logging off
logoff();
}
/**
* Callback called by the reader thread when it goes away.
*/
protected synchronized void readerDidExit () protected synchronized void readerDidExit ()
{ {
// clear out our reader reference // clear out our reader reference
@@ -100,6 +178,19 @@ class Communicator
// let the client know when we finally go away // let the client know when we finally go away
_client.communicatorDidExit(); _client.communicatorDidExit();
Log.info("Reader thread exited.");
}
/**
* Callback called by the writer thread when it goes away.
*/
protected synchronized void writerDidExit ()
{
// clear out our writer reference
_writer = null;
Log.info("Writer thread exited.");
} }
/** /**
@@ -109,7 +200,7 @@ class Communicator
throws IOException throws IOException
{ {
// first we flatten the message so that we can measure it's length // first we flatten the message so that we can measure it's length
msg.writeTo(_dout); TypedObjectFactory.writeTo(_dout, msg);
// then write the framed message to actual output stream // then write the framed message to actual output stream
_fout.writeFrameAndReset(_out); _fout.writeFrameAndReset(_out);
} }
@@ -121,11 +212,19 @@ class Communicator
protected DownstreamMessage receiveMessage () protected DownstreamMessage receiveMessage ()
throws IOException throws IOException
{ {
// read the frame size which comes first // read in the next message frame
int count = _din.readInt(); _fin.clearAndReadFrame(_in);
// then use the typed object factory to read and decode the proper
// downstream message instance
return (DownstreamMessage)TypedObjectFactory.readFrom(_din);
}
// now read /**
return null; * 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)
{
} }
/** /**
@@ -154,10 +253,9 @@ class Communicator
return; return;
} }
// once authenticated, we go into full-duplex mode, // now that we're authenticated, we manage the reading
// starting up another thread to listen for messages while // half of things by continuously reading messages from
// we handle the delivery of messages // the socket and processing them
startWriter();
listen(); listen();
} finally { } finally {
@@ -166,6 +264,22 @@ class Communicator
} }
} }
/**
* Informs the reader thread that it's no longer running. The next
* time through the read loop, it will exit.
*/
public synchronized void shutdown ()
{
_running = false;
// if we are not the reader thread, then we want to interrupt
// the reader thread as it may be blocked listening to the
// socket
if (Thread.currentThread() != this) {
interrupt();
}
}
protected void connect () protected void connect ()
throws IOException throws IOException
{ {
@@ -180,13 +294,14 @@ class Communicator
// establish a socket connection to said server // establish a socket connection to said server
_socket = new Socket(host, _client.getPort()); _socket = new Socket(host, _client.getPort());
// create our input and output streams // get a handle on our input and output streams
InputStream in = _socket.getInputStream(); _in = _socket.getInputStream();
_din = new DataInputStream(new BufferedInputStream(in));
_out = _socket.getOutputStream(); _out = _socket.getOutputStream();
// we frame our messages here and then write them directly to // our messages are framed (preceded by their length), so we
// the real output stream // use these helper streams to manage the framing
_fin = new FramedInputStream();
_din = new DataInputStream(_fin);
_fout = new FramingOutputStream(); _fout = new FramingOutputStream();
_dout = new DataOutputStream(_fout); _dout = new DataOutputStream(_fout);
} }
@@ -197,11 +312,74 @@ class Communicator
// construct an auth request and send it // construct an auth request and send it
AuthRequest req = new AuthRequest(_client.getCredentials()); AuthRequest req = new AuthRequest(_client.getCredentials());
sendMessage(req); sendMessage(req);
// now wait for the auth response
AuthResponse rsp = (AuthResponse)receiveMessage();
AuthResponseData data = rsp.getData();
// if the auth request failed, we want to let the communicator
// know by throwing a login exception
if (!data.code.equals(Codes.SUCCESS)) {
throw new LogonException(data.code);
}
// we're all clear. let the communicator know that we're in
logonSucceeded(data);
} }
protected void listen () protected void listen ()
{ {
DownstreamMessage msg = null;
while (isRunning()) {
try {
// read the next message from the socket
msg = receiveMessage();
// process the message
processMessage(msg);
} catch (ObjectStreamException ose) {
Log.warning("Error decoding message: " + ose);
// move on to the next message
} catch (InterruptedIOException iioe) {
// somebody set up us the bomb! we've been interrupted
// which means that we're being shut down, so we
// simply fall through and isRunning() will return
// false next time through the loop
Log.info("Reader thread woken up in time to die.");
} catch (EOFException eofe) {
Log.info("Connection closed by peer.");
// nothing left for us to do
shutdown();
} catch (IOException ioe) {
// let the communicator know that our connection
// failed
connectionFailed(ioe);
// and shut ourselves down
shutdown();
} catch (Exception e) {
Log.warning("Error processing message [msg=" + msg +
", error=" + e + "].");
// move on to the next message
}
}
} }
/**
* Must access _running via this member function to ensure that we
* are Chapter 17 compliant.
*/
protected synchronized boolean isRunning ()
{
return _running;
}
protected boolean _running = true;
} }
/** /**
@@ -213,6 +391,67 @@ class Communicator
{ {
public void run () public void run ()
{ {
try {
while (isRunning()) {
// fetch the next message from the queue
UpstreamMessage msg = (UpstreamMessage)_msgq.get();
// 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) {
break;
}
try {
// write the message out the socket
sendMessage(msg);
} catch (IOException ioe) {
// let the communicator know if we have any
// problems
connectionFailed(ioe);
// and bail
shutdown();
}
}
} finally {
writerDidExit();
}
}
/**
* Informs the writer thread that it's no longer running. The next
* time through the write loop, it will exit.
*/
public synchronized void shutdown ()
{
_running = false;
// post a bogus message to the outgoing queue to ensure that
// the writer thread notices that it's time to go
postMessage(new TerminationMessage());
}
/**
* Must access _running via this member function to ensure that we
* are Chapter 17 compliant.
*/
protected synchronized boolean isRunning ()
{
return _running;
}
protected boolean _running = true;
}
/** This is used to terminate the writer thread. */
protected static class TerminationMessage extends UpstreamMessage
{
public short getType ()
{
return -1;
} }
} }
@@ -221,11 +460,15 @@ class Communicator
protected Writer _writer; protected Writer _writer;
protected Socket _socket; protected Socket _socket;
protected DataInputStream _din; protected InputStream _in;
protected OutputStream _out; protected OutputStream _out;
protected Queue _msgq = new Queue(); protected Queue _msgq = new Queue();
/** We use this to frame our upstream messages. */ /** We use this to frame our upstream messages. */
protected FramingOutputStream _fout; protected FramingOutputStream _fout;
protected DataOutputStream _dout; protected DataOutputStream _dout;
/** We use this to frame our downstream messages. */
protected FramedInputStream _fin;
protected DataInputStream _din;
} }
@@ -1,5 +1,5 @@
// //
// $Id: DObject.java,v 1.1 2001/05/22 21:51:29 mdb Exp $ // $Id: DObject.java,v 1.2 2001/05/23 04:03:40 mdb Exp $
package com.samskivert.cocktail.cher.dobj; package com.samskivert.cocktail.cher.dobj;
@@ -10,7 +10,7 @@ import java.io.DataOutputStream;
import com.samskivert.cocktail.cher.io.TypedObject; import com.samskivert.cocktail.cher.io.TypedObject;
import com.samskivert.cocktail.cher.io.TypedObjectFactory; import com.samskivert.cocktail.cher.io.TypedObjectFactory;
public class DObject extends TypedObject public class DObject implements TypedObject
{ {
public static short TYPE = 400; public static short TYPE = 400;
@@ -1,5 +1,5 @@
// //
// $Id: TypedObject.java,v 1.1 2001/05/22 06:07:59 mdb Exp $ // $Id: TypedObject.java,v 1.2 2001/05/23 04:03:40 mdb Exp $
package com.samskivert.cocktail.cher.io; package com.samskivert.cocktail.cher.io;
@@ -10,9 +10,12 @@ import java.io.DataOutputStream;
/** /**
* A typed object is one that is associated with a particular type code. * A typed object is one that is associated with a particular type code.
* The type code can be communicated on the wire and used by the receiving * The type code can be communicated on the wire and used by the receiving
* end to instantiate the proper typed object class for decoding. * end to instantiate the proper typed object class for decoding (which is
* done by the <code>TypedObjectFactory</code>).
*
* @see TypedObjectFactory
*/ */
public abstract class TypedObject public interface TypedObject
{ {
/** /**
* Each typed object class must associate itself with a type value via * Each typed object class must associate itself with a type value via
@@ -22,28 +25,17 @@ public abstract class TypedObject
* *
* @return The type code associated with this object. * @return The type code associated with this object.
*/ */
public abstract short getType (); public short getType ();
/** /**
* Each typed object class must be able to write itself to a stream. * Each typed object class must be able to write itself to a stream.
* It should first call <code>super.writeTo()</code> before writing
* its own fields to the stream.
*/ */
public void writeTo (DataOutputStream out) public void writeTo (DataOutputStream out)
throws IOException throws IOException;
{
out.writeShort(getType());
}
/** /**
* Each typed object class must be able to read itself from a stream. * Each typed object class must be able to read itself from a stream.
* It should first call <code>super.readFrom()</code> before reading
* its own fields from the stream.
*/ */
public void readFrom (DataInputStream in) public void readFrom (DataInputStream in)
throws IOException throws IOException;
{
// nothing to do because the TypedObjectFactory already read our
// type value from the stream
}
} }
@@ -1,5 +1,5 @@
// //
// $Id: TypedObjectFactory.java,v 1.2 2001/05/22 21:51:29 mdb Exp $ // $Id: TypedObjectFactory.java,v 1.3 2001/05/23 04:03:40 mdb Exp $
package com.samskivert.cocktail.cher.io; package com.samskivert.cocktail.cher.io;
@@ -37,6 +37,19 @@ public class TypedObjectFactory
return msg; return msg;
} }
/**
* Writes (serializes) a typed object to the supplied data output
* stream.
*/
public static void writeTo (DataOutputStream dout, TypedObject tobj)
throws IOException
{
// first write the type of the object
dout.writeShort(tobj.getType());
// then write the object itself
tobj.writeTo(dout);
}
/** /**
* Registers the supplied class with the specified type code. If a * Registers the supplied class with the specified type code. If a
* class is already registered with that type code a runtime exception * class is already registered with that type code a runtime exception
@@ -1,5 +1,5 @@
// //
// $Id: AuthRequest.java,v 1.2 2001/05/22 21:51:29 mdb Exp $ // $Id: AuthRequest.java,v 1.3 2001/05/23 04:03:40 mdb Exp $
package com.samskivert.cocktail.cher.net; package com.samskivert.cocktail.cher.net;
@@ -39,7 +39,7 @@ public class AuthRequest extends UpstreamMessage
throws IOException throws IOException
{ {
super.writeTo(out); super.writeTo(out);
_creds.writeTo(out); TypedObjectFactory.writeTo(out, _creds);
} }
public void readFrom (DataInputStream in) public void readFrom (DataInputStream in)
@@ -1,5 +1,5 @@
// //
// $Id: AuthResponse.java,v 1.1 2001/05/22 21:51:29 mdb Exp $ // $Id: AuthResponse.java,v 1.2 2001/05/23 04:03:40 mdb Exp $
package com.samskivert.cocktail.cher.net; package com.samskivert.cocktail.cher.net;
@@ -7,7 +7,6 @@ import java.io.IOException;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import com.samskivert.cocktail.cher.dobj.DObject;
import com.samskivert.cocktail.cher.io.TypedObjectFactory; import com.samskivert.cocktail.cher.io.TypedObjectFactory;
/** /**
@@ -22,12 +21,6 @@ public class AuthResponse extends DownstreamMessage
/** The code for an auth response. */ /** The code for an auth response. */
public static final short TYPE = TYPE_BASE + 0; public static final short TYPE = TYPE_BASE + 0;
/** The response code key in the data object. */
public static final String CODE = "code";
/** The failure reason key in the data object. */
public static final String REASON = "reason";
/** /**
* Zero argument constructor used when unserializing an instance. * Zero argument constructor used when unserializing an instance.
*/ */
@@ -39,12 +32,12 @@ public class AuthResponse extends DownstreamMessage
/** /**
* Constructs a auth response with the supplied credentials. * Constructs a auth response with the supplied credentials.
*/ */
public AuthResponse (DObject data) public AuthResponse (AuthResponseData data)
{ {
_data = data; _data = data;
} }
public DObject getData () public AuthResponseData getData ()
{ {
return _data; return _data;
} }
@@ -58,15 +51,15 @@ public class AuthResponse extends DownstreamMessage
throws IOException throws IOException
{ {
super.writeTo(out); super.writeTo(out);
_data.writeTo(out); TypedObjectFactory.writeTo(out, _data);
} }
public void readFrom (DataInputStream in) public void readFrom (DataInputStream in)
throws IOException throws IOException
{ {
super.readFrom(in); super.readFrom(in);
_data = (DObject)TypedObjectFactory.readFrom(in); _data = (AuthResponseData)TypedObjectFactory.readFrom(in);
} }
protected DObject _data; protected AuthResponseData _data;
} }
@@ -0,0 +1,21 @@
//
// $Id: AuthResponseData.java,v 1.1 2001/05/23 04:03:40 mdb Exp $
package com.samskivert.cocktail.cher.net;
import com.samskivert.cocktail.cher.dobj.DObject;
/**
* An <code>AuthResponseData</code> object is communicated back to the
* client along with an authentication response. It contains an indicator
* of authentication success or failure along with bootstrap information
* for the client.
*/
public class AuthResponseData extends DObject
{
/**
* Either the string "success" or a reason code for why authentication
* failed.
*/
public String code;
}
@@ -1,8 +1,12 @@
// //
// $Id: Credentials.java,v 1.1 2001/05/22 06:07:59 mdb Exp $ // $Id: Credentials.java,v 1.2 2001/05/23 04:03:40 mdb Exp $
package com.samskivert.cocktail.cher.net; package com.samskivert.cocktail.cher.net;
import java.io.IOException;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import com.samskivert.cocktail.cher.io.TypedObject; import com.samskivert.cocktail.cher.io.TypedObject;
import com.samskivert.cocktail.cher.io.TypedObjectFactory; import com.samskivert.cocktail.cher.io.TypedObjectFactory;
@@ -17,7 +21,7 @@ import com.samskivert.cocktail.cher.io.TypedObjectFactory;
* that they can be instantiated prior to reconstruction from a data input * that they can be instantiated prior to reconstruction from a data input
* stream. * stream.
*/ */
public abstract class Credentials extends TypedObject public abstract class Credentials implements TypedObject
{ {
/** /**
* All credential derived classes should base their typed object code * All credential derived classes should base their typed object code
@@ -25,6 +29,28 @@ public abstract class Credentials extends TypedObject
*/ */
public static final short TYPE_BASE = 300; public static final short TYPE_BASE = 300;
/**
* Derived classes should override this function to write their fields
* out to the supplied data output stream. They <em>must</em> be sure
* to first call <code>super.writeTo()</code>.
*/
public void writeTo (DataOutputStream out)
throws IOException
{
// we don't do anything here, but we may want to some day
}
/**
* Derived classes should override this function to read their fields
* from the supplied data input stream. They <em>must</em> be sure to
* first call <code>super.readFrom()</code>.
*/
public void readFrom (DataInputStream in)
throws IOException
{
// we don't do anything here, but we may want to some day
}
// register our credential classes // register our credential classes
static { static {
TypedObjectFactory.registerClass(UsernamePasswordCreds.TYPE, TypedObjectFactory.registerClass(UsernamePasswordCreds.TYPE,
@@ -1,8 +1,12 @@
// //
// $Id: DownstreamMessage.java,v 1.2 2001/05/22 21:51:29 mdb Exp $ // $Id: DownstreamMessage.java,v 1.3 2001/05/23 04:03:40 mdb Exp $
package com.samskivert.cocktail.cher.net; package com.samskivert.cocktail.cher.net;
import java.io.IOException;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import com.samskivert.cocktail.cher.io.TypedObject; import com.samskivert.cocktail.cher.io.TypedObject;
import com.samskivert.cocktail.cher.io.TypedObjectFactory; import com.samskivert.cocktail.cher.io.TypedObjectFactory;
@@ -12,7 +16,7 @@ import com.samskivert.cocktail.cher.io.TypedObjectFactory;
* client. Downstream messages include object subscription, event * client. Downstream messages include object subscription, event
* forwarding and session management. * forwarding and session management.
*/ */
public abstract class DownstreamMessage extends TypedObject public abstract class DownstreamMessage implements TypedObject
{ {
/** /**
* All downstream message derived classes should base their typed * All downstream message derived classes should base their typed
@@ -41,6 +45,28 @@ public abstract class DownstreamMessage extends TypedObject
// nothing to do... // nothing to do...
} }
/**
* Derived classes should override this function to write their fields
* out to the supplied data output stream. They <em>must</em> be sure
* to first call <code>super.writeTo()</code>.
*/
public void writeTo (DataOutputStream out)
throws IOException
{
// we don't do anything here, but we may want to some day
}
/**
* Derived classes should override this function to read their fields
* from the supplied data input stream. They <em>must</em> be sure to
* first call <code>super.readFrom()</code>.
*/
public void readFrom (DataInputStream in)
throws IOException
{
// we don't do anything here, but we may want to some day
}
// register our downstream message classes // register our downstream message classes
static { static {
TypedObjectFactory.registerClass(AuthResponse.TYPE, TypedObjectFactory.registerClass(AuthResponse.TYPE,
@@ -1,5 +1,5 @@
// //
// $Id: ObjectResponse.java,v 1.1 2001/05/22 21:51:29 mdb Exp $ // $Id: ObjectResponse.java,v 1.2 2001/05/23 04:03:40 mdb Exp $
package com.samskivert.cocktail.cher.net; package com.samskivert.cocktail.cher.net;
@@ -43,7 +43,7 @@ public class ObjectResponse extends DownstreamMessage
{ {
super.writeTo(out); super.writeTo(out);
out.writeShort(messageId); out.writeShort(messageId);
_dobj.writeTo(out); TypedObjectFactory.writeTo(out, _dobj);
} }
public void readFrom (DataInputStream in) public void readFrom (DataInputStream in)
@@ -1,5 +1,5 @@
// //
// $Id: UpstreamMessage.java,v 1.2 2001/05/22 21:51:29 mdb Exp $ // $Id: UpstreamMessage.java,v 1.3 2001/05/23 04:03:40 mdb Exp $
package com.samskivert.cocktail.cher.net; package com.samskivert.cocktail.cher.net;
@@ -16,7 +16,7 @@ import com.samskivert.cocktail.cher.io.TypedObjectFactory;
* Upstream messages include object subscription, event forwarding and * Upstream messages include object subscription, event forwarding and
* session management. * session management.
*/ */
public abstract class UpstreamMessage extends TypedObject public abstract class UpstreamMessage implements TypedObject
{ {
/** /**
* All upstream message derived classes should base their typed object * All upstream message derived classes should base their typed object
@@ -53,7 +53,6 @@ public abstract class UpstreamMessage extends TypedObject
public void writeTo (DataOutputStream out) public void writeTo (DataOutputStream out)
throws IOException throws IOException
{ {
super.writeTo(out);
out.writeShort(messageId); out.writeShort(messageId);
} }
@@ -65,7 +64,6 @@ public abstract class UpstreamMessage extends TypedObject
public void readFrom (DataInputStream in) public void readFrom (DataInputStream in)
throws IOException throws IOException
{ {
super.readFrom(in);
messageId = in.readShort(); messageId = in.readShort();
} }
@@ -1,5 +1,5 @@
// //
// $Id: UsernamePasswordCreds.java,v 1.2 2001/05/22 21:51:29 mdb Exp $ // $Id: UsernamePasswordCreds.java,v 1.3 2001/05/23 04:03:40 mdb Exp $
package com.samskivert.cocktail.cher.net; package com.samskivert.cocktail.cher.net;
@@ -36,6 +36,7 @@ public class UsernamePasswordCreds extends Credentials
public void writeTo (DataOutputStream out) public void writeTo (DataOutputStream out)
throws IOException throws IOException
{ {
super.writeTo(out);
out.writeUTF(_username); out.writeUTF(_username);
out.writeUTF(_password); out.writeUTF(_password);
} }
@@ -43,6 +44,7 @@ public class UsernamePasswordCreds extends Credentials
public void readFrom (DataInputStream in) public void readFrom (DataInputStream in)
throws IOException throws IOException
{ {
super.readFrom(in);
_username = in.readUTF(); _username = in.readUTF();
_password = in.readUTF(); _password = in.readUTF();
} }
@@ -0,0 +1,17 @@
//
// $Id: CherCodes.java,v 1.1 2001/05/23 04:03:41 mdb Exp $
package com.samskivert.cocktail.cher.util;
/**
* The <code>Codes</code> class serves as a repository for miscellaneous
* string and integer constants used by componenets of the Cher system.
*/
public class Codes
{
/**
* Generally used in responses that can either have the value success,
* or a string code explaining the reason for failure.
*/
public static final String SUCCESS = "success";
}