@ -34,7 +34,9 @@ package com.jme3.network.base;
import java.io.IOException ;
import java.nio.ByteBuffer ;
import java.util.Map ;
import java.util.concurrent.atomic.AtomicBoolean ;
import java.util.concurrent.ConcurrentHashMap ;
import java.util.logging.Level ;
import java.util.logging.Logger ;
@ -69,6 +71,10 @@ public class KernelAdapter extends Thread
private Kernel kernel ;
private MessageListener < HostedConnection > messageDispatcher ;
private AtomicBoolean go = new AtomicBoolean ( true ) ;
// Keeps track of the in-progress messages that are received
// on reliable connections
private Map < Endpoint , MessageProtocol > messageBuffers = new ConcurrentHashMap < Endpoint , MessageProtocol > ( ) ;
// Marks the messages as reliable or not if they came
// through this connector.
@ -107,6 +113,10 @@ public class KernelAdapter extends Thread
protected void connectionClosed ( Endpoint p )
{
// Remove any message buffer we've been accumulating
// on behalf of this endpoing
messageBuffers . remove ( p ) ;
server . connectionClosed ( p ) ;
}
@ -156,16 +166,49 @@ public class KernelAdapter extends Thread
}
}
protected MessageProtocol getMessageBuffer ( Endpoint p )
{
if ( ! reliable ) {
// Since UDP comes in packets and they aren't split
// up, there is no reason to buffer. In fact, there would
// be a down side because there is no way for us to reliably
// clean these up later since we'd create another one for
// any random UDP packet that comes to the port.
return new MessageProtocol ( ) ;
} else {
// See if we already have one
MessageProtocol result = messageBuffers . get ( p ) ;
if ( result ! = null ) {
result = new MessageProtocol ( ) ;
messageBuffers . put ( p , result ) ;
}
return result ;
}
}
protected void createAndDispatch ( Envelope env )
{
MessageProtocol protocol = new MessageProtocol ( ) ;
MessageProtocol protocol = getMessageBuffer ( env . getSource ( ) ) ;
byte [ ] data = env . getData ( ) ;
ByteBuffer buffer = ByteBuffer . wrap ( data ) ;
int count = protocol . addBuffer ( buffer ) ;
if ( count = = 0 )
throw new RuntimeException ( "Envelope contained incomplete data:" + env ) ;
if ( count = = 0 ) {
// This can happen if there was only a partial message
// received. However, this should never happen for unreliable
// connections.
if ( ! reliable ) {
// Log some additional information about the packet.
int len = Math . min ( 10 , data . length ) ;
StringBuilder sb = new StringBuilder ( ) ;
for ( int i = 0 ; i < len ; i + + ) {
sb . append ( "[" + Integer . toHexString ( data [ i ] ) + "]" ) ;
}
log . log ( Level . INFO , "First 10 bytes of incomplete nessage:" + sb ) ;
throw new RuntimeException ( "Envelope contained incomplete data:" + env ) ;
}
}
// Should be complete... and maybe we should check but we don't
Message m = null ;