You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ak...@apache.org on 2004/09/18 06:16:58 UTC

svn commit: rev 46294 - in incubator/directory/seda/trunk/src: java/org/apache/seda/listener java/org/apache/seda/protocol test/org/apache/seda test/org/apache/seda/listener

Author: akarasulu
Date: Fri Sep 17 21:16:56 2004
New Revision: 46294

Added:
   incubator/directory/seda/trunk/src/java/org/apache/seda/listener/AvailablePortFinder.java   (contents, props changed)
   incubator/directory/seda/trunk/src/test/org/apache/seda/listener/AvailablePortFinderTest.java   (contents, props changed)
   incubator/directory/seda/trunk/src/test/org/apache/seda/listener/TCPListenerManagerTest.java
      - copied, changed from rev 46270, incubator/directory/seda/trunk/src/test/org/apache/seda/listener/DefaultListenerManagerTest.java
Removed:
   incubator/directory/seda/trunk/src/test/org/apache/seda/listener/DefaultListenerManagerTest.java
Modified:
   incubator/directory/seda/trunk/src/java/org/apache/seda/protocol/DefaultInetServicesDatabase.java
   incubator/directory/seda/trunk/src/java/org/apache/seda/protocol/InetServicesDatabase.java
   incubator/directory/seda/trunk/src/test/org/apache/seda/DefaultFrontendFactoryTest.java
Log:
Commit changes ...

Summary: added Trustin's patch for port scans

 o added Trustin's port scanner patch for servers
 o changed name of DefaultListenerManagerTest to TCPListenerManagerTest
 o added code to allow DefaultInetServicesDatabase to add entries after 
   database creation for changes to non-standard service locations which
   may be needed to test the code in test cases
 o changes test cases to use Trustin's port scanner
 o added more code to port scanner to make it just return next available free
   port in addition to a set of ports - this makes it return faster
 o changed test case in Trustin's patch to not scan the whole range and to
   now test the new methods
 o added ASF boiler plate for ASL 2.0 to Trustin's patches



Added: incubator/directory/seda/trunk/src/java/org/apache/seda/listener/AvailablePortFinder.java
==============================================================================
--- (empty file)
+++ incubator/directory/seda/trunk/src/java/org/apache/seda/listener/AvailablePortFinder.java	Fri Sep 17 21:16:56 2004
@@ -0,0 +1,177 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.seda.listener;
+
+
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.NoSuchElementException;
+import java.net.ServerSocket;
+import java.io.IOException;
+
+
+/**
+ * Finds currently available server ports.
+ *
+ * @author Trustin Lee
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ * @see <a href="http://www.iana.org/assignments/port-numbers">
+ */
+public class AvailablePortFinder {
+
+    /**
+     * The minimum number of server port number.
+     */
+    public static final int MIN_PORT_NUMBER = 0;
+
+    /**
+     * The maximum number of server port number.
+     */
+    public static final int MAX_PORT_NUMBER = 49151;
+
+
+    /**
+     * Creates a new instance.
+     */
+    public AvailablePortFinder()
+    {
+    }
+
+
+    /**
+     * Returns the {@link Set} of currently available port numbers
+     * ({@link Integer}).  This method is identical to
+     * <code>getAvailablePorts(MIN_PORT_NUMBER, MAX_PORT_NUMBER)</code>.
+     *
+     * WARNING: this can take a very long time.
+     */
+    public Set getAvailablePorts()
+    {
+        return getAvailablePorts( MIN_PORT_NUMBER, MAX_PORT_NUMBER ) ;
+    }
+
+
+    /**
+     * Gets the next available port starting at the lowest port number.
+     *
+     * @throws NoSuchElementException if there are no ports available
+     */
+    public static int getNextAvailable()
+    {
+        return getNextAvailable( MIN_PORT_NUMBER );
+    }
+
+
+    /**
+     * Gets the next available port starting at a port.
+     *
+     * @param fromPort the port to scan for availability
+     * @throws NoSuchElementException if there are no ports available
+     */
+    public static int getNextAvailable( int fromPort )
+    {
+        if ( fromPort < MIN_PORT_NUMBER || fromPort > MAX_PORT_NUMBER )
+        {
+            throw new IllegalArgumentException( "Invalid start port: " +
+                fromPort );
+        }
+
+        for ( int i = fromPort; i <= MAX_PORT_NUMBER; i++ )
+        {
+            ServerSocket s = null;
+
+            try
+            {
+                s = new ServerSocket( i );
+                return i;
+            }
+            catch ( IOException e )
+            {
+            }
+            finally
+            {
+                if ( s != null )
+                {
+                    try
+                    {
+                        s.close();
+                    }
+                    catch ( IOException e )
+                    {
+                        /* should not be thrown */
+                    }
+                }
+            }
+        }
+
+        throw new NoSuchElementException( "Could not find an available port " +
+            "above " + fromPort );
+    }
+
+
+    /**
+     * Returns the {@link Set| of currently avaliable port numbers ({@link Integer})
+     * between the specified port range.
+     *
+     * @throws IllegalArgumentException if port range is not between
+     * {@link MIN_PORT_NUMBER} and {@link MAX_PORT_NUMBER} or
+     * <code>fromPort</code> if greater than <code>toPort</code>.
+     */
+    public Set getAvailablePorts( int fromPort, int toPort )
+    {
+        if ( fromPort < MIN_PORT_NUMBER ||
+            toPort > MAX_PORT_NUMBER ||
+            fromPort > toPort )
+        {
+            throw new IllegalArgumentException( "Invalid port range: " +
+                fromPort + " ~ " + toPort );
+        }
+
+        Set result = new TreeSet();
+
+        for ( int i = fromPort; i <= toPort; i++ )
+        {
+            ServerSocket s = null;
+
+            try
+            {
+                s = new ServerSocket( i );
+                result.add( new Integer( i ) );
+            }
+            catch ( IOException e )
+            {
+            }
+            finally
+            {
+                if ( s != null )
+                {
+                    try
+                    {
+                        s.close();
+                    }
+                    catch ( IOException e )
+                    {
+                        /* should not be thrown */
+                    }
+                }
+            }
+        }
+
+        return result;
+    }
+}

Modified: incubator/directory/seda/trunk/src/java/org/apache/seda/protocol/DefaultInetServicesDatabase.java
==============================================================================
--- incubator/directory/seda/trunk/src/java/org/apache/seda/protocol/DefaultInetServicesDatabase.java	(original)
+++ incubator/directory/seda/trunk/src/java/org/apache/seda/protocol/DefaultInetServicesDatabase.java	Fri Sep 17 21:16:56 2004
@@ -35,6 +35,7 @@
     /** maps a port number to the authoritative service protocol name */
     private final Map protoByPort = new HashMap();
 
+
     public DefaultInetServicesDatabase( InetServiceEntry[] entries )
     {
         for ( int ii = 0; ii < entries.length; ii++ )
@@ -60,6 +61,69 @@
 
             // now map the port to the auth service name (protocol)
             protoByPort.put( iport, entries[ii].getName() );
+        }
+    }
+
+
+    /**
+     * Adds an entry to this database removing any other entry with the same
+     * port and authoritative service protocol identifier.
+     *
+     * @param entry the entry to add
+     */
+    public void addEntry( InetServiceEntry entry )
+    {
+        Integer iport = new Integer( entry.getPort() );
+
+        if ( protoByPort.containsKey( iport ) )
+        {
+            protoByPort.remove( iport );
+        }
+        protoByPort.put( iport, entry.getName() );
+
+        ArrayList list = null;
+        if ( entriesByPort.containsKey( iport ) )
+        {
+            list = ( ArrayList ) entriesByPort.get( iport );
+            for ( int ii = 0; ii < list.size(); ii++ )
+            {
+                InetServiceEntry ise = ( InetServiceEntry ) list.get( ii );
+                if ( ise != null && ise.getProtocol() == entry.getProtocol() )
+                {
+                    list.remove( ise );
+                }
+            }
+
+            list.add( entry );
+        }
+        else
+        {
+            list = new ArrayList( 2 );
+            list.add( entry );
+            entriesByPort.put( iport, list );
+        }
+
+
+        if ( entriesByName.containsKey( entry.getName() ) )
+        {
+            list = ( ArrayList ) entriesByName.get( entry.getName() );
+
+            for ( int ii = 0; ii < list.size(); ii++ )
+            {
+                InetServiceEntry ise = ( InetServiceEntry ) list.get( ii );
+                if ( ise != null && ise.getProtocol() == entry.getProtocol() )
+                {
+                    list.remove( ise );
+                }
+            }
+
+            list.add( entry );
+        }
+        else
+        {
+            list = new ArrayList( 2 );
+            list.add( entry );
+            entriesByName.put( entry.getName(), list );
         }
     }
 

Modified: incubator/directory/seda/trunk/src/java/org/apache/seda/protocol/InetServicesDatabase.java
==============================================================================
--- incubator/directory/seda/trunk/src/java/org/apache/seda/protocol/InetServicesDatabase.java	(original)
+++ incubator/directory/seda/trunk/src/java/org/apache/seda/protocol/InetServicesDatabase.java	Fri Sep 17 21:16:56 2004
@@ -17,14 +17,12 @@
 package org.apache.seda.protocol;
 
 
-import org.apache.seda.protocol.InetServiceEntry;
-
 import java.util.Iterator;
 
 
 /**
  * Interface for the internet services database.  The database is used by
- * jinetd to associate services with ports and transport protocols.
+ * seda to associate services with ports and transport protocols.
  *
  * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
  * @version $Rev$
@@ -51,7 +49,7 @@
     Iterator getByPort( int port );
 
     /**
-     * Gets the protocol associated with a port.
+     * Gets the service/protocol associated with a port.
      *
      * @param port the port one which the service resides
      */

Modified: incubator/directory/seda/trunk/src/test/org/apache/seda/DefaultFrontendFactoryTest.java
==============================================================================
--- incubator/directory/seda/trunk/src/test/org/apache/seda/DefaultFrontendFactoryTest.java	(original)
+++ incubator/directory/seda/trunk/src/test/org/apache/seda/DefaultFrontendFactoryTest.java	Fri Sep 17 21:16:56 2004
@@ -21,7 +21,9 @@
 import org.apache.seda.listener.ListenerConfig;
 import org.apache.seda.listener.TCPListenerConfig;
 import org.apache.seda.listener.SocketListenerAddress;
+import org.apache.seda.listener.AvailablePortFinder;
 import org.apache.seda.protocol.InetServiceEntry;
+import org.apache.seda.protocol.DefaultInetServicesDatabase;
 import org.apache.seda.examples.EchoProtocolProvider;
 import org.apache.commons.net.EchoTCPClient;
 
@@ -89,9 +91,10 @@
      */
     public void testBind() throws IOException
     {
+        int port = AvailablePortFinder.getNextAvailable();
         ListenerConfig config = null;
         config = new TCPListenerConfig( new SocketListenerAddress(
-            InetAddress.getLocalHost() ), new InetServiceEntry( "ldap", 10389 ) );
+            InetAddress.getLocalHost() ), new InetServiceEntry( "ldap", port ) );
         fe.getListenerManager().bind( config );
         fe.getListenerManager().unbind( config );
     }
@@ -99,14 +102,18 @@
 
     public void testEcho() throws IOException, InterruptedException
     {
+        InetServiceEntry srvEntry = new InetServiceEntry( "echo",
+            AvailablePortFinder.getNextAvailable( 6666 ) );
+        ( ( DefaultInetServicesDatabase ) fe.getInetServicesDatabase() )
+            .addEntry( srvEntry );
         ListenerConfig config = null;
         config = new TCPListenerConfig( new SocketListenerAddress(
-            InetAddress.getLocalHost() ), new InetServiceEntry( "echo", 7 ) );
+            InetAddress.getLocalHost() ), srvEntry );
         fe.getListenerManager().bind( config );
         fe.register( new EchoProtocolProvider() );
 
         EchoTCPClient client = new EchoTCPClient();
-        client.connect( InetAddress.getLocalHost(), 7 );
+        client.connect( InetAddress.getLocalHost(), srvEntry.getPort() );
         byte[] toSend = "Hello world!".getBytes();
         byte[] recieved = new byte[toSend.length];
         client.getOutputStream().write( toSend );

Added: incubator/directory/seda/trunk/src/test/org/apache/seda/listener/AvailablePortFinderTest.java
==============================================================================
--- (empty file)
+++ incubator/directory/seda/trunk/src/test/org/apache/seda/listener/AvailablePortFinderTest.java	Fri Sep 17 21:16:56 2004
@@ -0,0 +1,86 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.seda.listener;
+
+
+import junit.framework.TestCase;
+import junit.framework.Assert;
+
+
+/**
+ * Tests {@link AvailablePortFinder}.
+ *
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class AvailablePortFinderTest extends TestCase
+{
+    public void testDefault()
+    {
+        AvailablePortFinder finder = new AvailablePortFinder();
+        // this just scan just takes too much time
+        //finder.getAvailablePorts();
+
+        // keep range short so it does not take too long
+        finder.getAvailablePorts( 1024, 1048 );
+    }
+
+
+    public void testExceptions()
+    {
+        AvailablePortFinder finder = new AvailablePortFinder();
+
+        try
+        {
+            finder.getAvailablePorts(
+                AvailablePortFinder.MIN_PORT_NUMBER - 1, 10 );
+            Assert.fail( "IllegalArgumentException must be thrown." );
+        }
+        catch ( IllegalArgumentException e )
+        {
+        }
+
+        try
+        {
+            finder.getAvailablePorts( AvailablePortFinder.MAX_PORT_NUMBER - 1,
+                AvailablePortFinder.MAX_PORT_NUMBER + 1 );
+            Assert.fail( "IllegalArgumentException must be thrown." );
+        }
+        catch ( IllegalArgumentException e )
+        {
+        }
+
+        try
+        {
+            finder.getAvailablePorts( 10, 5 );
+            Assert.fail( "IllegalArgumentException must be thrown." );
+        }
+        catch ( IllegalArgumentException e )
+        {
+        }
+    }
+
+
+    public void testNextAvailable()
+    {
+        int port = AvailablePortFinder.getNextAvailable( 
+            AvailablePortFinder.MIN_PORT_NUMBER );
+        assertTrue( port >= AvailablePortFinder.MIN_PORT_NUMBER );
+        assertTrue( port <= AvailablePortFinder.MAX_PORT_NUMBER );
+        assertEquals( port, AvailablePortFinder.getNextAvailable() );
+    }
+}

Copied: incubator/directory/seda/trunk/src/test/org/apache/seda/listener/TCPListenerManagerTest.java (from rev 46270, incubator/directory/seda/trunk/src/test/org/apache/seda/listener/DefaultListenerManagerTest.java)
==============================================================================
--- incubator/directory/seda/trunk/src/test/org/apache/seda/listener/DefaultListenerManagerTest.java	(original)
+++ incubator/directory/seda/trunk/src/test/org/apache/seda/listener/TCPListenerManagerTest.java	Fri Sep 17 21:16:56 2004
@@ -32,7 +32,7 @@
  * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
  * @version $Rev$
  */
-public class DefaultListenerManagerTest extends TestCase
+public class TCPListenerManagerTest extends TestCase
 {
     /** An event router to use for testing */
     private EventRouter router = null;
@@ -40,7 +40,6 @@
     private TCPListenerManager listener = null;
     
     
-
     /*
      * @see TestCase#setUp()
      */
@@ -71,7 +70,7 @@
      * Constructor for DefaultListenerManagerTest.
      * @param arg0
      */
-    public DefaultListenerManagerTest( String arg0 )
+    public TCPListenerManagerTest( String arg0 )
     {
         super( arg0 );
     }
@@ -79,18 +78,22 @@
 
     public void testBind() throws Exception
     {
-        listener.bind( new TCPListenerConfig(
-            new SocketListenerAddress(InetAddress.getLocalHost()),
-                new InetServiceEntry( "ldap", 10389 ) ) );
+        int port = AvailablePortFinder.getNextAvailable();
+        ListenerConfig config = new TCPListenerConfig(
+            new SocketListenerAddress( InetAddress.getLocalHost() ),
+                new InetServiceEntry( "ldap", port ) );
+        listener.bind( config );
+        listener.unbind( config );
     }
 
     
     public void testUnbind() throws Exception
     {
-        ListenerConfig sl = new TCPListenerConfig(
+        int port = AvailablePortFinder.getNextAvailable();
+        ListenerConfig config = new TCPListenerConfig(
             new SocketListenerAddress(InetAddress.getLocalHost()),
-                new InetServiceEntry( "ldap", 10389 ) );
-        listener.bind( sl );
-        listener.unbind( sl );
+                new InetServiceEntry( "ldap", port ) );
+        listener.bind( config );
+        listener.unbind( config );
     }
 }