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.PingRequest;
|
||||
import com.threerings.presents.net.PongResponse;
|
||||
import com.threerings.presents.net.Transport;
|
||||
import com.threerings.presents.net.UpstreamMessage;
|
||||
import com.threerings.presents.util.DatagramSequencer;
|
||||
|
||||
@@ -163,7 +164,7 @@ public class BlockingCommunicator extends Communicator
|
||||
public void postMessage (UpstreamMessage msg)
|
||||
{
|
||||
// post as datagram if hinted and possible
|
||||
if (msg.datagram && _datagramWriter != null) {
|
||||
if (!msg.getTransport().isReliable() && _datagramWriter != null) {
|
||||
_dataq.append(msg);
|
||||
} else {
|
||||
_msgq.append(msg);
|
||||
@@ -486,6 +487,7 @@ public class BlockingCommunicator extends Communicator
|
||||
if (_datagramChannel.read(_buf) <= 0) {
|
||||
throw new IOException("No datagram available to read.");
|
||||
}
|
||||
_buf.flip();
|
||||
|
||||
// decode through the sequencer
|
||||
try {
|
||||
@@ -493,7 +495,6 @@ public class BlockingCommunicator extends Communicator
|
||||
if (msg == null) {
|
||||
return null; // received out of order
|
||||
}
|
||||
msg.datagram = true;
|
||||
if (debugLogMessages()) {
|
||||
Log.info("DATAGRAM " + msg);
|
||||
}
|
||||
@@ -802,7 +803,7 @@ public class BlockingCommunicator extends Communicator
|
||||
_datagramChannel.connect(new InetSocketAddress(_client.getHostname(), port));
|
||||
for (int ii = 0; ii < DATAGRAM_ATTEMPTS_PER_PORT; ii++) {
|
||||
// send a ping datagram
|
||||
sendDatagram(new PingRequest());
|
||||
sendDatagram(new PingRequest(Transport.UNRELIABLE_UNORDERED));
|
||||
|
||||
// wait for a response
|
||||
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.Subscriber;
|
||||
|
||||
import com.threerings.presents.net.Transport;
|
||||
|
||||
/**
|
||||
* Handles the client side management of the invocation services.
|
||||
*/
|
||||
@@ -195,6 +197,16 @@ public class InvocationDirector
|
||||
* invocation oid.
|
||||
*/
|
||||
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) {
|
||||
Log.warning("Dropping invocation request on shutdown director [code=" + invCode +
|
||||
@@ -218,7 +230,8 @@ public class InvocationDirector
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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.InvocationResponseEvent;
|
||||
|
||||
import com.threerings.presents.net.Transport;
|
||||
|
||||
/**
|
||||
* Provides a base from which all invocation service marshallers extend. Handles functionality
|
||||
* common to all marshallers.
|
||||
@@ -69,6 +71,10 @@ public class InvocationMarshaller
|
||||
* valid on the server. */
|
||||
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
|
||||
* if we are never responded-to.
|
||||
@@ -92,7 +98,7 @@ public class InvocationMarshaller
|
||||
{
|
||||
_invId = null;
|
||||
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. */
|
||||
protected transient String _invId;
|
||||
protected transient String _invId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,8 +152,8 @@ public class InvocationMarshaller
|
||||
public void requestProcessed ()
|
||||
{
|
||||
_invId = null;
|
||||
omgr.postEvent(
|
||||
new InvocationResponseEvent(callerOid, requestId, REQUEST_PROCESSED, null));
|
||||
omgr.postEvent(new InvocationResponseEvent(
|
||||
callerOid, requestId, REQUEST_PROCESSED, null, transport));
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
@@ -178,7 +184,7 @@ public class InvocationMarshaller
|
||||
{
|
||||
_invId = null;
|
||||
omgr.postEvent(new InvocationResponseEvent(
|
||||
callerOid, requestId, REQUEST_PROCESSED, new Object[] { result }));
|
||||
callerOid, requestId, REQUEST_PROCESSED, new Object[] { result }, transport));
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
@@ -248,7 +254,16 @@ public class InvocationMarshaller
|
||||
*/
|
||||
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. */
|
||||
|
||||
@@ -27,6 +27,8 @@ import java.util.HashMap;
|
||||
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
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;
|
||||
_oldValue = oldValue;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ import java.util.List;
|
||||
|
||||
import com.threerings.util.StreamableArrayList;
|
||||
|
||||
import com.threerings.presents.net.Transport;
|
||||
|
||||
/**
|
||||
* Used to manage and submit groups of events on a collection of
|
||||
* 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
|
||||
// accumulated some events)
|
||||
switch (_events.size()) {
|
||||
int size = _events.size();
|
||||
switch (size) {
|
||||
case 0: // nothing doing
|
||||
break;
|
||||
case 1: // no point in being compound
|
||||
_omgr.postEvent(_events.get(0));
|
||||
break;
|
||||
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);
|
||||
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
|
||||
public boolean applyToObject (DObject target)
|
||||
throws ObjectAccessException
|
||||
|
||||
@@ -23,6 +23,8 @@ package com.threerings.presents.dobj;
|
||||
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
_transport = transport;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,6 +134,24 @@ public abstract class DEvent implements Streamable
|
||||
_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
|
||||
* 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(", sourceOid=").append(_soid);
|
||||
if (_transport != Transport.DEFAULT) {
|
||||
buf.append(", transport=").append(_transport);
|
||||
}
|
||||
}
|
||||
|
||||
/** 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. */
|
||||
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
|
||||
* being the actual old value. */
|
||||
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.presents.Log;
|
||||
import com.threerings.presents.net.Transport;
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
_controller = controller;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
_tevent.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
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.
|
||||
*/
|
||||
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
|
||||
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.
|
||||
*/
|
||||
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
|
||||
T oldEntry = null;
|
||||
@@ -820,7 +858,7 @@ public class DObject
|
||||
}
|
||||
}
|
||||
// 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.threerings.presents.net.Transport;
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -49,7 +51,26 @@ public class ElementUpdatedEvent extends NamedEvent
|
||||
*/
|
||||
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;
|
||||
_oldValue = ovalue;
|
||||
_index = index;
|
||||
|
||||
@@ -95,7 +95,8 @@ public class EntryAddedEvent<T extends DSet.Entry> extends NamedEvent
|
||||
protected void notifyListener (Object listener)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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.net.Transport;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -44,7 +46,22 @@ public class EntryUpdatedEvent<T extends DSet.Entry> extends NamedEvent
|
||||
*/
|
||||
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;
|
||||
_oldEntry = oldEntry;
|
||||
}
|
||||
@@ -101,7 +118,8 @@ public class EntryUpdatedEvent<T extends DSet.Entry> extends NamedEvent
|
||||
protected void notifyListener (Object listener)
|
||||
{
|
||||
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.threerings.presents.net.Transport;
|
||||
|
||||
/**
|
||||
* Used to dispatch an invocation notification from the server to a
|
||||
* client.
|
||||
@@ -47,7 +49,27 @@ public class InvocationNotificationEvent extends DEvent
|
||||
public InvocationNotificationEvent (
|
||||
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;
|
||||
_methodId = (byte)methodId;
|
||||
_args = args;
|
||||
|
||||
@@ -23,6 +23,8 @@ package com.threerings.presents.dobj;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.presents.net.Transport;
|
||||
|
||||
/**
|
||||
* Used to dispatch an invocation request from the client to the server.
|
||||
*
|
||||
@@ -44,7 +46,25 @@ public class InvocationRequestEvent extends DEvent
|
||||
public InvocationRequestEvent (
|
||||
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;
|
||||
_methodId = (byte)methodId;
|
||||
_args = args;
|
||||
|
||||
@@ -23,6 +23,8 @@ package com.threerings.presents.dobj;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.presents.net.Transport;
|
||||
|
||||
/**
|
||||
* Used to dispatch an invocation response from the server to the client.
|
||||
*
|
||||
@@ -44,7 +46,25 @@ public class InvocationResponseEvent extends DEvent
|
||||
public InvocationResponseEvent (
|
||||
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;
|
||||
_methodId = (byte)methodId;
|
||||
_args = args;
|
||||
|
||||
@@ -23,6 +23,8 @@ package com.threerings.presents.dobj;
|
||||
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
package com.threerings.presents.dobj;
|
||||
|
||||
import com.threerings.presents.net.Transport;
|
||||
|
||||
/**
|
||||
* 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).
|
||||
@@ -36,7 +38,20 @@ public abstract class NamedEvent extends DEvent
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,14 +21,12 @@
|
||||
|
||||
package com.threerings.presents.net;
|
||||
|
||||
import com.threerings.io.SimpleStreamableObject;
|
||||
|
||||
/**
|
||||
* This class encapsulates a message in the distributed object protocol
|
||||
* that flows from the server to the client. Downstream messages include
|
||||
* 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
|
||||
@@ -37,12 +35,6 @@ public abstract class DownstreamMessage extends SimpleStreamableObject
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
||||
@@ -46,6 +46,19 @@ public class EventNotification extends DownstreamMessage
|
||||
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 ()
|
||||
{
|
||||
return "[type=EVT, evt=" + _event + "]";
|
||||
|
||||
@@ -49,6 +49,19 @@ public class ForwardEventRequest extends UpstreamMessage
|
||||
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 ()
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* by the low-level networking code.
|
||||
@@ -85,9 +93,21 @@ public class PingRequest extends UpstreamMessage
|
||||
in.defaultReadObject();
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public void setTransport (Transport transport)
|
||||
{
|
||||
_transport = transport;
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public Transport getTransport ()
|
||||
{
|
||||
return _transport;
|
||||
}
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
return "[type=PING, msgid=" + messageId + "]";
|
||||
return "[type=PING, msgid=" + messageId + ", transport=" + _transport + "]";
|
||||
}
|
||||
|
||||
/** 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
|
||||
* received on the network). */
|
||||
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
|
||||
* 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
|
||||
// delivery over the network
|
||||
_pingStamp = pingStamp;
|
||||
_transport = transport;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,9 +113,21 @@ public class PongResponse extends DownstreamMessage
|
||||
in.defaultReadObject();
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public void setTransport (Transport transport)
|
||||
{
|
||||
_transport = transport;
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public Transport getTransport ()
|
||||
{
|
||||
return _transport;
|
||||
}
|
||||
|
||||
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
|
||||
@@ -135,4 +148,7 @@ public class PongResponse extends DownstreamMessage
|
||||
* is to get a timestamp as close as possible to when the packet was
|
||||
* received on the network). */
|
||||
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;
|
||||
|
||||
import com.threerings.io.SimpleStreamableObject;
|
||||
|
||||
/**
|
||||
* This class encapsulates a message in the distributed object protocol
|
||||
* that flows from the client to the server. Upstream messages include
|
||||
* 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
|
||||
@@ -41,12 +39,6 @@ public abstract class UpstreamMessage extends SimpleStreamableObject
|
||||
/** A timestamp indicating when this upstream message was 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
|
||||
* 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.RootDObjectManager;
|
||||
|
||||
import com.threerings.presents.net.Transport;
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -183,7 +185,7 @@ public class InvocationManager
|
||||
/**
|
||||
* Get the class that is being used to dispatch the specified
|
||||
* invocation code, for informational purposes.
|
||||
*
|
||||
*
|
||||
* @return the Class, or null if no dispatcher is registered with
|
||||
* the specified code.
|
||||
*/
|
||||
@@ -201,7 +203,7 @@ public class InvocationManager
|
||||
if (event instanceof InvocationRequestEvent) {
|
||||
InvocationRequestEvent ire = (InvocationRequestEvent)event;
|
||||
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.
|
||||
*/
|
||||
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
|
||||
ClientObject source = (ClientObject)_omgr.getObject(clientOid);
|
||||
@@ -243,6 +245,7 @@ public class InvocationManager
|
||||
if (arg instanceof ListenerMarshaller) {
|
||||
ListenerMarshaller list = (ListenerMarshaller)arg;
|
||||
list.omgr = _omgr;
|
||||
list.transport = transport;
|
||||
// keep track of the listener we'll inform if anything
|
||||
// goes horribly awry
|
||||
if (rlist == null) {
|
||||
|
||||
@@ -28,6 +28,8 @@ import com.threerings.presents.client.InvocationReceiver.Registration;
|
||||
import com.threerings.presents.data.ClientObject;
|
||||
import com.threerings.presents.dobj.InvocationNotificationEvent;
|
||||
|
||||
import com.threerings.presents.net.Transport;
|
||||
|
||||
/**
|
||||
* Provides basic functionality used by all invocation sender classes.
|
||||
*/
|
||||
@@ -39,6 +41,16 @@ public abstract class InvocationSender
|
||||
*/
|
||||
public static void sendNotification (
|
||||
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
|
||||
// specific client
|
||||
@@ -55,7 +67,8 @@ public abstract class InvocationSender
|
||||
|
||||
// create and dispatch an invocation notification event
|
||||
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
|
||||
* server code either doesn't map things based on username before this call, or that it's
|
||||
* updated to reflect the change.
|
||||
*
|
||||
*
|
||||
* @return - true if the client was successfully renamed, false otherwise
|
||||
*/
|
||||
public boolean updateUsername (Name username)
|
||||
@@ -978,11 +978,9 @@ public class PresentsClient
|
||||
{
|
||||
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;
|
||||
PongResponse resp = new PongResponse(req.getUnpackStamp());
|
||||
resp.datagram = req.datagram;
|
||||
client.safePostMessage(resp);
|
||||
client.safePostMessage(new PongResponse(req.getUnpackStamp(), req.getTransport()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -376,7 +376,6 @@ public abstract class Connection implements NetEventHandler
|
||||
return; // received out of order
|
||||
}
|
||||
msg.received = when;
|
||||
msg.datagram = true;
|
||||
_handler.handleMessage(msg);
|
||||
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
|
||||
@@ -850,7 +850,7 @@ public class ConnectionManager extends LoopingThread
|
||||
|
||||
try {
|
||||
// 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);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import org.apache.tools.ant.AntClassLoader;
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.DirectoryScanner;
|
||||
import org.apache.tools.ant.Task;
|
||||
@@ -61,6 +62,9 @@ import com.samskivert.util.SortableArrayList;
|
||||
import com.samskivert.util.StringUtil;
|
||||
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.DSet;
|
||||
import com.threerings.presents.dobj.OidList;
|
||||
@@ -85,6 +89,11 @@ public class GenDObjectTask extends Task
|
||||
{
|
||||
_cloader = ClasspathUtils.getClassLoaderForPath(
|
||||
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. */
|
||||
@@ -107,6 +116,7 @@ public class GenDObjectTask extends Task
|
||||
_doclass = _cloader.loadClass(DObject.class.getName());
|
||||
_dsclass = _cloader.loadClass(DSet.class.getName());
|
||||
_olclass = _cloader.loadClass(OidList.class.getName());
|
||||
|
||||
} catch (Exception 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("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 (ftype.isArray()) {
|
||||
Class<?> etype = ftype.getComponentType();
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.presents.client.InvocationDecoder;
|
||||
import com.threerings.presents.data.ClientObject;
|
||||
import com.threerings.presents.net.Transport;
|
||||
import com.threerings.presents.server.InvocationSender;
|
||||
|
||||
/**
|
||||
@@ -85,7 +86,7 @@ public class GenReceiverTask extends InvocationTask
|
||||
methods.add(new ServiceMethod(m, imports));
|
||||
}
|
||||
methods.sort();
|
||||
|
||||
|
||||
// get rid of primitives and java.lang types
|
||||
imports.removeGlobals();
|
||||
|
||||
@@ -106,6 +107,7 @@ public class GenReceiverTask extends InvocationTask
|
||||
CollectionUtil.addAll(implist, imports);
|
||||
checkedAdd(implist, ClientObject.class.getName());
|
||||
checkedAdd(implist, InvocationSender.class.getName());
|
||||
checkedAdd(implist, Transport.class.getName());
|
||||
String dname = StringUtil.replace(rname, "Receiver", "Decoder");
|
||||
checkedAdd(implist, rpackage + "." + dname);
|
||||
implist.sort();
|
||||
|
||||
@@ -39,6 +39,7 @@ import com.threerings.presents.client.InvocationService;
|
||||
import com.threerings.presents.data.ClientObject;
|
||||
import com.threerings.presents.data.InvocationMarshaller;
|
||||
import com.threerings.presents.dobj.InvocationResponseEvent;
|
||||
import com.threerings.presents.net.Transport;
|
||||
import com.threerings.presents.server.InvocationDispatcher;
|
||||
import com.threerings.presents.server.InvocationException;
|
||||
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
|
||||
* 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)
|
||||
* 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
|
||||
* can be generated without problems.
|
||||
* can be generated without problems.
|
||||
*/
|
||||
public class GenServiceTask extends InvocationTask
|
||||
{
|
||||
@@ -61,7 +62,7 @@ public class GenServiceTask extends InvocationTask
|
||||
|
||||
public ComparableArrayList<ServiceMethod> methods =
|
||||
new ComparableArrayList<ServiceMethod>();
|
||||
|
||||
|
||||
/** Contains all imports required for the parameters of the methods in this listener. */
|
||||
public ImportSet imports = new ImportSet();
|
||||
|
||||
@@ -77,12 +78,12 @@ public class GenServiceTask extends InvocationTask
|
||||
continue;
|
||||
}
|
||||
if (_verbose) {
|
||||
System.out.println("Adding " + m + ", imports are " +
|
||||
System.out.println("Adding " + m + ", imports are " +
|
||||
StringUtil.toString(imports));
|
||||
}
|
||||
methods.add(new ServiceMethod(m, imports));
|
||||
if (_verbose) {
|
||||
System.out.println("Added " + m + ", imports are " +
|
||||
System.out.println("Added " + m + ", imports are " +
|
||||
StringUtil.toString(imports));
|
||||
}
|
||||
}
|
||||
@@ -137,7 +138,7 @@ public class GenServiceTask extends InvocationTask
|
||||
protected void processService (File source, Class service)
|
||||
{
|
||||
System.out.println("Processing " + service.getName() + "...");
|
||||
|
||||
|
||||
// verify that the service class name is as we expect it to be
|
||||
if (!service.getName().endsWith("Service")) {
|
||||
System.err.println("Cannot process '" + service.getName() + "':");
|
||||
@@ -167,7 +168,7 @@ public class GenServiceTask extends InvocationTask
|
||||
sdesc.spackage, ".client", ".data");
|
||||
|
||||
// ----------- Part I - java marshaller
|
||||
|
||||
|
||||
// start with all imports (service methods and listener methods)
|
||||
ImportSet imports = sdesc.constructAllImports();
|
||||
|
||||
@@ -175,30 +176,31 @@ public class GenServiceTask extends InvocationTask
|
||||
imports.add(sdesc.service);
|
||||
imports.add(Client.class);
|
||||
imports.add(InvocationMarshaller.class);
|
||||
imports.add(Transport.class);
|
||||
|
||||
// if any listeners are to be present, they need the response event
|
||||
if (sdesc.listeners.size() > 0) {
|
||||
imports.add(InvocationResponseEvent.class);
|
||||
}
|
||||
|
||||
|
||||
// import classes contained in arrays
|
||||
imports.translateClassArrays();
|
||||
|
||||
|
||||
// get rid of java.lang stuff and primitives
|
||||
imports.removeGlobals();
|
||||
|
||||
|
||||
// get rid of all arrays (they are automatic in java)
|
||||
imports.removeArrays();
|
||||
|
||||
|
||||
// for each listener type, also import the corresponding marshaller
|
||||
imports.duplicateAndMunge("*Listener",
|
||||
imports.duplicateAndMunge("*Listener",
|
||||
"Service", "Marshaller",
|
||||
"Listener", "Marshaller",
|
||||
".client.", ".data.");
|
||||
|
||||
// import the parent class of Foo$Bar
|
||||
imports.swapInnerClassesForParents();
|
||||
|
||||
|
||||
// remove imports in our own package
|
||||
imports.removeSamePackage(mpackage);
|
||||
|
||||
@@ -234,15 +236,15 @@ public class GenServiceTask extends InvocationTask
|
||||
|
||||
// start with the service method imports
|
||||
imports = sdesc.imports.clone();
|
||||
|
||||
|
||||
// add some things that marshallers just need
|
||||
imports.add(sdesc.service);
|
||||
imports.add(Client.class);
|
||||
imports.add(InvocationMarshaller.class);
|
||||
|
||||
|
||||
// replace inner classes with action script equivalents
|
||||
imports.translateInnerClasses();
|
||||
|
||||
|
||||
// replace primitive types with OOO types (required for unboxing)
|
||||
imports.replace("byte", "com.threerings.util.Byte");
|
||||
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
|
||||
imports.removeGlobals();
|
||||
|
||||
|
||||
if (imports.removeAll("[L*") > 0) {
|
||||
imports.add("com.threerings.io.TypedArray");
|
||||
}
|
||||
@@ -304,20 +306,20 @@ public class GenServiceTask extends InvocationTask
|
||||
|
||||
// start imports with just those used by listener methods
|
||||
imports = listener.imports.clone();
|
||||
|
||||
|
||||
// always need the super class and the listener class
|
||||
imports.add(imlm);
|
||||
imports.add(listener.listener);
|
||||
|
||||
|
||||
// replace '$' with '_' for action script naming convention
|
||||
imports.translateInnerClasses();
|
||||
|
||||
|
||||
// convert primitive java types to ooo util types
|
||||
imports.replace("long", "com.threerings.util.Long");
|
||||
|
||||
// get rid of remaining primitives and java.lang types
|
||||
imports.removeGlobals();
|
||||
|
||||
|
||||
// remove imports in our own package
|
||||
imports.removeSamePackage(mpackage);
|
||||
|
||||
@@ -359,7 +361,7 @@ public class GenServiceTask extends InvocationTask
|
||||
|
||||
// get rid of primitives and java.lang classes
|
||||
imports.removeGlobals();
|
||||
|
||||
|
||||
// get rid of remaining arrays
|
||||
imports.removeArrays();
|
||||
|
||||
@@ -394,20 +396,20 @@ public class GenServiceTask extends InvocationTask
|
||||
|
||||
// start with just the imports needed by listener methods
|
||||
imports = listener.imports.clone();
|
||||
|
||||
|
||||
// add things needed by all listeners
|
||||
imports.add(isil);
|
||||
imports.add(listener.listener);
|
||||
|
||||
|
||||
// change Foo$Bar to Foo_Bar
|
||||
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");
|
||||
|
||||
|
||||
// get rid of remaining primitives and java.lang types
|
||||
imports.removeGlobals();
|
||||
|
||||
|
||||
// remove imports in our own package
|
||||
imports.removeSamePackage(sdesc.spackage);
|
||||
|
||||
@@ -450,29 +452,29 @@ public class GenServiceTask extends InvocationTask
|
||||
// swap Client for ClientObject
|
||||
imports.add(ClientObject.class);
|
||||
imports.remove(Client.class);
|
||||
|
||||
|
||||
// add some classes required for all dispatchers
|
||||
imports.add(InvocationMarshaller.class);
|
||||
imports.add(InvocationDispatcher.class);
|
||||
imports.add(InvocationException.class);
|
||||
|
||||
|
||||
// import classes contained in arrays
|
||||
imports.translateClassArrays();
|
||||
|
||||
|
||||
// get rid of primitives and java.lang types
|
||||
imports.removeGlobals();
|
||||
|
||||
|
||||
// get rid of arrays
|
||||
imports.removeArrays();
|
||||
|
||||
// import the Marshaller corresponding to the service
|
||||
imports.addMunged(sdesc.service,
|
||||
imports.addMunged(sdesc.service,
|
||||
"Service", "Marshaller",
|
||||
".client.", ".data.");
|
||||
|
||||
// import Foo instead of Foo$Bar
|
||||
imports.swapInnerClassesForParents();
|
||||
|
||||
|
||||
// remove imports in our own package
|
||||
imports.removeSamePackage(dpackage);
|
||||
|
||||
@@ -504,7 +506,7 @@ public class GenServiceTask extends InvocationTask
|
||||
if (_verbose) {
|
||||
System.out.println("Generating provider");
|
||||
}
|
||||
|
||||
|
||||
String name = StringUtil.replace(sdesc.sname, "Service", "");
|
||||
String mpackage = StringUtil.replace(
|
||||
sdesc.spackage, ".client", ".server");
|
||||
@@ -515,24 +517,24 @@ public class GenServiceTask extends InvocationTask
|
||||
// swap Client for ClientObject
|
||||
imports.add(ClientObject.class);
|
||||
imports.remove(Client.class);
|
||||
|
||||
|
||||
// import superclass
|
||||
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()) {
|
||||
imports.add(InvocationException.class);
|
||||
}
|
||||
|
||||
|
||||
// import classes contained in arrays
|
||||
imports.translateClassArrays();
|
||||
|
||||
|
||||
// get rid of primitives and java.lang types
|
||||
imports.removeGlobals();
|
||||
|
||||
|
||||
// get rid of arrays
|
||||
imports.removeArrays();
|
||||
|
||||
|
||||
// import Foo instead of Foo$Bar
|
||||
imports.swapInnerClassesForParents();
|
||||
|
||||
@@ -593,19 +595,19 @@ public class GenServiceTask extends InvocationTask
|
||||
}
|
||||
}
|
||||
if (_verbose) {
|
||||
System.out.println("Adding " + m + ", imports are " +
|
||||
System.out.println("Adding " + m + ", imports are " +
|
||||
StringUtil.toString(imports));
|
||||
}
|
||||
methods.add(new ServiceMethod(m, imports));
|
||||
if (_verbose) {
|
||||
System.out.println("Added " + m + ", imports are " +
|
||||
System.out.println("Added " + m + ", imports are " +
|
||||
StringUtil.toString(imports));
|
||||
}
|
||||
}
|
||||
listeners.sort();
|
||||
methods.sort();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if any of the service method arguments are listener types.
|
||||
*/
|
||||
@@ -640,7 +642,7 @@ public class GenServiceTask extends InvocationTask
|
||||
ComparableArrayList<ServiceListener> listeners =
|
||||
new ComparableArrayList<ServiceListener>();
|
||||
}
|
||||
|
||||
|
||||
/** The path to our ActionScript source files. */
|
||||
protected File _asroot;
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import java.util.List;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import org.apache.tools.ant.AntClassLoader;
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.DirectoryScanner;
|
||||
import org.apache.tools.ant.Task;
|
||||
@@ -46,6 +47,9 @@ import org.apache.velocity.app.VelocityEngine;
|
||||
import com.samskivert.util.StringUtil;
|
||||
import com.samskivert.velocity.VelocityUtil;
|
||||
|
||||
import com.threerings.presents.annotation.TransportHint;
|
||||
import com.threerings.presents.net.Transport;
|
||||
|
||||
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. */
|
||||
public class ServiceMethod implements Comparable<ServiceMethod>
|
||||
{
|
||||
@@ -101,13 +105,13 @@ public abstract class InvocationTask extends Task
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public ServiceMethod (Method method, ImportSet imports)
|
||||
{
|
||||
this.method = method;
|
||||
|
||||
|
||||
// we need to look through our arguments and note any needed
|
||||
// imports in the supplied table
|
||||
Class<?>[] args = method.getParameterTypes();
|
||||
@@ -249,6 +253,16 @@ public abstract class InvocationTask extends Task
|
||||
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)
|
||||
{
|
||||
if (_ilistener.isAssignableFrom(clazz)) {
|
||||
@@ -306,6 +320,11 @@ public abstract class InvocationTask extends Task
|
||||
{
|
||||
_cloader = ClasspathUtils.getClassLoaderForPath(
|
||||
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. */
|
||||
@@ -405,7 +424,7 @@ public abstract class InvocationTask extends Task
|
||||
|
||||
/** Show extra output if set. */
|
||||
protected boolean _verbose;
|
||||
|
||||
|
||||
/** Used to do our own classpath business. */
|
||||
protected ClassLoader _cloader;
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
{
|
||||
$type ovalue = this.$field;
|
||||
requestAttributeChange(
|
||||
$capfield, $wrapfield, $wrapofield);
|
||||
$capfield, $wrapfield, $wrapofield,
|
||||
$transport);
|
||||
this.$field = $clonefield;
|
||||
}
|
||||
#if ($elemtype)
|
||||
@@ -28,7 +29,8 @@
|
||||
{
|
||||
$elemtype ovalue = this.$field[index];
|
||||
requestElementUpdate(
|
||||
$capfield, index, $wrapelem, $wrapoelem);
|
||||
$capfield, index, $wrapelem, $wrapoelem,
|
||||
$transport);
|
||||
this.$field[index] = value;
|
||||
}
|
||||
#end
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
*/
|
||||
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;
|
||||
omgr.postEvent(new InvocationResponseEvent(
|
||||
callerOid, requestId, $lm.code,
|
||||
new Object[] { $lm.getWrappedArgList(false) }));
|
||||
new Object[] { $lm.getWrappedArgList(false) }, transport));
|
||||
}
|
||||
|
||||
#end
|
||||
@@ -71,7 +71,7 @@ public class ${name}Marshaller extends InvocationMarshaller
|
||||
#end
|
||||
sendRequest(arg1, $m.code, new Object[] {
|
||||
$m.getWrappedArgList(true)
|
||||
});
|
||||
}, $m.transport);
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public class ${name}Sender extends InvocationSender
|
||||
{
|
||||
sendNotification(
|
||||
target, ${name}Decoder.RECEIVER_CODE, ${name}Decoder.$m.code,
|
||||
new Object[] { $m.getWrappedArgList(false) });
|
||||
new Object[] { $m.getWrappedArgList(false) }, $m.transport);
|
||||
}
|
||||
|
||||
#end
|
||||
|
||||
@@ -30,6 +30,9 @@ import java.util.Set;
|
||||
import com.threerings.io.UnreliableObjectInputStream;
|
||||
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
|
||||
* datagrams.
|
||||
@@ -48,7 +51,7 @@ public class DatagramSequencer
|
||||
/**
|
||||
* Writes a datagram to the underlying stream.
|
||||
*/
|
||||
public synchronized void writeDatagram (Object datagram)
|
||||
public synchronized void writeDatagram (Message datagram)
|
||||
throws IOException
|
||||
{
|
||||
// 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
|
||||
* out-of-order.
|
||||
*/
|
||||
public synchronized Object readDatagram ()
|
||||
public synchronized Message readDatagram ()
|
||||
throws IOException, ClassNotFoundException
|
||||
{
|
||||
// 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();
|
||||
|
||||
// read and return the contents of the datagram
|
||||
return _uin.readObject();
|
||||
// read the contents of the datagram, note the transport, and return
|
||||
Message datagram = (Message)_uin.readObject();
|
||||
datagram.setTransport(Transport.UNRELIABLE_ORDERED);
|
||||
return datagram;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user