jdk/src/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java
changeset 18192 fa6bd0992104
parent 14856 92a1bcf46888
child 23010 6dadb192ad81
--- a/jdk/src/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java	Thu Mar 14 14:45:55 2013 +0100
+++ b/jdk/src/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java	Thu Mar 14 13:46:15 2013 -0700
@@ -45,6 +45,22 @@
 {
     static JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess();
 
+    // true if this socket is exclusively bound
+    private final boolean exclusiveBind;
+
+    /*
+     * Set to true if SO_REUSEADDR is set after the socket is bound to
+     * indicate SO_REUSEADDR is being emulated
+     */
+    private boolean reuseAddressEmulated;
+
+    // emulates SO_REUSEADDR when exclusiveBind is true and socket is bound
+    private boolean isReuseAddress;
+
+    DualStackPlainDatagramSocketImpl(boolean exclBind) {
+        exclusiveBind = exclBind;
+    }
+
     protected void datagramSocketCreate() throws SocketException {
         if (fd == null)
             throw new SocketException("Socket closed");
@@ -61,7 +77,7 @@
         if (laddr == null)
             throw new NullPointerException("argument address");
 
-        socketBind(nativefd, laddr, lport);
+        socketBind(nativefd, laddr, lport, exclusiveBind);
         if (lport == 0) {
             localPort = socketLocalPort(nativefd);
         } else {
@@ -141,6 +157,7 @@
         fdAccess.set(fd, -1);
     }
 
+    @SuppressWarnings("fallthrough")
     protected void socketSetOption(int opt, Object val) throws SocketException {
         int nativefd = checkAndReturnNativeFD();
 
@@ -153,6 +170,13 @@
                 optionValue = ((Integer)val).intValue();
                 break;
             case SO_REUSEADDR :
+                if (exclusiveBind && localPort != 0)  {
+                    // socket already bound, emulate SO_REUSEADDR
+                    reuseAddressEmulated = true;
+                    isReuseAddress = (Boolean)val;
+                    return;
+                }
+                //Intentional fallthrough
             case SO_BROADCAST :
                 optionValue = ((Boolean)val).booleanValue() ? 1 : 0;
                 break;
@@ -170,6 +194,8 @@
         if (opt == SO_BINDADDR) {
             return socketLocalAddress(nativefd);
         }
+        if (opt == SO_REUSEADDR && reuseAddressEmulated)
+            return isReuseAddress;
 
         int value = socketGetIntOption(nativefd, opt);
         Object returnValue = null;
@@ -238,8 +264,8 @@
 
     private static native int socketCreate(boolean v6Only);
 
-    private static native void socketBind(int fd, InetAddress localAddress, int localport)
-        throws SocketException;
+    private static native void socketBind(int fd, InetAddress localAddress,
+            int localport, boolean exclBind) throws SocketException;
 
     private static native void socketConnect(int fd, InetAddress address, int port)
         throws SocketException;