--- a/src/java.base/share/classes/java/net/ServerSocket.java Wed Jan 23 19:56:28 2019 +0100
+++ b/src/java.base/share/classes/java/net/ServerSocket.java Wed Jan 23 19:30:59 2019 +0000
@@ -27,6 +27,7 @@
import jdk.internal.access.JavaNetSocketAccess;
import jdk.internal.access.SharedSecrets;
+import sun.nio.ch.NioSocketImpl;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -296,7 +297,7 @@
} else {
// No need to do a checkOldImpl() here, we know it's an up to date
// SocketImpl!
- impl = new SocksSocketImpl();
+ impl = new NioSocketImpl(true);
}
if (impl != null)
impl.setServerSocket(this);
@@ -542,41 +543,82 @@
* @spec JSR-51
*/
protected final void implAccept(Socket s) throws IOException {
- SocketImpl si = null;
- try {
- if (s.impl == null)
- s.setImpl();
- else {
- s.impl.reset();
+ SocketImpl impl = getImpl();
+ SocketImpl si = s.impl;
+
+ // Socket does not have a SocketImpl
+ if (si == null) {
+ // create a SocketImpl and accept the connection
+ si = Socket.createImpl();
+ impl.accept(si);
+
+ try {
+ // a custom impl has accepted the connection with a NIO SocketImpl
+ if (!(impl instanceof NioSocketImpl) && (si instanceof NioSocketImpl)) {
+ ((NioSocketImpl) si).postCustomAccept();
+ }
+ } finally {
+ securityCheckAccept(si); // closes si if permission check fails
}
- si = s.impl;
- s.impl = null;
- si.address = new InetAddress();
- si.fd = new FileDescriptor();
- getImpl().accept(si);
- SocketCleanable.register(si.fd); // raw fd has been set
+
+ // bind Socket to the SocketImpl and update socket state
+ s.setImpl(si);
+ s.postAccept();
+ return;
+ }
+
+ // ServerSocket or Socket is using NIO SocketImpl
+ if (impl instanceof NioSocketImpl || si instanceof NioSocketImpl) {
+ // not implemented
+ if (impl instanceof NioSocketImpl && impl.getClass() != NioSocketImpl.class)
+ throw new UnsupportedOperationException();
+
+ // accept connection via new SocketImpl
+ NioSocketImpl nsi = new NioSocketImpl(false);
+ impl.accept(nsi);
+ securityCheckAccept(nsi); // closes si if permission check fails
- SecurityManager security = System.getSecurityManager();
- if (security != null) {
- security.checkAccept(si.getInetAddress().getHostAddress(),
- si.getPort());
- }
- } catch (IOException e) {
- if (si != null)
+ // copy state to the existing SocketImpl and update socket state
+ nsi.copyTo(si);
+ s.postAccept();
+ return;
+ }
+
+ // ServerSocket and Socket bound to custom SocketImpls
+ s.impl = null; // break connection to impl
+ boolean completed = false;
+ try {
+ si.reset();
+ si.fd = new FileDescriptor();
+ si.address = new InetAddress();
+ impl.accept(si);
+ securityCheckAccept(si); // closes si if permission check fails
+ completed = true;
+ } finally {
+ if (!completed)
si.reset();
- s.impl = si;
- throw e;
- } catch (SecurityException e) {
- if (si != null)
- si.reset();
- s.impl = si;
- throw e;
+ s.impl = si; // restore connection to impl
}
- s.impl = si;
s.postAccept();
}
/**
+ * Invokes the security manager's checkAccept method. If the permission
+ * check fails then it closes the SocketImpl.
+ */
+ private void securityCheckAccept(SocketImpl si) throws IOException {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ try {
+ sm.checkAccept(si.getInetAddress().getHostAddress(), si.getPort());
+ } catch (SecurityException se) {
+ si.close();
+ throw se;
+ }
+ }
+ }
+
+ /**
* Closes this socket.
*
* Any thread currently blocked in {@link #accept()} will throw