public DefaultServer( String gameName, int version, Kernel reliable, Kernel fast ) { if( reliable == null ) throw new IllegalArgumentException( "Default server reqiures a reliable kernel instance." ); this.gameName = gameName; this.version = version; this.services = new HostedServiceManager(this); addStandardServices(); reliableAdapter = new KernelAdapter( this, reliable, dispatcher, true ); channels.add( reliableAdapter ); if( fast != null ) { fastAdapter = new KernelAdapter( this, fast, dispatcher, false ); channels.add( fastAdapter ); } }
@Override public void close() { if( !isRunning ) throw new IllegalStateException( "Server is not started." ); // First stop the services since we are about to // kill the connections they are using services.stop(); try { // Kill the adpaters, they will kill the kernels for( KernelAdapter ka : channels ) { ka.close(); } isRunning = false; // Now terminate all of the services services.terminate(); } catch( InterruptedException e ) { throw new RuntimeException( "Interrupted while closing", e ); } }
protected void createAndDispatch( EndpointEvent event ) { // Only need to tell the server about disconnects if( event.getType() == EndpointEvent.Type.REMOVE ) { connectionClosed( event.getEndpoint() ); } }
protected void flushEvents() { EndpointEvent event; while( (event = kernel.nextEvent()) != null ) { try { createAndDispatch( event ); } catch( Exception e ) { reportError(event.getEndpoint(), event, e); } } }
public void run() { while( go.get() ) { try { // Check for pending events flushEvents(); // 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 // when the connection add events come through flushEvents(); try { createAndDispatch( e ); } catch( Exception ex ) { reportError(e.getSource(), e, ex); } } catch( InterruptedException ex ) { if( !go.get() ) return; throw new RuntimeException( "Unexpected interruption", ex ); } } }
HostedConnection source = getConnection(p); if( source == null ) { if( reliable ) { reportError(p, m, e);
protected void createAndDispatch( Envelope env ) { MessageProtocol protocol = getMessageBuffer(env.getSource()); byte[] data = env.getData(); ByteBuffer buffer = ByteBuffer.wrap(data); int count = protocol.addBuffer( buffer ); 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.FINE, "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; while( (m = protocol.getMessage()) != null ) { m.setReliable(reliable); dispatch( env.getSource(), m ); } }
public KernelAdapter( DefaultServer server, Kernel kernel, MessageListener<HostedConnection> messageDispatcher, boolean reliable ) { super( String.valueOf(kernel) ); this.server = server; this.kernel = kernel; this.messageDispatcher = messageDispatcher; this.reliable = reliable; setDaemon(true); }
public void run() { while( go.get() ) { try { // Check for pending events flushEvents(); // 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 // when the connection add events come through flushEvents(); try { createAndDispatch( e ); } catch( Exception ex ) { reportError(e.getSource(), e, ex); } } catch( InterruptedException ex ) { if( !go.get() ) return; throw new RuntimeException( "Unexpected interruption", ex ); } } }
protected void flushEvents() { EndpointEvent event; while( (event = kernel.nextEvent()) != null ) { try { createAndDispatch( event ); } catch( Exception e ) { reportError(event.getEndpoint(), event, e); } } }
protected void createAndDispatch( Envelope env ) { MessageProtocol protocol = getMessageBuffer(env.getSource()); byte[] data = env.getData(); ByteBuffer buffer = ByteBuffer.wrap(data); int count = protocol.addBuffer( buffer ); 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.FINE, "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; while( (m = protocol.getMessage()) != null ) { m.setReliable(reliable); dispatch( env.getSource(), m ); } }
HostedConnection source = getConnection(p); if( source == null ) { if( reliable ) { reportError(p, m, e);
public KernelAdapter( DefaultServer server, Kernel kernel, MessageListener<HostedConnection> messageDispatcher, boolean reliable ) { super( String.valueOf(kernel) ); this.server = server; this.kernel = kernel; this.messageDispatcher = messageDispatcher; this.reliable = reliable; setDaemon(true); }
public void run() { while( go.get() ) { try { // Check for pending events flushEvents(); // 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 // when the connection add events come through flushEvents(); try { createAndDispatch( e ); } catch( Exception ex ) { reportError(e.getSource(), e, ex); } } catch( InterruptedException ex ) { if( !go.get() ) return; throw new RuntimeException( "Unexpected interruption", ex ); } } }
protected void flushEvents() { EndpointEvent event; while( (event = kernel.nextEvent()) != null ) { try { createAndDispatch( event ); } catch( Exception e ) { reportError(event.getEndpoint(), event, e); } } }
protected void createAndDispatch( Envelope env ) { MessageProtocol protocol = getMessageBuffer(env.getSource()); byte[] data = env.getData(); ByteBuffer buffer = ByteBuffer.wrap(data); int count = protocol.addBuffer( buffer ); 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; while( (m = protocol.getMessage()) != null ) { m.setReliable(reliable); dispatch( env.getSource(), m ); } }
HostedConnection source = getConnection(p); if( source == null ) { if( reliable ) { reportError(p, m, e);
@Override 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 createAndDispatch( EndpointEvent event ) { // Only need to tell the server about disconnects if( event.getType() == EndpointEvent.Type.REMOVE ) { connectionClosed( event.getEndpoint() ); } }
public KernelAdapter( DefaultServer server, Kernel kernel, MessageListener<HostedConnection> messageDispatcher, boolean reliable ) { super( String.valueOf(kernel) ); this.server = server; this.kernel = kernel; this.messageDispatcher = messageDispatcher; this.reliable = reliable; setDaemon(true); }