diff --git a/engine/src/networking/com/jme3/network/base/KernelAdapter.java b/engine/src/networking/com/jme3/network/base/KernelAdapter.java index 8c5d5576c..55599ef13 100644 --- a/engine/src/networking/com/jme3/network/base/KernelAdapter.java +++ b/engine/src/networking/com/jme3/network/base/KernelAdapter.java @@ -140,7 +140,9 @@ public class KernelAdapter extends Thread byte[] data = env.getData(); ByteBuffer buffer = ByteBuffer.wrap(data); - protocol.addBuffer( buffer ); + int count = protocol.addBuffer( buffer ); + if( count == 0 ) + throw new RuntimeException( "Envelope contained incomplete data:" + env ); // Should be complete... and maybe we should check but we don't Message m = null; @@ -153,7 +155,7 @@ public class KernelAdapter extends Thread protected void createAndDispatch( EndpointEvent event ) { // Only need to tell the server about disconnects - if( event.getType() == EndpointEvent.Type.REMOVE ) { + if( event.getType() == EndpointEvent.Type.REMOVE ) { connectionClosed( event.getEndpoint() ); } } @@ -177,6 +179,8 @@ public class KernelAdapter extends Thread // Grab the next envelope Envelope e = kernel.read(); + if( e == Kernel.EVENTS_PENDING ) + continue; // We'll catch it up above // Check for pending events that might have // come in while we were blocking. This is usually diff --git a/engine/src/networking/com/jme3/network/kernel/Kernel.java b/engine/src/networking/com/jme3/network/kernel/Kernel.java index efb2bfdb7..5e456dca0 100644 --- a/engine/src/networking/com/jme3/network/kernel/Kernel.java +++ b/engine/src/networking/com/jme3/network/kernel/Kernel.java @@ -46,6 +46,13 @@ import com.jme3.network.Filter; */ public interface Kernel { + /** + * A marker envelope returned from read() that indicates that + * there are events pending. This allows a single thread to + * more easily process the envelopes and endpoint events. + */ + public static final Envelope EVENTS_PENDING = new Envelope( null, new byte[0], false ); + /** * Initializes the kernel and starts any internal processing. */ diff --git a/engine/src/networking/com/jme3/network/kernel/tcp/SelectorKernel.java b/engine/src/networking/com/jme3/network/kernel/tcp/SelectorKernel.java index 7840f7114..cc74730c0 100644 --- a/engine/src/networking/com/jme3/network/kernel/tcp/SelectorKernel.java +++ b/engine/src/networking/com/jme3/network/kernel/tcp/SelectorKernel.java @@ -160,11 +160,22 @@ public class SelectorKernel extends AbstractKernel protected void removeEndpoint( NioEndpoint p, SocketChannel c ) { +System.out.println( "removeEndpoint(" + p + ", " + c + ")" ); endpoints.remove( p.getId() ); // Enqueue an endpoint event for the listeners addEvent( EndpointEvent.createRemove( this, p ) ); - } + + // If there are no pending messages then add one so that the + // kernel-user knows to wake up if it is only listening for + // envelopes. + if( !hasEnvelopes() ) { + // Note: this is not really a race condition. At worst, our + // event has already been handled by now and it does no harm + // to check again. + addEnvelope( EVENTS_PENDING ); + } + } /** * Called by the endpoints when they need to be closed. @@ -393,7 +404,11 @@ public class SelectorKernel extends AbstractKernel i.remove(); if( !key.isValid() ) + { + // When does this happen? + log.log( Level.INFO, "Key is not valid:{0}.", key ); continue; + } if( key.isAcceptable() ) accept(key);