Much work on generalizing the notion of message "transport" and
allowing the use of annotations to customize transport for DObject fields and service/receiver methods. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5099 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2008 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.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An annotation indicating the type of transport desired for a distributed object
|
||||||
|
* class, field, or method.
|
||||||
|
*/
|
||||||
|
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.TYPE })
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface TransportHint
|
||||||
|
{
|
||||||
|
/** The type of transport to use. */
|
||||||
|
Transport.Type type () default Transport.Type.RELIABLE_ORDERED;
|
||||||
|
|
||||||
|
/** For ordered transport types, the channel to use. */
|
||||||
|
int channel () default 0;
|
||||||
|
}
|
||||||
@@ -61,6 +61,7 @@ import com.threerings.presents.net.DownstreamMessage;
|
|||||||
import com.threerings.presents.net.LogoffRequest;
|
import com.threerings.presents.net.LogoffRequest;
|
||||||
import com.threerings.presents.net.PingRequest;
|
import com.threerings.presents.net.PingRequest;
|
||||||
import com.threerings.presents.net.PongResponse;
|
import com.threerings.presents.net.PongResponse;
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
import com.threerings.presents.net.UpstreamMessage;
|
import com.threerings.presents.net.UpstreamMessage;
|
||||||
import com.threerings.presents.util.DatagramSequencer;
|
import com.threerings.presents.util.DatagramSequencer;
|
||||||
|
|
||||||
@@ -163,7 +164,7 @@ public class BlockingCommunicator extends Communicator
|
|||||||
public void postMessage (UpstreamMessage msg)
|
public void postMessage (UpstreamMessage msg)
|
||||||
{
|
{
|
||||||
// post as datagram if hinted and possible
|
// post as datagram if hinted and possible
|
||||||
if (msg.datagram && _datagramWriter != null) {
|
if (!msg.getTransport().isReliable() && _datagramWriter != null) {
|
||||||
_dataq.append(msg);
|
_dataq.append(msg);
|
||||||
} else {
|
} else {
|
||||||
_msgq.append(msg);
|
_msgq.append(msg);
|
||||||
@@ -486,6 +487,7 @@ public class BlockingCommunicator extends Communicator
|
|||||||
if (_datagramChannel.read(_buf) <= 0) {
|
if (_datagramChannel.read(_buf) <= 0) {
|
||||||
throw new IOException("No datagram available to read.");
|
throw new IOException("No datagram available to read.");
|
||||||
}
|
}
|
||||||
|
_buf.flip();
|
||||||
|
|
||||||
// decode through the sequencer
|
// decode through the sequencer
|
||||||
try {
|
try {
|
||||||
@@ -493,7 +495,6 @@ public class BlockingCommunicator extends Communicator
|
|||||||
if (msg == null) {
|
if (msg == null) {
|
||||||
return null; // received out of order
|
return null; // received out of order
|
||||||
}
|
}
|
||||||
msg.datagram = true;
|
|
||||||
if (debugLogMessages()) {
|
if (debugLogMessages()) {
|
||||||
Log.info("DATAGRAM " + msg);
|
Log.info("DATAGRAM " + msg);
|
||||||
}
|
}
|
||||||
@@ -802,7 +803,7 @@ public class BlockingCommunicator extends Communicator
|
|||||||
_datagramChannel.connect(new InetSocketAddress(_client.getHostname(), port));
|
_datagramChannel.connect(new InetSocketAddress(_client.getHostname(), port));
|
||||||
for (int ii = 0; ii < DATAGRAM_ATTEMPTS_PER_PORT; ii++) {
|
for (int ii = 0; ii < DATAGRAM_ATTEMPTS_PER_PORT; ii++) {
|
||||||
// send a ping datagram
|
// send a ping datagram
|
||||||
sendDatagram(new PingRequest());
|
sendDatagram(new PingRequest(Transport.UNRELIABLE_UNORDERED));
|
||||||
|
|
||||||
// wait for a response
|
// wait for a response
|
||||||
int resp = _selector.select(DATAGRAM_RESPONSE_WAIT);
|
int resp = _selector.select(DATAGRAM_RESPONSE_WAIT);
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ import com.threerings.presents.dobj.MessageEvent;
|
|||||||
import com.threerings.presents.dobj.ObjectAccessException;
|
import com.threerings.presents.dobj.ObjectAccessException;
|
||||||
import com.threerings.presents.dobj.Subscriber;
|
import com.threerings.presents.dobj.Subscriber;
|
||||||
|
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the client side management of the invocation services.
|
* Handles the client side management of the invocation services.
|
||||||
*/
|
*/
|
||||||
@@ -195,6 +197,16 @@ public class InvocationDirector
|
|||||||
* invocation oid.
|
* invocation oid.
|
||||||
*/
|
*/
|
||||||
public void sendRequest (int invOid, int invCode, int methodId, Object[] args)
|
public void sendRequest (int invOid, int invCode, int methodId, Object[] args)
|
||||||
|
{
|
||||||
|
sendRequest(invOid, invCode, methodId, args, Transport.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the specified invocation request be packaged up and sent to the supplied
|
||||||
|
* invocation oid.
|
||||||
|
*/
|
||||||
|
public void sendRequest (
|
||||||
|
int invOid, int invCode, int methodId, Object[] args, Transport transport)
|
||||||
{
|
{
|
||||||
if (_clobj == null) {
|
if (_clobj == null) {
|
||||||
Log.warning("Dropping invocation request on shutdown director [code=" + invCode +
|
Log.warning("Dropping invocation request on shutdown director [code=" + invCode +
|
||||||
@@ -218,7 +230,8 @@ public class InvocationDirector
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create an invocation request event
|
// create an invocation request event
|
||||||
InvocationRequestEvent event = new InvocationRequestEvent(invOid, invCode, methodId, args);
|
InvocationRequestEvent event =
|
||||||
|
new InvocationRequestEvent(invOid, invCode, methodId, args, transport);
|
||||||
|
|
||||||
// because invocation directors are used on the server, we set the source oid here so that
|
// because invocation directors are used on the server, we set the source oid here so that
|
||||||
// invocation requests are properly attributed to the right client object when created by
|
// invocation requests are properly attributed to the right client object when created by
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ import com.threerings.presents.client.InvocationService;
|
|||||||
import com.threerings.presents.dobj.DObjectManager;
|
import com.threerings.presents.dobj.DObjectManager;
|
||||||
import com.threerings.presents.dobj.InvocationResponseEvent;
|
import com.threerings.presents.dobj.InvocationResponseEvent;
|
||||||
|
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a base from which all invocation service marshallers extend. Handles functionality
|
* Provides a base from which all invocation service marshallers extend. Handles functionality
|
||||||
* common to all marshallers.
|
* common to all marshallers.
|
||||||
@@ -69,6 +71,10 @@ public class InvocationMarshaller
|
|||||||
* valid on the server. */
|
* valid on the server. */
|
||||||
public transient DObjectManager omgr;
|
public transient DObjectManager omgr;
|
||||||
|
|
||||||
|
/** The transport mode through which the request was received. This is only valid on the
|
||||||
|
* server. */
|
||||||
|
public transient Transport transport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set an identifier for the invocation that this listener is used for, so we can report it
|
* Set an identifier for the invocation that this listener is used for, so we can report it
|
||||||
* if we are never responded-to.
|
* if we are never responded-to.
|
||||||
@@ -92,7 +98,7 @@ public class InvocationMarshaller
|
|||||||
{
|
{
|
||||||
_invId = null;
|
_invId = null;
|
||||||
omgr.postEvent(new InvocationResponseEvent(
|
omgr.postEvent(new InvocationResponseEvent(
|
||||||
callerOid, requestId, REQUEST_FAILED_RSPID, new Object[] { cause }));
|
callerOid, requestId, REQUEST_FAILED_RSPID, new Object[] { cause }, transport));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -130,7 +136,7 @@ public class InvocationMarshaller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** On the server, the id of the invocation method. */
|
/** On the server, the id of the invocation method. */
|
||||||
protected transient String _invId;
|
protected transient String _invId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -146,8 +152,8 @@ public class InvocationMarshaller
|
|||||||
public void requestProcessed ()
|
public void requestProcessed ()
|
||||||
{
|
{
|
||||||
_invId = null;
|
_invId = null;
|
||||||
omgr.postEvent(
|
omgr.postEvent(new InvocationResponseEvent(
|
||||||
new InvocationResponseEvent(callerOid, requestId, REQUEST_PROCESSED, null));
|
callerOid, requestId, REQUEST_PROCESSED, null, transport));
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
@@ -178,7 +184,7 @@ public class InvocationMarshaller
|
|||||||
{
|
{
|
||||||
_invId = null;
|
_invId = null;
|
||||||
omgr.postEvent(new InvocationResponseEvent(
|
omgr.postEvent(new InvocationResponseEvent(
|
||||||
callerOid, requestId, REQUEST_PROCESSED, new Object[] { result }));
|
callerOid, requestId, REQUEST_PROCESSED, new Object[] { result }, transport));
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
@@ -248,7 +254,16 @@ public class InvocationMarshaller
|
|||||||
*/
|
*/
|
||||||
protected void sendRequest (Client client, int methodId, Object[] args)
|
protected void sendRequest (Client client, int methodId, Object[] args)
|
||||||
{
|
{
|
||||||
client.getInvocationDirector().sendRequest(_invOid, _invCode, methodId, args);
|
sendRequest(client, methodId, args, Transport.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by generated invocation marshaller code; packages up and sends the specified
|
||||||
|
* invocation service request.
|
||||||
|
*/
|
||||||
|
protected void sendRequest (Client client, int methodId, Object[] args, Transport transport)
|
||||||
|
{
|
||||||
|
client.getInvocationDirector().sendRequest(_invOid, _invCode, methodId, args, transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The oid of the invocation object, where invocation service requests are sent. */
|
/** The oid of the invocation object, where invocation service requests are sent. */
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ import java.util.HashMap;
|
|||||||
|
|
||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An attribute changed event is dispatched when a single attribute of a distributed object has
|
* An attribute changed event is dispatched when a single attribute of a distributed object has
|
||||||
* changed. It can also be constructed to request an attribute change on an object and posted to
|
* changed. It can also be constructed to request an attribute change on an object and posted to
|
||||||
@@ -162,7 +164,24 @@ public class AttributeChangedEvent extends NamedEvent
|
|||||||
*/
|
*/
|
||||||
protected AttributeChangedEvent (int targetOid, String name, Object value, Object oldValue)
|
protected AttributeChangedEvent (int targetOid, String name, Object value, Object oldValue)
|
||||||
{
|
{
|
||||||
super(targetOid, name);
|
this(targetOid, name, value, oldValue, Transport.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new attribute changed event on the specified target object with the supplied
|
||||||
|
* attribute name and value. <em>Do not construct these objects by hand.</em> Use {@link
|
||||||
|
* DObject#changeAttribute} instead.
|
||||||
|
*
|
||||||
|
* @param targetOid the object id of the object whose attribute has changed.
|
||||||
|
* @param name the name of the attribute (data member) that has changed.
|
||||||
|
* @param value the new value of the attribute (in the case of primitive types, the
|
||||||
|
* reflection-defined object-alternative is used).
|
||||||
|
* @param transport a hint as to the type of transport desired for the event.
|
||||||
|
*/
|
||||||
|
protected AttributeChangedEvent (
|
||||||
|
int targetOid, String name, Object value, Object oldValue, Transport transport)
|
||||||
|
{
|
||||||
|
super(targetOid, name, transport);
|
||||||
_value = value;
|
_value = value;
|
||||||
_oldValue = oldValue;
|
_oldValue = oldValue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import java.util.List;
|
|||||||
|
|
||||||
import com.threerings.util.StreamableArrayList;
|
import com.threerings.util.StreamableArrayList;
|
||||||
|
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to manage and submit groups of events on a collection of
|
* Used to manage and submit groups of events on a collection of
|
||||||
* distributed objects in a single transaction.
|
* distributed objects in a single transaction.
|
||||||
@@ -91,13 +93,18 @@ public class CompoundEvent extends DEvent
|
|||||||
|
|
||||||
// then post this event onto the queue (but only if we actually
|
// then post this event onto the queue (but only if we actually
|
||||||
// accumulated some events)
|
// accumulated some events)
|
||||||
switch (_events.size()) {
|
int size = _events.size();
|
||||||
|
switch (size) {
|
||||||
case 0: // nothing doing
|
case 0: // nothing doing
|
||||||
break;
|
break;
|
||||||
case 1: // no point in being compound
|
case 1: // no point in being compound
|
||||||
_omgr.postEvent(_events.get(0));
|
_omgr.postEvent(_events.get(0));
|
||||||
break;
|
break;
|
||||||
default: // now we're talking
|
default: // now we're talking
|
||||||
|
_transport = _events.get(0).getTransport();
|
||||||
|
for (int ii = 1; ii < size; ii++) {
|
||||||
|
_transport = _events.get(ii).getTransport().combine(_transport);
|
||||||
|
}
|
||||||
_omgr.postEvent(this);
|
_omgr.postEvent(this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -139,6 +146,15 @@ public class CompoundEvent extends DEvent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override // from DEvent
|
||||||
|
public void setTransport (Transport transport)
|
||||||
|
{
|
||||||
|
super.setTransport(transport);
|
||||||
|
for (int ii = 0, nn = _events.size(); ii < nn; ii++) {
|
||||||
|
_events.get(ii).setTransport(transport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override // from DEvent
|
@Override // from DEvent
|
||||||
public boolean applyToObject (DObject target)
|
public boolean applyToObject (DObject target)
|
||||||
throws ObjectAccessException
|
throws ObjectAccessException
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ package com.threerings.presents.dobj;
|
|||||||
|
|
||||||
import com.threerings.io.Streamable;
|
import com.threerings.io.Streamable;
|
||||||
|
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A distributed object event is dispatched whenever any modification is made to a distributed
|
* A distributed object event is dispatched whenever any modification is made to a distributed
|
||||||
* object. It can also be dispatched purely for notification purposes, without making any
|
* object. It can also be dispatched purely for notification purposes, without making any
|
||||||
@@ -45,8 +47,19 @@ public abstract class DEvent implements Streamable
|
|||||||
* Constructs a new distributed object event that pertains to the specified distributed object.
|
* Constructs a new distributed object event that pertains to the specified distributed object.
|
||||||
*/
|
*/
|
||||||
public DEvent (int targetOid)
|
public DEvent (int targetOid)
|
||||||
|
{
|
||||||
|
this(targetOid, Transport.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new distributed object event that pertains to the specified distributed object.
|
||||||
|
*
|
||||||
|
* @param transport a hint as to the type of transport desired for the event.
|
||||||
|
*/
|
||||||
|
public DEvent (int targetOid, Transport transport)
|
||||||
{
|
{
|
||||||
_toid = targetOid;
|
_toid = targetOid;
|
||||||
|
_transport = transport;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -121,6 +134,24 @@ public abstract class DEvent implements Streamable
|
|||||||
_soid = sourceOid;
|
_soid = sourceOid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the transport parameters. For events received over the network, these indicate the
|
||||||
|
* mode of transport over which the event was received. When an event is sent over the
|
||||||
|
* network, these act as a hint as to the type of transport desired.
|
||||||
|
*/
|
||||||
|
public void setTransport (Transport transport)
|
||||||
|
{
|
||||||
|
_transport = transport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the transport parameters.
|
||||||
|
*/
|
||||||
|
public Transport getTransport ()
|
||||||
|
{
|
||||||
|
return _transport;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Events with associated listener interfaces should implement this function and notify the
|
* Events with associated listener interfaces should implement this function and notify the
|
||||||
* supplied listener if it implements their event listening interface. For example, the {@link
|
* supplied listener if it implements their event listening interface. For example, the {@link
|
||||||
@@ -152,6 +183,9 @@ public abstract class DEvent implements Streamable
|
|||||||
{
|
{
|
||||||
buf.append("targetOid=").append(_toid);
|
buf.append("targetOid=").append(_toid);
|
||||||
buf.append(", sourceOid=").append(_soid);
|
buf.append(", sourceOid=").append(_soid);
|
||||||
|
if (_transport != Transport.DEFAULT) {
|
||||||
|
buf.append(", transport=").append(_transport);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The oid of the object that is the target of this event. */
|
/** The oid of the object that is the target of this event. */
|
||||||
@@ -160,6 +194,9 @@ public abstract class DEvent implements Streamable
|
|||||||
/** The oid of the client that generated this event. */
|
/** The oid of the client that generated this event. */
|
||||||
protected transient int _soid = -1;
|
protected transient int _soid = -1;
|
||||||
|
|
||||||
|
/** The transport parameters. */
|
||||||
|
protected transient Transport _transport = Transport.DEFAULT;
|
||||||
|
|
||||||
/** Used to differentiate between null meaning we haven't initialized our old value and null
|
/** Used to differentiate between null meaning we haven't initialized our old value and null
|
||||||
* being the actual old value. */
|
* being the actual old value. */
|
||||||
protected static final Object UNSET_OLD_VALUE = new Object();
|
protected static final Object UNSET_OLD_VALUE = new Object();
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import com.threerings.io.Streamable;
|
|||||||
import com.threerings.util.TrackedObject;
|
import com.threerings.util.TrackedObject;
|
||||||
|
|
||||||
import com.threerings.presents.Log;
|
import com.threerings.presents.Log;
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The distributed object forms the foundation of the Presents system. All information shared among
|
* The distributed object forms the foundation of the Presents system. All information shared among
|
||||||
@@ -250,7 +251,7 @@ public class DObject
|
|||||||
public void setAccessController (AccessController controller)
|
public void setAccessController (AccessController controller)
|
||||||
{
|
{
|
||||||
_controller = controller;
|
_controller = controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a reference to the access controller in use by this object or null if none has been
|
* Returns a reference to the access controller in use by this object or null if none has been
|
||||||
@@ -524,11 +525,21 @@ public class DObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Posts a message event on this distrubuted object.
|
* Posts a message event on this distributed object.
|
||||||
*/
|
*/
|
||||||
public void postMessage (String name, Object... args)
|
public void postMessage (String name, Object... args)
|
||||||
{
|
{
|
||||||
postEvent(new MessageEvent(_oid, name, args));
|
postMessage(Transport.DEFAULT, name, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Posts a message event on this distributed object.
|
||||||
|
*
|
||||||
|
* @param transport a hint as to the type of transport desired for the message.
|
||||||
|
*/
|
||||||
|
public void postMessage (Transport transport, String name, Object... args)
|
||||||
|
{
|
||||||
|
postEvent(new MessageEvent(_oid, name, args, transport));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -683,7 +694,7 @@ public class DObject
|
|||||||
_tevent.commit();
|
_tevent.commit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this object is in the middle of a transaction or false if it is not.
|
* Returns true if this object is in the middle of a transaction or false if it is not.
|
||||||
@@ -714,7 +725,7 @@ public class DObject
|
|||||||
} else {
|
} else {
|
||||||
_tevent.cancel();
|
_tevent.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes this object from participation in any transaction in which it might be taking part.
|
* Removes this object from participation in any transaction in which it might be taking part.
|
||||||
@@ -736,19 +747,37 @@ public class DObject
|
|||||||
* Called by derived instances when an attribute setter method was called.
|
* Called by derived instances when an attribute setter method was called.
|
||||||
*/
|
*/
|
||||||
protected void requestAttributeChange (String name, Object value, Object oldValue)
|
protected void requestAttributeChange (String name, Object value, Object oldValue)
|
||||||
|
{
|
||||||
|
requestAttributeChange(name, value, oldValue, Transport.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by derived instances when an attribute setter method was called.
|
||||||
|
*/
|
||||||
|
protected void requestAttributeChange (
|
||||||
|
String name, Object value, Object oldValue, Transport transport)
|
||||||
{
|
{
|
||||||
// dispatch an attribute changed event
|
// dispatch an attribute changed event
|
||||||
postEvent(new AttributeChangedEvent(_oid, name, value, oldValue));
|
postEvent(new AttributeChangedEvent(_oid, name, value, oldValue, transport));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by derived instances when an element updater method was called.
|
* Called by derived instances when an element updater method was called.
|
||||||
*/
|
*/
|
||||||
protected void requestElementUpdate (String name, int index, Object value, Object oldValue)
|
protected void requestElementUpdate (String name, int index, Object value, Object oldValue)
|
||||||
|
{
|
||||||
|
requestElementUpdate(name, index, value, oldValue, Transport.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by derived instances when an element updater method was called.
|
||||||
|
*/
|
||||||
|
protected void requestElementUpdate (
|
||||||
|
String name, int index, Object value, Object oldValue, Transport transport)
|
||||||
{
|
{
|
||||||
// dispatch an attribute changed event
|
// dispatch an attribute changed event
|
||||||
postEvent(new ElementUpdatedEvent(
|
postEvent(new ElementUpdatedEvent(
|
||||||
_oid, name, value, oldValue, index));
|
_oid, name, value, oldValue, index, transport));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -810,6 +839,15 @@ public class DObject
|
|||||||
* Calls by derived instances when a set updater method was called.
|
* Calls by derived instances when a set updater method was called.
|
||||||
*/
|
*/
|
||||||
protected <T extends DSet.Entry> void requestEntryUpdate (String name, DSet<T> set, T entry)
|
protected <T extends DSet.Entry> void requestEntryUpdate (String name, DSet<T> set, T entry)
|
||||||
|
{
|
||||||
|
requestEntryUpdate(name, set, entry, Transport.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls by derived instances when a set updater method was called.
|
||||||
|
*/
|
||||||
|
protected <T extends DSet.Entry> void requestEntryUpdate (
|
||||||
|
String name, DSet<T> set, T entry, Transport transport)
|
||||||
{
|
{
|
||||||
// if we're on the authoritative server, we update the set immediately
|
// if we're on the authoritative server, we update the set immediately
|
||||||
T oldEntry = null;
|
T oldEntry = null;
|
||||||
@@ -820,7 +858,7 @@ public class DObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// dispatch an entry updated event
|
// dispatch an entry updated event
|
||||||
postEvent(new EntryUpdatedEvent<T>(_oid, name, entry, oldEntry));
|
postEvent(new EntryUpdatedEvent<T>(_oid, name, entry, oldEntry, transport));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import java.lang.reflect.Field;
|
|||||||
|
|
||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An element updated event is dispatched when an element of an array field in a distributed object
|
* An element updated event is dispatched when an element of an array field in a distributed object
|
||||||
* is updated. It can also be constructed to request the update of an entry and posted to the
|
* is updated. It can also be constructed to request the update of an entry and posted to the
|
||||||
@@ -49,7 +51,26 @@ public class ElementUpdatedEvent extends NamedEvent
|
|||||||
*/
|
*/
|
||||||
public ElementUpdatedEvent (int targetOid, String name, Object value, Object ovalue, int index)
|
public ElementUpdatedEvent (int targetOid, String name, Object value, Object ovalue, int index)
|
||||||
{
|
{
|
||||||
super(targetOid, name);
|
this(targetOid, name, value, ovalue, index, Transport.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new element updated event on the specified target object with the supplied
|
||||||
|
* attribute name, element and index.
|
||||||
|
*
|
||||||
|
* @param targetOid the object id of the object whose attribute has changed.
|
||||||
|
* @param name the name of the attribute (data member) for which an element has changed.
|
||||||
|
* @param value the new value of the element (in the case of primitive types, the
|
||||||
|
* reflection-defined object-alternative is used).
|
||||||
|
* @param oldValue the previous value of the element (in the case of primitive types, the
|
||||||
|
* reflection-defined object-alternative is used).
|
||||||
|
* @param index the index in the array of the updated element.
|
||||||
|
* @param transport a hint as to the type of transport desired for the event.
|
||||||
|
*/
|
||||||
|
public ElementUpdatedEvent (
|
||||||
|
int targetOid, String name, Object value, Object ovalue, int index, Transport transport)
|
||||||
|
{
|
||||||
|
super(targetOid, name, transport);
|
||||||
_value = value;
|
_value = value;
|
||||||
_oldValue = ovalue;
|
_oldValue = ovalue;
|
||||||
_index = index;
|
_index = index;
|
||||||
|
|||||||
@@ -95,7 +95,8 @@ public class EntryAddedEvent<T extends DSet.Entry> extends NamedEvent
|
|||||||
protected void notifyListener (Object listener)
|
protected void notifyListener (Object listener)
|
||||||
{
|
{
|
||||||
if (listener instanceof SetListener) {
|
if (listener instanceof SetListener) {
|
||||||
((SetListener)listener).entryAdded(this);
|
@SuppressWarnings("unchecked") SetListener<T> setlist = (SetListener<T>)listener;
|
||||||
|
setlist.entryAdded(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -99,7 +99,8 @@ public class EntryRemovedEvent<T extends DSet.Entry> extends NamedEvent
|
|||||||
protected void notifyListener (Object listener)
|
protected void notifyListener (Object listener)
|
||||||
{
|
{
|
||||||
if (listener instanceof SetListener) {
|
if (listener instanceof SetListener) {
|
||||||
((SetListener)listener).entryRemoved(this);
|
@SuppressWarnings("unchecked") SetListener<T> setlist = (SetListener<T>)listener;
|
||||||
|
setlist.entryRemoved(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import com.samskivert.util.StringUtil;
|
|||||||
|
|
||||||
import com.threerings.presents.Log;
|
import com.threerings.presents.Log;
|
||||||
|
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An entry updated event is dispatched when an entry of a {@link DSet} is updated. It can also be
|
* An entry updated event is dispatched when an entry of a {@link DSet} is updated. It can also be
|
||||||
* constructed to request the update of an entry and posted to the dobjmgr.
|
* constructed to request the update of an entry and posted to the dobjmgr.
|
||||||
@@ -44,7 +46,22 @@ public class EntryUpdatedEvent<T extends DSet.Entry> extends NamedEvent
|
|||||||
*/
|
*/
|
||||||
public EntryUpdatedEvent (int targetOid, String name, T entry, T oldEntry)
|
public EntryUpdatedEvent (int targetOid, String name, T entry, T oldEntry)
|
||||||
{
|
{
|
||||||
super(targetOid, name);
|
this(targetOid, name, entry, oldEntry, Transport.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new entry updated event on the specified target object for the specified set
|
||||||
|
* name and with the supplied updated entry.
|
||||||
|
*
|
||||||
|
* @param targetOid the object id of the object to whose set we will add an entry.
|
||||||
|
* @param name the name of the attribute in which to update the specified entry.
|
||||||
|
* @param entry the entry to update.
|
||||||
|
* @param oldEntry the previous value of the entry.
|
||||||
|
* @param transport a hint as to the type of transport desired for the event.
|
||||||
|
*/
|
||||||
|
public EntryUpdatedEvent (int targetOid, String name, T entry, T oldEntry, Transport transport)
|
||||||
|
{
|
||||||
|
super(targetOid, name, transport);
|
||||||
_entry = entry;
|
_entry = entry;
|
||||||
_oldEntry = oldEntry;
|
_oldEntry = oldEntry;
|
||||||
}
|
}
|
||||||
@@ -101,7 +118,8 @@ public class EntryUpdatedEvent<T extends DSet.Entry> extends NamedEvent
|
|||||||
protected void notifyListener (Object listener)
|
protected void notifyListener (Object listener)
|
||||||
{
|
{
|
||||||
if (listener instanceof SetListener) {
|
if (listener instanceof SetListener) {
|
||||||
((SetListener)listener).entryUpdated(this);
|
@SuppressWarnings("unchecked") SetListener<T> setlist = (SetListener<T>)listener;
|
||||||
|
setlist.entryUpdated(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ package com.threerings.presents.dobj;
|
|||||||
|
|
||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to dispatch an invocation notification from the server to a
|
* Used to dispatch an invocation notification from the server to a
|
||||||
* client.
|
* client.
|
||||||
@@ -47,7 +49,27 @@ public class InvocationNotificationEvent extends DEvent
|
|||||||
public InvocationNotificationEvent (
|
public InvocationNotificationEvent (
|
||||||
int targetOid, short receiverId, int methodId, Object[] args)
|
int targetOid, short receiverId, int methodId, Object[] args)
|
||||||
{
|
{
|
||||||
super(targetOid);
|
this(targetOid, receiverId, methodId, args, Transport.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new invocation notification event on the specified
|
||||||
|
* target object with the supplied receiver id, method id and
|
||||||
|
* arguments.
|
||||||
|
*
|
||||||
|
* @param targetOid the object id of the object on which the event is
|
||||||
|
* to be dispatched.
|
||||||
|
* @param receiverId identifies the receiver to which this notification
|
||||||
|
* is being dispatched.
|
||||||
|
* @param methodId the id of the method to be invoked.
|
||||||
|
* @param args the arguments for the method. This array should contain
|
||||||
|
* only values of valid distributed object types.
|
||||||
|
* @param transport a hint as to the type of transport desired for the event.
|
||||||
|
*/
|
||||||
|
public InvocationNotificationEvent (
|
||||||
|
int targetOid, short receiverId, int methodId, Object[] args, Transport transport)
|
||||||
|
{
|
||||||
|
super(targetOid, transport);
|
||||||
_receiverId = receiverId;
|
_receiverId = receiverId;
|
||||||
_methodId = (byte)methodId;
|
_methodId = (byte)methodId;
|
||||||
_args = args;
|
_args = args;
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ package com.threerings.presents.dobj;
|
|||||||
|
|
||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to dispatch an invocation request from the client to the server.
|
* Used to dispatch an invocation request from the client to the server.
|
||||||
*
|
*
|
||||||
@@ -44,7 +46,25 @@ public class InvocationRequestEvent extends DEvent
|
|||||||
public InvocationRequestEvent (
|
public InvocationRequestEvent (
|
||||||
int targetOid, int invCode, int methodId, Object[] args)
|
int targetOid, int invCode, int methodId, Object[] args)
|
||||||
{
|
{
|
||||||
super(targetOid);
|
this(targetOid, invCode, methodId, args, Transport.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new invocation request event on the specified target
|
||||||
|
* object with the supplied code, method and arguments.
|
||||||
|
*
|
||||||
|
* @param targetOid the object id of the object on which the event is
|
||||||
|
* to be dispatched.
|
||||||
|
* @param invCode the invocation provider identification code.
|
||||||
|
* @param methodId the id of the method to be invoked.
|
||||||
|
* @param args the arguments for the method. This array should contain
|
||||||
|
* only values of valid distributed object types.
|
||||||
|
* @param transport a hint as to the type of transport desired for the event.
|
||||||
|
*/
|
||||||
|
public InvocationRequestEvent (
|
||||||
|
int targetOid, int invCode, int methodId, Object[] args, Transport transport)
|
||||||
|
{
|
||||||
|
super(targetOid, transport);
|
||||||
_invCode = invCode;
|
_invCode = invCode;
|
||||||
_methodId = (byte)methodId;
|
_methodId = (byte)methodId;
|
||||||
_args = args;
|
_args = args;
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ package com.threerings.presents.dobj;
|
|||||||
|
|
||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to dispatch an invocation response from the server to the client.
|
* Used to dispatch an invocation response from the server to the client.
|
||||||
*
|
*
|
||||||
@@ -44,7 +46,25 @@ public class InvocationResponseEvent extends DEvent
|
|||||||
public InvocationResponseEvent (
|
public InvocationResponseEvent (
|
||||||
int targetOid, int requestId, int methodId, Object[] args)
|
int targetOid, int requestId, int methodId, Object[] args)
|
||||||
{
|
{
|
||||||
super(targetOid);
|
this(targetOid, requestId, methodId, args, Transport.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new invocation response event on the specified target
|
||||||
|
* object with the supplied code, method and arguments.
|
||||||
|
*
|
||||||
|
* @param targetOid the object id of the object on which the event is
|
||||||
|
* to be dispatched.
|
||||||
|
* @param requestId the id of the request to which we are responding.
|
||||||
|
* @param methodId the method to be invoked.
|
||||||
|
* @param args the arguments for the method. This array should contain
|
||||||
|
* only values of valid distributed object types.
|
||||||
|
* @param transport a hint as to the type of transport desired for the event.
|
||||||
|
*/
|
||||||
|
public InvocationResponseEvent (
|
||||||
|
int targetOid, int requestId, int methodId, Object[] args, Transport transport)
|
||||||
|
{
|
||||||
|
super(targetOid, transport);
|
||||||
_requestId = (short)requestId;
|
_requestId = (short)requestId;
|
||||||
_methodId = (byte)methodId;
|
_methodId = (byte)methodId;
|
||||||
_args = args;
|
_args = args;
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ package com.threerings.presents.dobj;
|
|||||||
|
|
||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A message event is used to dispatch a message to all subscribers of a
|
* A message event is used to dispatch a message to all subscribers of a
|
||||||
* distributed object without actually changing any of the fields of the
|
* distributed object without actually changing any of the fields of the
|
||||||
@@ -46,7 +48,23 @@ public class MessageEvent extends NamedEvent
|
|||||||
*/
|
*/
|
||||||
public MessageEvent (int targetOid, String name, Object[] args)
|
public MessageEvent (int targetOid, String name, Object[] args)
|
||||||
{
|
{
|
||||||
super(targetOid, name);
|
this(targetOid, name, args, Transport.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new message event on the specified target object with
|
||||||
|
* the supplied name and arguments.
|
||||||
|
*
|
||||||
|
* @param targetOid the object id of the object whose attribute has
|
||||||
|
* changed.
|
||||||
|
* @param name the name of the message event.
|
||||||
|
* @param args the arguments for this message. This array should
|
||||||
|
* contain only values of valid distributed object types.
|
||||||
|
* @param transport a hint as to the type of transport desired for the event.
|
||||||
|
*/
|
||||||
|
public MessageEvent (int targetOid, String name, Object[] args, Transport transport)
|
||||||
|
{
|
||||||
|
super(targetOid, name, transport);
|
||||||
_args = args;
|
_args = args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
package com.threerings.presents.dobj;
|
package com.threerings.presents.dobj;
|
||||||
|
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A common parent class for all events that are associated with a name
|
* A common parent class for all events that are associated with a name
|
||||||
* (in some cases a field name, in other cases just an identifying name).
|
* (in some cases a field name, in other cases just an identifying name).
|
||||||
@@ -36,7 +38,20 @@ public abstract class NamedEvent extends DEvent
|
|||||||
*/
|
*/
|
||||||
public NamedEvent (int targetOid, String name)
|
public NamedEvent (int targetOid, String name)
|
||||||
{
|
{
|
||||||
super(targetOid);
|
this(targetOid, name, Transport.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new named event for the specified target object with
|
||||||
|
* the supplied attribute name.
|
||||||
|
*
|
||||||
|
* @param targetOid the object id of the object in question.
|
||||||
|
* @param name the name associated with this event.
|
||||||
|
* @param transport a hint as to the type of transport desired for the event.
|
||||||
|
*/
|
||||||
|
public NamedEvent (int targetOid, String name, Transport transport)
|
||||||
|
{
|
||||||
|
super(targetOid, transport);
|
||||||
_name = name;
|
_name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,14 +21,12 @@
|
|||||||
|
|
||||||
package com.threerings.presents.net;
|
package com.threerings.presents.net;
|
||||||
|
|
||||||
import com.threerings.io.SimpleStreamableObject;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class encapsulates a message in the distributed object protocol
|
* This class encapsulates a message in the distributed object protocol
|
||||||
* that flows from the server to the client. Downstream messages include
|
* that flows from the server to the client. Downstream messages include
|
||||||
* object subscription, event forwarding and session management.
|
* object subscription, event forwarding and session management.
|
||||||
*/
|
*/
|
||||||
public abstract class DownstreamMessage extends SimpleStreamableObject
|
public abstract class DownstreamMessage extends Message
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The message id of the upstream message with which this downstream
|
* The message id of the upstream message with which this downstream
|
||||||
@@ -37,12 +35,6 @@ public abstract class DownstreamMessage extends SimpleStreamableObject
|
|||||||
*/
|
*/
|
||||||
public short messageId = -1;
|
public short messageId = -1;
|
||||||
|
|
||||||
/**
|
|
||||||
* When sending, this acts as a hint that the message may be transmitted as a datagram.
|
|
||||||
* When receiving, it indicates that the message was received as a datagram.
|
|
||||||
*/
|
|
||||||
public transient boolean datagram;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a string representation of this instance.
|
* Generates a string representation of this instance.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -46,6 +46,19 @@ public class EventNotification extends DownstreamMessage
|
|||||||
return _event;
|
return _event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override // documentation inherited
|
||||||
|
public void setTransport (Transport transport)
|
||||||
|
{
|
||||||
|
// the event handles the transport
|
||||||
|
_event.setTransport(transport);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override // documentation inherited
|
||||||
|
public Transport getTransport ()
|
||||||
|
{
|
||||||
|
return _event.getTransport();
|
||||||
|
}
|
||||||
|
|
||||||
public String toString ()
|
public String toString ()
|
||||||
{
|
{
|
||||||
return "[type=EVT, evt=" + _event + "]";
|
return "[type=EVT, evt=" + _event + "]";
|
||||||
|
|||||||
@@ -49,6 +49,19 @@ public class ForwardEventRequest extends UpstreamMessage
|
|||||||
return _event;
|
return _event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override // documentation inherited
|
||||||
|
public void setTransport (Transport transport)
|
||||||
|
{
|
||||||
|
// the event handles the transport
|
||||||
|
_event.setTransport(transport);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override // documentation inherited
|
||||||
|
public Transport getTransport ()
|
||||||
|
{
|
||||||
|
return _event.getTransport();
|
||||||
|
}
|
||||||
|
|
||||||
public String toString ()
|
public String toString ()
|
||||||
{
|
{
|
||||||
return "[type=FWD, evt=" + _event + "]";
|
return "[type=FWD, evt=" + _event + "]";
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// $Id: DownstreamMessage.java 5090 2008-05-13 21:12:39Z andrzej $
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2007 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.net;
|
||||||
|
|
||||||
|
import com.threerings.io.SimpleStreamableObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The superclass of {@link UpstreamMessage} and {@link DownstreamMessage}.
|
||||||
|
*/
|
||||||
|
public abstract class Message extends SimpleStreamableObject
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Sets the message transport parameters. For messages received over the network, these
|
||||||
|
* describe the mode of transport over which the message was received. When sending messages,
|
||||||
|
* they act as a hint as to the type of transport desired. Calling this method may have no
|
||||||
|
* effect, depending on whether non-default modes of transport are supported for this message
|
||||||
|
* type.
|
||||||
|
*/
|
||||||
|
public void setTransport (Transport transport)
|
||||||
|
{
|
||||||
|
// no-op by default
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the message transport parameters.
|
||||||
|
*/
|
||||||
|
public Transport getTransport ()
|
||||||
|
{
|
||||||
|
return Transport.DEFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,6 +41,14 @@ public class PingRequest extends UpstreamMessage
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new ping request using the specified transport.
|
||||||
|
*/
|
||||||
|
public PingRequest (Transport transport)
|
||||||
|
{
|
||||||
|
_transport = transport;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a timestamp that was obtained when this packet was encoded
|
* Returns a timestamp that was obtained when this packet was encoded
|
||||||
* by the low-level networking code.
|
* by the low-level networking code.
|
||||||
@@ -85,9 +93,21 @@ public class PingRequest extends UpstreamMessage
|
|||||||
in.defaultReadObject();
|
in.defaultReadObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override // documentation inherited
|
||||||
|
public void setTransport (Transport transport)
|
||||||
|
{
|
||||||
|
_transport = transport;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override // documentation inherited
|
||||||
|
public Transport getTransport ()
|
||||||
|
{
|
||||||
|
return _transport;
|
||||||
|
}
|
||||||
|
|
||||||
public String toString ()
|
public String toString ()
|
||||||
{
|
{
|
||||||
return "[type=PING, msgid=" + messageId + "]";
|
return "[type=PING, msgid=" + messageId + ", transport=" + _transport + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A time stamp obtained when we serialize this object. */
|
/** A time stamp obtained when we serialize this object. */
|
||||||
@@ -97,4 +117,7 @@ public class PingRequest extends UpstreamMessage
|
|||||||
* is to get a timestamp as close as possible to when the packet was
|
* is to get a timestamp as close as possible to when the packet was
|
||||||
* received on the network). */
|
* received on the network). */
|
||||||
protected transient long _unpackStamp;
|
protected transient long _unpackStamp;
|
||||||
|
|
||||||
|
/** The transport parameters. */
|
||||||
|
protected transient Transport _transport = Transport.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,11 +42,12 @@ public class PongResponse extends DownstreamMessage
|
|||||||
* Constructs a pong response which will use the supplied ping time to
|
* Constructs a pong response which will use the supplied ping time to
|
||||||
* establish the end-to-end processing delay introduced by the server.
|
* establish the end-to-end processing delay introduced by the server.
|
||||||
*/
|
*/
|
||||||
public PongResponse (long pingStamp)
|
public PongResponse (long pingStamp, Transport transport)
|
||||||
{
|
{
|
||||||
// save this for when we are serialized in preparation for
|
// save this for when we are serialized in preparation for
|
||||||
// delivery over the network
|
// delivery over the network
|
||||||
_pingStamp = pingStamp;
|
_pingStamp = pingStamp;
|
||||||
|
_transport = transport;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,9 +113,21 @@ public class PongResponse extends DownstreamMessage
|
|||||||
in.defaultReadObject();
|
in.defaultReadObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override // documentation inherited
|
||||||
|
public void setTransport (Transport transport)
|
||||||
|
{
|
||||||
|
_transport = transport;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override // documentation inherited
|
||||||
|
public Transport getTransport ()
|
||||||
|
{
|
||||||
|
return _transport;
|
||||||
|
}
|
||||||
|
|
||||||
public String toString ()
|
public String toString ()
|
||||||
{
|
{
|
||||||
return "[type=PONG, msgid=" + messageId + "]";
|
return "[type=PONG, msgid=" + messageId + ", transport=" + _transport + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The ping unpack stamp provided at construct time to this pong
|
/** The ping unpack stamp provided at construct time to this pong
|
||||||
@@ -135,4 +148,7 @@ public class PongResponse extends DownstreamMessage
|
|||||||
* is to get a timestamp as close as possible to when the packet was
|
* is to get a timestamp as close as possible to when the packet was
|
||||||
* received on the network). */
|
* received on the network). */
|
||||||
protected transient long _unpackStamp;
|
protected transient long _unpackStamp;
|
||||||
|
|
||||||
|
/** The transport parameters. */
|
||||||
|
protected transient Transport _transport = Transport.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,256 @@
|
|||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2008 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.net;
|
||||||
|
|
||||||
|
import java.util.EnumMap;
|
||||||
|
|
||||||
|
import com.samskivert.util.HashIntMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message transport parameters. These include the type of transport and the channel (used to
|
||||||
|
* define independent streams for ordered transport), and may eventually include message
|
||||||
|
* priority, etc.
|
||||||
|
*/
|
||||||
|
public class Transport
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The available types of transport.
|
||||||
|
*/
|
||||||
|
public enum Type
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Messages are neither guaranteed to arrive nor, if they do arrive, to arrive in order
|
||||||
|
* and without duplicates. Functionally identical to UDP.
|
||||||
|
*/
|
||||||
|
UNRELIABLE_UNORDERED(false, false) {
|
||||||
|
public Type combine (Type other) {
|
||||||
|
return other; // we defer to all
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Messages are not guaranteed to arrive, but if they do arrive, then they will arrive in
|
||||||
|
* order and without duplicates. In other words, out-of-order packets will be dropped.
|
||||||
|
*/
|
||||||
|
UNRELIABLE_ORDERED(false, true) {
|
||||||
|
public Type combine (Type other) {
|
||||||
|
return other.isReliable() ? RELIABLE_ORDERED : this;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Messages are guaranteed to arrive eventually, but they are not guaranteed to arrive in
|
||||||
|
* order.
|
||||||
|
*/
|
||||||
|
RELIABLE_UNORDERED(true, false) {
|
||||||
|
public Type combine (Type other) {
|
||||||
|
return other.isOrdered() ? RELIABLE_ORDERED : this;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Messages are guaranteed to arrive, and will arrive in the order in which they are sent.
|
||||||
|
* Functionally identical to TCP.
|
||||||
|
*/
|
||||||
|
RELIABLE_ORDERED(true, true) {
|
||||||
|
public Type combine (Type other) {
|
||||||
|
return this; // we override all
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this transport type guarantees that messages will be delivered.
|
||||||
|
*/
|
||||||
|
public boolean isReliable ()
|
||||||
|
{
|
||||||
|
return _reliable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this transport type guarantees that messages will be received in the
|
||||||
|
* order in which they were sent, if they are received at all.
|
||||||
|
*/
|
||||||
|
public boolean isOrdered ()
|
||||||
|
{
|
||||||
|
return _ordered;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a transport type that combines the requirements of this type with those of the
|
||||||
|
* specified other type.
|
||||||
|
*/
|
||||||
|
public abstract Type combine (Type other);
|
||||||
|
|
||||||
|
Type (boolean reliable, boolean ordered)
|
||||||
|
{
|
||||||
|
_reliable = reliable;
|
||||||
|
_ordered = ordered;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean _reliable, _ordered;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The unreliable/unordered mode of transport. */
|
||||||
|
public static final Transport UNRELIABLE_UNORDERED = getInstance(Type.UNRELIABLE_UNORDERED);
|
||||||
|
|
||||||
|
/** The unreliable/ordered mode on the default channel. */
|
||||||
|
public static final Transport UNRELIABLE_ORDERED = getInstance(Type.UNRELIABLE_ORDERED, 0);
|
||||||
|
|
||||||
|
/** The reliable/unordered mode. */
|
||||||
|
public static final Transport RELIABLE_UNORDERED = getInstance(Type.RELIABLE_UNORDERED);
|
||||||
|
|
||||||
|
/** The reliable/ordered mode on the default channel. */
|
||||||
|
public static final Transport RELIABLE_ORDERED = getInstance(Type.RELIABLE_ORDERED, 0);
|
||||||
|
|
||||||
|
/** The default mode of transport. */
|
||||||
|
public static final Transport DEFAULT = RELIABLE_ORDERED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the shared instance with the specified parameters.
|
||||||
|
*/
|
||||||
|
public static Transport getInstance (Type type)
|
||||||
|
{
|
||||||
|
return getInstance(type, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the shared instance with the specified parameters.
|
||||||
|
*/
|
||||||
|
public static Transport getInstance (Type type, int channel)
|
||||||
|
{
|
||||||
|
// were there more parameters in transport objects, it would be better to have a single map
|
||||||
|
// of instances and use Transport objects as keys (as in examples of the flyweight
|
||||||
|
// pattern). however, doing it this way avoids the need to create a new object on lookup
|
||||||
|
if (_unordered == null) {
|
||||||
|
_unordered = new EnumMap<Type, Transport>(Type.class);
|
||||||
|
_ordered = new EnumMap<Type, HashIntMap<Transport>>(Type.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// for unordered transport, we map on the type alone
|
||||||
|
if (!type.isOrdered()) {
|
||||||
|
Transport instance = _unordered.get(type);
|
||||||
|
if (instance == null) {
|
||||||
|
_unordered.put(type, instance = new Transport(type));
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for ordered transport, we map on the type and channel
|
||||||
|
HashIntMap<Transport> instances = _ordered.get(type);
|
||||||
|
if (instances == null) {
|
||||||
|
_ordered.put(type, instances = new HashIntMap<Transport>());
|
||||||
|
}
|
||||||
|
Transport instance = instances.get(channel);
|
||||||
|
if (instance == null) {
|
||||||
|
instances.put(channel, instance = new Transport(type, channel));
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the type of transport.
|
||||||
|
*/
|
||||||
|
public Type getType ()
|
||||||
|
{
|
||||||
|
return _type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the transport channel.
|
||||||
|
*/
|
||||||
|
public int getChannel ()
|
||||||
|
{
|
||||||
|
return _channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this transport guarantees that messages will be delivered.
|
||||||
|
*/
|
||||||
|
public boolean isReliable ()
|
||||||
|
{
|
||||||
|
return _type.isReliable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this transport guarantees that messages will be received in the order in
|
||||||
|
* which they were sent, if they are received at all.
|
||||||
|
*/
|
||||||
|
public boolean isOrdered ()
|
||||||
|
{
|
||||||
|
return _type.isOrdered();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a transport that satisfies the requirements of this and the specified other
|
||||||
|
* transport.
|
||||||
|
*/
|
||||||
|
public Transport combine (Transport other)
|
||||||
|
{
|
||||||
|
// if the channels are different, we fall back to the default channel
|
||||||
|
return getInstance(
|
||||||
|
_type.combine(other._type),
|
||||||
|
(_channel == other._channel) ? _channel : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override // documentation inherited
|
||||||
|
public int hashCode ()
|
||||||
|
{
|
||||||
|
return 31*_type.hashCode() + _channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override // documentation inherited
|
||||||
|
public boolean equals (Object other)
|
||||||
|
{
|
||||||
|
Transport otrans;
|
||||||
|
return other instanceof Transport && (otrans = (Transport)other)._type == _type &&
|
||||||
|
otrans._channel == _channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override // documentation inherited
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
return "[type=" + _type + ", channel=" + _channel + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Transport (Type type)
|
||||||
|
{
|
||||||
|
this(type, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Transport (Type type, int channel)
|
||||||
|
{
|
||||||
|
_type = type;
|
||||||
|
_channel = channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The type of transport. */
|
||||||
|
protected Type _type;
|
||||||
|
|
||||||
|
/** The transport channel. */
|
||||||
|
protected int _channel;
|
||||||
|
|
||||||
|
/** Unordered instances mapped by type. */
|
||||||
|
protected static EnumMap<Type, Transport> _unordered;
|
||||||
|
|
||||||
|
/** Ordered instances mapped by type and channel. */
|
||||||
|
protected static EnumMap<Type, HashIntMap<Transport>> _ordered;
|
||||||
|
}
|
||||||
@@ -21,14 +21,12 @@
|
|||||||
|
|
||||||
package com.threerings.presents.net;
|
package com.threerings.presents.net;
|
||||||
|
|
||||||
import com.threerings.io.SimpleStreamableObject;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class encapsulates a message in the distributed object protocol
|
* This class encapsulates a message in the distributed object protocol
|
||||||
* that flows from the client to the server. Upstream messages include
|
* that flows from the client to the server. Upstream messages include
|
||||||
* object subscription, event forwarding and session management.
|
* object subscription, event forwarding and session management.
|
||||||
*/
|
*/
|
||||||
public abstract class UpstreamMessage extends SimpleStreamableObject
|
public abstract class UpstreamMessage extends Message
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* This is a unique (within the context of a reasonable period of
|
* This is a unique (within the context of a reasonable period of
|
||||||
@@ -41,12 +39,6 @@ public abstract class UpstreamMessage extends SimpleStreamableObject
|
|||||||
/** A timestamp indicating when this upstream message was received. */
|
/** A timestamp indicating when this upstream message was received. */
|
||||||
public transient long received;
|
public transient long received;
|
||||||
|
|
||||||
/**
|
|
||||||
* When sending, this acts as a hint that the message may be transmitted as a datagram.
|
|
||||||
* When receiving, it indicates that the message was received as a datagram.
|
|
||||||
*/
|
|
||||||
public transient boolean datagram;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each upstream message derived class must provide a zero argument
|
* Each upstream message derived class must provide a zero argument
|
||||||
* constructor so that it can be unserialized when read from the
|
* constructor so that it can be unserialized when read from the
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ import com.threerings.presents.dobj.InvocationRequestEvent;
|
|||||||
import com.threerings.presents.dobj.ObjectAccessException;
|
import com.threerings.presents.dobj.ObjectAccessException;
|
||||||
import com.threerings.presents.dobj.RootDObjectManager;
|
import com.threerings.presents.dobj.RootDObjectManager;
|
||||||
|
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The invocation services provide client to server invocations (service requests) and server to
|
* The invocation services provide client to server invocations (service requests) and server to
|
||||||
* client invocations (responses and notifications). Via this mechanism, the client can make
|
* client invocations (responses and notifications). Via this mechanism, the client can make
|
||||||
@@ -183,7 +185,7 @@ public class InvocationManager
|
|||||||
/**
|
/**
|
||||||
* Get the class that is being used to dispatch the specified
|
* Get the class that is being used to dispatch the specified
|
||||||
* invocation code, for informational purposes.
|
* invocation code, for informational purposes.
|
||||||
*
|
*
|
||||||
* @return the Class, or null if no dispatcher is registered with
|
* @return the Class, or null if no dispatcher is registered with
|
||||||
* the specified code.
|
* the specified code.
|
||||||
*/
|
*/
|
||||||
@@ -201,7 +203,7 @@ public class InvocationManager
|
|||||||
if (event instanceof InvocationRequestEvent) {
|
if (event instanceof InvocationRequestEvent) {
|
||||||
InvocationRequestEvent ire = (InvocationRequestEvent)event;
|
InvocationRequestEvent ire = (InvocationRequestEvent)event;
|
||||||
dispatchRequest(ire.getSourceOid(), ire.getInvCode(),
|
dispatchRequest(ire.getSourceOid(), ire.getInvCode(),
|
||||||
ire.getMethodId(), ire.getArgs());
|
ire.getMethodId(), ire.getArgs(), ire.getTransport());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,7 +213,7 @@ public class InvocationManager
|
|||||||
* registered invocation dispatcher.
|
* registered invocation dispatcher.
|
||||||
*/
|
*/
|
||||||
protected void dispatchRequest (
|
protected void dispatchRequest (
|
||||||
int clientOid, int invCode, int methodId, Object[] args)
|
int clientOid, int invCode, int methodId, Object[] args, Transport transport)
|
||||||
{
|
{
|
||||||
// make sure the client is still around
|
// make sure the client is still around
|
||||||
ClientObject source = (ClientObject)_omgr.getObject(clientOid);
|
ClientObject source = (ClientObject)_omgr.getObject(clientOid);
|
||||||
@@ -243,6 +245,7 @@ public class InvocationManager
|
|||||||
if (arg instanceof ListenerMarshaller) {
|
if (arg instanceof ListenerMarshaller) {
|
||||||
ListenerMarshaller list = (ListenerMarshaller)arg;
|
ListenerMarshaller list = (ListenerMarshaller)arg;
|
||||||
list.omgr = _omgr;
|
list.omgr = _omgr;
|
||||||
|
list.transport = transport;
|
||||||
// keep track of the listener we'll inform if anything
|
// keep track of the listener we'll inform if anything
|
||||||
// goes horribly awry
|
// goes horribly awry
|
||||||
if (rlist == null) {
|
if (rlist == null) {
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ import com.threerings.presents.client.InvocationReceiver.Registration;
|
|||||||
import com.threerings.presents.data.ClientObject;
|
import com.threerings.presents.data.ClientObject;
|
||||||
import com.threerings.presents.dobj.InvocationNotificationEvent;
|
import com.threerings.presents.dobj.InvocationNotificationEvent;
|
||||||
|
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides basic functionality used by all invocation sender classes.
|
* Provides basic functionality used by all invocation sender classes.
|
||||||
*/
|
*/
|
||||||
@@ -39,6 +41,16 @@ public abstract class InvocationSender
|
|||||||
*/
|
*/
|
||||||
public static void sendNotification (
|
public static void sendNotification (
|
||||||
ClientObject target, String receiverCode, int methodId, Object[] args)
|
ClientObject target, String receiverCode, int methodId, Object[] args)
|
||||||
|
{
|
||||||
|
sendNotification(target, receiverCode, methodId, args, Transport.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the specified invocation notification be packaged up and sent to the supplied
|
||||||
|
* target client.
|
||||||
|
*/
|
||||||
|
public static void sendNotification (
|
||||||
|
ClientObject target, String receiverCode, int methodId, Object[] args, Transport transport)
|
||||||
{
|
{
|
||||||
// convert the receiver hash id into the code used on this
|
// convert the receiver hash id into the code used on this
|
||||||
// specific client
|
// specific client
|
||||||
@@ -55,7 +67,8 @@ public abstract class InvocationSender
|
|||||||
|
|
||||||
// create and dispatch an invocation notification event
|
// create and dispatch an invocation notification event
|
||||||
target.postEvent(
|
target.postEvent(
|
||||||
new InvocationNotificationEvent(target.getOid(), rreg.receiverId, methodId, args));
|
new InvocationNotificationEvent(
|
||||||
|
target.getOid(), rreg.receiverId, methodId, args, transport));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ public class PresentsClient
|
|||||||
* does it in the existing client object. Care must be taken to ensure that any client or
|
* 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
|
* server code either doesn't map things based on username before this call, or that it's
|
||||||
* updated to reflect the change.
|
* updated to reflect the change.
|
||||||
*
|
*
|
||||||
* @return - true if the client was successfully renamed, false otherwise
|
* @return - true if the client was successfully renamed, false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean updateUsername (Name username)
|
public boolean updateUsername (Name username)
|
||||||
@@ -978,11 +978,9 @@ public class PresentsClient
|
|||||||
{
|
{
|
||||||
public void dispatch (PresentsClient client, UpstreamMessage msg)
|
public void dispatch (PresentsClient client, UpstreamMessage msg)
|
||||||
{
|
{
|
||||||
// send a pong response
|
// send a pong response using the transport with which the message was received
|
||||||
PingRequest req = (PingRequest)msg;
|
PingRequest req = (PingRequest)msg;
|
||||||
PongResponse resp = new PongResponse(req.getUnpackStamp());
|
client.safePostMessage(new PongResponse(req.getUnpackStamp(), req.getTransport()));
|
||||||
resp.datagram = req.datagram;
|
|
||||||
client.safePostMessage(resp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -376,7 +376,6 @@ public abstract class Connection implements NetEventHandler
|
|||||||
return; // received out of order
|
return; // received out of order
|
||||||
}
|
}
|
||||||
msg.received = when;
|
msg.received = when;
|
||||||
msg.datagram = true;
|
|
||||||
_handler.handleMessage(msg);
|
_handler.handleMessage(msg);
|
||||||
|
|
||||||
} catch (ClassNotFoundException cnfe) {
|
} catch (ClassNotFoundException cnfe) {
|
||||||
|
|||||||
@@ -850,7 +850,7 @@ public class ConnectionManager extends LoopingThread
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// send it as a datagram if hinted and possible
|
// send it as a datagram if hinted and possible
|
||||||
if (msg.datagram && conn.getDatagramAddress() != null) {
|
if (!msg.getTransport().isReliable() && conn.getDatagramAddress() != null) {
|
||||||
postDatagram(conn, msg);
|
postDatagram(conn, msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import org.apache.commons.io.FileUtils;
|
|||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
|
||||||
|
import org.apache.tools.ant.AntClassLoader;
|
||||||
import org.apache.tools.ant.BuildException;
|
import org.apache.tools.ant.BuildException;
|
||||||
import org.apache.tools.ant.DirectoryScanner;
|
import org.apache.tools.ant.DirectoryScanner;
|
||||||
import org.apache.tools.ant.Task;
|
import org.apache.tools.ant.Task;
|
||||||
@@ -61,6 +62,9 @@ import com.samskivert.util.SortableArrayList;
|
|||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
import com.samskivert.velocity.VelocityUtil;
|
import com.samskivert.velocity.VelocityUtil;
|
||||||
|
|
||||||
|
import com.threerings.presents.annotation.TransportHint;
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
import com.threerings.presents.dobj.DObject;
|
import com.threerings.presents.dobj.DObject;
|
||||||
import com.threerings.presents.dobj.DSet;
|
import com.threerings.presents.dobj.DSet;
|
||||||
import com.threerings.presents.dobj.OidList;
|
import com.threerings.presents.dobj.OidList;
|
||||||
@@ -85,6 +89,11 @@ public class GenDObjectTask extends Task
|
|||||||
{
|
{
|
||||||
_cloader = ClasspathUtils.getClassLoaderForPath(
|
_cloader = ClasspathUtils.getClassLoaderForPath(
|
||||||
getProject(), pathref);
|
getProject(), pathref);
|
||||||
|
|
||||||
|
// set the parent of the classloader to be the classloader used to load this task,
|
||||||
|
// rather than the classloader used to load Ant, so that we have access to Narya
|
||||||
|
// classes like TransportHint
|
||||||
|
((AntClassLoader)_cloader).setParent(getClass().getClassLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Performs the actual work of the task. */
|
/** Performs the actual work of the task. */
|
||||||
@@ -107,6 +116,7 @@ public class GenDObjectTask extends Task
|
|||||||
_doclass = _cloader.loadClass(DObject.class.getName());
|
_doclass = _cloader.loadClass(DObject.class.getName());
|
||||||
_dsclass = _cloader.loadClass(DSet.class.getName());
|
_dsclass = _cloader.loadClass(DSet.class.getName());
|
||||||
_olclass = _cloader.loadClass(OidList.class.getName());
|
_olclass = _cloader.loadClass(OidList.class.getName());
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new BuildException("Can't resolve InvocationListener", e);
|
throw new BuildException("Can't resolve InvocationListener", e);
|
||||||
}
|
}
|
||||||
@@ -198,6 +208,18 @@ public class GenDObjectTask extends Task
|
|||||||
ctx.put("capfield", StringUtil.unStudlyName(fname).toUpperCase());
|
ctx.put("capfield", StringUtil.unStudlyName(fname).toUpperCase());
|
||||||
ctx.put("upfield", StringUtils.capitalize(fname));
|
ctx.put("upfield", StringUtils.capitalize(fname));
|
||||||
|
|
||||||
|
// determine the type of transport
|
||||||
|
TransportHint hint = f.getAnnotation(TransportHint.class);
|
||||||
|
String transport;
|
||||||
|
if (hint == null) {
|
||||||
|
transport = "DEFAULT";
|
||||||
|
} else {
|
||||||
|
transport = "getInstance(\n" +
|
||||||
|
" com.threerings.presents.net.Transport.Type." +
|
||||||
|
hint.type().name() + ", " + hint.channel() + ")";
|
||||||
|
}
|
||||||
|
ctx.put("transport", "com.threerings.presents.net.Transport." + transport);
|
||||||
|
|
||||||
// if this field is an array, we need its component types
|
// if this field is an array, we need its component types
|
||||||
if (ftype.isArray()) {
|
if (ftype.isArray()) {
|
||||||
Class<?> etype = ftype.getComponentType();
|
Class<?> etype = ftype.getComponentType();
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import com.samskivert.util.StringUtil;
|
|||||||
|
|
||||||
import com.threerings.presents.client.InvocationDecoder;
|
import com.threerings.presents.client.InvocationDecoder;
|
||||||
import com.threerings.presents.data.ClientObject;
|
import com.threerings.presents.data.ClientObject;
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
import com.threerings.presents.server.InvocationSender;
|
import com.threerings.presents.server.InvocationSender;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,7 +86,7 @@ public class GenReceiverTask extends InvocationTask
|
|||||||
methods.add(new ServiceMethod(m, imports));
|
methods.add(new ServiceMethod(m, imports));
|
||||||
}
|
}
|
||||||
methods.sort();
|
methods.sort();
|
||||||
|
|
||||||
// get rid of primitives and java.lang types
|
// get rid of primitives and java.lang types
|
||||||
imports.removeGlobals();
|
imports.removeGlobals();
|
||||||
|
|
||||||
@@ -106,6 +107,7 @@ public class GenReceiverTask extends InvocationTask
|
|||||||
CollectionUtil.addAll(implist, imports);
|
CollectionUtil.addAll(implist, imports);
|
||||||
checkedAdd(implist, ClientObject.class.getName());
|
checkedAdd(implist, ClientObject.class.getName());
|
||||||
checkedAdd(implist, InvocationSender.class.getName());
|
checkedAdd(implist, InvocationSender.class.getName());
|
||||||
|
checkedAdd(implist, Transport.class.getName());
|
||||||
String dname = StringUtil.replace(rname, "Receiver", "Decoder");
|
String dname = StringUtil.replace(rname, "Receiver", "Decoder");
|
||||||
checkedAdd(implist, rpackage + "." + dname);
|
checkedAdd(implist, rpackage + "." + dname);
|
||||||
implist.sort();
|
implist.sort();
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import com.threerings.presents.client.InvocationService;
|
|||||||
import com.threerings.presents.data.ClientObject;
|
import com.threerings.presents.data.ClientObject;
|
||||||
import com.threerings.presents.data.InvocationMarshaller;
|
import com.threerings.presents.data.InvocationMarshaller;
|
||||||
import com.threerings.presents.dobj.InvocationResponseEvent;
|
import com.threerings.presents.dobj.InvocationResponseEvent;
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
import com.threerings.presents.server.InvocationDispatcher;
|
import com.threerings.presents.server.InvocationDispatcher;
|
||||||
import com.threerings.presents.server.InvocationException;
|
import com.threerings.presents.server.InvocationException;
|
||||||
import com.threerings.presents.server.InvocationProvider;
|
import com.threerings.presents.server.InvocationProvider;
|
||||||
@@ -46,11 +47,11 @@ import com.threerings.presents.server.InvocationProvider;
|
|||||||
/**
|
/**
|
||||||
* An Ant task for generating invocation service marshalling and
|
* An Ant task for generating invocation service marshalling and
|
||||||
* unmarshalling classes.
|
* unmarshalling classes.
|
||||||
* TODO: when generating the imports for exported action script files, there are just enough
|
* TODO: when generating the imports for exported action script files, there are just enough
|
||||||
* conversions of primitive types (e.g. float -> Number), array types (e.g. int[] -> TypedArray)
|
* conversions of primitive types (e.g. float -> Number), array types (e.g. int[] -> TypedArray)
|
||||||
* and three rings utility types (e.g. float -> Float) to make the existing serivces work. It
|
* and three rings utility types (e.g. float -> Float) to make the existing serivces work. It
|
||||||
* should be possible to create a complete list of these conversions so that future services
|
* should be possible to create a complete list of these conversions so that future services
|
||||||
* can be generated without problems.
|
* can be generated without problems.
|
||||||
*/
|
*/
|
||||||
public class GenServiceTask extends InvocationTask
|
public class GenServiceTask extends InvocationTask
|
||||||
{
|
{
|
||||||
@@ -61,7 +62,7 @@ public class GenServiceTask extends InvocationTask
|
|||||||
|
|
||||||
public ComparableArrayList<ServiceMethod> methods =
|
public ComparableArrayList<ServiceMethod> methods =
|
||||||
new ComparableArrayList<ServiceMethod>();
|
new ComparableArrayList<ServiceMethod>();
|
||||||
|
|
||||||
/** Contains all imports required for the parameters of the methods in this listener. */
|
/** Contains all imports required for the parameters of the methods in this listener. */
|
||||||
public ImportSet imports = new ImportSet();
|
public ImportSet imports = new ImportSet();
|
||||||
|
|
||||||
@@ -77,12 +78,12 @@ public class GenServiceTask extends InvocationTask
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
System.out.println("Adding " + m + ", imports are " +
|
System.out.println("Adding " + m + ", imports are " +
|
||||||
StringUtil.toString(imports));
|
StringUtil.toString(imports));
|
||||||
}
|
}
|
||||||
methods.add(new ServiceMethod(m, imports));
|
methods.add(new ServiceMethod(m, imports));
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
System.out.println("Added " + m + ", imports are " +
|
System.out.println("Added " + m + ", imports are " +
|
||||||
StringUtil.toString(imports));
|
StringUtil.toString(imports));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,7 +138,7 @@ public class GenServiceTask extends InvocationTask
|
|||||||
protected void processService (File source, Class service)
|
protected void processService (File source, Class service)
|
||||||
{
|
{
|
||||||
System.out.println("Processing " + service.getName() + "...");
|
System.out.println("Processing " + service.getName() + "...");
|
||||||
|
|
||||||
// verify that the service class name is as we expect it to be
|
// verify that the service class name is as we expect it to be
|
||||||
if (!service.getName().endsWith("Service")) {
|
if (!service.getName().endsWith("Service")) {
|
||||||
System.err.println("Cannot process '" + service.getName() + "':");
|
System.err.println("Cannot process '" + service.getName() + "':");
|
||||||
@@ -167,7 +168,7 @@ public class GenServiceTask extends InvocationTask
|
|||||||
sdesc.spackage, ".client", ".data");
|
sdesc.spackage, ".client", ".data");
|
||||||
|
|
||||||
// ----------- Part I - java marshaller
|
// ----------- Part I - java marshaller
|
||||||
|
|
||||||
// start with all imports (service methods and listener methods)
|
// start with all imports (service methods and listener methods)
|
||||||
ImportSet imports = sdesc.constructAllImports();
|
ImportSet imports = sdesc.constructAllImports();
|
||||||
|
|
||||||
@@ -175,30 +176,31 @@ public class GenServiceTask extends InvocationTask
|
|||||||
imports.add(sdesc.service);
|
imports.add(sdesc.service);
|
||||||
imports.add(Client.class);
|
imports.add(Client.class);
|
||||||
imports.add(InvocationMarshaller.class);
|
imports.add(InvocationMarshaller.class);
|
||||||
|
imports.add(Transport.class);
|
||||||
|
|
||||||
// if any listeners are to be present, they need the response event
|
// if any listeners are to be present, they need the response event
|
||||||
if (sdesc.listeners.size() > 0) {
|
if (sdesc.listeners.size() > 0) {
|
||||||
imports.add(InvocationResponseEvent.class);
|
imports.add(InvocationResponseEvent.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
// import classes contained in arrays
|
// import classes contained in arrays
|
||||||
imports.translateClassArrays();
|
imports.translateClassArrays();
|
||||||
|
|
||||||
// get rid of java.lang stuff and primitives
|
// get rid of java.lang stuff and primitives
|
||||||
imports.removeGlobals();
|
imports.removeGlobals();
|
||||||
|
|
||||||
// get rid of all arrays (they are automatic in java)
|
// get rid of all arrays (they are automatic in java)
|
||||||
imports.removeArrays();
|
imports.removeArrays();
|
||||||
|
|
||||||
// for each listener type, also import the corresponding marshaller
|
// for each listener type, also import the corresponding marshaller
|
||||||
imports.duplicateAndMunge("*Listener",
|
imports.duplicateAndMunge("*Listener",
|
||||||
"Service", "Marshaller",
|
"Service", "Marshaller",
|
||||||
"Listener", "Marshaller",
|
"Listener", "Marshaller",
|
||||||
".client.", ".data.");
|
".client.", ".data.");
|
||||||
|
|
||||||
// import the parent class of Foo$Bar
|
// import the parent class of Foo$Bar
|
||||||
imports.swapInnerClassesForParents();
|
imports.swapInnerClassesForParents();
|
||||||
|
|
||||||
// remove imports in our own package
|
// remove imports in our own package
|
||||||
imports.removeSamePackage(mpackage);
|
imports.removeSamePackage(mpackage);
|
||||||
|
|
||||||
@@ -234,15 +236,15 @@ public class GenServiceTask extends InvocationTask
|
|||||||
|
|
||||||
// start with the service method imports
|
// start with the service method imports
|
||||||
imports = sdesc.imports.clone();
|
imports = sdesc.imports.clone();
|
||||||
|
|
||||||
// add some things that marshallers just need
|
// add some things that marshallers just need
|
||||||
imports.add(sdesc.service);
|
imports.add(sdesc.service);
|
||||||
imports.add(Client.class);
|
imports.add(Client.class);
|
||||||
imports.add(InvocationMarshaller.class);
|
imports.add(InvocationMarshaller.class);
|
||||||
|
|
||||||
// replace inner classes with action script equivalents
|
// replace inner classes with action script equivalents
|
||||||
imports.translateInnerClasses();
|
imports.translateInnerClasses();
|
||||||
|
|
||||||
// replace primitive types with OOO types (required for unboxing)
|
// replace primitive types with OOO types (required for unboxing)
|
||||||
imports.replace("byte", "com.threerings.util.Byte");
|
imports.replace("byte", "com.threerings.util.Byte");
|
||||||
imports.replace("int", "com.threerings.util.Integer");
|
imports.replace("int", "com.threerings.util.Integer");
|
||||||
@@ -268,7 +270,7 @@ public class GenServiceTask extends InvocationTask
|
|||||||
|
|
||||||
// get rid of java.lang stuff and any remaining primitives
|
// get rid of java.lang stuff and any remaining primitives
|
||||||
imports.removeGlobals();
|
imports.removeGlobals();
|
||||||
|
|
||||||
if (imports.removeAll("[L*") > 0) {
|
if (imports.removeAll("[L*") > 0) {
|
||||||
imports.add("com.threerings.io.TypedArray");
|
imports.add("com.threerings.io.TypedArray");
|
||||||
}
|
}
|
||||||
@@ -304,20 +306,20 @@ public class GenServiceTask extends InvocationTask
|
|||||||
|
|
||||||
// start imports with just those used by listener methods
|
// start imports with just those used by listener methods
|
||||||
imports = listener.imports.clone();
|
imports = listener.imports.clone();
|
||||||
|
|
||||||
// always need the super class and the listener class
|
// always need the super class and the listener class
|
||||||
imports.add(imlm);
|
imports.add(imlm);
|
||||||
imports.add(listener.listener);
|
imports.add(listener.listener);
|
||||||
|
|
||||||
// replace '$' with '_' for action script naming convention
|
// replace '$' with '_' for action script naming convention
|
||||||
imports.translateInnerClasses();
|
imports.translateInnerClasses();
|
||||||
|
|
||||||
// convert primitive java types to ooo util types
|
// convert primitive java types to ooo util types
|
||||||
imports.replace("long", "com.threerings.util.Long");
|
imports.replace("long", "com.threerings.util.Long");
|
||||||
|
|
||||||
// get rid of remaining primitives and java.lang types
|
// get rid of remaining primitives and java.lang types
|
||||||
imports.removeGlobals();
|
imports.removeGlobals();
|
||||||
|
|
||||||
// remove imports in our own package
|
// remove imports in our own package
|
||||||
imports.removeSamePackage(mpackage);
|
imports.removeSamePackage(mpackage);
|
||||||
|
|
||||||
@@ -359,7 +361,7 @@ public class GenServiceTask extends InvocationTask
|
|||||||
|
|
||||||
// get rid of primitives and java.lang classes
|
// get rid of primitives and java.lang classes
|
||||||
imports.removeGlobals();
|
imports.removeGlobals();
|
||||||
|
|
||||||
// get rid of remaining arrays
|
// get rid of remaining arrays
|
||||||
imports.removeArrays();
|
imports.removeArrays();
|
||||||
|
|
||||||
@@ -394,20 +396,20 @@ public class GenServiceTask extends InvocationTask
|
|||||||
|
|
||||||
// start with just the imports needed by listener methods
|
// start with just the imports needed by listener methods
|
||||||
imports = listener.imports.clone();
|
imports = listener.imports.clone();
|
||||||
|
|
||||||
// add things needed by all listeners
|
// add things needed by all listeners
|
||||||
imports.add(isil);
|
imports.add(isil);
|
||||||
imports.add(listener.listener);
|
imports.add(listener.listener);
|
||||||
|
|
||||||
// change Foo$Bar to Foo_Bar
|
// change Foo$Bar to Foo_Bar
|
||||||
imports.translateInnerClasses();
|
imports.translateInnerClasses();
|
||||||
|
|
||||||
// convert java primitive types to ooo util types
|
// convert java primitive types to ooo util types
|
||||||
imports.replace("long", "com.threerings.util.Long");
|
imports.replace("long", "com.threerings.util.Long");
|
||||||
|
|
||||||
// get rid of remaining primitives and java.lang types
|
// get rid of remaining primitives and java.lang types
|
||||||
imports.removeGlobals();
|
imports.removeGlobals();
|
||||||
|
|
||||||
// remove imports in our own package
|
// remove imports in our own package
|
||||||
imports.removeSamePackage(sdesc.spackage);
|
imports.removeSamePackage(sdesc.spackage);
|
||||||
|
|
||||||
@@ -450,29 +452,29 @@ public class GenServiceTask extends InvocationTask
|
|||||||
// swap Client for ClientObject
|
// swap Client for ClientObject
|
||||||
imports.add(ClientObject.class);
|
imports.add(ClientObject.class);
|
||||||
imports.remove(Client.class);
|
imports.remove(Client.class);
|
||||||
|
|
||||||
// add some classes required for all dispatchers
|
// add some classes required for all dispatchers
|
||||||
imports.add(InvocationMarshaller.class);
|
imports.add(InvocationMarshaller.class);
|
||||||
imports.add(InvocationDispatcher.class);
|
imports.add(InvocationDispatcher.class);
|
||||||
imports.add(InvocationException.class);
|
imports.add(InvocationException.class);
|
||||||
|
|
||||||
// import classes contained in arrays
|
// import classes contained in arrays
|
||||||
imports.translateClassArrays();
|
imports.translateClassArrays();
|
||||||
|
|
||||||
// get rid of primitives and java.lang types
|
// get rid of primitives and java.lang types
|
||||||
imports.removeGlobals();
|
imports.removeGlobals();
|
||||||
|
|
||||||
// get rid of arrays
|
// get rid of arrays
|
||||||
imports.removeArrays();
|
imports.removeArrays();
|
||||||
|
|
||||||
// import the Marshaller corresponding to the service
|
// import the Marshaller corresponding to the service
|
||||||
imports.addMunged(sdesc.service,
|
imports.addMunged(sdesc.service,
|
||||||
"Service", "Marshaller",
|
"Service", "Marshaller",
|
||||||
".client.", ".data.");
|
".client.", ".data.");
|
||||||
|
|
||||||
// import Foo instead of Foo$Bar
|
// import Foo instead of Foo$Bar
|
||||||
imports.swapInnerClassesForParents();
|
imports.swapInnerClassesForParents();
|
||||||
|
|
||||||
// remove imports in our own package
|
// remove imports in our own package
|
||||||
imports.removeSamePackage(dpackage);
|
imports.removeSamePackage(dpackage);
|
||||||
|
|
||||||
@@ -504,7 +506,7 @@ public class GenServiceTask extends InvocationTask
|
|||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
System.out.println("Generating provider");
|
System.out.println("Generating provider");
|
||||||
}
|
}
|
||||||
|
|
||||||
String name = StringUtil.replace(sdesc.sname, "Service", "");
|
String name = StringUtil.replace(sdesc.sname, "Service", "");
|
||||||
String mpackage = StringUtil.replace(
|
String mpackage = StringUtil.replace(
|
||||||
sdesc.spackage, ".client", ".server");
|
sdesc.spackage, ".client", ".server");
|
||||||
@@ -515,24 +517,24 @@ public class GenServiceTask extends InvocationTask
|
|||||||
// swap Client for ClientObject
|
// swap Client for ClientObject
|
||||||
imports.add(ClientObject.class);
|
imports.add(ClientObject.class);
|
||||||
imports.remove(Client.class);
|
imports.remove(Client.class);
|
||||||
|
|
||||||
// import superclass
|
// import superclass
|
||||||
imports.add(InvocationProvider.class);
|
imports.add(InvocationProvider.class);
|
||||||
|
|
||||||
// any method that takes a listener may throw this
|
// any method that takes a listener may throw this
|
||||||
if (sdesc.hasAnyListenerArgs()) {
|
if (sdesc.hasAnyListenerArgs()) {
|
||||||
imports.add(InvocationException.class);
|
imports.add(InvocationException.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
// import classes contained in arrays
|
// import classes contained in arrays
|
||||||
imports.translateClassArrays();
|
imports.translateClassArrays();
|
||||||
|
|
||||||
// get rid of primitives and java.lang types
|
// get rid of primitives and java.lang types
|
||||||
imports.removeGlobals();
|
imports.removeGlobals();
|
||||||
|
|
||||||
// get rid of arrays
|
// get rid of arrays
|
||||||
imports.removeArrays();
|
imports.removeArrays();
|
||||||
|
|
||||||
// import Foo instead of Foo$Bar
|
// import Foo instead of Foo$Bar
|
||||||
imports.swapInnerClassesForParents();
|
imports.swapInnerClassesForParents();
|
||||||
|
|
||||||
@@ -593,19 +595,19 @@ public class GenServiceTask extends InvocationTask
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
System.out.println("Adding " + m + ", imports are " +
|
System.out.println("Adding " + m + ", imports are " +
|
||||||
StringUtil.toString(imports));
|
StringUtil.toString(imports));
|
||||||
}
|
}
|
||||||
methods.add(new ServiceMethod(m, imports));
|
methods.add(new ServiceMethod(m, imports));
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
System.out.println("Added " + m + ", imports are " +
|
System.out.println("Added " + m + ", imports are " +
|
||||||
StringUtil.toString(imports));
|
StringUtil.toString(imports));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
listeners.sort();
|
listeners.sort();
|
||||||
methods.sort();
|
methods.sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if any of the service method arguments are listener types.
|
* Checks if any of the service method arguments are listener types.
|
||||||
*/
|
*/
|
||||||
@@ -640,7 +642,7 @@ public class GenServiceTask extends InvocationTask
|
|||||||
ComparableArrayList<ServiceListener> listeners =
|
ComparableArrayList<ServiceListener> listeners =
|
||||||
new ComparableArrayList<ServiceListener>();
|
new ComparableArrayList<ServiceListener>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The path to our ActionScript source files. */
|
/** The path to our ActionScript source files. */
|
||||||
protected File _asroot;
|
protected File _asroot;
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import java.util.List;
|
|||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
|
import org.apache.tools.ant.AntClassLoader;
|
||||||
import org.apache.tools.ant.BuildException;
|
import org.apache.tools.ant.BuildException;
|
||||||
import org.apache.tools.ant.DirectoryScanner;
|
import org.apache.tools.ant.DirectoryScanner;
|
||||||
import org.apache.tools.ant.Task;
|
import org.apache.tools.ant.Task;
|
||||||
@@ -46,6 +47,9 @@ import org.apache.velocity.app.VelocityEngine;
|
|||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
import com.samskivert.velocity.VelocityUtil;
|
import com.samskivert.velocity.VelocityUtil;
|
||||||
|
|
||||||
|
import com.threerings.presents.annotation.TransportHint;
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
import com.threerings.presents.client.InvocationService.InvocationListener;
|
import com.threerings.presents.client.InvocationService.InvocationListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,7 +94,7 @@ public abstract class InvocationTask extends Task
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Used to keep track of invocation service methods or listener
|
/** Used to keep track of invocation service methods or listener
|
||||||
* methods. */
|
* methods. */
|
||||||
public class ServiceMethod implements Comparable<ServiceMethod>
|
public class ServiceMethod implements Comparable<ServiceMethod>
|
||||||
{
|
{
|
||||||
@@ -101,13 +105,13 @@ public abstract class InvocationTask extends Task
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new service method.
|
* Creates a new service method.
|
||||||
* @param method the method to inspect
|
* @param method the method to inspect
|
||||||
* @param imports will be filled with the types required by the method
|
* @param imports will be filled with the types required by the method
|
||||||
*/
|
*/
|
||||||
public ServiceMethod (Method method, ImportSet imports)
|
public ServiceMethod (Method method, ImportSet imports)
|
||||||
{
|
{
|
||||||
this.method = method;
|
this.method = method;
|
||||||
|
|
||||||
// we need to look through our arguments and note any needed
|
// we need to look through our arguments and note any needed
|
||||||
// imports in the supplied table
|
// imports in the supplied table
|
||||||
Class<?>[] args = method.getParameterTypes();
|
Class<?>[] args = method.getParameterTypes();
|
||||||
@@ -249,6 +253,16 @@ public abstract class InvocationTask extends Task
|
|||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getTransport ()
|
||||||
|
{
|
||||||
|
TransportHint hint = method.getAnnotation(TransportHint.class);
|
||||||
|
if (hint == null) {
|
||||||
|
return "Transport.DEFAULT";
|
||||||
|
}
|
||||||
|
return "Transport.getInstance(Transport.Type." +
|
||||||
|
hint.type().name() + ", " + hint.channel() + ")";
|
||||||
|
}
|
||||||
|
|
||||||
protected String boxArgument (Class<?> clazz, int index)
|
protected String boxArgument (Class<?> clazz, int index)
|
||||||
{
|
{
|
||||||
if (_ilistener.isAssignableFrom(clazz)) {
|
if (_ilistener.isAssignableFrom(clazz)) {
|
||||||
@@ -306,6 +320,11 @@ public abstract class InvocationTask extends Task
|
|||||||
{
|
{
|
||||||
_cloader = ClasspathUtils.getClassLoaderForPath(
|
_cloader = ClasspathUtils.getClassLoaderForPath(
|
||||||
getProject(), pathref);
|
getProject(), pathref);
|
||||||
|
|
||||||
|
// set the parent of the classloader to be the classloader used to load this task,
|
||||||
|
// rather than the classloader used to load Ant, so that we have access to Narya
|
||||||
|
// classes like TransportHint
|
||||||
|
((AntClassLoader)_cloader).setParent(getClass().getClassLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Performs the actual work of the task. */
|
/** Performs the actual work of the task. */
|
||||||
@@ -405,7 +424,7 @@ public abstract class InvocationTask extends Task
|
|||||||
|
|
||||||
/** Show extra output if set. */
|
/** Show extra output if set. */
|
||||||
protected boolean _verbose;
|
protected boolean _verbose;
|
||||||
|
|
||||||
/** Used to do our own classpath business. */
|
/** Used to do our own classpath business. */
|
||||||
protected ClassLoader _cloader;
|
protected ClassLoader _cloader;
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
{
|
{
|
||||||
$type ovalue = this.$field;
|
$type ovalue = this.$field;
|
||||||
requestAttributeChange(
|
requestAttributeChange(
|
||||||
$capfield, $wrapfield, $wrapofield);
|
$capfield, $wrapfield, $wrapofield,
|
||||||
|
$transport);
|
||||||
this.$field = $clonefield;
|
this.$field = $clonefield;
|
||||||
}
|
}
|
||||||
#if ($elemtype)
|
#if ($elemtype)
|
||||||
@@ -28,7 +29,8 @@
|
|||||||
{
|
{
|
||||||
$elemtype ovalue = this.$field[index];
|
$elemtype ovalue = this.$field[index];
|
||||||
requestElementUpdate(
|
requestElementUpdate(
|
||||||
$capfield, index, $wrapelem, $wrapoelem);
|
$capfield, index, $wrapelem, $wrapoelem,
|
||||||
|
$transport);
|
||||||
this.$field[index] = value;
|
this.$field[index] = value;
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
|
|||||||
@@ -25,7 +25,9 @@
|
|||||||
*/
|
*/
|
||||||
public void update$upfield ($etype elem)
|
public void update$upfield ($etype elem)
|
||||||
{
|
{
|
||||||
requestEntryUpdate($capfield, $field, elem);
|
requestEntryUpdate(
|
||||||
|
$capfield, $field, elem,
|
||||||
|
$transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public class ${name}Marshaller extends InvocationMarshaller
|
|||||||
_invId = null;
|
_invId = null;
|
||||||
omgr.postEvent(new InvocationResponseEvent(
|
omgr.postEvent(new InvocationResponseEvent(
|
||||||
callerOid, requestId, $lm.code,
|
callerOid, requestId, $lm.code,
|
||||||
new Object[] { $lm.getWrappedArgList(false) }));
|
new Object[] { $lm.getWrappedArgList(false) }, transport));
|
||||||
}
|
}
|
||||||
|
|
||||||
#end
|
#end
|
||||||
@@ -71,7 +71,7 @@ public class ${name}Marshaller extends InvocationMarshaller
|
|||||||
#end
|
#end
|
||||||
sendRequest(arg1, $m.code, new Object[] {
|
sendRequest(arg1, $m.code, new Object[] {
|
||||||
$m.getWrappedArgList(true)
|
$m.getWrappedArgList(true)
|
||||||
});
|
}, $m.transport);
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public class ${name}Sender extends InvocationSender
|
|||||||
{
|
{
|
||||||
sendNotification(
|
sendNotification(
|
||||||
target, ${name}Decoder.RECEIVER_CODE, ${name}Decoder.$m.code,
|
target, ${name}Decoder.RECEIVER_CODE, ${name}Decoder.$m.code,
|
||||||
new Object[] { $m.getWrappedArgList(false) });
|
new Object[] { $m.getWrappedArgList(false) }, $m.transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
#end
|
#end
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ import java.util.Set;
|
|||||||
import com.threerings.io.UnreliableObjectInputStream;
|
import com.threerings.io.UnreliableObjectInputStream;
|
||||||
import com.threerings.io.UnreliableObjectOutputStream;
|
import com.threerings.io.UnreliableObjectOutputStream;
|
||||||
|
|
||||||
|
import com.threerings.presents.net.Message;
|
||||||
|
import com.threerings.presents.net.Transport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used on both the client and the server to handle the encoding and decoding of sequenced
|
* Used on both the client and the server to handle the encoding and decoding of sequenced
|
||||||
* datagrams.
|
* datagrams.
|
||||||
@@ -48,7 +51,7 @@ public class DatagramSequencer
|
|||||||
/**
|
/**
|
||||||
* Writes a datagram to the underlying stream.
|
* Writes a datagram to the underlying stream.
|
||||||
*/
|
*/
|
||||||
public synchronized void writeDatagram (Object datagram)
|
public synchronized void writeDatagram (Message datagram)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
// first write the sequence and acknowledge numbers
|
// first write the sequence and acknowledge numbers
|
||||||
@@ -79,7 +82,7 @@ public class DatagramSequencer
|
|||||||
* @return the contents of the datagram, or <code>null</code> if the datagram was received
|
* @return the contents of the datagram, or <code>null</code> if the datagram was received
|
||||||
* out-of-order.
|
* out-of-order.
|
||||||
*/
|
*/
|
||||||
public synchronized Object readDatagram ()
|
public synchronized Message readDatagram ()
|
||||||
throws IOException, ClassNotFoundException
|
throws IOException, ClassNotFoundException
|
||||||
{
|
{
|
||||||
// read in the sequence number and determine if it's out-of-order
|
// read in the sequence number and determine if it's out-of-order
|
||||||
@@ -104,8 +107,10 @@ public class DatagramSequencer
|
|||||||
}
|
}
|
||||||
_sendrecs.subList(0, remove).clear();
|
_sendrecs.subList(0, remove).clear();
|
||||||
|
|
||||||
// read and return the contents of the datagram
|
// read the contents of the datagram, note the transport, and return
|
||||||
return _uin.readObject();
|
Message datagram = (Message)_uin.readObject();
|
||||||
|
datagram.setTransport(Transport.UNRELIABLE_ORDERED);
|
||||||
|
return datagram;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user