/* ** j###t ########## #### #### ** j###t ########## #### #### ** j###T "###L J###" ** ######P' ########## ######### ** ######k, ########## T######T ** ####~###L #### ** #### q###L ########## .##### ** #### \###L ########## #####" ** ** $Id$ ** ** Class History ** ** Date Name Description ** ---------|------------|----------------------------------------------- ** 19Aug98 subtle start of recorded history ** */ package key; import java.net.*; import java.io.*; import java.util.Vector; /** * This class is a thread which opens and binds a port, * creating new instances of 'InteractiveConnectionion' to * deal with each connection request that comes in. */ public class TelnetConnectPort extends Daemon { private static final long serialVersionUID = -9053728784766596365L; public static final AtomicElement[] ELEMENTS = { AtomicElement.construct( TelnetConnectPort.class, Integer.TYPE, "port", AtomicElement.PUBLIC_FIELD | AtomicElement.READ_ONLY, "the port number connections are being accepted on" ) }; public static final AtomicStructure STRUCTURE = new AtomicStructure( Daemon.STRUCTURE, ELEMENTS ); // sleep for 5 minutes when we exceed our limit of connections public static final int SLEEP_DURATION = 5 * 60 * 1000; public int port = 2809; private transient ServerSocket socket = null; public TelnetConnectPort() { } public TelnetConnectPort( int portNumber ) { port = portNumber; } public TelnetConnectPort( Object key, int portNumber ) { port = portNumber; setKey( key ); } public AtomicStructure getDeclaredStructure() { return( STRUCTURE ); } public void argument( String args ) { if( args.length() > 0 ) { try { port = Integer.parseInt( args ); } catch( NumberFormatException e ) { throw new IllegalArgumentException( "'" + args + "' is not an integer port number" ); } } } public void run() { while( true ) { try { serveRequests(); } catch( Throwable t ) { if( t instanceof ThreadDeath ) throw (ThreadDeath) t; else Log.fatal( this, t.toString() ); } } } private static final String CONNECTION_LOG = "connection"; private void serveRequests() { if( socket != null ) { try { socket.close(); } catch( Exception e ) { } socket = null; } try { socket = new ServerSocket( port ); } catch( java.io.IOException e ) { Log.error( e ); Log.fatal( this, e.toString() ); } InetAddress ourAddress = socket.getInetAddress(); String hn = ourAddress.getHostName(); Log.log( CONNECTION_LOG, "'" + hn + " " + port + "' initialised" ); TelnetIC tc = null; ConnectingPlayer cp = null; Socket thisConnection = null; try { while( true ) { try { thisConnection = socket.accept(); } catch( java.net.SocketException e ) { // this almost certainly means we've been killed socket.close(); Log.error( e ); break; } // not all these options are supported on all platforms, // but we want to try each of them in case: try { // linger for up to three seconds thisConnection.setSoLinger( true, 300 ); } catch( java.net.SocketException e ) { } try { // timeout in an hour of no data thisConnection.setSoTimeout( 60 * 60 * 1000 ); } catch( java.net.SocketException e ) { } try { // ensure we're waiting for packets thisConnection.setTcpNoDelay( false ); } catch( java.net.SocketException e ) { } try { tc = new TelnetIC( thisConnection ); } catch( IOException e ) { continue; } catch( LimitExceededException e ) { // generally means we've exceeded our // limit of sockets, or something // really funny has happened try { Thread.sleep( SLEEP_DURATION ); } catch( InterruptedException ex ) { } continue; } Site site = tc.getSite(); tc.send( "site is " + site.toString() ); if( !site.connectionsAllowed() ) { TextParagraph siteBanned = (TextParagraph) Key.instance().getOnline().getElement( "siteban" ); if ( siteBanned == null ) tc.send( "\n\nThis site has been completely banned.\n\n" ); else tc.send( siteBanned, false ); tc.close(); } else { cp = new ConnectingPlayer(); tc.interactWith( cp ); tc.start(); } // clean up our references so that they // can be garbage collected cp = null; tc = null; thisConnection = null; yield(); } } catch( Exception e ) { if( Key.isRunning() ) { Log.error( "during scan", e ); } } catch( Error e ) { Log.error( e ); throw e; } } }