--- a/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -33,6 +33,9 @@
import sun.net.ConnectionResetException;
import sun.net.NetHooks;
import sun.net.ResourceManager;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
/**
* Default Socket Implementation. This implementation does
@@ -87,6 +90,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 socket with a boolean that specifies whether this
* is a stream socket (true) or an unconnected UDP socket (false).
@@ -269,6 +311,13 @@
throw new SocketException("bad parameter for SO_REUSEADDR");
on = ((Boolean)val).booleanValue();
break;
+ case SO_REUSEPORT:
+ if (val == null || !(val instanceof Boolean))
+ throw new SocketException("bad parameter for SO_REUSEPORT");
+ if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT))
+ throw new UnsupportedOperationException("unsupported option");
+ on = ((Boolean)val).booleanValue();
+ break;
default:
throw new SocketException("unrecognized TCP option: " + opt);
}
@@ -326,6 +375,12 @@
case SO_KEEPALIVE:
ret = socketGetOption(opt, null);
return Boolean.valueOf(ret != -1);
+ case SO_REUSEPORT:
+ if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
+ throw new UnsupportedOperationException("unsupported option");
+ }
+ ret = socketGetOption(opt, null);
+ return Boolean.valueOf(ret != -1);
// should never get here
default:
return null;
@@ -723,4 +778,6 @@
public static final int SHUT_RD = 0;
public static final int SHUT_WR = 1;
+
+ private static native boolean isReusePortAvailable0();
}