[kaffe] Bug Report: multiple sockets can't bind to same multicast address

Everton da Silva Marques everton@lab.ipaccess.diveo.net.br
Wed Oct 29 14:08:02 2003


--liOOAslEiF7prFVr
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Wed, Oct 29, 2003 at 02:02:54PM -0200, Everton da Silva Marques wrote:
> On Tue, Oct 07, 2003 at 02:46:22PM -0300, Everton da Silva Marques wrote:
> > 
> > Kaffe (1.1.1 and 1.1.2) does not allow multiple multicast
> > sockets to bind to the same address/port pair.
> 
> I think the problem is, MulticastSocket constructors call setReuseAddress(true)
> _after_ the invokation of super(). But super() (DatagramSocket) tries to
> bind the socket, and gets an exception.
> 
> Thus, the fix for this problem requires to setReuseAddress(true) before
> binding the socket.

Please find attached a possible patch for this issue.

Regards,
Everton


--liOOAslEiF7prFVr
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="MulticastSocket.java.diff"

--- kaffe-1.1.2-orig/libraries/javalib/java/net/MulticastSocket.java	2003-08-30 11:18:32.000000000 -0300
+++ kaffe-1.1.2/libraries/javalib/java/net/MulticastSocket.java	2003-10-29 15:15:15.000000000 -0200
@@ -80,8 +80,7 @@
    */
   public MulticastSocket() throws IOException
   {
-    super(0, null);
-    setReuseAddress (true);
+    super(0, null, true);
   }
 
   /**
@@ -95,8 +94,7 @@
    */
   public MulticastSocket(int port) throws IOException
   {
-    super(port, null);
-    setReuseAddress (true);
+    super(port, null, true);
   }
 
   /**
@@ -112,8 +110,7 @@
    */
   public MulticastSocket(SocketAddress address) throws IOException
   {
-    super(address);
-    setReuseAddress (true);
+    super(address, true);
   }
   
   /**

--liOOAslEiF7prFVr
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="DatagramSocket.java.diff"

--- kaffe-1.1.2-orig/libraries/javalib/java/net/DatagramSocket.java	2003-09-28 16:54:10.000000000 -0300
+++ kaffe-1.1.2/libraries/javalib/java/net/DatagramSocket.java	2003-10-29 17:48:19.000000000 -0200
@@ -98,7 +98,7 @@
    * 
    * @since 1.4
    */
-  protected DatagramSocket (DatagramSocketImpl impl)
+  protected DatagramSocket(DatagramSocketImpl impl)
   {
     this.impl = impl;
     this.remoteAddress = null;
@@ -133,42 +133,37 @@
     this(port, null);
   }
 
-  /**
-   * Initializes a new instance of <code>DatagramSocket</code> that binds to 
-   * the specified local port and address.
-   *
-   * @param port The local port number to bind to.
-   * @param laddr The local address to bind to.
-   *
-   * @exception SecurityException If a security manager exists and its
-   * checkListen method doesn't allow the operation.
-   * @exception SocketException If an error occurs.
-   */
-  public DatagramSocket(int port, InetAddress laddr) throws SocketException
+  private void loadSocketImpl() throws SocketException
   {
-    if (port < 0 || port > 65535)
-      throw new IllegalArgumentException("Invalid port: " + port);
-
-    SecurityManager s = System.getSecurityManager();
-    if (s != null)
-      s.checkListen(port);
-
     String propVal = System.getProperty("impl.prefix");
     if (propVal == null || propVal.equals(""))
       impl = new PlainDatagramSocketImpl();
     else
       try
-	{
+        {
           impl = (DatagramSocketImpl) Class.forName
             ("java.net." + propVal + "DatagramSocketImpl").newInstance();
-	}
+        }
       catch (Exception e)
-	{
-	  System.err.println("Could not instantiate class: java.net." +
-	    propVal + "DatagramSocketImpl");
-	  impl = new PlainDatagramSocketImpl();
-	}
+        {
+          System.err.println("Could not instantiate class: java.net." +
+                             propVal + "DatagramSocketImpl");
+          impl = new PlainDatagramSocketImpl();
+        }
     impl.create();
+  }
+
+  private void initDatagramSocket(int port, InetAddress laddr) throws SocketException
+  {
+    if (port < 0 || port > 65535)
+      throw new IllegalArgumentException("Invalid port: " + port);
+
+    SecurityManager s = System.getSecurityManager();
+    if (s != null)
+      s.checkListen(port);
+
+    if (impl == null)
+	loadSocketImpl();
 
     if (laddr == null)
       laddr = InetAddress.ANY_IF;
@@ -194,6 +189,41 @@
       }
   }
 
+  DatagramSocket(int port, InetAddress laddr, boolean reuseAddr) throws SocketException
+  {
+    setReuseAddress(reuseAddr);
+    initDatagramSocket(port, laddr);
+  }
+
+  DatagramSocket(InetAddress laddr, boolean reuseAddr) throws SocketException
+  {
+    setReuseAddress(reuseAddr);
+    initDatagramSocket(0, laddr);
+  }
+
+  /**
+   * Initializes a new instance of <code>DatagramSocket</code> that binds to 
+   * the specified local port and address.
+   *
+   * @param port The local port number to bind to.
+   * @param laddr The local address to bind to.
+   *
+   * @exception SecurityException If a security manager exists and its
+   * checkListen method doesn't allow the operation.
+   * @exception SocketException If an error occurs.
+   */
+  public DatagramSocket(int port, InetAddress laddr) throws SocketException
+  {
+    initDatagramSocket(port, laddr);
+  }
+
+  DatagramSocket(SocketAddress address, boolean reuseAddr) throws SocketException
+  {
+    this (((InetSocketAddress) address).getPort (),
+          ((InetSocketAddress) address).getAddress (),
+          reuseAddr);
+  }
+
   /**
    * Initializes a new instance of <code>DatagramSocket</code> that binds to 
    * the specified local port and address.
@@ -207,7 +237,7 @@
    *
    * @since 1.4
    */
-  public DatagramSocket (SocketAddress address) throws SocketException
+  public DatagramSocket(SocketAddress address) throws SocketException
   {
     this (((InetSocketAddress) address).getPort (),
           ((InetSocketAddress) address).getAddress ());
@@ -714,7 +744,7 @@
   public void setReuseAddress(boolean on) throws SocketException
   {
     if (impl == null)
-      throw new SocketException ("Cannot initialize Socket implementation");
+	loadSocketImpl();
 
     impl.setOption (SocketOptions.SO_REUSEADDR, new Boolean (on));
   }

--liOOAslEiF7prFVr--