--- a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,9 @@
import java.io.IOException;
import java.security.AccessController;
import sun.net.ResourceManager;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
/**
* Abstract datagram and multicast socket implementation base class.
@@ -70,6 +73,45 @@
});
}
+ private static volatile boolean checkedReusePort;
+ private static volatile boolean isReusePortAvailable;
+
+ /**
+ * Tells whether SO_REUSEPORT is supported.
+ */
+ static boolean isReusePortAvailable() {
+ if (!checkedReusePort) {
+ isReusePortAvailable = isReusePortAvailable0();
+ checkedReusePort = true;
+ }
+ return isReusePortAvailable;
+ }
+
+ private static volatile Set<SocketOption<?>> socketOptions;
+
+ /**
+ * Returns a set of SocketOptions supported by this impl
+ * and by this impl's socket (Socket or ServerSocket)
+ *
+ * @return a Set of SocketOptions
+ */
+ @Override
+ protected Set<SocketOption<?>> supportedOptions() {
+ Set<SocketOption<?>> options = socketOptions;
+ if (options == null) {
+ if (isReusePortAvailable()) {
+ options = new HashSet<>();
+ options.addAll(super.supportedOptions());
+ options.add(StandardSocketOptions.SO_REUSEPORT);
+ options = Collections.unmodifiableSet(options);
+ } else {
+ options = super.supportedOptions();
+ }
+ socketOptions = options;
+ }
+ return options;
+ }
+
/**
* Creates a datagram socket
*/
@@ -303,6 +345,14 @@
if (o == null || !(o instanceof Boolean))
throw new SocketException("bad argument for IP_MULTICAST_LOOP");
break;
+ case SO_REUSEPORT:
+ if (o == null || !(o instanceof Boolean)) {
+ throw new SocketException("bad argument for SO_REUSEPORT");
+ }
+ if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
+ throw new UnsupportedOperationException("unsupported option");
+ }
+ break;
default:
throw new SocketException("invalid option: " + optID);
}
@@ -343,6 +393,13 @@
result = socketGetOption(optID);
break;
+ case SO_REUSEPORT:
+ if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
+ throw new UnsupportedOperationException("unsupported option");
+ }
+ result = socketGetOption(optID);
+ break;
+
default:
throw new SocketException("invalid option: " + optID);
}
@@ -364,4 +421,5 @@
}
abstract int dataAvailable();
+ private static native boolean isReusePortAvailable0();
}