From e84d8300ddcea0c50f65b0ef1b389b8c15e22c0f Mon Sep 17 00:00:00 2001 From: "PSp..om" Date: Fri, 16 Dec 2011 10:28:50 +0000 Subject: [PATCH] Modified Client/Server to support alternate channels. The server can configure additional ports that will be sent to the client upon connection. These channels can be used to send messages in parallel to the normal messages. This is useful to keeping several separate command pathways flowing smoothly despite potentially large messages on one channel. git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8938 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- .../networking/com/jme3/network/Client.java | 6 ++ .../com/jme3/network/MessageConnection.java | 6 ++ .../networking/com/jme3/network/Network.java | 7 +- .../networking/com/jme3/network/Server.java | 27 +++++++ .../jme3/network/base/ConnectorFactory.java | 48 ++++++++++++ .../com/jme3/network/base/DefaultClient.java | 50 ++++++++++++- .../com/jme3/network/base/DefaultServer.java | 71 +++++++++++++++++- .../com/jme3/network/base/KernelFactory.java | 51 +++++++++++++ .../jme3/network/base/NioKernelFactory.java | 53 +++++++++++++ .../network/base/TcpConnectorFactory.java | 60 +++++++++++++++ .../network/message/ChannelInfoMessage.java | 74 +++++++++++++++++++ .../jme3/network/serializing/Serializer.java | 2 + 12 files changed, 444 insertions(+), 11 deletions(-) create mode 100644 engine/src/networking/com/jme3/network/base/ConnectorFactory.java create mode 100644 engine/src/networking/com/jme3/network/base/KernelFactory.java create mode 100644 engine/src/networking/com/jme3/network/base/NioKernelFactory.java create mode 100644 engine/src/networking/com/jme3/network/base/TcpConnectorFactory.java create mode 100644 engine/src/networking/com/jme3/network/message/ChannelInfoMessage.java 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); } /**