diff --git a/engine/src/networking/com/jme3/network/Client.java b/engine/src/networking/com/jme3/network/Client.java index 8b4fc2b07..b324954fc 100644 --- a/engine/src/networking/com/jme3/network/Client.java +++ b/engine/src/networking/com/jme3/network/Client.java @@ -79,6 +79,12 @@ public interface Client extends MessageConnection */ public void send( Message message ); + /** + * Sends a message to the other end of the connection using + * the specified alternate channel. + */ + public void send( int channel, Message message ); + /** * Closes this connection to the server. */ diff --git a/engine/src/networking/com/jme3/network/MessageConnection.java b/engine/src/networking/com/jme3/network/MessageConnection.java index 712d82108..1f5730e84 100644 --- a/engine/src/networking/com/jme3/network/MessageConnection.java +++ b/engine/src/networking/com/jme3/network/MessageConnection.java @@ -46,5 +46,11 @@ public interface MessageConnection * Sends a message to the other end of the connection. */ public void send( Message message ); + + /** + * Sends a message to the other end of the connection using + * the specified alternate channel. + */ + public void send( int channel, Message message ); } diff --git a/engine/src/networking/com/jme3/network/Network.java b/engine/src/networking/com/jme3/network/Network.java index c32d38124..81fccee42 100644 --- a/engine/src/networking/com/jme3/network/Network.java +++ b/engine/src/networking/com/jme3/network/Network.java @@ -34,6 +34,7 @@ package com.jme3.network; import com.jme3.network.base.DefaultClient; import com.jme3.network.base.DefaultServer; +import com.jme3.network.base.TcpConnectorFactory; import com.jme3.network.kernel.tcp.SelectorKernel; import com.jme3.network.kernel.tcp.SocketConnector; import com.jme3.network.kernel.udp.UdpConnector; @@ -85,7 +86,7 @@ public class Network * @param tcpPort The port upon which the TCP hosting will listen for new connections. * @param udpPort The port upon which the UDP hosting will listen for new 'fast' UDP * messages. Set to -1 if 'fast' traffic should go over TCP. This will - * comletely disable UDP traffic for this server. + * completely disable UDP traffic for this server. */ public static Server createServer( String gameName, int version, int tcpPort, int udpPort ) throws IOException { @@ -164,7 +165,7 @@ public class Network UdpConnector fast = remoteUdpPort == -1 ? null : new UdpConnector( remoteAddress, remoteUdpPort ); SocketConnector reliable = new SocketConnector( remoteAddress, hostPort ); - return new DefaultClient( gameName, version, reliable, fast ); + return new DefaultClient( gameName, version, reliable, fast, new TcpConnectorFactory(remoteAddress) ); } @@ -185,7 +186,7 @@ public class Network UdpConnector fast = new UdpConnector( address, remoteUdpPort ); SocketConnector reliable = new SocketConnector( address, port ); - setConnectors( reliable, fast ); + setPrimaryConnectors( reliable, fast, new TcpConnectorFactory(address) ); } } } diff --git a/engine/src/networking/com/jme3/network/Server.java b/engine/src/networking/com/jme3/network/Server.java index 8a1b2cfb2..4099340a5 100644 --- a/engine/src/networking/com/jme3/network/Server.java +++ b/engine/src/networking/com/jme3/network/Server.java @@ -76,12 +76,39 @@ public interface Server */ public void broadcast( Filter filter, Message message ); + /** + * Sends the specified message over the specified alternate channel to all connected + * clients that match the filter. If no filter is specified then this is the same as + * calling broadcast(message) and the message will be delivered to + * all connections. + *

Examples:

+ *
+     *    // Broadcast to connections: conn1, conn2, and conn3
+     *    server.broadcast( Filters.in( conn1, conn2, conn3 ), message );
+     *
+     *    // Broadcast to all connections exception source
+     *    server.broadcast( Filters.notEqualTo( source ), message );
+     *  
+ */ + public void broadcast( int channel, Filter filter, Message message ); + /** * Start the server so that it will began accepting new connections * and processing messages. */ public void start(); + /** + * Adds an alternate channel to the server, using the specified port. This is an + * entirely separate connection where messages are sent and received in parallel + * to the two primary default channels. All channels must be added before the connection + * is started. + * Returns the ID of the created channel for use when specifying the channel in send or + * broadcast calls. The ID is returned entirely out of convenience since the IDs + * are predictably incremented. The first channel is 0, second is 1, and so on. + */ + public int addChannel( int port ); + /** * Returns true if the server has been started. */ diff --git a/engine/src/networking/com/jme3/network/base/ConnectorFactory.java b/engine/src/networking/com/jme3/network/base/ConnectorFactory.java new file mode 100644 index 000000000..375e91e21 --- /dev/null +++ b/engine/src/networking/com/jme3/network/base/ConnectorFactory.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2011 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jme3.network.base; + +import com.jme3.network.kernel.Connector; +import java.io.IOException; + + +/** + * Creates Connectors for a specific host. + * + * @version $Revision$ + * @author Paul Speed + */ +public interface ConnectorFactory +{ + public Connector createConnector( int channel, int port ) throws IOException; +} diff --git a/engine/src/networking/com/jme3/network/base/DefaultClient.java b/engine/src/networking/com/jme3/network/base/DefaultClient.java index 3b3e5f022..e84692f3a 100644 --- a/engine/src/networking/com/jme3/network/base/DefaultClient.java +++ b/engine/src/networking/com/jme3/network/base/DefaultClient.java @@ -35,8 +35,10 @@ package com.jme3.network.base; import com.jme3.network.ClientStateListener.DisconnectInfo; import com.jme3.network.*; import com.jme3.network.kernel.Connector; +import com.jme3.network.message.ChannelInfoMessage; import com.jme3.network.message.ClientRegistrationMessage; import com.jme3.network.message.DisconnectMessage; +import java.io.IOException; import java.nio.ByteBuffer; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; @@ -62,6 +64,7 @@ public class DefaultClient implements Client // separate. private static final int CH_RELIABLE = 0; private static final int CH_UNRELIABLE = 1; + private static final int CH_FIRST = 2; private ThreadLocal dataBuffer = new ThreadLocal(); @@ -75,6 +78,8 @@ public class DefaultClient implements Client private List> errorListeners = new CopyOnWriteArrayList>(); private Redispatch dispatcher = new Redispatch(); private List channels = new ArrayList(); + + private ConnectorFactory connectorFactory; public DefaultClient( String gameName, int version ) { @@ -82,13 +87,14 @@ public class DefaultClient implements Client this.version = version; } - public DefaultClient( String gameName, int version, Connector reliable, Connector fast ) + public DefaultClient( String gameName, int version, Connector reliable, Connector fast, + ConnectorFactory connectorFactory ) { this( gameName, version ); - setPrimaryConnectors( reliable, fast ); + setPrimaryConnectors( reliable, fast, connectorFactory ); } - protected void setPrimaryConnectors( Connector reliable, Connector fast ) + protected void setPrimaryConnectors( Connector reliable, Connector fast, ConnectorFactory connectorFactory ) { if( reliable == null ) throw new IllegalArgumentException( "The reliable connector cannot be null." ); @@ -97,6 +103,7 @@ public class DefaultClient implements Client if( !channels.isEmpty() ) throw new IllegalStateException( "Channels already exist." ); + this.connectorFactory = connectorFactory; channels.add(new ConnectorAdapter(reliable, dispatcher, dispatcher, true)); if( fast != null ) { channels.add(new ConnectorAdapter(fast, dispatcher, dispatcher, false)); @@ -203,6 +210,13 @@ public class DefaultClient implements Client send(CH_UNRELIABLE, message, true); } } + + public void send( int channel, Message message ) + { + if( channel < 0 || channel + CH_FIRST >= channels.size() ) + throw new IllegalArgumentException( "Channel is undefined:" + channel ); + send( channel + CH_FIRST, message, true ); + } protected void send( int channel, Message message, boolean waitForConnected ) { @@ -340,6 +354,29 @@ public class DefaultClient implements Client } } + protected void configureChannels( long tempId, int[] ports ) { + + try { + for( int i = 0; i < ports.length; i++ ) { + Connector c = connectorFactory.createConnector( i, ports[i] ); + ConnectorAdapter ca = new ConnectorAdapter(c, dispatcher, dispatcher, true); + int ch = channels.size(); + channels.add( ca ); + + // Need to send the connection its hook-up registration + // and start it. + ca.start(); + ClientRegistrationMessage reg; + reg = new ClientRegistrationMessage(); + reg.setId(tempId); + reg.setReliable(true); + send( ch, reg, false ); + } + } catch( IOException e ) { + throw new RuntimeException( "Error configuring channels", e ); + } + } + protected void dispatch( Message m ) { // Pull off the connection management messages we're @@ -351,7 +388,12 @@ public class DefaultClient implements Client connecting.countDown(); fireConnected(); return; - } if( m instanceof DisconnectMessage ) { + } else if( m instanceof ChannelInfoMessage ) { + // This is an interum step in the connection process and + // now we need to add a bunch of connections + configureChannels( ((ChannelInfoMessage)m).getId(), ((ChannelInfoMessage)m).getPorts() ); + return; + } else if( m instanceof DisconnectMessage ) { // Can't do too much else yet String reason = ((DisconnectMessage)m).getReason(); log.log( Level.SEVERE, "Connection terminated, reason:{0}.", reason ); diff --git a/engine/src/networking/com/jme3/network/base/DefaultServer.java b/engine/src/networking/com/jme3/network/base/DefaultServer.java index 628e8ab54..8b8ed34c6 100644 --- a/engine/src/networking/com/jme3/network/base/DefaultServer.java +++ b/engine/src/networking/com/jme3/network/base/DefaultServer.java @@ -35,8 +35,10 @@ package com.jme3.network.base; import com.jme3.network.*; import com.jme3.network.kernel.Endpoint; import com.jme3.network.kernel.Kernel; +import com.jme3.network.message.ChannelInfoMessage; import com.jme3.network.message.ClientRegistrationMessage; import com.jme3.network.message.DisconnectMessage; +import java.io.IOException; import java.nio.ByteBuffer; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -60,15 +62,17 @@ public class DefaultServer implements Server // unreliable private static final int CH_RELIABLE = 0; private static final int CH_UNRELIABLE = 1; + private static final int CH_FIRST = 2; private boolean isRunning = false; private AtomicInteger nextId = new AtomicInteger(0); private String gameName; private int version; - //private KernelFactory kernelFactory = KernelFactory.DEFAULT; + private KernelFactory kernelFactory = KernelFactory.DEFAULT; private KernelAdapter reliableAdapter; private KernelAdapter fastAdapter; private List channels = new ArrayList(); + private List alternatePorts = new ArrayList(); private Redispatch dispatcher = new Redispatch(); private Map connections = new ConcurrentHashMap(); private Map endpointConnections @@ -109,6 +113,42 @@ public class DefaultServer implements Server return version; } + public int addChannel( int port ) + { + if( isRunning ) + throw new IllegalStateException( "Channels cannot be added once server is started." ); + + // Note: it does bug me that channels aren't 100% universal and + // setup externally but it requires a more invasive set of changes + // for "connection types" and some kind of registry of kernel and + // connector factories. This really would be the best approach and + // would allow all kinds of channel customization maybe... but for + // now, we hard-code the standard connections and treat the +2 extras + // differently. + + // Check for consistency with the channels list + if( channels.size() - CH_FIRST != alternatePorts.size() ) + throw new IllegalStateException( "Channel and port lists do not match." ); + + try { + int result = alternatePorts.size(); + alternatePorts.add(port); + + Kernel kernel = kernelFactory.createKernel(result, port); + channels.add( new KernelAdapter(this, kernel, dispatcher, true) ); + + return result; + } catch( IOException e ) { + throw new RuntimeException( "Error adding channel for port:" + port, e ); + } + } + + protected void checkChannel( int channel ) + { + if( channel < 0 || channel >= alternatePorts.size() ) + throw new IllegalArgumentException( "Channel is undefined:" + channel ); + } + public void start() { if( isRunning ) @@ -163,7 +203,6 @@ public class DefaultServer implements Server FilterAdapter adapter = filter == null ? null : new FilterAdapter(filter); - // Ignore the filter for the moment if( message.isReliable() || fastAdapter == null ) { // Don't need to copy the data because message protocol is already // giving us a fresh buffer @@ -173,6 +212,20 @@ public class DefaultServer implements Server } } + public void broadcast( int channel, Filter filter, Message message ) + { + if( connections.isEmpty() ) + return; + + checkChannel(channel); + + ByteBuffer buffer = MessageProtocol.messageToBuffer(message, null); + + FilterAdapter adapter = filter == null ? null : new FilterAdapter(filter); + + channels.get(channel+CH_FIRST).broadcast( adapter, buffer, true, false ); + } + public HostedConnection getConnection( int id ) { return connections.get(id); @@ -295,7 +348,10 @@ public class DefaultServer implements Server } // Else send the extra channel information to the client - // TBD + if( !alternatePorts.isEmpty() ) { + ChannelInfoMessage cim = new ChannelInfoMessage( m.getId(), alternatePorts ); + c.send(cim); + } } if( c.isComplete() ) { @@ -349,7 +405,7 @@ public class DefaultServer implements Server // closed already. // Also note: this method will be called multiple times per - // HostedConnection if it has two endpoints. + // HostedConnection if it has multiple endpoints. Connection removed = null; synchronized( this ) { @@ -431,6 +487,13 @@ public class DefaultServer implements Server channels[CH_UNRELIABLE].send( buffer ); } } + + public void send( int channel, Message message ) + { + checkChannel(channel); + ByteBuffer buffer = MessageProtocol.messageToBuffer(message, null); + channels[channel+CH_FIRST].send(buffer); + } protected void closeConnection() { diff --git a/engine/src/networking/com/jme3/network/base/KernelFactory.java b/engine/src/networking/com/jme3/network/base/KernelFactory.java new file mode 100644 index 000000000..ca1ce4852 --- /dev/null +++ b/engine/src/networking/com/jme3/network/base/KernelFactory.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jme3.network.base; + +import com.jme3.network.kernel.Kernel; +import java.io.IOException; + + +/** + * Supplied to the DefaultServer to create any additional + * channel kernels that might be required. + * + * @version $Revision$ + * @author Paul Speed + */ +public interface KernelFactory +{ + public static final KernelFactory DEFAULT = new NioKernelFactory(); + + public Kernel createKernel( int channel, int port ) throws IOException; +} diff --git a/engine/src/networking/com/jme3/network/base/NioKernelFactory.java b/engine/src/networking/com/jme3/network/base/NioKernelFactory.java new file mode 100644 index 000000000..79b08def4 --- /dev/null +++ b/engine/src/networking/com/jme3/network/base/NioKernelFactory.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jme3.network.base; + +import com.jme3.network.kernel.Kernel; +import com.jme3.network.kernel.tcp.SelectorKernel; +import java.io.IOException; + + +/** + * KernelFactory implemention for creating TCP kernels + * using the NIO selector model. + * + * @version $Revision$ + * @author Paul Speed + */ +public class NioKernelFactory implements KernelFactory +{ + public Kernel createKernel( int channel, int port ) throws IOException + { + return new SelectorKernel(port); + } +} diff --git a/engine/src/networking/com/jme3/network/base/TcpConnectorFactory.java b/engine/src/networking/com/jme3/network/base/TcpConnectorFactory.java new file mode 100644 index 000000000..c0de8d397 --- /dev/null +++ b/engine/src/networking/com/jme3/network/base/TcpConnectorFactory.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2011 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jme3.network.base; + +import com.jme3.network.kernel.Connector; +import com.jme3.network.kernel.tcp.SocketConnector; +import java.io.IOException; +import java.net.InetAddress; + + +/** + * Creates TCP connectors to a specific remote address. + * + * @version $Revision$ + * @author Paul Speed + */ +public class TcpConnectorFactory implements ConnectorFactory +{ + private InetAddress remoteAddress; + + public TcpConnectorFactory( InetAddress remoteAddress ) + { + this.remoteAddress = remoteAddress; + } + + public Connector createConnector( int channel, int port ) throws IOException + { + return new SocketConnector( remoteAddress, port ); + } +} diff --git a/engine/src/networking/com/jme3/network/message/ChannelInfoMessage.java b/engine/src/networking/com/jme3/network/message/ChannelInfoMessage.java new file mode 100644 index 000000000..91e54bc6b --- /dev/null +++ b/engine/src/networking/com/jme3/network/message/ChannelInfoMessage.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2011 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jme3.network.message; + +import com.jme3.network.AbstractMessage; +import com.jme3.network.serializing.Serializable; +import java.util.Arrays; +import java.util.List; + +/** + * Contains information about any extra server channels (if they exist). + * + * @author Paul Speed + */ +@Serializable() +public class ChannelInfoMessage extends AbstractMessage { + private long id; + private int[] ports; + + public ChannelInfoMessage() { + super( true ); + } + + public ChannelInfoMessage( long id, List ports ) { + super( true ); + this.id = id; + this.ports = new int[ports.size()]; + for( int i = 0; i < ports.size(); i++ ) { + this.ports[i] = ports.get(i); + } + } + + public long getId() { + return id; + } + + public int[] getPorts() { + return ports; + } + + public String toString() { + return "ChannelInfoMessage[" + id + ", " + Arrays.asList(ports) + "]"; + } +} diff --git a/engine/src/networking/com/jme3/network/serializing/Serializer.java b/engine/src/networking/com/jme3/network/serializing/Serializer.java index 11773b737..a4e197123 100644 --- a/engine/src/networking/com/jme3/network/serializing/Serializer.java +++ b/engine/src/networking/com/jme3/network/serializing/Serializer.java @@ -33,6 +33,7 @@ package com.jme3.network.serializing; import com.jme3.math.Vector3f; +import com.jme3.network.message.ChannelInfoMessage; import com.jme3.network.message.ClientRegistrationMessage; import com.jme3.network.message.DisconnectMessage; import com.jme3.network.message.GZIPCompressedMessage; @@ -126,6 +127,7 @@ public abstract class Serializer { registerClass(DisconnectMessage.class); registerClass(ClientRegistrationMessage.class); + registerClass(ChannelInfoMessage.class); } /**