Further progress. Heeya!
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@3 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: Communicator.java,v 1.1 2001/05/22 06:07:59 mdb Exp $
|
||||
// $Id: Communicator.java,v 1.2 2001/05/22 21:51:29 mdb Exp $
|
||||
|
||||
package com.samskivert.cocktail.cher.client;
|
||||
|
||||
@@ -8,7 +8,9 @@ import java.net.Socket;
|
||||
import java.net.InetAddress;
|
||||
|
||||
import com.samskivert.util.Queue;
|
||||
|
||||
import com.samskivert.cocktail.cher.Log;
|
||||
import com.samskivert.cocktail.cher.io.FramingOutputStream;
|
||||
import com.samskivert.cocktail.cher.net.*;
|
||||
|
||||
/**
|
||||
@@ -100,6 +102,38 @@ class Communicator
|
||||
_client.communicatorDidExit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the supplied message to the socket.
|
||||
*/
|
||||
protected void sendMessage (UpstreamMessage msg)
|
||||
throws IOException
|
||||
{
|
||||
// first we flatten the message so that we can measure it's length
|
||||
msg.writeTo(_dout);
|
||||
// then write the framed message to actual output stream
|
||||
_fout.writeFrameAndReset(_out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a new message from the socket (blocking until a message has
|
||||
* arrived).
|
||||
*/
|
||||
protected DownstreamMessage receiveMessage ()
|
||||
throws IOException
|
||||
{
|
||||
// read the frame size which comes first
|
||||
int count = _din.readInt();
|
||||
|
||||
// now read
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
protected class Reader extends Thread
|
||||
{
|
||||
public void run ()
|
||||
@@ -145,11 +179,24 @@ class Communicator
|
||||
|
||||
// establish a socket connection to said server
|
||||
_socket = new Socket(host, _client.getPort());
|
||||
|
||||
// create our input and output streams
|
||||
InputStream in = _socket.getInputStream();
|
||||
_din = new DataInputStream(new BufferedInputStream(in));
|
||||
_out = _socket.getOutputStream();
|
||||
|
||||
// we frame our messages here and then write them directly to
|
||||
// the real output stream
|
||||
_fout = new FramingOutputStream();
|
||||
_dout = new DataOutputStream(_fout);
|
||||
}
|
||||
|
||||
protected void logon ()
|
||||
throws LogonException
|
||||
throws IOException, LogonException
|
||||
{
|
||||
// construct an auth request and send it
|
||||
AuthRequest req = new AuthRequest(_client.getCredentials());
|
||||
sendMessage(req);
|
||||
}
|
||||
|
||||
protected void listen ()
|
||||
@@ -157,6 +204,11 @@ class Communicator
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
protected class Writer extends Thread
|
||||
{
|
||||
public void run ()
|
||||
@@ -170,6 +222,10 @@ class Communicator
|
||||
|
||||
protected Socket _socket;
|
||||
protected DataInputStream _din;
|
||||
protected DataInputStream _dout;
|
||||
protected OutputStream _out;
|
||||
protected Queue _msgq = new Queue();
|
||||
|
||||
/** We use this to frame our upstream messages. */
|
||||
protected FramingOutputStream _fout;
|
||||
protected DataOutputStream _dout;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// $Id: DObject.java,v 1.1 2001/05/22 21:51:29 mdb Exp $
|
||||
|
||||
package com.samskivert.cocktail.cher.dobj;
|
||||
|
||||
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.TypedObjectFactory;
|
||||
|
||||
public class DObject extends TypedObject
|
||||
{
|
||||
public static short TYPE = 400;
|
||||
|
||||
public short getType ()
|
||||
{
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
public void writeTo (DataOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
public void readFrom (DataInputStream in)
|
||||
throws IOException
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
//
|
||||
// $Id: FramedInputStream.java,v 1.1 2001/05/22 21:51:29 mdb Exp $
|
||||
|
||||
package com.samskivert.cocktail.cher.io;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
/**
|
||||
* The framed input stream reads input that was framed by a framing output
|
||||
* stream. Framing in this case simply means writing the length of the
|
||||
* frame followed by the data associated with the frame so that an entire
|
||||
* frame can be loaded from the network layer before any higher layer
|
||||
* attempts to process it. Additionally, any failure in decoding a frame
|
||||
* won't result in the entire stream being skewed due to the remainder of
|
||||
* the undecoded frame.
|
||||
*
|
||||
* <p>The framed input stream reads an entire frame worth of data into its
|
||||
* internal buffer when <code>readFrame()</code> is called. It then
|
||||
* behaves as if this is the only data available on the stream (meaning
|
||||
* that when the data in the frame is exhausted, it will behave as if the
|
||||
* end of the stream has been reached). A new frame can be read at any
|
||||
* time and will be appended to the data available (the frame length data
|
||||
* is never inserted into the stream data), but it is assumed that the
|
||||
* caller will want to read and process an entire frame before going on to
|
||||
* read the next frame (so that <code>clear()</code> can be called in the
|
||||
* event of a frame decoding failure without clearing out the data from
|
||||
* subsequent frames).
|
||||
*
|
||||
* <p><em>Note:</em> The framing input stream does not synchronize reads
|
||||
* from its internal buffer. It is intended to only be accessed from a
|
||||
* single thread.
|
||||
*
|
||||
* <p>Implementation note: maybe this should derive from
|
||||
* <code>FilterInputStream</code> and be tied to a single
|
||||
* <code>InputStream</code> for its lifetime.
|
||||
*/
|
||||
public class FramedInputStream extends InputStream
|
||||
{
|
||||
public FramedInputStream ()
|
||||
{
|
||||
_header = new byte[HEADER_SIZE];
|
||||
_buffer = new byte[INITIAL_BUFFER_SIZE];
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a single frame from the provided input stream and appends
|
||||
* that data to the existing data available via the framed input
|
||||
* stream's read methods.
|
||||
*
|
||||
* @return the length of the read frame in bytes.
|
||||
*/
|
||||
public synchronized int readFrame (InputStream source)
|
||||
throws IOException
|
||||
{
|
||||
// first read in the frame length
|
||||
if (source.read(_header, 0, HEADER_SIZE) < HEADER_SIZE) {
|
||||
throw new EOFException();
|
||||
}
|
||||
|
||||
// now decode the frame length
|
||||
int flength = (_header[0] << 24) & 0xFF;
|
||||
flength += (_header[1] << 16) & 0xFF;
|
||||
flength += (_header[2] << 8) & 0xFF;
|
||||
flength += _header[3] & 0xFF;
|
||||
|
||||
// expand our buffer to accomodate the frame data
|
||||
int newcount = _count + flength;
|
||||
if (newcount > _buffer.length) {
|
||||
// increase the buffer size in large increments
|
||||
byte[] newbuf = new byte[Math.max(_buffer.length << 1, newcount)];
|
||||
System.arraycopy(_buffer, 0, newbuf, 0, _count);
|
||||
_buffer = newbuf;
|
||||
}
|
||||
|
||||
// read the data into the buffer
|
||||
source.read(_buffer, _count, flength);
|
||||
_count = newcount;
|
||||
|
||||
return flength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears out any previously read frame data and reads a new frame
|
||||
* into the buffer.
|
||||
*
|
||||
* @return the length of the read frame in bytes.
|
||||
*/
|
||||
public int clearAndReadFrame (InputStream source)
|
||||
throws IOException
|
||||
{
|
||||
clear();
|
||||
return readFrame(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears out any frame data already in the buffer including anything
|
||||
* that hasn't yet been read.
|
||||
*/
|
||||
public void clear ()
|
||||
{
|
||||
_pos = 0;
|
||||
_count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the next byte of data from this input stream. The value byte
|
||||
* is returned as an <code>int</code> in the range <code>0</code> to
|
||||
* <code>255</code>. If no byte is available because the end of the
|
||||
* stream has been reached, the value <code>-1</code> is returned.
|
||||
*
|
||||
* <p>This <code>read</code> method cannot block.
|
||||
*
|
||||
* @return the next byte of data, or <code>-1</code> if the end of the
|
||||
* stream has been reached.
|
||||
*/
|
||||
public int read ()
|
||||
{
|
||||
return (_pos < _count) ? (_buffer[_pos++] & 0xff) : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads up to <code>len</code> bytes of data into an array of bytes
|
||||
* from this input stream. If <code>pos</code> equals
|
||||
* <code>count</code>, then <code>-1</code> is returned to indicate
|
||||
* end of file. Otherwise, the number <code>k</code> of bytes read is
|
||||
* equal to the smaller of <code>len</code> and
|
||||
* <code>count-pos</code>. If <code>k</code> is positive, then bytes
|
||||
* <code>buf[pos]</code> through <code>buf[pos+k-1]</code> are copied
|
||||
* into <code>b[off]</code> through <code>b[off+k-1]</code> in the
|
||||
* manner performed by <code>System.arraycopy</code>. The value
|
||||
* <code>k</code> is added into <code>pos</code> and <code>k</code> is
|
||||
* returned.
|
||||
*
|
||||
* <p>This <code>read</code> method cannot block.
|
||||
*
|
||||
* @param b the buffer into which the data is read.
|
||||
* @param off the start offset of the data.
|
||||
* @param len the maximum number of bytes read.
|
||||
*
|
||||
* @return the total number of bytes read into the buffer, or
|
||||
* <code>-1</code> if there is no more data because the end of the
|
||||
* stream has been reached.
|
||||
*/
|
||||
public int read (byte[] b, int off, int len)
|
||||
{
|
||||
// sanity check the arguments
|
||||
if (b == null) {
|
||||
throw new NullPointerException();
|
||||
} else if ((off < 0) || (off > b.length) || (len < 0) ||
|
||||
((off + len) > b.length) || ((off + len) < 0)) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
// figure out how much data we'll return
|
||||
if (_pos >= _count) {
|
||||
return -1;
|
||||
}
|
||||
if (_pos + len > _count) {
|
||||
len = _count - _pos;
|
||||
}
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// copy and advance
|
||||
System.arraycopy(_buffer, _pos, b, off, len);
|
||||
_pos += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips <code>n</code> bytes of input from this input stream. Fewer
|
||||
* bytes might be skipped if the end of the input stream is reached.
|
||||
* The actual number <code>k</code> of bytes to be skipped is equal to
|
||||
* the smaller of <code>n</code> and <code>count-pos</code>. The value
|
||||
* <code>k</code> is added into <code>pos</code> and <code>k</code> is
|
||||
* returned.
|
||||
*
|
||||
* @param n the number of bytes to be skipped.
|
||||
*
|
||||
* @return the actual number of bytes skipped.
|
||||
*/
|
||||
public long skip (long n)
|
||||
{
|
||||
if (_pos + n > _count) {
|
||||
n = _count - _pos;
|
||||
}
|
||||
if (n <= 0) {
|
||||
return 0;
|
||||
}
|
||||
_pos += n;
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes that can be read from this input stream
|
||||
* without blocking. The value returned is <code>count - pos</code>,
|
||||
* which is the number of bytes remaining to be read from the input
|
||||
* buffer.
|
||||
*
|
||||
* @return the number of bytes remaining to be read from the buffered
|
||||
* frames.
|
||||
*/
|
||||
public int available ()
|
||||
{
|
||||
return _count - _pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always returns false as framed input streams do not support
|
||||
* marking.
|
||||
*/
|
||||
public boolean markSupported ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does nothing, as marking is not supported.
|
||||
*/
|
||||
public void mark (int readAheadLimit)
|
||||
{
|
||||
// not supported; do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the buffer to the beginning of the buffered frames.
|
||||
*/
|
||||
public void reset ()
|
||||
{
|
||||
_pos = 0;
|
||||
}
|
||||
|
||||
protected byte[] _header;
|
||||
protected byte[] _buffer;
|
||||
protected int _pos;
|
||||
protected int _count;
|
||||
|
||||
/** The size of the frame header (a 32-bit integer). */
|
||||
protected static final int HEADER_SIZE = 4;
|
||||
|
||||
/** The default initial size of the internal buffer. */
|
||||
protected static final int INITIAL_BUFFER_SIZE = 32;
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// $Id: FramingOutputStream.java,v 1.1 2001/05/22 21:51:29 mdb Exp $
|
||||
|
||||
package com.samskivert.cocktail.cher.io;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* The framing output stream accumulates output into a byte array just
|
||||
* like the byte array output stream, but can then be instructed to send
|
||||
* its contents down another output stream, prefixed by the length
|
||||
* (written as an integer) of those contents. It does this efficiently so
|
||||
* that data is copied as little as possible and so that the output stream
|
||||
* to which the data is written need not be buffered because the framed
|
||||
* output is written in a single call to <code>write()</code>.
|
||||
*
|
||||
* <p><em>Note:</em> The framing output stream does not synchronize writes
|
||||
* to its internal buffer. It is intended to only be accessed from a
|
||||
* single thread.
|
||||
*
|
||||
* <p>Implementation note: maybe this should derive from
|
||||
* <code>FilterOutputStream</code> and be tied to a single
|
||||
* <code>OutputStream</code> for its lifetime.
|
||||
*/
|
||||
public class FramingOutputStream extends OutputStream
|
||||
{
|
||||
public FramingOutputStream ()
|
||||
{
|
||||
_buffer = new byte[INITIAL_BUFFER_SIZE];
|
||||
_count = 4; // leave room for the frame size at the beginning
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the specified byte to this framing output stream.
|
||||
*
|
||||
* @param b the byte to be written.
|
||||
*/
|
||||
public void write (int b)
|
||||
{
|
||||
// expand our buffer if necessary
|
||||
int newcount = _count + 1;
|
||||
if (newcount > _buffer.length) {
|
||||
// increase the buffer size in large increments
|
||||
byte[] newbuf = new byte[Math.max(_buffer.length << 1, newcount)];
|
||||
System.arraycopy(_buffer, 0, newbuf, 0, _count);
|
||||
_buffer = newbuf;
|
||||
}
|
||||
|
||||
// copy and advance
|
||||
_buffer[_count] = (byte)b;
|
||||
_count = newcount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes <code>len</code> bytes from the specified byte array
|
||||
* starting at offset <code>off</code> to this framing output stream.
|
||||
*
|
||||
* @param b the data.
|
||||
* @param off the start offset in the data.
|
||||
* @param len the number of bytes to write.
|
||||
*/
|
||||
public void write (byte[] b, int off, int len)
|
||||
{
|
||||
// sanity check the arguments
|
||||
if ((off < 0) || (off > b.length) || (len < 0) ||
|
||||
((off + len) > b.length) || ((off + len) < 0)) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
} else if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// expand the buffer if necessary
|
||||
int newcount = _count + len;
|
||||
if (newcount > _buffer.length) {
|
||||
// increase the buffer size in large increments
|
||||
byte[] newbuf = new byte[Math.max(_buffer.length << 1, newcount)];
|
||||
System.arraycopy(_buffer, 0, newbuf, 0, _count);
|
||||
_buffer = newbuf;
|
||||
}
|
||||
|
||||
// copy and advance
|
||||
System.arraycopy(b, off, _buffer, _count, len);
|
||||
_count = newcount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the contents of this framing output stream to the target
|
||||
* output stream, prefixed by an integer with value equal to the
|
||||
* number of bytes written folling that integer. It then resets the
|
||||
* framing output stream to prepare for another framed message.
|
||||
*/
|
||||
public synchronized void writeFrameAndReset (OutputStream target)
|
||||
throws IOException
|
||||
{
|
||||
// prefix the frame with the byte count in network byte order (the
|
||||
// format used by DataOutputStream)
|
||||
int count = _count - 4;
|
||||
_buffer[0] = (byte)((count >>> 24) & 0xFF);
|
||||
_buffer[1] = (byte)((count >>> 16) & 0xFF);
|
||||
_buffer[2] = (byte)((count >>> 8) & 0xFF);
|
||||
_buffer[3] = (byte)((count >>> 0) & 0xFF);
|
||||
|
||||
// write the data
|
||||
target.write(_buffer, 0, _count);
|
||||
|
||||
// reset our internal buffer
|
||||
reset();
|
||||
}
|
||||
|
||||
public void reset ()
|
||||
{
|
||||
// leave room for the frame size at the beginning
|
||||
_count = 4;
|
||||
}
|
||||
|
||||
protected byte[] _buffer;
|
||||
protected int _count;
|
||||
|
||||
/** The default initial size of the internal buffer. */
|
||||
protected static final int INITIAL_BUFFER_SIZE = 32;
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
//
|
||||
// $Id: ObjectStreamException.java,v 1.1 2001/05/22 06:07:59 mdb Exp $
|
||||
// $Id: ObjectStreamException.java,v 1.2 2001/05/22 21:51:29 mdb Exp $
|
||||
|
||||
package com.samskivert.cocktail.cher.io;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* The object stream exception is used to communicate an error in
|
||||
* processing a typed object stream. As any error is fatal, we don't
|
||||
@@ -10,7 +12,7 @@ package com.samskivert.cocktail.cher.io;
|
||||
* the nature of the error in the exception message with the assumption
|
||||
* that the caller will want to raise holy hell in every case.
|
||||
*/
|
||||
public class ObjectStreamException extends Exception
|
||||
public class ObjectStreamException extends IOException
|
||||
{
|
||||
public ObjectStreamException (String message)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: TypedObjectFactory.java,v 1.1 2001/05/22 06:07:59 mdb Exp $
|
||||
// $Id: TypedObjectFactory.java,v 1.2 2001/05/22 21:51:29 mdb Exp $
|
||||
|
||||
package com.samskivert.cocktail.cher.io;
|
||||
|
||||
@@ -37,6 +37,28 @@ public class TypedObjectFactory
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the supplied class with the specified type code. If a
|
||||
* class is already registered with that type code a runtime exception
|
||||
* will be thrown so that the proper freaking out can occur.
|
||||
*/
|
||||
public static void registerClass (short type, Class clazz)
|
||||
{
|
||||
Short key = new Short(type);
|
||||
|
||||
// make sure no funny business is afoot
|
||||
if (_classes.containsKey(key)) {
|
||||
Class incumbent = (Class)_classes.get(key);
|
||||
String errmsg = "Cannot register " + clazz.getName() +
|
||||
" as type " + type + " because " + incumbent.getName() +
|
||||
" is already registered with that type.";
|
||||
throw new RuntimeException(errmsg);
|
||||
}
|
||||
|
||||
// set up the mapping
|
||||
_classes.put(key, clazz);
|
||||
}
|
||||
|
||||
protected static TypedObject newObjectByType (short type)
|
||||
throws ObjectStreamException
|
||||
{
|
||||
@@ -55,23 +77,6 @@ public class TypedObjectFactory
|
||||
}
|
||||
}
|
||||
|
||||
protected static void registerClass (short type, Class clazz)
|
||||
{
|
||||
Short key = new Short(type);
|
||||
|
||||
// make sure no funny business is afoot
|
||||
if (_classes.containsKey(key)) {
|
||||
Class incumbent = (Class)_classes.get(key);
|
||||
String errmsg = "Cannot register " + clazz.getName() +
|
||||
" as type " + type + " because " + incumbent.getName() +
|
||||
" is already registered with that type.";
|
||||
throw new RuntimeException(errmsg);
|
||||
}
|
||||
|
||||
// set up the mapping
|
||||
_classes.put(key, clazz);
|
||||
}
|
||||
|
||||
/** Our type to class mapping table. */
|
||||
protected static HashMap _classes = new HashMap();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: AuthRequest.java,v 1.1 2001/05/22 06:07:59 mdb Exp $
|
||||
// $Id: AuthRequest.java,v 1.2 2001/05/22 21:51:29 mdb Exp $
|
||||
|
||||
package com.samskivert.cocktail.cher.net;
|
||||
|
||||
@@ -9,23 +9,23 @@ import java.io.DataOutputStream;
|
||||
|
||||
import com.samskivert.cocktail.cher.io.TypedObjectFactory;
|
||||
|
||||
public class AuthenticationRequest extends UpstreamMessage
|
||||
public class AuthRequest extends UpstreamMessage
|
||||
{
|
||||
/** The code for an object subscription request. */
|
||||
/** The code for an auth request. */
|
||||
public static final short TYPE = TYPE_BASE + 0;
|
||||
|
||||
/**
|
||||
* Zero argument constructor used when unserializing an instance.
|
||||
*/
|
||||
public AuthenticationRequest ()
|
||||
public AuthRequest ()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a authentication request with the supplied credentials.
|
||||
* Constructs a auth request with the supplied credentials.
|
||||
*/
|
||||
public AuthenticationRequest (Credentials creds)
|
||||
public AuthRequest (Credentials creds)
|
||||
{
|
||||
_creds = creds;
|
||||
}
|
||||
@@ -50,8 +50,7 @@ public class AuthenticationRequest extends UpstreamMessage
|
||||
}
|
||||
|
||||
/**
|
||||
* The object id of the distributed object to which we are
|
||||
* subscribing.
|
||||
* The credentials associated with this auth request.
|
||||
*/
|
||||
protected Credentials _creds;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// $Id: AuthResponse.java,v 1.1 2001/05/22 21:51:29 mdb Exp $
|
||||
|
||||
package com.samskivert.cocktail.cher.net;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
|
||||
import com.samskivert.cocktail.cher.dobj.DObject;
|
||||
import com.samskivert.cocktail.cher.io.TypedObjectFactory;
|
||||
|
||||
/**
|
||||
* The auth response communicates authentication success or failure as
|
||||
* well as associated information via a distribted object transmitted
|
||||
* along with the response. The distributed object simply serves as a
|
||||
* container for the varied and manifold data involved in the
|
||||
* authentication process.
|
||||
*/
|
||||
public class AuthResponse extends DownstreamMessage
|
||||
{
|
||||
/** The code for an auth response. */
|
||||
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.
|
||||
*/
|
||||
public AuthResponse ()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a auth response with the supplied credentials.
|
||||
*/
|
||||
public AuthResponse (DObject data)
|
||||
{
|
||||
_data = data;
|
||||
}
|
||||
|
||||
public DObject getData ()
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
public short getType ()
|
||||
{
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
public void writeTo (DataOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
super.writeTo(out);
|
||||
_data.writeTo(out);
|
||||
}
|
||||
|
||||
public void readFrom (DataInputStream in)
|
||||
throws IOException
|
||||
{
|
||||
super.readFrom(in);
|
||||
_data = (DObject)TypedObjectFactory.readFrom(in);
|
||||
}
|
||||
|
||||
protected DObject _data;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: DownstreamMessage.java,v 1.1 2001/05/22 06:07:59 mdb Exp $
|
||||
// $Id: DownstreamMessage.java,v 1.2 2001/05/22 21:51:29 mdb Exp $
|
||||
|
||||
package com.samskivert.cocktail.cher.net;
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.samskivert.cocktail.cher.io.TypedObjectFactory;
|
||||
* client. Downstream messages include object subscription, event
|
||||
* forwarding and session management.
|
||||
*/
|
||||
public class DownstreamMessage
|
||||
public abstract class DownstreamMessage extends TypedObject
|
||||
{
|
||||
/**
|
||||
* All downstream message derived classes should base their typed
|
||||
@@ -43,30 +43,15 @@ public class DownstreamMessage
|
||||
|
||||
// register our downstream message classes
|
||||
static {
|
||||
TypedObjectFactory.registerClass(AuthenticationRequest.TYPE,
|
||||
AuthenticationRequest.class);
|
||||
TypedObjectFactory.registerClass(SubscribeRequest.TYPE,
|
||||
SubscribeRequest.class);
|
||||
TypedObjectFactory.registerClass(FetchRequest.TYPE,
|
||||
FetchRequest.class);
|
||||
TypedObjectFactory.registerClass(UnsubscribeNotification.TYPE,
|
||||
UnsubscribeNotification.class);
|
||||
TypedObjectFactory.registerClass(ForwardEventNotification.TYPE,
|
||||
ForwardEventNotification.class);
|
||||
TypedObjectFactory.registerClass(PingNotification.TYPE,
|
||||
PingNotification.class);
|
||||
TypedObjectFactory.registerClass(LogoffNotification.TYPE,
|
||||
LogoffNotification.class);
|
||||
TypedObjectFactory.registerClass(AuthResponse.TYPE,
|
||||
AuthResponse.class);
|
||||
TypedObjectFactory.registerClass(EventNotification.TYPE,
|
||||
EventNotification.class);
|
||||
TypedObjectFactory.registerClass(ObjectResponse.TYPE,
|
||||
ObjectResponse.class);
|
||||
TypedObjectFactory.registerClass(FailureResponse.TYPE,
|
||||
FailureResponse.class);
|
||||
TypedObjectFactory.registerClass(PongNotification.TYPE,
|
||||
PongNotification.class);
|
||||
}
|
||||
|
||||
/** The code for an event notification. */
|
||||
public static final byte EVENT = 0x00;
|
||||
/** The code for a fetch/subscribe object response. */
|
||||
public static final byte OBJECT = 0x01;
|
||||
/** The code for a request failure. */
|
||||
public static final byte FAILURE = 0x02;
|
||||
/** The code for a pong response. */
|
||||
public static final byte PONG = 0x03;
|
||||
/** The code for an end of transmission notification. */
|
||||
public static final byte EOT = 0x04;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
//
|
||||
// $Id: EventNotification.java,v 1.1 2001/05/22 06:07:59 mdb Exp $
|
||||
// $Id: EventNotification.java,v 1.2 2001/05/22 21:51:29 mdb Exp $
|
||||
|
||||
package com.samskivert.cocktail.cher.net;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
|
||||
import com.samskivert.cocktail.cher.dobj.Event;
|
||||
import com.samskivert.cocktail.cher.dobj.EventFactory;
|
||||
|
||||
public class EventNotification extends DownstreamMessage
|
||||
{
|
||||
/** The code for an event notification. */
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// $Id: FailureResponse.java,v 1.1 2001/05/22 21:51:29 mdb Exp $
|
||||
|
||||
package com.samskivert.cocktail.cher.net;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
|
||||
public class FailureResponse extends DownstreamMessage
|
||||
{
|
||||
/** The code for a logoff notification. */
|
||||
public static final short TYPE = TYPE_BASE + 3;
|
||||
|
||||
/**
|
||||
* Zero argument constructor used when unserializing an instance.
|
||||
*/
|
||||
public FailureResponse ()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a failure response that is associated with the specified
|
||||
* upstream message id.
|
||||
*/
|
||||
public FailureResponse (short messageId)
|
||||
{
|
||||
this.messageId = messageId;
|
||||
}
|
||||
|
||||
public short getType ()
|
||||
{
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
public void writeTo (DataOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
super.writeTo(out);
|
||||
out.writeShort(messageId);
|
||||
}
|
||||
|
||||
public void readFrom (DataInputStream in)
|
||||
throws IOException
|
||||
{
|
||||
super.readFrom(in);
|
||||
messageId = in.readShort();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// $Id: ObjectResponse.java,v 1.1 2001/05/22 21:51:29 mdb Exp $
|
||||
|
||||
package com.samskivert.cocktail.cher.net;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
|
||||
import com.samskivert.cocktail.cher.dobj.DObject;
|
||||
import com.samskivert.cocktail.cher.io.TypedObjectFactory;
|
||||
|
||||
public class ObjectResponse extends DownstreamMessage
|
||||
{
|
||||
/** The code for an event notification. */
|
||||
public static final short TYPE = TYPE_BASE + 2;
|
||||
|
||||
/**
|
||||
* Zero argument constructor used when unserializing an instance.
|
||||
*/
|
||||
public ObjectResponse ()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an object response with supplied distributed object that
|
||||
* is associated with the specified upstream message id.
|
||||
*/
|
||||
public ObjectResponse (short messageId, DObject dobj)
|
||||
{
|
||||
this.messageId = messageId;
|
||||
_dobj = dobj;
|
||||
}
|
||||
|
||||
public short getType ()
|
||||
{
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
public void writeTo (DataOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
super.writeTo(out);
|
||||
out.writeShort(messageId);
|
||||
_dobj.writeTo(out);
|
||||
}
|
||||
|
||||
public void readFrom (DataInputStream in)
|
||||
throws IOException
|
||||
{
|
||||
super.readFrom(in);
|
||||
messageId = in.readShort();
|
||||
_dobj = (DObject)TypedObjectFactory.readFrom(in);
|
||||
}
|
||||
|
||||
/** The object which is associated with this response. */
|
||||
protected DObject _dobj;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// $Id: PongResponse.java,v 1.1 2001/05/22 21:51:29 mdb Exp $
|
||||
|
||||
package com.samskivert.cocktail.cher.net;
|
||||
|
||||
public class PongNotification extends DownstreamMessage
|
||||
{
|
||||
/** The code for a pong notification. */
|
||||
public static final short TYPE = TYPE_BASE + 4;
|
||||
|
||||
/**
|
||||
* Zero argument constructor used when unserializing an instance.
|
||||
*/
|
||||
public PongNotification ()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public short getType ()
|
||||
{
|
||||
return TYPE;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: UpstreamMessage.java,v 1.1 2001/05/22 06:08:00 mdb Exp $
|
||||
// $Id: UpstreamMessage.java,v 1.2 2001/05/22 21:51:29 mdb Exp $
|
||||
|
||||
package com.samskivert.cocktail.cher.net;
|
||||
|
||||
@@ -87,8 +87,8 @@ public abstract class UpstreamMessage extends TypedObject
|
||||
|
||||
// register our upstream message classes
|
||||
static {
|
||||
TypedObjectFactory.registerClass(AuthenticationRequest.TYPE,
|
||||
AuthenticationRequest.class);
|
||||
TypedObjectFactory.registerClass(AuthRequest.TYPE,
|
||||
AuthRequest.class);
|
||||
TypedObjectFactory.registerClass(SubscribeRequest.TYPE,
|
||||
SubscribeRequest.class);
|
||||
TypedObjectFactory.registerClass(FetchRequest.TYPE,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: UsernamePasswordCreds.java,v 1.1 2001/05/22 06:08:00 mdb Exp $
|
||||
// $Id: UsernamePasswordCreds.java,v 1.2 2001/05/22 21:51:29 mdb Exp $
|
||||
|
||||
package com.samskivert.cocktail.cher.net;
|
||||
|
||||
@@ -7,7 +7,7 @@ import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class UsernamePasswordCreds
|
||||
public class UsernamePasswordCreds extends Credentials
|
||||
{
|
||||
public static final short TYPE = TYPE_BASE + 0;
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
//
|
||||
// $Id: FrameTest.java,v 1.1 2001/05/22 21:51:29 mdb Exp $
|
||||
|
||||
package com.samskivert.cocktail.cher.io.test;
|
||||
|
||||
import java.io.*;
|
||||
import com.samskivert.cocktail.cher.io.*;
|
||||
|
||||
public class FrameTest
|
||||
{
|
||||
public static void writeFrames (OutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
FramingOutputStream fout = new FramingOutputStream();
|
||||
DataOutputStream dout = new DataOutputStream(fout);
|
||||
|
||||
// create a few frames and write them to the output stream
|
||||
dout.writeUTF("This is a test.");
|
||||
dout.writeUTF("This is only a test.");
|
||||
dout.writeUTF("If this were not a test, there would be " +
|
||||
"meaningful data in this frame and someone " +
|
||||
"would probably be enjoying themselves.");
|
||||
fout.writeFrameAndReset(out);
|
||||
|
||||
dout.writeUTF("Now is the time for all good men to come to the " +
|
||||
"aid of their country.");
|
||||
dout.writeUTF("Every good boy deserves fudge.");
|
||||
dout.writeUTF("The quick brown fox jumped over the lazy cow.");
|
||||
fout.writeFrameAndReset(out);
|
||||
|
||||
dout.writeUTF("Third time is the charm.");
|
||||
fout.writeFrameAndReset(out);
|
||||
}
|
||||
|
||||
public static void readFrames (InputStream in)
|
||||
throws IOException
|
||||
{
|
||||
FramedInputStream fin = new FramedInputStream();
|
||||
DataInputStream din = new DataInputStream(fin);
|
||||
|
||||
// read the first frame
|
||||
fin.readFrame(in);
|
||||
System.out.println(din.readUTF());
|
||||
System.out.println(din.readUTF());
|
||||
System.out.println(din.readUTF());
|
||||
System.out.println("This should be -1: " + fin.read());
|
||||
|
||||
// read the second frame
|
||||
fin.readFrame(in);
|
||||
System.out.println(din.readUTF());
|
||||
System.out.println(din.readUTF());
|
||||
System.out.println(din.readUTF());
|
||||
System.out.println("This should be -1: " + fin.read());
|
||||
|
||||
// read the third frame
|
||||
fin.readFrame(in);
|
||||
System.out.println(din.readUTF());
|
||||
System.out.println("This should be -1: " + fin.read());
|
||||
}
|
||||
|
||||
public static void main (String[] args)
|
||||
{
|
||||
try {
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
writeFrames(bout);
|
||||
|
||||
byte[] data = bout.toByteArray();
|
||||
ByteArrayInputStream bin = new ByteArrayInputStream(data);
|
||||
readFrames(bin);
|
||||
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user